X-Git-Url: http://lists.indexdata.dk/cgi-bin?a=blobdiff_plain;ds=sidebyside;f=isamc%2Fmerge.c;h=f44f84deb1937daa71ba54b554c63481f6666ebe;hb=3726bf6622da6a8b983bb4cbb7d654e84c3216d7;hp=b0d4315de57b08255deb99073e70c1e84bbed2ba;hpb=c0826c3b142ac40494080a5c45c42abbd8ffc3f8;p=idzebra-moved-to-github.git diff --git a/isamc/merge.c b/isamc/merge.c index b0d4315..f44f84d 100644 --- a/isamc/merge.c +++ b/isamc/merge.c @@ -1,43 +1,7 @@ /* * Copyright (c) 1996-1998, Index Data. * See the file LICENSE for details. - * Sebastian Hammer, Adam Dickmeiss - * - * $Log: merge.c,v $ - * Revision 1.9 1998-03-19 10:04:38 adam - * Minor changes. - * - * Revision 1.8 1998/03/18 09:23:55 adam - * Blocks are stored in chunks on free list - up to factor 2 in speed. - * Fixed bug that could occur in block category rearrangemen. - * - * 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. - * - * Revision 1.3 1996/11/04 14:08:59 adam - * Optimized free block usage. - * - * Revision 1.2 1996/11/01 13:36:46 adam - * New element, max_blocks_mem, that control how many blocks of max size - * to store in memory during isc_merge. - * Function isc_merge now ignores delete/update of identical keys and - * the proper blocks are then non-dirty and not written in flush_blocks. - * - * Revision 1.1 1996/11/01 08:59:15 adam - * First version of isc_merge that supports update/delete. + * Sebastian Hammer, Adam Dickmeiss, Heikki Levanto * */ @@ -45,9 +9,9 @@ #include #include #include - #include #include "isamc-p.h" +#include "isamh-p.h" struct isc_merge_block { int offset; /* offset in r_buf */ @@ -55,7 +19,8 @@ struct isc_merge_block { int dirty; /* block is different from that on file */ }; -static void opt_blocks (ISAMC is, struct isc_merge_block *mb, int ptr, int last) +static void opt_blocks (ISAMC is, struct isc_merge_block *mb, int ptr, + int last) { int i, no_dirty = 0; for (i = 0; imethod->code_reset); + + if ( 0==ipos) + { /* new block */ + pp->cat=0; /* start small... */ + pp->pos = isamh_alloc_block(is,pp->cat); + pp->size= pp->offset = ISAMH_BLOCK_OFFSET_1 ; + r_clientData = (*is->method->code_start)(ISAMH_ENCODE); + if (pp->is->method->debug > 2) + logf(LOG_LOG,"isamh_append: starting with new block %d",pp->pos); + } + else + { /* existing block */ + if (isamh_block(firstpp->lastblock) == firstpp->pos) + { /* only one block, we have it already */ + pp->offset=ISAMH_BLOCK_OFFSET_1; + if (pp->is->method->debug > 2) + logf(LOG_LOG,"isamh_append: starting with one block %d",pp->pos); + } + else + { + if (pp->is->method->debug > 2) + logf(LOG_LOG,"isamh_append: starting with multiple blocks %d>%d>%d", + firstpp->pos,isamh_block(firstpp->next),isamh_block(firstpp->lastblock)); + pp=isamh_pp_open(is,firstpp->lastblock); + /* dirty, but this can also read a N-block. Just clear extra values*/ + pp->lastblock=0; + pp->offset=ISAMH_BLOCK_OFFSET_N; + } /* get last */ + r_clientData = (*is->method->code_start)(ISAMH_ENCODE); + if (pp->is->method->debug > 3) + logf(LOG_LOG,"isamh_append: scanning to end of block %d %d->%d", + pp->pos, pp->offset, pp->size); + codeptr=codebuffer; + while (pp->offsetsize) { + codeptr=codebuffer; + bufptr=pp->buf + pp->offset; + (*is->method->code_item)(ISAMH_DECODE, r_clientData, &codeptr, &bufptr); + codelen = bufptr - (pp->buf+pp->offset) ; + if (pp->is->method->debug > 3) + logf(LOG_LOG,"isamh_append: dec at %d %d/%d:%s", + pp->offset, codelen, codeptr-codebuffer, + hexdump(codebuffer,codeptr-codebuffer,0) ); + pp->offset += codelen; + } + } /* existing block */ + + + i_item_ptr = i_item; + i_more = (*data->read_item)(data->clientData,&i_item_ptr,&i_mode); + if (pp->is->method->debug > 3) + logf(LOG_LOG,"isamh_append 1: m=%d l=%d %s", + i_mode, i_item_ptr-i_item, hexdump(i_item,i_item_ptr-i_item,0)); + + maxsize = is->method->filecat[pp->cat].bsize; + + while(i_more) { + if (i_mode) + { /* insert key, ignore all delete keys time being... */ + codeptr = codebuffer; + i_item_ptr=i_item; + (*is->method->code_item)(ISAMH_ENCODE, r_clientData, &codeptr, &i_item_ptr); + codelen = codeptr-codebuffer; + + assert( (codelen < 128) && (codelen>0)); + + if (pp->is->method->debug > 3) + logf(LOG_LOG,"isamh_append: coded into %d:%s (nk=%d)", + codelen,hexdump(codebuffer,codelen,0),firstpp->numKeys); + + if ( pp->offset + codelen > maxsize ) + { /* oops, block full, do something */ + newcat = pp->cat; + maxkeys = is->method->filecat[pp->cat].mblocks; /* max keys */ + if (pp->is->method->debug > 2) + logf(LOG_LOG,"isamh_append: need new block: %d > %d (k:%d/%d)", + pp->offset + codelen, maxsize, firstpp->numKeys,maxkeys ); + if ( (maxkeys>0) && (firstpp->numKeys > maxkeys) ) + { /* time to increase block size */ + newcat++; + maxsize = is->method->filecat[newcat].bsize; + pp->buf=xrealloc(pp->buf,maxsize); + if (pp->is->method->debug > 2) + logf(LOG_LOG,"isamh_append: increased to cat %d ",newcat); + } + + newblock = isamh_alloc_block(is,newcat); + pp->next = isamh_addr(newblock,newcat); + if (firstpp!=pp) + { /* not first block, write to disk already now */ + isamh_buildlaterblock(pp); + isamh_write_block(is,pp->cat,pp->pos,pp->buf); + } + else + { /* we had only one block, allocate a second buffer */ + pp = isamh_pp_open(is,0); + } + pp->cat = newcat; + pp->pos = newblock; + + pp->size=pp->offset=ISAMH_BLOCK_OFFSET_N ; + pp->next=0; + pp->lastblock=0; + if (pp->is->method->debug > 2) + logf(LOG_LOG,"isamh_append: got a new block %d:%d",pp->cat,pp->pos); + + /* reset the encoding, and code again */ + (*is->method->code_reset)(r_clientData); + codeptr = codebuffer; + i_item_ptr=i_item; + (*is->method->code_item)(ISAMH_ENCODE, r_clientData, &codeptr, &i_item_ptr); + codelen = codeptr-codebuffer; + if (pp->is->method->debug > 3) + logf(LOG_LOG,"isamh_append: coded again %d:%s (nk=%d)", + codelen,hexdump(codebuffer,codelen,0),firstpp->numKeys); + + } /* block full */ + + /* ok, now we can write it */ + memcpy(&(pp->buf[pp->offset]), codebuffer, codelen); + pp->offset += codelen; + pp->size += codelen; + firstpp->numKeys++; + } /* not a delete */ + + /* try to read the next element */ + i_item_ptr = i_item; + i_more = (*data->read_item)(data->clientData,&i_item_ptr,&i_mode); + if (pp->is->method->debug > 3) + logf(LOG_LOG,"isamh_append 2: m=%d l=%d %s", + i_mode, i_item_ptr-i_item, hexdump(i_item,i_item_ptr-i_item,0)); + + } /* while */ + + /* Write the last (partial) block, if needed. */ + if (pp!=firstpp) + { + pp->next=0; /* just to be sure */ + isamh_buildlaterblock(pp); + isamh_write_block(is,pp->cat,pp->pos,pp->buf); + } + + /* update first block and write it */ + firstpp->lastblock = isamh_addr(pp->pos,pp->cat); + isamh_buildfirstblock(firstpp); + isamh_write_block(is,firstpp->cat,firstpp->pos,firstpp->buf); + + /* release the second block, if we allocated one */ + if ( firstpp != pp ) + isamh_pp_close(pp); + + /* get return value (before it disappears at close! */ + retval = isamh_addr(firstpp->pos,firstpp->cat); + + isamh_pp_close(firstpp); + + return retval; + +} /* isamh_append */ + + +/* + * $Log: merge.c,v $ + * Revision 1.18 1999-07-13 15:24:50 heikki + * Removed the one-block append, it had a serious flaw. + * + * Revision 1.16 1999/07/08 14:23:27 heikki + * Fixed a bug in isamh_pp_read and cleaned up a bit + * + * Revision 1.15 1999/07/07 09:36:04 heikki + * Fixed an assertion in isamh + * + * Revision 1.13 1999/07/06 09:37:05 heikki + * Working on isamh - not ready yet. + * + * Revision 1.12 1999/06/30 15:03:55 heikki + * first take on isamh, the append-only isam structure + * + * Revision 1.11 1999/05/26 07:49:14 adam + * C++ compilation. + * + * Revision 1.10 1998/03/19 12:22:09 adam + * Minor change. + * + * Revision 1.9 1998/03/19 10:04:38 adam + * Minor changes. + * + * Revision 1.8 1998/03/18 09:23:55 adam + * Blocks are stored in chunks on free list - up to factor 2 in speed. + * Fixed bug that could occur in block category rearrangemen. + * + * 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. + * + * Revision 1.3 1996/11/04 14:08:59 adam + * Optimized free block usage. + * + * Revision 1.2 1996/11/01 13:36:46 adam + * New element, max_blocks_mem, that control how many blocks of max size + * to store in memory during isc_merge. + * Function isc_merge now ignores delete/update of identical keys and + * the proper blocks are then non-dirty and not written in flush_blocks. + * + * Revision 1.1 1996/11/01 08:59:15 adam + * First version of isc_merge that supports update/delete. + * + */ + +