2 * Copyright (c) 1995-1998, Index Data.
3 * See the file LICENSE for details.
4 * $Id: isamd.c,v 1.16 1999-10-05 09:57:40 heikki Exp $
6 * Isamd - isam with diffs
7 * Programmed by: Heikki Levanto
10 * - Statistics are missing and/or completely wrong
11 * - Lots of code stolen from isamc, not all needed any more
21 #include "../index/index.h" /* isamd uses the internal structure of it_key */
24 static void flush_block (ISAMD is, int cat);
25 static void release_fc (ISAMD is, int cat);
26 static void init_fc (ISAMD is, int cat);
28 #define ISAMD_FREELIST_CHUNK 1
32 ISAMD_M isamd_getmethod (ISAMD_M me)
34 static struct ISAMD_filecat_s def_cat[] = {
36 /* blocksz, max. Unused time being */
37 { 32, 40 }, /* 24 is the smallest unreasonable size! */
61 { 24, 1 }, /* Experimental sizes */
72 ISAMD_M m = (ISAMD_M) xmalloc (sizeof(*m)); /* never released! */
73 m->filecat = def_cat; /* ok, only alloc'd once */
80 m->compare_item = NULL;
82 m->debug = 0; /* default to no debug */
84 m->max_blocks_mem = 10;
91 ISAMD isamd_open (BFiles bfs, const char *name, int writeflag, ISAMD_M method)
94 ISAMD_filecat filecat;
97 is = (ISAMD) xmalloc (sizeof(*is));
99 is->method = (ISAMD_M) xmalloc (sizeof(*is->method));
100 memcpy (is->method, method, sizeof(*method));
101 filecat = is->method->filecat;
104 /* determine number of block categories */
105 if (is->method->debug>0)
106 logf (LOG_LOG, "isamd: bsize maxkeys");
109 if (is->method->debug>0)
110 logf (LOG_LOG, "isamd:%6d %6d",
111 filecat[i].bsize, filecat[i].mblocks);
112 } while (filecat[i++].mblocks);
116 assert (is->no_files > 0);
117 assert (is->max_cat <=8 ); /* we have only 3 bits for it */
119 is->files = (ISAMD_file) xmalloc (sizeof(*is->files)*is->no_files);
121 for (i = 0; i<is->no_files; i++)
125 sprintf (fname, "%s%c", name, i+'A');
126 is->files[i].bf = bf_open (bfs, fname, is->method->filecat[i].bsize,
128 is->files[i].head_is_dirty = 0;
129 if (!bf_read (is->files[i].bf, 0, 0, sizeof(ISAMD_head),
132 is->files[i].head.lastblock = 1;
133 is->files[i].head.freelist = 0;
135 is->files[i].alloc_entries_num = 0;
136 is->files[i].alloc_entries_max =
137 is->method->filecat[i].bsize / sizeof(int) - 1;
138 is->files[i].alloc_buf = (char *)
139 xmalloc (is->method->filecat[i].bsize);
140 is->files[i].no_writes = 0; /* clear statistics */
141 is->files[i].no_reads = 0;
142 is->files[i].no_skip_writes = 0;
143 is->files[i].no_allocated = 0;
144 is->files[i].no_released = 0;
145 is->files[i].no_remap = 0;
146 is->files[i].no_forward = 0;
147 is->files[i].no_backward = 0;
148 is->files[i].sum_forward = 0;
149 is->files[i].sum_backward = 0;
150 is->files[i].no_next = 0;
151 is->files[i].no_prev = 0;
152 is->files[i].no_op_diffonly=0;
153 is->files[i].no_op_main=0;
180 int isamd_block_used (ISAMD is, int type)
182 if (type < 0 || type >= is->no_files)
184 return is->files[type].head.lastblock-1;
187 int isamd_block_size (ISAMD is, int type)
189 ISAMD_filecat filecat = is->method->filecat;
190 if (type < 0 || type >= is->no_files)
192 return filecat[type].bsize;
195 int isamd_close (ISAMD is)
200 if (is->method->debug>0)
202 logf (LOG_LOG, "isamd statistics");
203 logf (LOG_LOG, "f nxt forw mid-f prev backw mid-b");
204 for (i = 0; i<is->no_files; i++)
205 logf (LOG_LOG, "%d%7d%7d%7.1f%7d%7d%7.1f",i,
206 is->files[i].no_next,
207 is->files[i].no_forward,
208 is->files[i].no_forward ?
209 (double) is->files[i].sum_forward/is->files[i].no_forward
211 is->files[i].no_prev,
212 is->files[i].no_backward,
213 is->files[i].no_backward ?
214 (double) is->files[i].sum_backward/is->files[i].no_backward
217 if (is->method->debug>0)
218 logf (LOG_LOG, "f writes reads skipped alloc released ");
219 for (i = 0; i<is->no_files; i++)
222 assert (is->files[i].bf);
223 if (is->files[i].head_is_dirty)
224 bf_write (is->files[i].bf, 0, 0, sizeof(ISAMD_head),
226 if (is->method->debug>0)
227 logf (LOG_LOG, "%d%8d%8d%8d%8d%8d",i,
228 is->files[i].no_writes,
229 is->files[i].no_reads,
230 is->files[i].no_skip_writes,
231 is->files[i].no_allocated,
232 is->files[i].no_released);
233 xfree (is->files[i].fc_list);
235 bf_close (is->files[i].bf);
238 if (is->method->debug>0)
240 logf (LOG_LOG, "f opens main diffonly");
241 for (i = 0; i<is->no_files; i++)
243 logf (LOG_LOG, "%d%8d%8d%8d",i,
244 is->files[i].no_op_main+
245 is->files[i].no_op_diffonly,
246 is->files[i].no_op_main,
247 is->files[i].no_op_diffonly);
249 logf(LOG_LOG,"single %8d", is->no_op_single);
250 logf(LOG_LOG,"new %8d", is->no_op_new);
252 logf(LOG_LOG, "new build %8d", is->no_fbuilds);
253 logf(LOG_LOG, "append %8d", is->no_appds);
254 logf(LOG_LOG, " merges %8d", is->no_merges);
255 logf(LOG_LOG, " singles %8d", is->no_singles);
256 logf(LOG_LOG, " non %8d", is->no_non);
258 logf(LOG_LOG, "read blocks %8d", is->no_read);
259 logf(LOG_LOG, "read keys: %8d %8.1f k/bl",
261 1.0*(is->no_read_keys+1)/(is->no_read+1) );
262 logf(LOG_LOG, "read main-k %8d %8.1f %% of keys",
264 100.0*(is->no_read_main+1)/(is->no_read_keys+1) );
265 logf(LOG_LOG, "read ends: %8d %8.1f k/e",
267 1.0*(is->no_read_keys+1)/(is->no_read_eof+1) );
268 s= is->no_seek_nxt+ is->no_seek_sam+ is->no_seek_fwd +
269 is->no_seek_prv+ is->no_seek_bak+ is->no_seek_cat;
272 logf(LOG_LOG, "seek same %8d %8.1f%%",
273 is->no_seek_sam, 100.0*is->no_seek_sam/s );
274 logf(LOG_LOG, "seek next %8d %8.1f%%",
275 is->no_seek_nxt, 100.0*is->no_seek_nxt/s );
276 logf(LOG_LOG, "seek prev %8d %8.1f%%",
277 is->no_seek_prv, 100.0*is->no_seek_prv/s );
278 logf(LOG_LOG, "seek forw %8d %8.1f%%",
279 is->no_seek_fwd, 100.0*is->no_seek_fwd/s );
280 logf(LOG_LOG, "seek back %8d %8.1f%%",
281 is->no_seek_bak, 100.0*is->no_seek_bak/s );
282 logf(LOG_LOG, "seek cat %8d %8.1f%%",
283 is->no_seek_cat, 100.0*is->no_seek_cat/s );
291 static void isamd_seek_stat(ISAMD is, int cat, int pos)
293 if (cat != is->last_cat)
295 else if ( pos == is->last_pos)
297 else if ( pos == is->last_pos+1)
299 else if ( pos == is->last_pos-1)
301 else if ( pos > is->last_pos)
303 else if ( pos < is->last_pos)
309 int isamd_read_block (ISAMD is, int cat, int pos, char *dst)
311 isamd_seek_stat(is,cat,pos);
312 ++(is->files[cat].no_reads);
314 if (is->method->debug > 6)
315 logf (LOG_LOG, "isamd: read_block %d:%d",cat, pos);
316 return bf_read (is->files[cat].bf, pos, 0, 0, dst);
319 int isamd_write_block (ISAMD is, int cat, int pos, char *src)
321 isamd_seek_stat(is,cat,pos);
322 ++(is->files[cat].no_writes);
324 if (is->method->debug > 6)
325 logf (LOG_LOG, "isamd: write_block %d:%d", cat, pos);
326 return bf_write (is->files[cat].bf, pos, 0, 0, src);
329 int isamd_write_dblock (ISAMD is, int cat, int pos, char *src,
330 int nextpos, int offset)
332 ISAMD_BLOCK_SIZE size = offset + ISAMD_BLOCK_OFFSET_N;
333 if (is->method->debug > 4)
334 logf (LOG_LOG, "isamd: write_dblock. size=%d nextpos=%d",
335 (int) size, nextpos);
336 src -= ISAMD_BLOCK_OFFSET_N;
337 assert( ISAMD_BLOCK_OFFSET_N == sizeof(int)+sizeof(int) );
338 memcpy (src, &nextpos, sizeof(int));
339 memcpy (src + sizeof(int), &size, sizeof(size));
340 return isamd_write_block (is, cat, pos, src);
343 #if ISAMD_FREELIST_CHUNK
344 static void flush_block (ISAMD is, int cat)
346 char *abuf = is->files[cat].alloc_buf;
347 int block = is->files[cat].head.freelist;
348 if (block && is->files[cat].alloc_entries_num)
350 memcpy (abuf, &is->files[cat].alloc_entries_num, sizeof(int));
351 bf_write (is->files[cat].bf, block, 0, 0, abuf);
352 is->files[cat].alloc_entries_num = 0;
357 static int alloc_block (ISAMD is, int cat)
359 int block = is->files[cat].head.freelist;
360 char *abuf = is->files[cat].alloc_buf;
362 (is->files[cat].no_allocated)++;
366 block = (is->files[cat].head.lastblock)++; /* no free list */
367 is->files[cat].head_is_dirty = 1;
371 if (!is->files[cat].alloc_entries_num) /* read first time */
373 bf_read (is->files[cat].bf, block, 0, 0, abuf);
374 memcpy (&is->files[cat].alloc_entries_num, abuf,
375 sizeof(is->files[cat].alloc_entries_num));
376 assert (is->files[cat].alloc_entries_num > 0);
378 /* have some free blocks now */
379 assert (is->files[cat].alloc_entries_num > 0);
380 is->files[cat].alloc_entries_num--;
381 if (!is->files[cat].alloc_entries_num) /* last one in block? */
383 memcpy (&is->files[cat].head.freelist, abuf + sizeof(int),
385 is->files[cat].head_is_dirty = 1;
387 if (is->files[cat].head.freelist)
389 bf_read (is->files[cat].bf, is->files[cat].head.freelist,
391 memcpy (&is->files[cat].alloc_entries_num, abuf,
392 sizeof(is->files[cat].alloc_entries_num));
393 assert (is->files[cat].alloc_entries_num);
397 memcpy (&block, abuf + sizeof(int) + sizeof(int) *
398 is->files[cat].alloc_entries_num, sizeof(int));
403 static void release_block (ISAMD is, int cat, int pos)
405 char *abuf = is->files[cat].alloc_buf;
406 int block = is->files[cat].head.freelist;
408 (is->files[cat].no_released)++;
410 if (block && !is->files[cat].alloc_entries_num) /* must read block */
412 bf_read (is->files[cat].bf, block, 0, 0, abuf);
413 memcpy (&is->files[cat].alloc_entries_num, abuf,
414 sizeof(is->files[cat].alloc_entries_num));
415 assert (is->files[cat].alloc_entries_num > 0);
417 assert (is->files[cat].alloc_entries_num <= is->files[cat].alloc_entries_max);
418 if (is->files[cat].alloc_entries_num == is->files[cat].alloc_entries_max)
421 memcpy (abuf, &is->files[cat].alloc_entries_num, sizeof(int));
422 bf_write (is->files[cat].bf, block, 0, 0, abuf);
423 is->files[cat].alloc_entries_num = 0;
425 if (!is->files[cat].alloc_entries_num) /* make new buffer? */
427 memcpy (abuf + sizeof(int), &block, sizeof(int));
428 is->files[cat].head.freelist = pos;
429 is->files[cat].head_is_dirty = 1;
433 memcpy (abuf + sizeof(int) +
434 is->files[cat].alloc_entries_num*sizeof(int),
437 is->files[cat].alloc_entries_num++;
440 static void flush_block (ISAMD is, int cat)
442 char *abuf = is->files[cat].alloc_buf;
446 static int alloc_block (ISAMD is, int cat)
449 char buf[sizeof(int)];
451 is->files[cat].head_is_dirty = 1;
452 (is->files[cat].no_allocated)++;
453 if ((block = is->files[cat].head.freelist))
455 bf_read (is->files[cat].bf, block, 0, sizeof(int), buf);
456 memcpy (&is->files[cat].head.freelist, buf, sizeof(int));
459 block = (is->files[cat].head.lastblock)++;
463 static void release_block (ISAMD is, int cat, int pos)
465 char buf[sizeof(int)];
467 (is->files[cat].no_released)++;
468 is->files[cat].head_is_dirty = 1;
469 memcpy (buf, &is->files[cat].head.freelist, sizeof(int));
470 is->files[cat].head.freelist = pos;
471 bf_write (is->files[cat].bf, pos, 0, sizeof(int), buf);
475 int isamd_alloc_block (ISAMD is, int cat)
479 if (is->files[cat].fc_list)
482 for (j = 0; j < is->files[cat].fc_max; j++)
483 if ((nb = is->files[cat].fc_list[j]) && (!block || nb < block))
485 is->files[cat].fc_list[j] = 0;
491 block = alloc_block (is, cat);
492 if (is->method->debug > 4)
493 logf (LOG_LOG, "isamd: alloc_block in cat %d: %d", cat, block);
497 void isamd_release_block (ISAMD is, int cat, int pos)
499 if (is->method->debug > 4)
500 logf (LOG_LOG, "isamd: release_block in cat %d: %d", cat, pos);
503 if (is->files[cat].fc_list)
506 for (j = 0; j<is->files[cat].fc_max; j++)
507 if (!is->files[cat].fc_list[j])
509 is->files[cat].fc_list[j] = pos;
513 release_block (is, cat, pos);
516 static void init_fc (ISAMD is, int cat)
520 is->files[cat].fc_max = j;
521 is->files[cat].fc_list = (int *)
522 xmalloc (sizeof(*is->files[0].fc_list) * j);
524 is->files[cat].fc_list[j] = 0;
527 static void release_fc (ISAMD is, int cat)
529 int b, j = is->files[cat].fc_max;
532 if ((b = is->files[cat].fc_list[j]))
534 release_block (is, cat, b);
535 is->files[cat].fc_list[j] = 0;
539 void isamd_pp_close (ISAMD_PP pp)
543 (*is->method->code_stop)(ISAMD_DECODE, pp->decodeClientData);
544 isamd_free_diffs(pp); /* see merge-d.h */
547 if (is->method->debug > 5)
548 logf (LOG_LOG, "isamd_pp_close %p %d=%d:%d sz=%d n=%d=%d:%d",
549 pp, isamd_addr(pp->pos, pp->cat), pp->cat, pp->pos, pp->size,
550 pp->next, isamd_type(pp->next), isamd_block(pp->next) );
555 ISAMD_PP isamd_pp_open (ISAMD is, ISAMD_P ipos)
557 ISAMD_PP pp = (ISAMD_PP) xmalloc (sizeof(*pp));
559 int sz = is->method->filecat[is->max_cat].bsize;
560 /* always allocate for the largest blocks, saves trouble */
561 struct it_key singlekey;
562 char *c_ptr; /* for fake encoding the singlekey */
567 src = pp->buf = (char *) xmalloc (sz);
568 memset(src,'\0',sz); /* clear the buffer, for new blocks */
577 pp->decodeClientData = (*is->method->code_start)(ISAMD_DECODE);
579 if ( is_singleton(ipos) )
583 if (is->method->debug > 5)
584 logf (LOG_LOG, "isamd_pp_open %p %d=%d:%d sz=%d n=%d=%d:%d",
585 pp, isamd_addr(pp->pos, pp->cat), pp->cat, pp->pos, pp->size,
586 pp->next, isamd_type(pp->next), isamd_block(pp->next) );
587 singleton_decode(ipos, &singlekey );
588 pp->offset=ISAMD_BLOCK_OFFSET_1;
590 ofs=pp->offset+sizeof(int); /* reserve length of diffsegment */
591 singlekey.seqno = singlekey.seqno * 2 + 1; /* make an insert diff */
592 c_ptr=&(pp->buf[ofs]);
593 i_ptr=(char*)(&singlekey);
594 (*is->method->code_item)(ISAMD_ENCODE, pp->decodeClientData,
596 (*is->method->code_reset)(pp->decodeClientData);
597 ofs += c_ptr-&(pp->buf[ofs]);
598 memcpy( &(pp->buf[pp->offset]), &ofs, sizeof(int) );
599 /* since we memset buf earlier, we already have a zero endmark! */
601 if (is->method->debug > 5)
602 logf (LOG_LOG, "isamd_pp_open single %d=%x: %d.%d sz=%d",
604 singlekey.sysno, singlekey.seqno/2,
610 pp->cat = isamd_type(ipos);
611 pp->pos = isamd_block(ipos);
619 isamd_read_block (is, pp->cat, pp->pos, src);
620 memcpy (&pp->next, src, sizeof(pp->next));
621 src += sizeof(pp->next);
622 memcpy (&pp->size, src, sizeof(pp->size));
623 src += sizeof(pp->size);
624 memcpy (&pp->numKeys, src, sizeof(pp->numKeys));
625 src += sizeof(pp->numKeys);
626 assert (pp->next != isamd_addr(pp->pos,pp->cat));
627 pp->offset = src - pp->buf;
628 assert (pp->offset == ISAMD_BLOCK_OFFSET_1);
629 assert(pp->size>=ISAMD_BLOCK_OFFSET_1); /*??*/
631 is->files[pp->cat].no_op_main++;
633 is->files[pp->cat].no_op_diffonly++;
635 if (is->method->debug > 5)
636 logf (LOG_LOG, "isamd_pp_open %p %d=%d:%d sz=%d n=%d=%d:%d",
637 pp, isamd_addr(pp->pos, pp->cat), pp->cat, pp->pos, pp->size,
638 pp->next, isamd_type(pp->next), isamd_block(pp->next) );
645 void isamd_buildfirstblock(ISAMD_PP pp){
648 assert(pp->next != isamd_addr(pp->pos,pp->cat));
649 memcpy(dst, &pp->next, sizeof(pp->next) );
650 dst += sizeof(pp->next);
651 memcpy(dst, &pp->size,sizeof(pp->size));
652 dst += sizeof(pp->size);
653 memcpy(dst, &pp->numKeys, sizeof(pp->numKeys));
654 dst += sizeof(pp->numKeys);
655 assert (dst - pp->buf == ISAMD_BLOCK_OFFSET_1);
656 if (pp->is->method->debug > 5)
657 logf (LOG_LOG, "isamd: bldfirst: p=%d=%d:%d n=%d:%d:%d sz=%d nk=%d ",
658 isamd_addr(pp->pos,pp->cat),pp->cat, pp->pos,
659 pp->next, isamd_type(pp->next), isamd_block(pp->next),
660 pp->size, pp->numKeys);
663 void isamd_buildlaterblock(ISAMD_PP pp){
666 assert(pp->next != isamd_addr(pp->pos,pp->cat));
667 memcpy(dst, &pp->next, sizeof(pp->next) );
668 dst += sizeof(pp->next);
669 memcpy(dst, &pp->size,sizeof(pp->size));
670 dst += sizeof(pp->size);
671 assert (dst - pp->buf == ISAMD_BLOCK_OFFSET_N);
672 if (pp->is->method->debug > 5)
673 logf (LOG_LOG, "isamd: l8r: sz=%d p=%d/%d>%d/%d",
676 isamd_block(pp->next), isamd_type(pp->next) );
681 /* returns non-zero if item could be read; 0 otherwise */
682 int isamd_pp_read (ISAMD_PP pp, void *buf)
685 return isamd_read_item (pp, (char **) &buf);
686 /* note: isamd_read_item is in merge-d.c, because it is so */
687 /* convoluted with the merge process */
690 /* read one main item from file - decode and store it in *dst.
691 Does not worry about diffs
694 1 if item could be read ok
696 int isamd_read_main_item (ISAMD_PP pp, char **dst)
699 char *src = pp->buf + pp->offset;
703 if (pp->offset >= pp->size)
708 return 0; /* end of file */
710 if (pp->next > pp->pos)
712 if (pp->next == pp->pos + 1)
713 is->files[pp->cat].no_next++;
716 is->files[pp->cat].no_forward++;
717 is->files[pp->cat].sum_forward += pp->next - pp->pos;
722 if (pp->next + 1 == pp->pos)
723 is->files[pp->cat].no_prev++;
726 is->files[pp->cat].no_backward++;
727 is->files[pp->cat].sum_backward += pp->pos - pp->next;
730 /* out new block position */
731 newcat = isamd_type(pp->next);
732 pp->pos = isamd_block(pp->next);
733 pp->cat = isamd_type(pp->next);
734 pp->is->no_read_main++;
736 /* read block and save 'next' and 'size' entry */
737 isamd_read_block (is, pp->cat, pp->pos, src);
738 memcpy (&pp->next, src, sizeof(pp->next));
739 src += sizeof(pp->next);
740 memcpy (&pp->size, src, sizeof(pp->size));
741 src += sizeof(pp->size);
742 /* assume block is non-empty */
743 pp->offset = oldoffs = src - pp->buf;
744 assert (pp->offset == ISAMD_BLOCK_OFFSET_N);
745 assert (pp->next != isamd_addr(pp->pos,pp->cat));
746 (*is->method->code_reset)(pp->decodeClientData);
747 /* finally, read the item */
748 (*is->method->code_item)(ISAMD_DECODE, pp->decodeClientData, dst, &src);
749 pp->offset = src - pp->buf;
750 if (is->method->debug > 8)
751 logf (LOG_LOG, "isamd: read_m: block %d:%d sz=%d ofs=%d-%d next=%d",
752 pp->cat, pp->pos, pp->size, oldoffs, pp->offset, pp->next);
756 (*is->method->code_item)(ISAMD_DECODE, pp->decodeClientData, dst, &src);
757 pp->offset = src - pp->buf;
758 if (is->method->debug > 8)
759 logf (LOG_LOG, "isamd: read_m: got %d:%d sz=%d ofs=%d-%d next=%d",
760 pp->cat, pp->pos, pp->size, oldoffs, pp->offset, pp->next);
764 int isamd_pp_num (ISAMD_PP pp)
769 static char *hexdump(unsigned char *p, int len, char *buff) {
770 static char localbuff[128];
772 if (!buff) buff=localbuff;
775 sprintf(bytebuff,"%02x",*p);
777 strcat(buff,bytebuff);
778 if (len) strcat(buff," ");
784 void isamd_pp_dump (ISAMD is, ISAMD_P ipos)
795 int olddebug= is->method->debug;
796 is->method->debug=0; /* no debug logs while reading for dump */
798 logf(LOG_LOG,"dumping isamd block %d (%d:%d)",
799 (int)ipos, isamd_type(ipos), isamd_block(ipos) );
800 pp=isamd_pp_open(is,ipos);
801 logf(LOG_LOG,"numKeys=%d, ofs=%d sz=%d",
802 pp->numKeys, pp->offset, pp->size );
803 diffidx=oldoffs= pp->offset;
804 while ((diffidx < is->method->filecat[pp->cat].bsize) && (diffmax>0))
806 memcpy(&diffmax,&(pp->buf[diffidx]),sizeof(int));
807 logf (LOG_LOG,"diff set at %d-%d: %s", diffidx, diffmax,
808 hexdump(pp->buf+diffidx,8,0));
809 /*! todo: dump the actual diffs as well !!! */
813 while(isamd_pp_read(pp, &key))
815 if (oldaddr != isamd_addr(pp->pos,pp->cat) )
817 oldaddr = isamd_addr(pp->pos,pp->cat);
818 logf(LOG_LOG,"block %d=%d:%d sz=%d nx=%d=%d:%d ofs=%d",
819 isamd_addr(pp->pos,pp->cat), pp->cat, pp->pos,
821 pp->next, isamd_type(pp->next), isamd_block(pp->next),
827 logf(LOG_LOG," %05x: %s",i,hexdump(pp->buf+i,n,hexbuff));
830 if (oldoffs > ISAMD_BLOCK_OFFSET_N)
831 oldoffs=ISAMD_BLOCK_OFFSET_N;
834 logf (LOG_LOG," got %d:%d=%x:%x from %s at %d=%x",
835 key.sysno, key.seqno,
836 key.sysno, key.seqno,
837 hexdump(pp->buf+oldoffs, pp->offset-oldoffs, hexbuff),
839 oldoffs = pp->offset;
841 /*!*/ /*TODO: dump diffs too!!! */
843 is->method->debug=olddebug;
848 * Revision 1.16 1999-10-05 09:57:40 heikki
849 * Tuning the isam-d (and fixed a small "detail")
851 * Revision 1.15 1999/09/27 14:36:36 heikki
854 * Revision 1.14 1999/09/23 18:01:18 heikki
855 * singleton optimising
857 * Revision 1.13 1999/09/20 15:48:06 heikki
860 * Revision 1.12 1999/09/13 13:28:28 heikki
861 * isam-d optimizing: merging input data in the same go
863 * Revision 1.11 1999/08/25 18:09:24 heikki
864 * Starting to optimize
866 * Revision 1.10 1999/08/24 13:17:42 heikki
867 * Block sizes, comments
869 * Revision 1.9 1999/08/20 12:25:58 heikki
870 * Statistics in isamd
872 * Revision 1.8 1999/08/18 13:28:16 heikki
873 * Set log levels to decent values
875 * Revision 1.6 1999/08/17 19:44:25 heikki
878 * Revision 1.4 1999/08/04 14:21:18 heikki
879 * isam-d seems to be working.
881 * Revision 1.3 1999/07/21 14:24:50 heikki
882 * isamd write and read functions ok, except when diff block full.
883 * (merge not yet done)
885 * Revision 1.1 1999/07/14 12:34:43 heikki
886 * Copied from isamh, starting to change things...