X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=isamc%2Fmerge.c;h=27281942adc8afbe8cb6a13df0ee152e90734481;hb=154c6dacd76fe573d1d6ee3bc7284a05f0445bc6;hp=bb89fa10093ecb2593e200d269897fef386dd96b;hpb=7af74fb4a98eb4baeffb6a1a648e837563fe7b4f;p=idzebra-moved-to-github.git diff --git a/isamc/merge.c b/isamc/merge.c index bb89fa1..2728194 100644 --- a/isamc/merge.c +++ b/isamc/merge.c @@ -1,10 +1,22 @@ /* - * Copyright (c) 1996, Index Data. + * Copyright (c) 1996-1998, Index Data. * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * * $Log: merge.c,v $ - * Revision 1.4 1996-11-08 11:15:31 adam + * Revision 1.7 1998-03-11 11:18:18 adam + * Changed the isc_merge to take into account the mfill (minimum-fill). + * + * Revision 1.6 1998/03/06 13:54:03 adam + * Fixed two nasty bugs in isc_merge. + * + * Revision 1.5 1997/02/12 20:42:43 adam + * Bug fix: during isc_merge operations, some pages weren't marked dirty + * even though they should be. At this point the merge operation marks + * a page dirty if the previous page changed at all. A better approach is + * to mark it dirty if the last key written changed in previous page. + * + * Revision 1.4 1996/11/08 11:15:31 adam * Number of keys in chain are stored in first block and the function * to retrieve this information, isc_pp_num is implemented. * @@ -47,32 +59,40 @@ static void flush_blocks (ISAMC is, struct isc_merge_block *mb, int ptr, unsigned short ssize; char *src; - /* skip rest if not dirty */ - if (!mb[i].dirty) - { - assert (mb[i].block); - if (!*firstpos) - *firstpos = mb[i].block; - if (is->method->debug > 2) - logf (LOG_LOG, "isc: skip block %d %d", cat, mb[i].block); - ++(is->files[cat].no_skip_writes); - continue; - } /* consider this block number */ - if (!mb[i].block) + { mb[i].block = isc_alloc_block (is, cat); + mb[i].dirty = 1; + } /* consider next block pointer */ if (last && i == ptr-1) mb[i+1].block = 0; else if (!mb[i+1].block) + { mb[i+1].block = isc_alloc_block (is, cat); + mb[i+1].dirty = 1; + mb[i].dirty = 1; + } - /* write block */ ssize = mb[i+1].offset - mb[i].offset; assert (ssize); + /* skip rest if not dirty */ + if (!mb[i].dirty) + { + assert (mb[i].block); + if (!*firstpos) + *firstpos = mb[i].block; + if (is->method->debug > 2) + logf (LOG_LOG, "isc: skip ptr=%d size=%d %d %d", + i, ssize, cat, mb[i].block); + ++(is->files[cat].no_skip_writes); + continue; + } + /* write block */ + if (!*firstpos) { *firstpos = mb[i].block; @@ -82,16 +102,16 @@ static void flush_blocks (ISAMC is, struct isc_merge_block *mb, int ptr, memcpy (src+sizeof(int)+sizeof(ssize), numkeys, sizeof(*numkeys)); if (is->method->debug > 2) - logf (LOG_LOG, "isc: flush numk=%d size=%d nextpos=%d", - *numkeys, (int) ssize, mb[i+1].block); + logf (LOG_LOG, "isc: flush ptr=%d numk=%d size=%d nextpos=%d", + i, *numkeys, (int) ssize, mb[i+1].block); } else { src = r_buf + mb[i].offset - ISAMC_BLOCK_OFFSET_N; ssize += ISAMC_BLOCK_OFFSET_N; if (is->method->debug > 2) - logf (LOG_LOG, "isc: flush size=%d nextpos=%d", - (int) ssize, mb[i+1].block); + logf (LOG_LOG, "isc: flush ptr=%d size=%d nextpos=%d", + i, (int) ssize, mb[i+1].block); } memcpy (src, &mb[i+1].block, sizeof(int)); memcpy (src+sizeof(int), &ssize, sizeof(ssize)); @@ -173,25 +193,30 @@ ISAMC_P isc_merge (ISAMC is, ISAMC_P ipos, ISAMC_I data) { /* the resulting output is of the same category as the the original - */ - if (mb[ptr].offset == r_offset) + */ + if (r_offset <= mb[ptr].offset +is->method->filecat[cat].mfill) { - /* the resulting output block is empty. Delete + /* the resulting output block is too small/empty. Delete the original (if any) - */ + */ if (is->method->debug > 3) logf (LOG_LOG, "isc: release A"); if (mb[ptr].block) isc_release_block (is, pp->cat, mb[ptr].block); mb[ptr].block = pp->pos; - mb[ptr].dirty = 0; + mb[ptr].dirty = 1; + if (ptr > 0) + mb[ptr-1].dirty = 1; } else { /* indicate new boundary based on the original file */ mb[++ptr].block = pp->pos; - mb[ptr].dirty = 0; + mb[ptr].dirty = (mb[ptr-1].dirty > 1) ? 1 : 0; mb[ptr].offset = r_offset; + if (is->method->debug > 3) + logf (LOG_LOG, "isc: bound ptr=%d,offset=%d", + ptr, r_offset); if (cat==is->max_cat && ptr >= is->method->max_blocks_mem) { /* We are dealing with block(s) of max size. Block(s) @@ -200,8 +225,7 @@ ISAMC_P isc_merge (ISAMC is, ISAMC_P ipos, ISAMC_I data) if (is->method->debug > 2) logf (LOG_LOG, "isc: flush A %d sections", ptr); flush_blocks (is, mb, ptr-1, r_buf, &firstpos, cat, - 0, &numKeys); - + 0, &pp->numKeys); mb[0].block = mb[ptr-1].block; mb[0].dirty = mb[ptr-1].dirty; memcpy (r_buf, r_buf + mb[ptr-1].offset, @@ -235,7 +259,7 @@ ISAMC_P isc_merge (ISAMC is, ISAMC_P ipos, ISAMC_I data) /* is next input item the same as current except for the delete flag? */ cmp = (*is->method->compare_item)(i_item, f_item); - if (!cmp && i_mode) + if (!cmp && i_mode) /* delete/insert nop? */ { /* yes! insert as if it was an insert only */ memcpy (r_item, i_item, i_item_ptr - i_item); @@ -247,7 +271,7 @@ ISAMC_P isc_merge (ISAMC is, ISAMC_P ipos, ISAMC_I data) { /* no! delete the item */ r_item = NULL; - mb[ptr].dirty = 1; + mb[ptr].dirty = 2; } } else @@ -279,7 +303,7 @@ ISAMC_P isc_merge (ISAMC is, ISAMC_P ipos, ISAMC_I data) abort (); } memcpy (r_item, i_item, i_item_ptr - i_item); - mb[ptr].dirty = 1; + mb[ptr].dirty = 2; /* move i */ i_item_ptr = i_item; i_more = (*data->read_item)(data->clientData, &i_item_ptr, @@ -314,8 +338,7 @@ ISAMC_P isc_merge (ISAMC is, ISAMC_P ipos, ISAMC_I data) if (is->method->debug > 2) logf (LOG_LOG, "isc: flush B %d sections", ptr-1); flush_blocks (is, mb, ptr-1, r_buf, &firstpos, cat, - 0, &numKeys); - + 0, &pp->numKeys); mb[0].block = mb[ptr-1].block; mb[0].dirty = mb[ptr-1].dirty; memcpy (r_buf, r_buf + mb[ptr-1].offset, @@ -390,7 +413,8 @@ ISAMC_P isc_merge (ISAMC is, ISAMC_P ipos, ISAMC_I data) logf (LOG_LOG, "isc: release C"); isc_release_block (is, pp->cat, mb[ptr].block); mb[ptr].block = 0; - mb[ptr].dirty = 1; + if (ptr > 0) + mb[ptr-1].dirty = 1; } }