Added isam-d files. Compiles (almost) clean. Doesn't work at all
[idzebra-moved-to-github.git] / isamc / isamd.c
1 /*
2  * Copyright (c) 1995-1998, Index Data.
3  * See the file LICENSE for details.
4  * Heikki Levanto
5  * 
6  * Isamd - isam with diffs 
7  *
8  * todo
9  *   most of it, this is just a copy of isamh
10  *
11  */
12
13
14
15
16 #include <stdlib.h>
17 #include <assert.h>
18 #include <string.h>
19 #include <stdio.h>
20
21 #include <log.h>
22 #include "isamd-p.h"
23
24 #include "../index/index.h" /* for dump */
25
26 static void flush_block (ISAMH is, int cat);
27 static void release_fc (ISAMH is, int cat);
28 static void init_fc (ISAMH is, int cat);
29
30 #define ISAMH_FREELIST_CHUNK 1
31
32 #define SMALL_TEST 1
33
34 ISAMH_M isamd_getmethod (void)
35 {
36     static struct ISAMH_filecat_s def_cat[] = {
37 #if SMALL_TEST
38 /*        blocksz,   max keys before switching size */
39   /*      {    32,  40 }, */
40         {   128,   0 },
41 #else
42         {    24,   40 },
43         {  2048, 2048 },
44         { 16384,    0  },
45
46 #endif 
47 #ifdef OLDVALUES
48         {    24,   40 },
49         {   128,  256 },
50         {   512, 1024 },
51         {  2048, 4096 },
52         {  8192,16384 },
53         { 32768,   0  },
54
55 #endif
56 /* assume about 2 bytes per pointer, when compressed. The head uses */
57 /* 16 bytes, and other blocks use 8 for header info... If you want 3 */
58 /* blocks of 32 bytes, say max 16+24+24 = 64 keys */
59
60     };
61     ISAMH_M m = (ISAMH_M) xmalloc (sizeof(*m));
62     m->filecat = def_cat;
63
64     m->code_start = NULL;
65     m->code_item = NULL;
66     m->code_stop = NULL;
67     m->code_reset = NULL;
68
69     m->compare_item = NULL;
70
71     m->debug = 1;
72
73     m->max_blocks_mem = 10;
74
75     return m;
76 }
77
78
79
80 ISAMH isamd_open (BFiles bfs, const char *name, int writeflag, ISAMH_M method)
81 {
82     ISAMH is;
83     ISAMH_filecat filecat;
84     int i = 0;
85     int max_buf_size = 0;
86
87     is = (ISAMH) xmalloc (sizeof(*is));
88
89     is->method = (ISAMH_M) xmalloc (sizeof(*is->method));
90     memcpy (is->method, method, sizeof(*method));
91     filecat = is->method->filecat;
92     assert (filecat);
93
94     /* determine number of block categories */
95     if (is->method->debug)
96         logf (LOG_LOG, "isc: bsize  maxkeys");
97     do
98     {
99         if (is->method->debug)
100             logf (LOG_LOG, "isc:%6d %6d",
101                   filecat[i].bsize, filecat[i].mblocks);
102         if (max_buf_size < filecat[i].bsize)
103             max_buf_size = filecat[i].bsize;
104     } while (filecat[i++].mblocks);
105     is->no_files = i;
106     is->max_cat = --i;
107 #ifdef SKIPTHIS
108     /* max_buf_size is the larget buffer to be used during merge */
109     max_buf_size = (1 + max_buf_size / filecat[i].bsize) * filecat[i].bsize;
110     if (max_buf_size < (1+is->method->max_blocks_mem) * filecat[i].bsize)
111         max_buf_size = (1+is->method->max_blocks_mem) * filecat[i].bsize;
112 #endif
113
114     if (is->method->debug)
115         logf (LOG_LOG, "isc: max_buf_size %d", max_buf_size);
116     
117     assert (is->no_files > 0);
118     is->files = (ISAMH_file) xmalloc (sizeof(*is->files)*is->no_files);
119     if (writeflag)
120     {
121 #ifdef SKIPTHIS
122         is->merge_buf = (char *) xmalloc (max_buf_size+256);
123         memset (is->merge_buf, 0, max_buf_size+256);
124 #else
125         is->startblock = (char *) xmalloc (max_buf_size+256);
126         memset (is->startblock, 0, max_buf_size+256);
127         is->lastblock = (char *) xmalloc (max_buf_size+256);
128         memset (is->lastblock, 0, max_buf_size+256);
129         /* The spare 256 bytes should not be needed! */
130 #endif
131     }
132     else
133         is->startblock = is->lastblock = NULL;
134
135     for (i = 0; i<is->no_files; i++)
136     {
137         char fname[512];
138
139         sprintf (fname, "%s%c", name, i+'A');
140         is->files[i].bf = bf_open (bfs, fname, is->method->filecat[i].bsize,
141                                    writeflag);
142         is->files[i].head_is_dirty = 0;
143         if (!bf_read (is->files[i].bf, 0, 0, sizeof(ISAMH_head),
144                      &is->files[i].head))
145         {
146             is->files[i].head.lastblock = 1;
147             is->files[i].head.freelist = 0;
148         }
149         is->files[i].alloc_entries_num = 0;
150         is->files[i].alloc_entries_max =
151             is->method->filecat[i].bsize / sizeof(int) - 1;
152         is->files[i].alloc_buf = (char *)
153             xmalloc (is->method->filecat[i].bsize);
154         is->files[i].no_writes = 0;
155         is->files[i].no_reads = 0;
156         is->files[i].no_skip_writes = 0;
157         is->files[i].no_allocated = 0;
158         is->files[i].no_released = 0;
159         is->files[i].no_remap = 0;
160         is->files[i].no_forward = 0;
161         is->files[i].no_backward = 0;
162         is->files[i].sum_forward = 0;
163         is->files[i].sum_backward = 0;
164         is->files[i].no_next = 0;
165         is->files[i].no_prev = 0;
166
167         init_fc (is, i);
168     }
169     return is;
170 }
171
172 int isamd_block_used (ISAMH is, int type)
173 {
174     if (type < 0 || type >= is->no_files)
175         return -1;
176     return is->files[type].head.lastblock-1;
177 }
178
179 int isamd_block_size (ISAMH is, int type)
180 {
181     ISAMH_filecat filecat = is->method->filecat;
182     if (type < 0 || type >= is->no_files)
183         return -1;
184     return filecat[type].bsize;
185 }
186
187 int isamd_close (ISAMH is)
188 {
189     int i;
190
191     if (is->method->debug)
192     {
193         logf (LOG_LOG, "isc:    next    forw   mid-f    prev   backw   mid-b");
194         for (i = 0; i<is->no_files; i++)
195             logf (LOG_LOG, "isc:%8d%8d%8.1f%8d%8d%8.1f",
196                   is->files[i].no_next,
197                   is->files[i].no_forward,
198                   is->files[i].no_forward ?
199                   (double) is->files[i].sum_forward/is->files[i].no_forward
200                   : 0.0,
201                   is->files[i].no_prev,
202                   is->files[i].no_backward,
203                   is->files[i].no_backward ?
204                   (double) is->files[i].sum_backward/is->files[i].no_backward
205                   : 0.0);
206     }
207     if (is->method->debug)
208         logf (LOG_LOG, "isc:  writes   reads skipped   alloc released  remap");
209     for (i = 0; i<is->no_files; i++)
210     {
211         release_fc (is, i);
212         assert (is->files[i].bf);
213         if (is->files[i].head_is_dirty)
214             bf_write (is->files[i].bf, 0, 0, sizeof(ISAMH_head),
215                  &is->files[i].head);
216         if (is->method->debug)
217             logf (LOG_LOG, "isc:%8d%8d%8d%8d%8d%8d",
218                   is->files[i].no_writes,
219                   is->files[i].no_reads,
220                   is->files[i].no_skip_writes,
221                   is->files[i].no_allocated,
222                   is->files[i].no_released,
223                   is->files[i].no_remap);
224         xfree (is->files[i].fc_list);
225         flush_block (is, i);
226         bf_close (is->files[i].bf);
227     }
228     xfree (is->files);
229     xfree (is->startblock);
230     xfree (is->lastblock);
231     xfree (is->method);
232     xfree (is);
233     return 0;
234 }
235
236 int isamd_read_block (ISAMH is, int cat, int pos, char *dst)
237 {
238     ++(is->files[cat].no_reads);
239     return bf_read (is->files[cat].bf, pos, 0, 0, dst);
240 }
241
242 int isamd_write_block (ISAMH is, int cat, int pos, char *src)
243 {
244     ++(is->files[cat].no_writes);
245     if (is->method->debug > 2)
246         logf (LOG_LOG, "isc: write_block %d %d", cat, pos);
247     return bf_write (is->files[cat].bf, pos, 0, 0, src);
248 }
249
250 int isamd_write_dblock (ISAMH is, int cat, int pos, char *src,
251                       int nextpos, int offset)
252 {
253     ISAMH_BLOCK_SIZE size = offset + ISAMH_BLOCK_OFFSET_N;
254     if (is->method->debug > 2)
255         logf (LOG_LOG, "isc: write_dblock. size=%d nextpos=%d",
256               (int) size, nextpos);
257     src -= ISAMH_BLOCK_OFFSET_N;
258     memcpy (src, &nextpos, sizeof(int));
259     memcpy (src + sizeof(int), &size, sizeof(size));
260     return isamd_write_block (is, cat, pos, src);
261 }
262
263 #if ISAMH_FREELIST_CHUNK
264 static void flush_block (ISAMH is, int cat)
265 {
266     char *abuf = is->files[cat].alloc_buf;
267     int block = is->files[cat].head.freelist;
268     if (block && is->files[cat].alloc_entries_num)
269     {
270         memcpy (abuf, &is->files[cat].alloc_entries_num, sizeof(int));
271         bf_write (is->files[cat].bf, block, 0, 0, abuf);
272         is->files[cat].alloc_entries_num = 0;
273     }
274     xfree (abuf);
275 }
276
277 static int alloc_block (ISAMH is, int cat)
278 {
279     int block = is->files[cat].head.freelist;
280     char *abuf = is->files[cat].alloc_buf;
281
282     (is->files[cat].no_allocated)++;
283
284     if (!block)
285     {
286         block = (is->files[cat].head.lastblock)++;   /* no free list */
287         is->files[cat].head_is_dirty = 1;
288     }
289     else
290     {
291         if (!is->files[cat].alloc_entries_num) /* read first time */
292         {
293             bf_read (is->files[cat].bf, block, 0, 0, abuf);
294             memcpy (&is->files[cat].alloc_entries_num, abuf,
295                     sizeof(is->files[cat].alloc_entries_num));
296             assert (is->files[cat].alloc_entries_num > 0);
297         }
298         /* have some free blocks now */
299         assert (is->files[cat].alloc_entries_num > 0);
300         is->files[cat].alloc_entries_num--;
301         if (!is->files[cat].alloc_entries_num)  /* last one in block? */
302         {
303             memcpy (&is->files[cat].head.freelist, abuf + sizeof(int),
304                     sizeof(int));
305             is->files[cat].head_is_dirty = 1;
306
307             if (is->files[cat].head.freelist)
308             {
309                 bf_read (is->files[cat].bf, is->files[cat].head.freelist,
310                          0, 0, abuf);
311                 memcpy (&is->files[cat].alloc_entries_num, abuf,
312                         sizeof(is->files[cat].alloc_entries_num));
313                 assert (is->files[cat].alloc_entries_num);
314             }
315         }
316         else
317             memcpy (&block, abuf + sizeof(int) + sizeof(int) *
318                     is->files[cat].alloc_entries_num, sizeof(int));
319     }
320     return block;
321 }
322
323 static void release_block (ISAMH is, int cat, int pos)
324 {
325     char *abuf = is->files[cat].alloc_buf;
326     int block = is->files[cat].head.freelist;
327
328     (is->files[cat].no_released)++;
329
330     if (block && !is->files[cat].alloc_entries_num) /* must read block */
331     {
332         bf_read (is->files[cat].bf, block, 0, 0, abuf);
333         memcpy (&is->files[cat].alloc_entries_num, abuf,
334                 sizeof(is->files[cat].alloc_entries_num));
335         assert (is->files[cat].alloc_entries_num > 0);
336     }
337     assert (is->files[cat].alloc_entries_num <= is->files[cat].alloc_entries_max);
338     if (is->files[cat].alloc_entries_num == is->files[cat].alloc_entries_max)
339     {
340         assert (block);
341         memcpy (abuf, &is->files[cat].alloc_entries_num, sizeof(int));
342         bf_write (is->files[cat].bf, block, 0, 0, abuf);
343         is->files[cat].alloc_entries_num = 0;
344     }
345     if (!is->files[cat].alloc_entries_num) /* make new buffer? */
346     {
347         memcpy (abuf + sizeof(int), &block, sizeof(int));
348         is->files[cat].head.freelist = pos;
349         is->files[cat].head_is_dirty = 1; 
350     }
351     else
352     {
353         memcpy (abuf + sizeof(int) +
354                 is->files[cat].alloc_entries_num*sizeof(int),
355                 &pos, sizeof(int));
356     }
357     is->files[cat].alloc_entries_num++;
358 }
359 #else
360 static void flush_block (ISAMH is, int cat)
361 {
362     char *abuf = is->files[cat].alloc_buf;
363     xfree (abuf);
364 }
365
366 static int alloc_block (ISAMH is, int cat)
367 {
368     int block;
369     char buf[sizeof(int)];
370
371     is->files[cat].head_is_dirty = 1;
372     (is->files[cat].no_allocated)++;
373     if ((block = is->files[cat].head.freelist))
374     {
375         bf_read (is->files[cat].bf, block, 0, sizeof(int), buf);
376         memcpy (&is->files[cat].head.freelist, buf, sizeof(int));
377     }
378     else
379         block = (is->files[cat].head.lastblock)++;
380     return block;
381 }
382
383 static void release_block (ISAMH is, int cat, int pos)
384 {
385     char buf[sizeof(int)];
386    
387     (is->files[cat].no_released)++;
388     is->files[cat].head_is_dirty = 1; 
389     memcpy (buf, &is->files[cat].head.freelist, sizeof(int));
390     is->files[cat].head.freelist = pos;
391     bf_write (is->files[cat].bf, pos, 0, sizeof(int), buf);
392 }
393 #endif
394
395 int isamd_alloc_block (ISAMH is, int cat)
396 {
397     int block = 0;
398
399     if (is->files[cat].fc_list)
400     {
401         int j, nb;
402         for (j = 0; j < is->files[cat].fc_max; j++)
403             if ((nb = is->files[cat].fc_list[j]) && (!block || nb < block))
404             {
405                 is->files[cat].fc_list[j] = 0;
406                 block = nb;
407                 break;
408             }
409     }
410     if (!block)
411         block = alloc_block (is, cat);
412     if (is->method->debug > 3)
413         logf (LOG_LOG, "isc: alloc_block in cat %d: %d", cat, block);
414     return block;
415 }
416
417 void isamd_release_block (ISAMH is, int cat, int pos)
418 {
419     if (is->method->debug > 3)
420         logf (LOG_LOG, "isc: release_block in cat %d: %d", cat, pos);
421     if (is->files[cat].fc_list)
422     {
423         int j;
424         for (j = 0; j<is->files[cat].fc_max; j++)
425             if (!is->files[cat].fc_list[j])
426             {
427                 is->files[cat].fc_list[j] = pos;
428                 return;
429             }
430     }
431     release_block (is, cat, pos);
432 }
433
434 static void init_fc (ISAMH is, int cat)
435 {
436     int j = 100;
437         
438     is->files[cat].fc_max = j;
439     is->files[cat].fc_list = (int *)
440         xmalloc (sizeof(*is->files[0].fc_list) * j);
441     while (--j >= 0)
442         is->files[cat].fc_list[j] = 0;
443 }
444
445 static void release_fc (ISAMH is, int cat)
446 {
447     int b, j = is->files[cat].fc_max;
448
449     while (--j >= 0)
450         if ((b = is->files[cat].fc_list[j]))
451         {
452             release_block (is, cat, b);
453             is->files[cat].fc_list[j] = 0;
454         }
455 }
456
457 void isamd_pp_close (ISAMH_PP pp)
458 {
459     ISAMH is = pp->is;
460
461     (*is->method->code_stop)(ISAMH_DECODE, pp->decodeClientData);
462     xfree (pp->buf);
463     xfree (pp);
464 }
465
466 ISAMH_PP isamd_pp_open (ISAMH is, ISAMH_P ipos)
467 {
468     ISAMH_PP pp = (ISAMH_PP) xmalloc (sizeof(*pp));
469     char *src;
470    
471     pp->cat = isamd_type(ipos);
472     pp->pos = isamd_block(ipos); 
473
474     src = pp->buf = (char *) xmalloc (is->method->filecat[pp->cat].bsize);
475
476     pp->next = 0;
477     pp->size = 0;
478     pp->offset = 0;
479     pp->is = is;
480     pp->decodeClientData = (*is->method->code_start)(ISAMH_DECODE);
481     pp->deleteFlag = 0;
482     pp->numKeys = 0;
483     pp->lastblock=0;
484     
485     if (pp->pos)
486     {
487         src = pp->buf;
488         isamd_read_block (is, pp->cat, pp->pos, src);
489         memcpy (&pp->next, src, sizeof(pp->next));
490         src += sizeof(pp->next);
491         memcpy (&pp->size, src, sizeof(pp->size));
492         src += sizeof(pp->size);
493         memcpy (&pp->numKeys, src, sizeof(pp->numKeys));
494         src += sizeof(pp->numKeys);
495         memcpy (&pp->lastblock, src, sizeof(pp->lastblock));
496         src += sizeof(pp->lastblock);
497         assert (pp->next != pp->pos);
498         pp->offset = src - pp->buf; 
499         assert (pp->offset == ISAMH_BLOCK_OFFSET_1);
500         if (is->method->debug > 2)
501             logf (LOG_LOG, "isamd_pp_open sz=%d c=%d p=%d n=%d",
502                  pp->size, pp->cat, pp->pos, isamd_block(pp->next));
503     }
504     return pp;
505 }
506
507
508
509 void isamd_buildfirstblock(ISAMH_PP pp){
510   char *dst=pp->buf;
511   assert(pp->buf);
512   assert(pp->next != pp->pos); 
513   memcpy(dst, &pp->next, sizeof(pp->next) );
514   dst += sizeof(pp->next);
515   memcpy(dst, &pp->size,sizeof(pp->size));
516   dst += sizeof(pp->size);
517   memcpy(dst, &pp->numKeys, sizeof(pp->numKeys));
518   dst += sizeof(pp->numKeys);
519   memcpy(dst, &pp->lastblock, sizeof(pp->lastblock));
520   dst += sizeof(pp->lastblock);  
521   assert (dst - pp->buf  == ISAMH_BLOCK_OFFSET_1);
522   if (pp->is->method->debug > 2)
523      logf (LOG_LOG, "isamd: first: sz=%d  p=%d/%d>%d/%d>%d/%d nk=%d",
524            pp->size, 
525            pp->pos, pp->cat, 
526            isamd_block(pp->next), isamd_type(pp->next),
527            isamd_block(pp->lastblock), isamd_type(pp->lastblock),
528            pp->numKeys);
529 }
530
531 void isamd_buildlaterblock(ISAMH_PP pp){
532   char *dst=pp->buf;
533   assert(pp->buf);
534   assert(pp->next != isamd_addr(pp->pos,pp->cat)); 
535   memcpy(dst, &pp->next, sizeof(pp->next) );
536   dst += sizeof(pp->next);
537   memcpy(dst, &pp->size,sizeof(pp->size));
538   dst += sizeof(pp->size);
539   assert (dst - pp->buf  == ISAMH_BLOCK_OFFSET_N);
540   if (pp->is->method->debug > 2)
541      logf (LOG_LOG, "isamd: l8r: sz=%d  p=%d/%d>%d/%d",
542            pp->size, 
543            pp->pos, pp->cat, 
544            isamd_block(pp->next), isamd_type(pp->next) );
545 }
546
547
548
549 /* returns non-zero if item could be read; 0 otherwise */
550 int isamd_pp_read (ISAMH_PP pp, void *buf)
551 {
552     return isamd_read_item (pp, (char **) &buf);
553 }
554
555 /* read one item from file - decode and store it in *dst.
556    Returns
557      0 if end-of-file
558      1 if item could be read ok and NO boundary
559      2 if item could be read ok and boundary */
560 int isamd_read_item (ISAMH_PP pp, char **dst)
561 {
562     ISAMH is = pp->is;
563     char *src = pp->buf + pp->offset;
564     int newcat;
565
566     if (pp->offset >= pp->size)
567     {
568         if (!pp->next)
569         {
570             pp->pos = 0;
571             return 0; /* end of file */
572         }
573         if (pp->next > pp->pos)
574         {
575             if (pp->next == pp->pos + 1)
576                 is->files[pp->cat].no_next++;
577             else
578             {
579                 is->files[pp->cat].no_forward++;
580                 is->files[pp->cat].sum_forward += pp->next - pp->pos;
581             }
582         }
583         else
584         {
585             if (pp->next + 1 == pp->pos)
586                 is->files[pp->cat].no_prev++;
587             else
588             {
589                 is->files[pp->cat].no_backward++;
590                 is->files[pp->cat].sum_backward += pp->pos - pp->next;
591             }
592         }
593         /* out new block position */
594         newcat = isamd_type(pp->next);
595         if (pp->cat != newcat ) {
596           pp->buf = xrealloc(pp->buf, is->method->filecat[newcat].bsize);
597         }
598         pp->pos = isamd_block(pp->next);
599         pp->cat = isamd_type(pp->next);
600         
601         src = pp->buf;
602         /* read block and save 'next' and 'size' entry */
603         isamd_read_block (is, pp->cat, pp->pos, src);
604         memcpy (&pp->next, src, sizeof(pp->next));
605         src += sizeof(pp->next);
606         memcpy (&pp->size, src, sizeof(pp->size));
607         src += sizeof(pp->size);
608         /* assume block is non-empty */
609         assert (src - pp->buf == ISAMH_BLOCK_OFFSET_N);
610         assert (pp->next != isamd_addr(pp->pos,pp->cat));
611         if (pp->deleteFlag)
612             isamd_release_block (is, pp->cat, pp->pos);
613         (*is->method->code_reset)(pp->decodeClientData);
614         (*is->method->code_item)(ISAMH_DECODE, pp->decodeClientData, dst, &src);
615         pp->offset = src - pp->buf; 
616         if (is->method->debug > 2)
617             logf (LOG_LOG, "isc: read_block size=%d %d %d next=%d",
618                  pp->size, pp->cat, pp->pos, pp->next);
619         return 2;
620     }
621     (*is->method->code_item)(ISAMH_DECODE, pp->decodeClientData, dst, &src);
622     pp->offset = src - pp->buf; 
623     return 1;
624 }
625
626 int isamd_pp_num (ISAMH_PP pp)
627 {
628     return pp->numKeys;
629 }
630
631 static char *hexdump(unsigned char *p, int len, char *buff) {
632   static char localbuff[128];
633   char bytebuff[8];
634   if (!buff) buff=localbuff;
635   *buff='\0';
636   while (len--) {
637     sprintf(bytebuff,"%02x",*p);
638     p++;
639     strcat(buff,bytebuff);
640     if (len) strcat(buff," ");
641   }
642   return buff;
643 }
644
645
646 void isamd_pp_dump (ISAMH is, ISAMH_P ipos)
647 {
648   ISAMH_PP pp;
649   ISAMH_P oldaddr=0;
650   struct it_key key;
651   int i,n;
652   int occur =0;
653   int oldoffs;
654   char hexbuff[64];
655   
656   logf(LOG_LOG,"dumping isamd block %d (%d:%d)",
657                   (int)ipos, isamd_type(ipos), isamd_block(ipos) );
658   pp=isamd_pp_open(is,ipos);
659   logf(LOG_LOG,"numKeys=%d, last=%d (%d:%d) ofs=%d ",
660        pp->numKeys, 
661        pp->lastblock, 
662        isamd_type(pp->lastblock), isamd_block(pp->lastblock),
663        pp->offset);
664   oldoffs= pp->offset;
665   while(isamd_pp_read(pp, &key))
666   {
667      if (oldaddr != isamd_addr(pp->pos,pp->cat) )
668      {
669         oldaddr = isamd_addr(pp->pos,pp->cat); 
670         logf(LOG_LOG,"block %d (%d:%d) sz=%d nx=%d (%d:%d) ofs=%d",
671                   isamd_addr(pp->pos,pp->cat), 
672                   pp->cat, pp->pos, pp->size,
673                   pp->next, isamd_type(pp->next), isamd_block(pp->next),
674                   pp->offset);
675         i=0;      
676         while (i<pp->size) {
677           n=pp->size-i;
678           if (n>8) n=8;
679           logf(LOG_LOG,"  %05x: %s",i,hexdump(pp->buf+i,n,hexbuff));
680           i+=n;
681         }
682         if (oldoffs >  ISAMH_BLOCK_OFFSET_N)
683            oldoffs=ISAMH_BLOCK_OFFSET_N;
684      } /* new block */
685      occur++;
686      logf (LOG_LOG,"    got %d:%d=%x:%x from %s at %d=%x",
687                   key.sysno, key.seqno,
688                   key.sysno, key.seqno,
689                   hexdump(pp->buf+oldoffs, pp->offset-oldoffs, hexbuff),
690                   oldoffs, oldoffs);
691      oldoffs = pp->offset;
692   }
693   isamd_pp_close(pp);
694 } /* dump */
695
696 /*
697  * $Log: isamd.c,v $
698  * Revision 1.1  1999-07-14 12:34:43  heikki
699  * Copied from isamh, starting to change things...
700  *
701  *
702  */