-/* $Id: isamb.c,v 1.69 2005-01-15 19:38:31 adam Exp $
- Copyright (C) 1995-2005
+/* $Id: isamb.c,v 1.86 2006-11-14 12:03:48 adam Exp $
+ Copyright (C) 1995-2006
-along with Zebra; see the file LICENSE.zebra. If not, write to the
-Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
#endif
ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
#endif
ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
{
ISAMB isamb = xmalloc(sizeof(*isamb));
int i, b_size = ISAMB_MIN_SIZE;
isamb->bfs = bfs;
isamb->method = (ISAMC_M *) xmalloc(sizeof(*method));
{
ISAMB isamb = xmalloc(sizeof(*isamb));
int i, b_size = ISAMB_MIN_SIZE;
isamb->bfs = bfs;
isamb->method = (ISAMC_M *) xmalloc(sizeof(*method));
sprintf(fname, "%s%c", name, i+'A');
if (cache)
isamb->file[i].bf = bf_open(bfs, fname, ISAMB_CACHE_ENTRY_SIZE,
sprintf(fname, "%s%c", name, i+'A');
if (cache)
isamb->file[i].bf = bf_open(bfs, fname, ISAMB_CACHE_ENTRY_SIZE,
else
isamb->file[i].bf = bf_open(bfs, fname, b_size, writeflag);
else
isamb->file[i].bf = bf_open(bfs, fname, b_size, writeflag);
/* fill-in default values (for empty isamb) */
isamb->file[i].head.first_block = ISAMB_CACHE_ENTRY_SIZE/b_size+1;
isamb->file[i].head.last_block = isamb->file[i].head.first_block;
/* fill-in default values (for empty isamb) */
isamb->file[i].head.first_block = ISAMB_CACHE_ENTRY_SIZE/b_size+1;
isamb->file[i].head.last_block = isamb->file[i].head.first_block;
decode_ptr(&src, &isamb->file[i].head.first_block);
decode_ptr(&src, &isamb->file[i].head.last_block);
decode_ptr(&src, &zint_tmp);
decode_ptr(&src, &isamb->file[i].head.first_block);
decode_ptr(&src, &isamb->file[i].head.last_block);
decode_ptr(&src, &zint_tmp);
decode_ptr(&src, &isamb->file[i].head.free_list);
}
assert (isamb->file[i].head.block_size >= isamb->file[i].head.block_offset);
decode_ptr(&src, &isamb->file[i].head.free_list);
}
assert (isamb->file[i].head.block_size >= isamb->file[i].head.block_offset);
-static int get_block (ISAMB b, ISAMC_P pos, char *userbuf, int wr)
+static int cache_block (ISAMB b, ISAM_P pos, unsigned char *userbuf, int wr)
bf_write(b->file[cat].bf, ce_this->pos, 0, 0, ce_this->buf);
}
xfree(ce_this->buf);
bf_write(b->file[cat].bf, ce_this->pos, 0, 0, ce_this->buf);
}
xfree(ce_this->buf);
if (!bf_read(b->file[cat].bf, norm, 0, 0, ce_this->buf))
memset (ce_this->buf, 0, ISAMB_CACHE_ENTRY_SIZE);
if (wr)
if (!bf_read(b->file[cat].bf, norm, 0, 0, ce_this->buf))
memset (ce_this->buf, 0, ISAMB_CACHE_ENTRY_SIZE);
if (wr)
yaz_log(YLOG_DEBUG, "isamb_close level leaf-%d: "ZINT_FORMAT" read, "
ZINT_FORMAT" skipped",
i, isamb->accessed_nodes[i], isamb->skipped_nodes[i]);
yaz_log(YLOG_DEBUG, "isamb_close level leaf-%d: "ZINT_FORMAT" read, "
ZINT_FORMAT" skipped",
i, isamb->accessed_nodes[i], isamb->skipped_nodes[i]);
bf_write(isamb->file[i].bf, pos, 0, 0, hbuf + pos*b_size);
}
}
bf_write(isamb->file[i].bf, pos, 0, 0, hbuf + pos*b_size);
}
}
* Reserve 5 bytes for large block sizes. 1 for small ones .. Number
of items. We can thus have at most 2^40 nodes.
*/
* Reserve 5 bytes for large block sizes. 1 for small ones .. Number
of items. We can thus have at most 2^40 nodes.
*/
- if (!get_block (b, pos, p->buf, 0))
+ if (!cache_block (b, pos, p->buf, 0))
- if (!bf_read(b->file[cat].bf, pos/CAT_MAX, 0, 0, p->buf))
+ if (bf_read(b->file[cat].bf, pos/CAT_MAX, 0, 0, p->buf) != 1)
{
yaz_log(YLOG_FATAL, "isamb: read fail for pos=%ld block=%ld",
(long) pos, (long) pos/CAT_MAX);
{
yaz_log(YLOG_FATAL, "isamb: read fail for pos=%ld block=%ld",
(long) pos, (long) pos/CAT_MAX);
- if (!get_block (b, p->pos, p->buf, 0))
+ if (!cache_block (b, p->pos, p->buf, 0))
{
yaz_log(b->log_io, "bf_read: new_block");
if (!bf_read(b->file[cat].bf, p->pos/CAT_MAX, 0, 0, p->buf))
{
yaz_log(YLOG_FATAL, "isamb: read fail for pos=%ld block=%ld",
(long) p->pos/CAT_MAX, (long) p->pos/CAT_MAX);
{
yaz_log(b->log_io, "bf_read: new_block");
if (!bf_read(b->file[cat].bf, p->pos/CAT_MAX, 0, 0, p->buf))
{
yaz_log(YLOG_FATAL, "isamb: read fail for pos=%ld block=%ld",
(long) p->pos/CAT_MAX, (long) p->pos/CAT_MAX);
}
}
yaz_log(b->log_freelist, "got block " ZINT_FORMAT " from freelist %d:" ZINT_FORMAT, p->pos,
}
}
yaz_log(b->log_freelist, "got block " ZINT_FORMAT " from freelist %d:" ZINT_FORMAT, p->pos,
p->cat = cat;
b->file[cat].head_dirty = 1;
memset (p->buf, 0, b->file[cat].head.block_size);
p->cat = cat;
b->file[cat].head_dirty = 1;
memset (p->buf, 0, b->file[cat].head.block_size);
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;
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))
+ if (!cache_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);
{
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);
- if (!get_block (b, p->pos, p->buf, 1))
+ if (!cache_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);
{
yaz_log(b->log_io, "bf_write: close_block");
bf_write(b->file[p->cat].bf, p->pos/CAT_MAX, 0, 0, p->buf);
struct ISAMB_block *sub_p1 = 0, *sub_p2 = 0;
char sub_item[DST_ITEM_MAX];
int sub_size;
struct ISAMB_block *sub_p1 = 0, *sub_p2 = 0;
char sub_item[DST_ITEM_MAX];
int sub_size;
if (p->size <= b->file[p->cat].head.block_max)
{
/* it fits OK in this block */
memcpy (startp, dst_buf, dst - dst_buf);
if (p->size <= b->file[p->cat].head.block_max)
{
/* it fits OK in this block */
memcpy (startp, dst_buf, dst - dst_buf);
int cut_item_size = 0;
int no_items = 0; /* number of items (total) */
int no_items_1 = 0; /* number of items (first half) */
int cut_item_size = 0;
int no_items = 0; /* number of items (total) */
int no_items_1 = 0; /* number of items (first half) */
/* this loop runs when we are "appending" to a leaf page. That is
either it's empty (new) or all file items have been read in
previous loop */
/* this loop runs when we are "appending" to a leaf page. That is
either it's empty (new) or all file items have been read in
previous loop */
{
/* this is append. So a delete is bad */
yaz_log(YLOG_WARN, "isamb: Inconsistent register (2)");
{
/* this is append. So a delete is bad */
yaz_log(YLOG_WARN, "isamb: Inconsistent register (2)");
memcpy (p->bytes, dst_buf, half1 - dst_buf);
p->no_items = no_items_1;
memcpy (p->bytes, dst_buf, half1 - dst_buf);
p->no_items = no_items_1;
memcpy (first_dst, half2, dst - half2);
(*sp2)->size = (first_dst - (*sp2)->bytes) + (dst - half2);
memcpy (first_dst, half2, dst - half2);
(*sp2)->size = (first_dst - (*sp2)->bytes) + (dst - half2);
more = insert_sub (b, &p, item_buf, &i_mode, stream, &sp,
sub_item, &sub_size, 0);
if (sp)
more = insert_sub (b, &p, item_buf, &i_mode, stream, &sp,
sub_item, &sub_size, 0);
if (sp)
-ISAMB_PP isamb_pp_open_x(ISAMB isamb, ISAMB_P pos, int *level, int scope)
+ISAMB_PP isamb_pp_open_x(ISAMB isamb, ISAM_P pos, int *level, int scope)
{
return isamb_pp_open_x(isamb, pos, 0, scope);
}
{
return isamb_pp_open_x(isamb, pos, 0, scope);
}
yaz_log(YLOG_DEBUG, "isamb_pp_close lev=%d returned "ZINT_FORMAT" values, "
"skipped "ZINT_FORMAT,
pp->maxlevel, pp->skipped_numbers, pp->returned_numbers);
yaz_log(YLOG_DEBUG, "isamb_pp_close lev=%d returned "ZINT_FORMAT" values, "
"skipped "ZINT_FORMAT,
pp->maxlevel, pp->skipped_numbers, pp->returned_numbers);
if (pp->skipped_nodes[i] || pp->accessed_nodes[i])
yaz_log(YLOG_DEBUG, "isamb_pp_close level leaf-%d: "
ZINT_FORMAT" read, "ZINT_FORMAT" skipped", i,
pp->accessed_nodes[i], pp->skipped_nodes[i]);
pp->isamb->skipped_numbers += pp->skipped_numbers;
pp->isamb->returned_numbers += pp->returned_numbers;
if (pp->skipped_nodes[i] || pp->accessed_nodes[i])
yaz_log(YLOG_DEBUG, "isamb_pp_close level leaf-%d: "
ZINT_FORMAT" read, "ZINT_FORMAT" skipped", i,
pp->accessed_nodes[i], pp->skipped_nodes[i]);
pp->isamb->skipped_numbers += pp->skipped_numbers;
pp->isamb->returned_numbers += pp->returned_numbers;
{
pp->isamb->accessed_nodes[i] += pp->accessed_nodes[i];
pp->isamb->skipped_nodes[i] += pp->skipped_nodes[i];
{
pp->isamb->accessed_nodes[i] += pp->accessed_nodes[i];
pp->isamb->skipped_nodes[i] += pp->skipped_nodes[i];
-static void isamb_dump_r (ISAMB b, ISAMB_P pos, void (*pr)(const char *str),
+static void isamb_dump_r (ISAMB b, ISAM_P pos, void (*pr)(const char *str),
{
isamb_dump_r(b, pos, pr, 0);
}
{
isamb_dump_r(b, pos, pr, 0);
}
{ /* climbs higher in the tree, until finds a level with data left */
/* returns the node to (consider to) descend to in *pos) */
struct ISAMB_block *p = pp->block[pp->level];
{ /* climbs higher in the tree, until finds a level with data left */
/* returns the node to (consider to) descend to in *pos) */
struct ISAMB_block *p = pp->block[pp->level];
const void *untilbuf)
{ /* climbs down the tree, from pos, to the leftmost leaf */
struct ISAMB_block *p = pp->block[pp->level];
const void *untilbuf)
{ /* climbs down the tree, from pos, to the leftmost leaf */
struct ISAMB_block *p = pp->block[pp->level];
if (!isamb_pp_climb_level(pp, &pos))
return 0;
isamb_pp_descend_to_leaf(pp, pos, 0);
if (!isamb_pp_climb_level(pp, &pos))
return 0;
isamb_pp_descend_to_leaf(pp, pos, 0);
static int isamb_pp_climb_desc(ISAMB_PP pp, const void *untilbuf)
{ /* climbs up and descends to a leaf where values >= *untilbuf are found */
static int isamb_pp_climb_desc(ISAMB_PP pp, const void *untilbuf)
{ /* climbs up and descends to a leaf where values >= *untilbuf are found */
#if ISAMB_DEBUG
struct ISAMB_block *p = pp->block[pp->level];
yaz_log(YLOG_DEBUG, "isamb_pp_climb_desc starting "
#if ISAMB_DEBUG
struct ISAMB_block *p = pp->block[pp->level];
yaz_log(YLOG_DEBUG, "isamb_pp_climb_desc starting "
void isamb_pp_pos(ISAMB_PP pp, double *current, double *total)
{ /* return an estimate of the current position and of the total number of */
/* occureences in the isam tree, based on the current leaf */
void isamb_pp_pos(ISAMB_PP pp, double *current, double *total)
{ /* return an estimate of the current position and of the total number of */
/* occureences in the isam tree, based on the current leaf */
*current = (double) pp->returned_numbers;
#if ISAMB_DEBUG
yaz_log(YLOG_LOG, "isamb_pp_pos returning: cur= %0.1f tot=%0.1f rn="
*current = (double) pp->returned_numbers;
#if ISAMB_DEBUG
yaz_log(YLOG_LOG, "isamb_pp_pos returning: cur= %0.1f tot=%0.1f rn="