-/* $Id: isamb.c,v 1.88 2006-12-12 13:46:41 adam Exp $
- Copyright (C) 1995-2006
+/* $Id: isamb.c,v 1.94 2007-11-28 09:56:42 adam Exp $
+ Copyright (C) 1995-2007
Index Data ApS
This file is part of the Zebra server.
#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;
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 {
b->cache_size = v;
}
-ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
- int cache)
+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->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; i<ISAMB_MAX_LEVEL; i++)
isamb->skipped_nodes[i] = isamb->accessed_nodes[i] = 0;
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)
{
}
/* 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;
- assert(b_size <= ISAMB_CACHE_ENTRY_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;
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))
{
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;
}
}
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");
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; i<CAT_NO; i++)
+ {
+ sizes[i] = b_size;
+ b_size = b_size * ISAMB_FAC_SIZE;
+ }
+ return isamb_open2(bfs, name, writeflag, method, cache,
+ CAT_NO, sizes, 0);
+}
+
static void flush_blocks (ISAMB b, int cat)
{
while (b->file[cat].cache_entries)
yaz_log(YLOG_DEBUG, "isamb_close returned "ZINT_FORMAT" values, "
"skipped "ZINT_FORMAT,
isamb->skipped_numbers, isamb->returned_numbers);
+
for (i = 0; i<isamb->no_cat; i++)
{
flush_blocks (isamb, i);
{
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;
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);
#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);
#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);
assert(*lookahead_mode);
}
}
+ else if (d == 0 && *lookahead_mode == 2)
+ {
+ /* For mode == 2, we insert the new key anyway - even
+ though the comparison is 0. */
+ dst_item = lookahead_item;
+ p->dirty = 1;
+ }
else
dst_item = file_item_buf;
- if (!*lookahead_mode && d == 0)
+ if (d == 0 && !*lookahead_mode)
{
- /* it's a deletion and they match so there is nothing to be
- inserted anyway .. But mark the thing bad (file item
- was part of input.. The item will not be part of output */
+ /* it's a deletion and they match so there is nothing
+ to be inserted anyway .. But mark the thing dirty
+ (file item was part of input.. The item will not be
+ part of output */
p->dirty = 1;
}
else if (!half1 && dst > mid_cut)
#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);
/* simple recursive dumper .. */
static void isamb_dump_r (ISAMB b, ISAM_P pos, void (*pr)(const char *str),
- int level)
+ int level)
{
char buf[1024];
char prefix_str[1024];
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