Logo Search packages:      
Sourcecode: maqview version File versions  Download package

read_cache.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "caches.h"

ReadCache* read_cache_init(MapIndex *index){
      int i;
      ReadCache *cache;
      cache = (ReadCache*)malloc(sizeof(ReadCache));
      cache->index    = index;
      cache->ref_id   = -1;
      cache->capacity = 2 * 1024;
      cache->reads    = (Read*)malloc(sizeof(Read) * cache->capacity);
      cache->size     = 0;
      cache->offset   = 0;
      cache->start    = 0;
      cache->end      = 0;
      cache->n_ref    = index->mm->n_ref;
      cache->ref_lengths = (int64_t*)malloc(sizeof(int64_t) * cache->n_ref);
      for(i=0;i<cache->n_ref;i++){
            cache->ref_lengths[i] = index->trees[i]->right + MAX_READ_SIZE;
      }
      return cache;
}

void read_cache_free(ReadCache *cache){
      close_map_index(cache->index);
      free(cache->reads);
      free(cache);
}

#define let2read(let, reads) memcpy(&((reads)->read), let, sizeof(maplet)); (reads)->flag = 0; (reads)->y = 0

int read_cache_put(ReadCache *cache, int ref_id, int64_t start, int64_t end){
      maplet *let;
      BTree *tree;
      int i, m, n;
      int64_t t;

      if(ref_id < 0 || ref_id >= cache->index->mm->n_ref) return -2;

      tree = cache->index->trees[ref_id];
      if(start < tree->left) start = tree->left;
      if(end  > tree->right + MAX_READ_SIZE) end   = tree->right + MAX_READ_SIZE;

      if(ref_id != cache->ref_id){
            cache->ref_id = ref_id;
            cache->length = cache->ref_lengths[ref_id];
            goto RELOAD;
      }
      if(start < cache->start){
            if(end < cache->start){
                  goto RELOAD;
            } else if(end <= cache->end){
                  goto APPEND_LEFT;
            } else {
                  goto RELOAD;
            }
      } else if(start <= cache->end){
            if(end <= cache->end){
                  return 0;
            } else {
                  goto APPEND_RIGHT;
            }
      } else {
            goto RELOAD;
      }

      RELOAD:
      let = read_map_index(cache->index, ref_id, start, end, &n);
      cache->stream_pos = zrtell(cache->index->stream);
      if(let == NULL) return -1;
      if(n > cache->capacity){ cache->capacity = n; cache->reads = (Read*)realloc(cache->reads, sizeof(Read) * cache->capacity);}
      cache->offset = 0;
      memset(cache->reads, 0, sizeof(Read) * cache->capacity);
      for(i=0;i<n;i++){
            let2read(let + i, cache->reads + i);
      }
      cache->size = n;
      free(let);
      if(n){
            cache->start = read_pos(cache->reads[cache->offset].read.pos);
            if(cache->start > start) cache->start = start;
            cache->end   = read_pos(cache->reads[cache->offset+cache->size-1].read.pos);
            if(cache->end < end) cache->end = end;
      } else {
            cache->start = start;
            cache->end   = end;
      }
      return 1;

      APPEND_LEFT:
      t = end;
      end = cache->start;
      if(start >= end) return 0;
      let = read_map_index(cache->index, ref_id, start, end, &n);
      cache->stream_pos = zrtell(cache->index->stream);
      if(let == NULL) return -1;
      m = n;
      for(;n>0;n--){
            if(read_pos(let[n-1].pos) <= cache->start) break;
      }
      if(n <= 0){ cache->start = start; return 0; }
      if(n + cache->size > cache->capacity){
            if(read_pos(let[m-1].pos) >= t){
                  if(m > cache->capacity){
                        cache->capacity = m;
                        cache->reads = (Read*)realloc(cache->reads, sizeof(Read) * cache->capacity);
                  }
                  n = m;
                  cache->offset = cache->capacity;
                  cache->size   = 0;
                  cache->end    = read_pos(let[n-1].pos);
            } else {
                  cache->capacity = cache->size + n;
                  cache->reads = (Read*)realloc(cache->reads, sizeof(Read) * cache->capacity);
            }
      }
      if(cache->offset < n){
            if(cache->size)
                  memmove(cache->reads + cache->capacity - cache->size, cache->reads + cache->offset, sizeof(Read) * cache->size);
            cache->offset = cache->capacity - cache->size;
      }
      for(;n>0;n--){
            cache->offset --;
            cache->size ++;
            let2read(let + n - 1, cache->reads + cache->offset);
      }
      free(let);
      cache->start = read_pos(cache->reads[cache->offset].read.pos);
      if(cache->start > start) cache->start = start;
      return 2;

      APPEND_RIGHT:
      t = start;
      start = cache->end;
      if(start >= end) return 0;
      if(cache->stream_pos == zrtell(cache->index->stream)){
            let = read_map_next_to(cache->index, ref_id, end + MAX_READ_SIZE, &n);
      } else {
            let = read_map_index(cache->index, ref_id, start, end, &n);
      }
      cache->stream_pos = zrtell(cache->index->stream);
      if(let == NULL) return -1;
      m = n;
      for(n=0;n<m;n++){
            if(read_pos(let[n].pos) > cache->end) break;
      }
      if(n == m){ cache->end = end; return 0; }
      if(m - n + cache->size > cache->capacity){
            if(read_pos(let[0].pos) <= t - MAX_READ_SIZE){
                  if(m > cache->capacity){
                        cache->capacity = m;
                        cache->reads = (Read*)realloc(cache->reads, sizeof(Read) * cache->capacity);
                  }
                  n = 0;
                  cache->offset = 0;
                  cache->size   = 0;
                  cache->start  = read_pos(let[0].pos);
            } else {
                  for(i=cache->size-1;i>=0;i--){
                        if(read_pos(cache->reads[cache->offset + i].read.pos) < t - MAX_READ_SIZE) break;
                  }
                  i ++;
                  if(i > 0){
                        cache->size -= i;
                        if(cache->size){
                              memmove(cache->reads, cache->reads + cache->offset + i, sizeof(Read) * cache->size);
                              cache->start  = read_pos(cache->reads[0].read.pos);
                        } else {
                              cache->start  = read_pos(let[0].pos);
                        }
                        cache->offset = 0;
                  }
                  if(m - n + cache->size > cache->capacity){
                        cache->capacity = m - n + cache->size;
                        cache->reads = (Read*)realloc(cache->reads, sizeof(Read) * cache->capacity);
                  }
            }
      }
      if(cache->offset){
            memmove(cache->reads, cache->reads + cache->offset, sizeof(Read) * cache->size);
            cache->offset = 0;
      }
      for(;n<m;n++){
            let2read(let + n, cache->reads + cache->offset + cache->size);
            cache->size ++;
      }
      cache->end = read_pos(cache->reads[cache->offset+cache->size-1].read.pos);
      if(cache->end < end) cache->end = end;
      return 3;
}

Generated by  Doxygen 1.6.0   Back to index