📄 isamb.c
字号:
assert (p->size >= 0); if (p->size <= b->file[p->cat].head.block_max) { memcpy (startp, dst_buf, dst - dst_buf); } else { int p_new_size; char *half; src = dst_buf; endp = dst; half = src + b->file[p->cat].head.block_size/2; decode_ptr (&src, &pos); while (src <= half) { decode_ptr (&src, split_size); src += *split_size; decode_ptr (&src, &pos); } p_new_size = src - dst_buf; memcpy (p->bytes, dst_buf, p_new_size); decode_ptr (&src, split_size); memcpy (split_item, src, *split_size); src += *split_size; *sp = new_int (b, p->cat); (*sp)->size = endp - src; memcpy ((*sp)->bytes, src, (*sp)->size); p->size = p_new_size; } p->dirty = 1; close_block (b, sub_p2); } close_block (b, sub_p1); return more;}int insert_leaf (ISAMB b, struct ISAMB_block **sp1, void *lookahead_item, int *lookahead_mode, ISAMC_I *stream, struct ISAMB_block **sp2, void *sub_item, int *sub_size, void *max_item){ struct ISAMB_block *p = *sp1; char *src = 0, *endp = 0; char dst_buf[DST_BUF_SIZE], *dst = dst_buf; int new_size; void *c1 = (*b->method->code_start)(ISAMC_DECODE); void *c2 = (*b->method->code_start)(ISAMC_ENCODE); int more = 1; int quater = b->file[b->no_cat-1].head.block_max / 4; char *cut = dst_buf + quater * 2; char *maxp = dst_buf + b->file[b->no_cat-1].head.block_max; char *half1 = 0; char *half2 = 0; char cut_item_buf[DST_ITEM_MAX]; int cut_item_size = 0; if (p && p->size) { char file_item_buf[DST_ITEM_MAX]; char *file_item = file_item_buf; src = p->bytes; endp = p->bytes + p->size; (*b->method->code_item)(ISAMC_DECODE, c1, &file_item, &src); while (1) { char *dst_item = 0; char *dst_0 = dst; char *lookahead_next; int d = -1; if (lookahead_item) d = (*b->method->compare_item)(file_item_buf, lookahead_item); if (d > 0) { dst_item = lookahead_item; if (!*lookahead_mode) { yaz_log (LOG_WARN, "isamb: Inconsistent register (1)"); assert (*lookahead_mode); } } else dst_item = file_item_buf; if (!*lookahead_mode && d == 0) { p->dirty = 1; } else if (!half1 && dst > cut) { char *dst_item_0 = dst_item; half1 = dst; /* candidate for splitting */ (*b->method->code_item)(ISAMC_ENCODE, c2, &dst, &dst_item); cut_item_size = dst_item - dst_item_0; memcpy (cut_item_buf, dst_item_0, cut_item_size); half2 = dst; } else (*b->method->code_item)(ISAMC_ENCODE, c2, &dst, &dst_item); if (d > 0) { if (dst > maxp) { dst = dst_0; lookahead_item = 0; } else { lookahead_next = lookahead_item; if (!(*stream->read_item)(stream->clientData, &lookahead_next, lookahead_mode)) { lookahead_item = 0; more = 0; } if (lookahead_item && max_item && (*b->method->compare_item)(max_item, lookahead_item) <= 0) { /* max_item 1 */ lookahead_item = 0; } p->dirty = 1; } } else if (d == 0) { lookahead_next = lookahead_item; if (!(*stream->read_item)(stream->clientData, &lookahead_next, lookahead_mode)) { lookahead_item = 0; more = 0; } if (src == endp) break; file_item = file_item_buf; (*b->method->code_item)(ISAMC_DECODE, c1, &file_item, &src); } else { if (src == endp) break; file_item = file_item_buf; (*b->method->code_item)(ISAMC_DECODE, c1, &file_item, &src); } } } maxp = dst_buf + b->file[b->no_cat-1].head.block_max + quater; while (lookahead_item) { char *dst_item = lookahead_item; char *dst_0 = dst; if (max_item && (*b->method->compare_item)(max_item, lookahead_item) <= 0) { /* max_item 2 */ break; } if (!*lookahead_mode) { yaz_log (LOG_WARN, "isamb: Inconsistent register (2)"); abort(); } else if (!half1 && dst > cut) { char *dst_item_0 = dst_item; half1 = dst; /* candidate for splitting */ (*b->method->code_item)(ISAMC_ENCODE, c2, &dst, &dst_item); cut_item_size = dst_item - dst_item_0; memcpy (cut_item_buf, dst_item_0, cut_item_size); half2 = dst; } else (*b->method->code_item)(ISAMC_ENCODE, c2, &dst, &dst_item); if (dst > maxp) { dst = dst_0; break; } if (p) p->dirty = 1; dst_item = lookahead_item; if (!(*stream->read_item)(stream->clientData, &dst_item, lookahead_mode)) { lookahead_item = 0; more = 0; } } new_size = dst - dst_buf; if (p && p->cat != b->no_cat-1 && new_size > b->file[p->cat].head.block_max) { /* non-btree block will be removed */ p->deleted = 1; close_block (b, p); /* delete it too!! */ p = 0; /* make a new one anyway */ } if (!p) { /* must create a new one */ int i; for (i = 0; i < b->no_cat; i++) if (new_size <= b->file[i].head.block_max) break; if (i == b->no_cat) i = b->no_cat - 1; p = new_leaf (b, i); } if (new_size > b->file[p->cat].head.block_max) { char *first_dst; char *cut_item = cut_item_buf; assert (half1); assert (half2); /* first half */ p->size = half1 - dst_buf; memcpy (p->bytes, dst_buf, half1 - dst_buf); /* second half */ *sp2 = new_leaf (b, p->cat); (*b->method->code_reset)(c2); first_dst = (*sp2)->bytes; (*b->method->code_item)(ISAMC_ENCODE, c2, &first_dst, &cut_item); memcpy (first_dst, half2, dst - half2); (*sp2)->size = (first_dst - (*sp2)->bytes) + (dst - half2); (*sp2)->dirty = 1; p->dirty = 1; memcpy (sub_item, cut_item_buf, cut_item_size); *sub_size = cut_item_size; } else { memcpy (p->bytes, dst_buf, dst - dst_buf); p->size = new_size; } (*b->method->code_stop)(ISAMC_DECODE, c1); (*b->method->code_stop)(ISAMC_ENCODE, c2); *sp1 = p; return more;}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, void *max_item){ if (!*p || (*p)->leaf) return insert_leaf (b, p, new_item, mode, stream, sp, sub_item, sub_size, max_item); else return insert_int (b, *p, new_item, mode, stream, sp, sub_item, sub_size, max_item);}int isamb_unlink (ISAMB b, ISAMC_P pos){ struct ISAMB_block *p1; if (!pos) return 0; p1 = open_block(b, pos); p1->deleted = 1; if (!p1->leaf) { int sub_p; int item_len; char *src = p1->bytes + p1->offset; decode_ptr(&src, &sub_p); isamb_unlink(b, sub_p); while (src != p1->bytes + p1->size) { decode_ptr(&src, &item_len); src += item_len; decode_ptr(&src, &sub_p); isamb_unlink(b, sub_p); } } close_block(b, p1); return 0;}int isamb_merge (ISAMB b, ISAMC_P pos, ISAMC_I *stream){ char item_buf[DST_ITEM_MAX]; char *item_ptr; int i_mode; int more; if (b->cache < 0) { int more = 1; while (more) { item_ptr = item_buf; more = (*stream->read_item)(stream->clientData, &item_ptr, &i_mode); } return 1; } item_ptr = item_buf; more = (*stream->read_item)(stream->clientData, &item_ptr, &i_mode); while (more) { struct ISAMB_block *p = 0, *sp = 0; char sub_item[DST_ITEM_MAX]; int sub_size; if (pos) p = open_block (b, pos); more = insert_sub (b, &p, item_buf, &i_mode, stream, &sp, sub_item, &sub_size, 0); if (sp) { /* increase level of tree by one */ struct ISAMB_block *p2 = new_int (b, p->cat); char *dst = p2->bytes + p2->size; encode_ptr (&dst, p->pos); assert (sub_size < 20); encode_ptr (&dst, sub_size); memcpy (dst, sub_item, sub_size); dst += sub_size; encode_ptr (&dst, sp->pos); p2->size = dst - p2->bytes; pos = p2->pos; /* return new super page */ close_block (b, sp); close_block (b, p2); } else pos = p->pos; /* return current one (again) */ close_block (b, p); } return pos;}ISAMB_PP isamb_pp_open_x (ISAMB isamb, ISAMB_P pos, int *level){ ISAMB_PP pp = xmalloc (sizeof(*pp)); pp->isamb = isamb; pp->block = xmalloc (10 * sizeof(*pp->block)); pp->pos = pos; pp->level = 0; pp->total_size = 0; pp->no_blocks = 0; while (1) { struct ISAMB_block *p = open_block (isamb, pos); char *src = p->bytes + p->offset; pp->block[pp->level] = p; pp->total_size += p->size; pp->no_blocks++; if (p->leaf) break; decode_ptr (&src, &pos); p->offset = src - p->bytes; pp->level++; } pp->block[pp->level+1] = 0; if (level) *level = pp->level; return pp;}ISAMB_PP isamb_pp_open (ISAMB isamb, ISAMB_P pos){ return isamb_pp_open_x (isamb, pos, 0);}void isamb_pp_close_x (ISAMB_PP pp, int *size, int *blocks){ int i; if (!pp) return; if (size) *size = pp->total_size; if (blocks) *blocks = pp->no_blocks; for (i = 0; i <= pp->level; i++) close_block (pp->isamb, pp->block[i]); xfree (pp->block); xfree (pp);}int isamb_block_info (ISAMB isamb, int cat){ if (cat >= 0 && cat < isamb->no_cat) return isamb->file[cat].head.block_size; return -1;}void isamb_pp_close (ISAMB_PP pp){ isamb_pp_close_x (pp, 0, 0);}int isamb_pp_read (ISAMB_PP pp, void *buf){ char *dst = buf; char *src; struct ISAMB_block *p = pp->block[pp->level]; if (!p) return 0; while (p->offset == p->size) { int pos, item_len; while (p->offset == p->size) { if (pp->level == 0) return 0; close_block (pp->isamb, pp->block[pp->level]); pp->block[pp->level] = 0; (pp->level)--; p = pp->block[pp->level]; assert (!p->leaf); /* must be int */ } src = p->bytes + p->offset; decode_ptr (&src, &item_len); src += item_len; decode_ptr (&src, &pos); p->offset = src - (char*) p->bytes; ++(pp->level); while (1) { pp->block[pp->level] = p = open_block (pp->isamb, pos); pp->total_size += p->size; pp->no_blocks++; if (p->leaf) /* leaf */ { break; } src = p->bytes + p->offset; decode_ptr (&src, &pos); p->offset = src - (char*) p->bytes; pp->level++; } } assert (p->offset < p->size); assert (p->leaf); src = p->bytes + p->offset; (*pp->isamb->method->code_item)(ISAMC_DECODE, p->decodeClientData, &dst, &src); p->offset = src - (char*) p->bytes; return 1;}int isamb_pp_num (ISAMB_PP pp){ return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -