X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=isamb%2Fisamb.c;h=9d4d4008588ad1cb8fd2c9af92d5cb9459c2b1d9;hb=28045b27be52a2f8ac41900051612f5640cea165;hp=0578ff7931bb3a913196bfe5248b3bb81feb5593;hpb=5d2484328c438d0e3c8565b6531383e866fbac4e;p=idzebra-moved-to-github.git diff --git a/isamb/isamb.c b/isamb/isamb.c index 0578ff7..9d4d400 100644 --- a/isamb/isamb.c +++ b/isamb/isamb.c @@ -1,5 +1,5 @@ -/* $Id: isamb.c,v 1.86 2006-11-14 12:03:48 adam Exp $ - Copyright (C) 1995-2006 +/* $Id: isamb.c,v 1.93 2007-04-03 16:54:46 adam Exp $ + Copyright (C) 1995-2007 Index Data ApS This file is part of the Zebra server. @@ -33,7 +33,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define ISAMB_MAJOR_VERSION 3 -#define ISAMB_MINOR_VERSION 0 +#define ISAMB_MINOR_VERSION_NO_ROOT 0 +#define ISAMB_MINOR_VERSION_WITH_ROOT 1 struct ISAMB_head { zint first_block; @@ -53,8 +54,9 @@ struct ISAMB_head { #define ISAMB_MAX_LEVEL 10 /* approx 2*max page + max size of item */ -#define DST_BUF_SIZE 16840 +#define DST_BUF_SIZE (2*4096+300) +/* should be maximum block size of multiple thereof */ #define ISAMB_CACHE_ENTRY_SIZE 4096 /* CAT_MAX: _must_ be power of 2 */ @@ -99,6 +101,12 @@ struct ISAMB_s { zint returned_numbers; zint skipped_nodes[ISAMB_MAX_LEVEL]; /* [0]=skipped leaves, 1 = higher etc */ zint accessed_nodes[ISAMB_MAX_LEVEL]; /* nodes we did not skip */ + zint number_of_int_splits; + zint number_of_leaf_splits; + int enable_int_count; /* whether we count nodes (or not) */ + int cache_size; /* size of blocks to cache (if cache=1) */ + int minor_version; + zint root_ptr; }; struct ISAMB_block { @@ -179,25 +187,57 @@ static void decode_ptr(const char **src, zint *pos) } #endif -ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method, - int cache) + +void isamb_set_int_count(ISAMB b, int v) +{ + b->enable_int_count = v; +} + +void isamb_set_cache_size(ISAMB b, int v) +{ + b->cache_size = v; +} + +ISAMB isamb_open2(BFiles bfs, const char *name, int writeflag, ISAMC_M *method, + int cache, int no_cat, int *sizes, int use_root_ptr) { ISAMB isamb = xmalloc(sizeof(*isamb)); - int i, b_size = ISAMB_MIN_SIZE; + int i; + + assert(no_cat <= CAT_MAX); isamb->bfs = bfs; isamb->method = (ISAMC_M *) xmalloc(sizeof(*method)); memcpy(isamb->method, method, sizeof(*method)); - isamb->no_cat = CAT_NO; + isamb->no_cat = no_cat; isamb->log_io = 0; isamb->log_freelist = 0; isamb->cache = cache; isamb->skipped_numbers = 0; isamb->returned_numbers = 0; + isamb->number_of_int_splits = 0; + isamb->number_of_leaf_splits = 0; + isamb->enable_int_count = 1; + isamb->cache_size = 40; + + if (use_root_ptr) + isamb->minor_version = ISAMB_MINOR_VERSION_WITH_ROOT; + else + isamb->minor_version = ISAMB_MINOR_VERSION_NO_ROOT; + + isamb->root_ptr = 0; + for (i = 0; iskipped_nodes[i] = isamb->accessed_nodes[i] = 0; - assert(cache == 0); + if (cache == -1) + { + yaz_log(YLOG_WARN, "isamb_open %s. Degraded TEST mode", name); + } + else + { + assert(cache == 0 || cache == 1); + } isamb->file = xmalloc(sizeof(*isamb->file) * isamb->no_cat); for (i = 0; i < isamb->no_cat; i++) @@ -217,7 +257,7 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method, isamb->file[i].bf = bf_open(bfs, fname, ISAMB_CACHE_ENTRY_SIZE, writeflag); else - isamb->file[i].bf = bf_open(bfs, fname, b_size, writeflag); + isamb->file[i].bf = bf_open(bfs, fname, sizes[i], writeflag); if (!isamb->file[i].bf) { @@ -226,11 +266,12 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method, } /* fill-in default values (for empty isamb) */ - isamb->file[i].head.first_block = ISAMB_CACHE_ENTRY_SIZE/b_size+1; + isamb->file[i].head.first_block = ISAMB_CACHE_ENTRY_SIZE/sizes[i]+1; isamb->file[i].head.last_block = isamb->file[i].head.first_block; - isamb->file[i].head.block_size = b_size; + isamb->file[i].head.block_size = sizes[i]; + assert(sizes[i] <= ISAMB_CACHE_ENTRY_SIZE); #if ISAMB_PTR_CODEC - if (i == isamb->no_cat-1 || b_size > 128) + if (i == isamb->no_cat-1 || sizes[i] > 128) isamb->file[i].head.block_offset = 8; else isamb->file[i].head.block_offset = 4; @@ -238,7 +279,7 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method, isamb->file[i].head.block_offset = 11; #endif isamb->file[i].head.block_max = - b_size - isamb->file[i].head.block_offset; + sizes[i] - isamb->file[i].head.block_offset; isamb->file[i].head.free_list = 0; if (bf_read(isamb->file[i].bf, 0, 0, 0, hbuf)) { @@ -250,27 +291,31 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method, if (memcmp(hbuf, "isamb", 5)) { yaz_log(YLOG_WARN, "bad isamb header for file %s", fname); + isamb_close(isamb); return 0; } if (sscanf(hbuf+5, "%d %d %d", &major, &minor, &len) != 3) { yaz_log(YLOG_WARN, "bad isamb header for file %s", fname); + isamb_close(isamb); return 0; } if (major != ISAMB_MAJOR_VERSION) { yaz_log(YLOG_WARN, "bad major version for file %s %d, must be %d", fname, major, ISAMB_MAJOR_VERSION); + isamb_close(isamb); return 0; } - for (left = len - b_size; left > 0; left = left - b_size) + for (left = len - sizes[i]; left > 0; left = left - sizes[i]) { pos++; - if (!bf_read(isamb->file[i].bf, pos, 0, 0, hbuf + pos*b_size)) + if (!bf_read(isamb->file[i].bf, pos, 0, 0, hbuf + pos*sizes[i])) { yaz_log(YLOG_WARN, "truncated isamb header for " "file=%s len=%d pos=%d", fname, len, pos); + isamb_close(isamb); return 0; } } @@ -282,11 +327,16 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method, decode_ptr(&src, &zint_tmp); isamb->file[i].head.block_max = (int) zint_tmp; decode_ptr(&src, &isamb->file[i].head.free_list); + if (isamb->minor_version >= ISAMB_MINOR_VERSION_WITH_ROOT) + decode_ptr(&src, &isamb->root_ptr); } assert (isamb->file[i].head.block_size >= isamb->file[i].head.block_offset); - isamb->file[i].head_dirty = 0; - assert(isamb->file[i].head.block_size == b_size); - b_size = b_size * ISAMB_FAC_SIZE; + /* must rewrite the header if root ptr is in use (bug #1017) */ + if (use_root_ptr && writeflag) + isamb->file[i].head_dirty = 1; + else + isamb->file[i].head_dirty = 0; + assert(isamb->file[i].head.block_size == sizes[i]); } #if ISAMB_DEBUG yaz_log(YLOG_WARN, "isamb debug enabled. Things will be slower than usual"); @@ -294,6 +344,21 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method, return isamb; } +ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method, + int cache) +{ + int sizes[CAT_NO]; + int i, b_size = ISAMB_MIN_SIZE; + + for (i = 0; ifile[cat].cache_entries) @@ -348,9 +413,8 @@ static int cache_block (ISAMB b, ISAM_P pos, unsigned char *userbuf, int wr) return 1; } } - if (no >= 40) + if (no >= b->cache_size) { - assert (no == 40); assert (ce_last && *ce_last); ce_this = *ce_last; *ce_last = 0; /* remove the last entry from list */ @@ -394,6 +458,7 @@ void isamb_close (ISAMB isamb) yaz_log(YLOG_DEBUG, "isamb_close returned "ZINT_FORMAT" values, " "skipped "ZINT_FORMAT, isamb->skipped_numbers, isamb->returned_numbers); + for (i = 0; ino_cat; i++) { flush_blocks (isamb, i); @@ -401,7 +466,6 @@ void isamb_close (ISAMB isamb) { char hbuf[DST_BUF_SIZE]; int major = ISAMB_MAJOR_VERSION; - int minor = ISAMB_MINOR_VERSION; int len = 16; char *dst = hbuf + 16; int pos = 0, left; @@ -412,12 +476,17 @@ void isamb_close (ISAMB isamb) encode_ptr(&dst, isamb->file[i].head.block_size); encode_ptr(&dst, isamb->file[i].head.block_max); encode_ptr(&dst, isamb->file[i].head.free_list); + + if (isamb->minor_version >= ISAMB_MINOR_VERSION_WITH_ROOT) + encode_ptr(&dst, isamb->root_ptr); + memset(dst, '\0', b_size); /* ensure no random bytes are written */ len = dst - hbuf; /* print exactly 16 bytes (including trailing 0) */ - sprintf(hbuf, "isamb%02d %02d %02d\r\n", major, minor, len); + sprintf(hbuf, "isamb%02d %02d %02d\r\n", major, + isamb->minor_version, len); bf_write(isamb->file[i].bf, pos, 0, 0, hbuf); @@ -572,7 +641,7 @@ static void check_block (ISAMB b, struct ISAMB_block *p) #else zint item_len; decode_item_len(&src, &item_len); - assert (item_len > 0 && item_len < 80); + assert (item_len > 0 && item_len < 128); src += item_len; #endif decode_ptr(&src, &pos); @@ -720,7 +789,7 @@ int insert_int (ISAMB b, struct ISAMB_block *p, void *lookahead_item, #if INT_ENCODE const char *sub_item_ptr = sub_item; #endif - assert (sub_size < 80 && sub_size > 1); + assert (sub_size < 128 && sub_size > 1); memcpy (dst, startp, src - startp); @@ -767,6 +836,8 @@ int insert_int (ISAMB b, struct ISAMB_block *p, void *lookahead_item, const char *half; src = dst_buf; endp = dst; + + b->number_of_int_splits++; p->dirty = 1; close_block(b, sub_p2); @@ -774,10 +845,13 @@ int insert_int (ISAMB b, struct ISAMB_block *p, void *lookahead_item, half = src + b->file[p->cat].head.block_size/2; decode_ptr(&src, &pos); - /* read sub block so we can get no_items for it */ - sub_p3 = open_block(b, pos); - no_items_first_half += sub_p3->no_items; - close_block(b, sub_p3); + if (b->enable_int_count) + { + /* read sub block so we can get no_items for it */ + sub_p3 = open_block(b, pos); + no_items_first_half += sub_p3->no_items; + close_block(b, sub_p3); + } while (src <= half) { @@ -792,10 +866,13 @@ int insert_int (ISAMB b, struct ISAMB_block *p, void *lookahead_item, #endif decode_ptr(&src, &pos); - /* read sub block so we can get no_items for it */ - sub_p3 = open_block(b, pos); - no_items_first_half += sub_p3->no_items; - close_block(b, sub_p3); + if (b->enable_int_count) + { + /* read sub block so we can get no_items for it */ + sub_p3 = open_block(b, pos); + no_items_first_half += sub_p3->no_items; + close_block(b, sub_p3); + } } /* p is first half */ p_new_size = src - dst_buf; @@ -1083,6 +1160,8 @@ int insert_leaf (ISAMB b, struct ISAMB_block **sp1, void *lookahead_item, (*b->method->codec.reset)(c2); + b->number_of_leaf_splits++; + first_dst = (*sp2)->bytes; (*b->method->codec.encode)(c2, &first_dst, &cut_item); @@ -1207,7 +1286,7 @@ void isamb_merge(ISAMB b, ISAM_P *pos, ISAMC_I *stream) #endif encode_ptr(&dst, p->pos); - assert (sub_size < 80 && sub_size > 1); + assert (sub_size < 128 && sub_size > 1); #if INT_ENCODE (*b->method->codec.reset)(c1); (*b->method->codec.encode)(c1, &dst, &sub_item_ptr); @@ -1960,6 +2039,28 @@ again: } return 1; } + +zint isamb_get_int_splits(ISAMB b) +{ + return b->number_of_int_splits; +} + +zint isamb_get_leaf_splits(ISAMB b) +{ + return b->number_of_leaf_splits; +} + +zint isamb_get_root_ptr(ISAMB b) +{ + return b->root_ptr; +} + +void isamb_set_root_ptr(ISAMB b, zint root_ptr) +{ + b->root_ptr = root_ptr; +} + + /* * Local variables: * c-basic-offset: 4