From 5a4211916c8b14d4b0ec9cc717e613b88394affb Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Wed, 12 Feb 1997 20:42:43 +0000 Subject: [PATCH] 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. --- isamc/isamc.c | 16 ++++++++++++--- isamc/merge.c | 63 +++++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 54 insertions(+), 25 deletions(-) diff --git a/isamc/isamc.c b/isamc/isamc.c index a5e1364..e276a07 100644 --- a/isamc/isamc.c +++ b/isamc/isamc.c @@ -4,7 +4,13 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: isamc.c,v $ - * Revision 1.6 1996-11-08 11:15:29 adam + * Revision 1.7 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.6 1996/11/08 11:15:29 adam * Number of keys in chain are stored in first block and the function * to retrieve this information, isc_pp_num is implemented. * @@ -171,8 +177,6 @@ int isc_close (ISAMC is) int isc_read_block (ISAMC is, int cat, int pos, char *dst) { ++(is->files[cat].no_reads); - if (is->method->debug > 2) - logf (LOG_LOG, "isc: read_block %d %d", cat, pos); return bf_read (is->files[cat].bf, pos, 0, 0, dst); } @@ -325,6 +329,9 @@ ISAMC_PP isc_pp_open (ISAMC is, ISAMC_P ipos) assert (pp->next != pp->pos); pp->offset = src - pp->buf; assert (pp->offset == ISAMC_BLOCK_OFFSET_1); + if (is->method->debug > 2) + logf (LOG_LOG, "isc: read_block size=%d %d %d", + pp->size, pp->cat, pp->pos); } return pp; } @@ -359,6 +366,9 @@ int isc_read_item (ISAMC_PP pp, char **dst) isc_release_block (is, pp->cat, pp->pos); (*is->method->code_item)(ISAMC_DECODE, pp->decodeClientData, dst, &src); pp->offset = src - pp->buf; + if (is->method->debug > 2) + logf (LOG_LOG, "isc: read_block size=%d %d %d", + pp->size, pp->cat, pp->pos); return 2; } (*is->method->code_item)(ISAMC_DECODE, pp->decodeClientData, dst, &src); diff --git a/isamc/merge.c b/isamc/merge.c index bb89fa1..c2578a8 100644 --- a/isamc/merge.c +++ b/isamc/merge.c @@ -4,7 +4,13 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: merge.c,v $ - * Revision 1.4 1996-11-08 11:15:31 adam + * 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 +53,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 +96,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)); @@ -184,14 +198,19 @@ ISAMC_P isc_merge (ISAMC is, ISAMC_P ipos, ISAMC_I data) 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 = 2; + 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) @@ -247,7 +266,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 +298,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, -- 1.7.10.4