/*
- * 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.
*
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;
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));
{
/* 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)
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,
/* 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);
{
/* no! delete the item */
r_item = NULL;
- mb[ptr].dirty = 1;
+ mb[ptr].dirty = 2;
}
}
else
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,
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,
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;
}
}