+ assert ((pos&CAT_MASK) == p->cat);
+ }
+ }
+ }
+}
+
+void close_block (ISAMB b, struct ISAMB_block *p)
+{
+ if (!p)
+ return;
+ if (p->deleted)
+ {
+ yaz_log (b->log_freelist, "release block " ZINT_FORMAT " from freelist %d:" ZINT_FORMAT,
+ p->pos, p->cat, p->pos/CAT_MAX);
+ memcpy (p->buf, &b->file[p->cat].head.free_list, sizeof(zint));
+ b->file[p->cat].head.free_list = p->pos;
+ if (!get_block (b, p->pos, p->buf, 1))
+ {
+ yaz_log (b->log_io, "bf_write: close_block (deleted)");
+ bf_write (b->file[p->cat].bf, p->pos/CAT_MAX, 0, 0, p->buf);
+ }
+ }
+ else if (p->dirty)
+ {
+ int offset = b->file[p->cat].head.block_offset;
+ int size = p->size + offset;
+ char *dst = p->buf + 3;
+ assert (p->size >= 0);
+
+ /* memset becuase encode_ptr usually does not write all bytes */
+ memset(p->buf, 0, b->file[p->cat].head.block_offset);
+ p->buf[0] = p->leaf;
+ p->buf[1] = size & 255;
+ p->buf[2] = size >> 8;
+ encode_ptr(&dst, p->no_items);
+ check_block(b, p);
+ if (!get_block (b, p->pos, p->buf, 1))
+ {
+ yaz_log (b->log_io, "bf_write: close_block");
+ bf_write (b->file[p->cat].bf, p->pos/CAT_MAX, 0, 0, p->buf);
+ }
+ }
+ (*b->method->codec.stop)(p->decodeClientData);
+ xfree (p->buf);
+ xfree (p);
+}
+
+int insert_sub (ISAMB b, struct ISAMB_block **p,
+ void *new_item, int *mode,
+ ISAMC_I *stream,
+ struct ISAMB_block **sp,
+ void *sub_item, int *sub_size,
+ const void *max_item);
+
+int insert_int (ISAMB b, struct ISAMB_block *p, void *lookahead_item,
+ int *mode,
+ ISAMC_I *stream, struct ISAMB_block **sp,
+ void *split_item, int *split_size, const void *last_max_item)
+{
+ char *startp = p->bytes;
+ const char *src = startp;
+ char *endp = p->bytes + p->size;
+ ISAMB_P pos;
+ struct ISAMB_block *sub_p1 = 0, *sub_p2 = 0;
+ char sub_item[DST_ITEM_MAX];
+ int sub_size;
+ int more = 0;
+ zint diff_terms = 0;
+
+ *sp = 0;
+
+ assert(p->size >= 0);
+ decode_ptr (&src, &pos);
+ while (src != endp)
+ {
+ zint item_len;
+ int d;
+ const char *src0 = src;
+ decode_ptr (&src, &item_len);
+ d = (*b->method->compare_item)(src, lookahead_item);
+ if (d > 0)
+ {
+ sub_p1 = open_block (b, pos);
+ assert (sub_p1);
+ diff_terms -= sub_p1->no_items;
+ more = insert_sub (b, &sub_p1, lookahead_item, mode,
+ stream, &sub_p2,
+ sub_item, &sub_size, src);
+ diff_terms += sub_p1->no_items;
+ src = src0;
+ break;
+ }
+ src += item_len;
+ decode_ptr (&src, &pos);
+ }
+ if (!sub_p1)
+ {
+ sub_p1 = open_block (b, pos);
+ assert (sub_p1);
+ diff_terms -= sub_p1->no_items;
+ more = insert_sub (b, &sub_p1, lookahead_item, mode, stream, &sub_p2,
+ sub_item, &sub_size, last_max_item);
+ diff_terms += sub_p1->no_items;
+ }
+ if (sub_p2)
+ diff_terms += sub_p2->no_items;
+ if (diff_terms)
+ {
+ p->dirty = 1;
+ p->no_items += diff_terms;
+ }
+ if (sub_p2)
+ {
+ /* there was a split - must insert pointer in this one */
+ char dst_buf[DST_BUF_SIZE];
+ char *dst = dst_buf;
+
+ assert (sub_size < 80 && sub_size > 1);
+
+ memcpy (dst, startp, src - startp);
+
+ dst += src - startp;
+
+ encode_ptr (&dst, sub_size); /* sub length and item */
+ memcpy (dst, sub_item, sub_size);
+ dst += sub_size;
+
+ encode_ptr (&dst, sub_p2->pos); /* pos */
+
+ if (endp - src) /* remaining data */
+ {
+ memcpy (dst, src, endp - src);
+ dst += endp - src;
+ }
+ p->size = dst - dst_buf;
+ assert (p->size >= 0);
+
+
+ if (p->size <= b->file[p->cat].head.block_max)
+ {
+ memcpy (startp, dst_buf, dst - dst_buf);
+ }
+ else
+ {
+ struct ISAMB_block *sub_p3;
+ zint split_size_tmp;
+ zint no_items_first_half = 0;
+ int p_new_size;
+ const char *half;
+ src = dst_buf;
+ endp = dst;
+
+ 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);
+
+ while (src <= half)
+ {
+ decode_ptr (&src, &split_size_tmp);
+ *split_size = (int) split_size_tmp;
+
+ src += *split_size;
+ 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);
+ }
+ /* p is first half */
+ p_new_size = src - dst_buf;
+ memcpy (p->bytes, dst_buf, p_new_size);
+
+ decode_ptr (&src, &split_size_tmp);
+ *split_size = (int) split_size_tmp;
+ memcpy (split_item, src, *split_size);
+ src += *split_size;