+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)
+ {
+ struct ISAMB_cache_entry *ce_this = b->file[cat].cache_entries;
+ b->file[cat].cache_entries = ce_this->next;
+
+ if (ce_this->dirty)
+ {
+ yaz_log(b->log_io, "bf_write: flush_blocks");
+ bf_write(b->file[cat].bf, ce_this->pos, 0, 0, ce_this->buf);
+ }
+ xfree(ce_this->buf);
+ xfree(ce_this);
+ }
+}
+
+static int cache_block(ISAMB b, ISAM_P pos, unsigned char *userbuf, int wr)
+{
+ int cat = (int) (pos&CAT_MASK);
+ int off = (int) (((pos/CAT_MAX) &
+ (ISAMB_CACHE_ENTRY_SIZE / b->file[cat].head.block_size - 1))
+ * b->file[cat].head.block_size);
+ zint norm = pos / (CAT_MASK*ISAMB_CACHE_ENTRY_SIZE / b->file[cat].head.block_size);
+ int no = 0;
+ struct ISAMB_cache_entry **ce, *ce_this = 0, **ce_last = 0;
+
+ if (!b->cache)
+ return 0;
+
+ assert(ISAMB_CACHE_ENTRY_SIZE >= b->file[cat].head.block_size);
+ for (ce = &b->file[cat].cache_entries; *ce; ce = &(*ce)->next, no++)
+ {
+ ce_last = ce;
+ if ((*ce)->pos == norm)
+ {
+ ce_this = *ce;
+ *ce = (*ce)->next; /* remove from list */
+
+ ce_this->next = b->file[cat].cache_entries; /* move to front */
+ b->file[cat].cache_entries = ce_this;
+
+ if (wr)
+ {
+ memcpy(ce_this->buf + off, userbuf,
+ b->file[cat].head.block_size);
+ ce_this->dirty = 1;
+ }
+ else
+ memcpy(userbuf, ce_this->buf + off,
+ b->file[cat].head.block_size);
+ return 1;
+ }
+ }
+ if (no >= b->cache_size)
+ {
+ assert(ce_last && *ce_last);
+ ce_this = *ce_last;
+ *ce_last = 0; /* remove the last entry from list */
+ if (ce_this->dirty)
+ {
+ yaz_log(b->log_io, "bf_write: cache_block");
+ bf_write(b->file[cat].bf, ce_this->pos, 0, 0, ce_this->buf);
+ }
+ xfree(ce_this->buf);
+ xfree(ce_this);
+ }
+ ce_this = xmalloc(sizeof(*ce_this));
+ ce_this->next = b->file[cat].cache_entries;
+ b->file[cat].cache_entries = ce_this;
+ ce_this->buf = xmalloc(ISAMB_CACHE_ENTRY_SIZE);
+ ce_this->pos = norm;
+ yaz_log(b->log_io, "bf_read: cache_block");
+ if (!bf_read(b->file[cat].bf, norm, 0, 0, ce_this->buf))
+ memset(ce_this->buf, 0, ISAMB_CACHE_ENTRY_SIZE);
+ if (wr)
+ {
+ memcpy(ce_this->buf + off, userbuf, b->file[cat].head.block_size);
+ ce_this->dirty = 1;
+ }
+ else
+ {
+ ce_this->dirty = 0;
+ memcpy(userbuf, ce_this->buf + off, b->file[cat].head.block_size);
+ }
+ return 1;
+}
+
+
+void isamb_close(ISAMB isamb)