Commit 963f8e5e authored by Per Cederqvist's avatar Per Cederqvist
Browse files

(add_block_before): New static function.

(find_block): Return a pointer to the last block instead of a NULL
	pointer if a too large local text number is supplied.
(l2g_expensive_set): Now fully implemented.
parent 2e58007c
...@@ -219,6 +219,49 @@ add_block(Local_to_global *l2g) ...@@ -219,6 +219,49 @@ add_block(Local_to_global *l2g)
return binfo; return binfo;
} }
/* Insert a new block in the middle of an l2g structure. This
is only used by l2g_expensive_set, so it doesn't have to be
optimally efficient. */
static void
add_block_before(Local_to_global *l2g,
int position)
{
struct l2g_block_info * binfo;
struct l2g_block_info * new_blocks;
int ix;
/* Allocate a new block pointer array. */
new_blocks = smalloc((l2g->num_blocks+1) * sizeof(struct l2g_block_info));
/* Copy blocks before and after position. */
for (ix = 0; ix < position; ix++)
new_blocks[ix] = l2g->blocks[ix];
for (ix = position; ix < l2g->num_blocks; ix++)
new_blocks[ix+1] = l2g->blocks[ix];
/* Discard the old block pointers. */
sfree(l2g->blocks);
l2g->blocks = new_blocks;
l2g->num_blocks++;
/* Initialize the new block. */
binfo = &new_blocks[position];
binfo->first_free = 0;
binfo->zeroes = L2G_BLOCKSIZE;
#ifndef NDEBUG
binfo->start = 0xdeadbeef;
#endif
binfo->key_block = NULL;
binfo->value_block = smalloc(L2G_BLOCKSIZE * sizeof(Text_no));
#ifndef NDEBUG
for (ix = 0; ix < L2G_BLOCKSIZE; ++ix)
binfo->value_block[ix] = 0xdeadbeef;
#endif
if (++nr_blocks > nr_blocks_peak)
nr_blocks_peak = nr_blocks;
}
/* /*
* Delete a block from the Local_to_global L2G. The pointer BINFO * Delete a block from the Local_to_global L2G. The pointer BINFO
...@@ -287,14 +330,15 @@ make_sparse(struct l2g_block_info *binfo) ...@@ -287,14 +330,15 @@ make_sparse(struct l2g_block_info *binfo)
/* /*
* Find the block where the local text no LNO is and return a pointer * Find the block where the local text no LNO should be and return a
* to it. Returning a pointer does not mean that the text still exists, * pointer to it. Returning a pointer does not necessarily mean that
* so a search within the block must also be done later. If LNO is * the text exists, so a search within the block must also be done
* smaller than the smallest number in the structure a pointer to the * later. If LNO is smaller than the smallest number in the structure
* first block will be returned. * a pointer to the first block will be returned. If LNO is larger
* than the largest number in the structure a pointer to the last
* block will be returned.
* *
* Return NULL if LNO is bigger than the highest number in the * Return NULL if (and only if) the structure is empty.
* structure, or if the structure is empty.
*/ */
static struct l2g_block_info * static struct l2g_block_info *
...@@ -309,11 +353,6 @@ find_block(const Local_to_global *l2g, Local_text_no lno) ...@@ -309,11 +353,6 @@ find_block(const Local_to_global *l2g, Local_text_no lno)
/* Let binfo point to the last block. */ /* Let binfo point to the last block. */
binfo = &(l2g->blocks[l2g->num_blocks - 1]); binfo = &(l2g->blocks[l2g->num_blocks - 1]);
/* If lno is greater than the biggest local number, return NULL. */
assert(binfo->first_free > 0);
if (lno > key_value(binfo, binfo->first_free - 1))
return NULL;
/* Find the block where lno *could* be. */ /* Find the block where lno *could* be. */
/* FIXME: Binary search? */ /* FIXME: Binary search? */
while (binfo > l2g->blocks) while (binfo > l2g->blocks)
...@@ -708,7 +747,7 @@ l2g_append(Local_to_global *l2g, ...@@ -708,7 +747,7 @@ l2g_append(Local_to_global *l2g,
binfo->zeroes--; binfo->zeroes--;
} }
#if 0 /* Not yet completely implemented. */
void void
l2g_expensive_set(Local_to_global *l2g, l2g_expensive_set(Local_to_global *l2g,
Local_text_no lno, Local_text_no lno,
...@@ -716,6 +755,7 @@ l2g_expensive_set(Local_to_global *l2g, ...@@ -716,6 +755,7 @@ l2g_expensive_set(Local_to_global *l2g,
{ {
struct l2g_block_info * binfo; struct l2g_block_info * binfo;
Local_text_no_iter ix; Local_text_no_iter ix;
int block_no;
if (lno >= l2g->first_unused) if (lno >= l2g->first_unused)
{ {
...@@ -732,26 +772,43 @@ l2g_expensive_set(Local_to_global *l2g, ...@@ -732,26 +772,43 @@ l2g_expensive_set(Local_to_global *l2g,
binfo = find_block(l2g, lno); binfo = find_block(l2g, lno);
if (binfo == NULL) if (binfo == NULL)
{ {
assert(l2g->num_blocks == 0);
/* Append a new block. */ /* Append a new block. */
FIXME; binfo = add_block(l2g);
assert(binfo->first_free == 0);
assert(binfo->key_block == NULL);
binfo->start = lno;
binfo->value_block[0] = tno;
binfo->first_free = 1;
binfo->zeroes--;
} }
else if (lno < binfo->start) else if (lno < binfo->start)
{ {
assert(binfo == l2g->blocks); assert(binfo == l2g->blocks);
/* Prepend a new block. */ /* Prepend a new block. */
FIXME; add_block_before(l2g, 0);
binfo = l2g->blocks;
binfo->start = lno;
binfo->value_block[0] = tno;
binfo->first_free = 1;
binfo->zeroes--;
} }
else if (is_dense(binfo)) else if (is_dense(binfo))
{ {
assert(binfo->start <= lno); assert(binfo->start <= lno);
if (lno < binfo->start + L2G_BLOCKSIZE) if (lno < binfo->start + L2G_BLOCKSIZE)
{ {
/* The number can be entered into this block. */
while (binfo->start + binfo->first_free <= lno) while (binfo->start + binfo->first_free <= lno)
{
binfo->value_block[binfo->first_free++] = 0; binfo->value_block[binfo->first_free++] = 0;
assert(binfo->first_free <= L2G_BLOCKSIZE);
}
assert(lno < binfo->start + binfo->first_free); assert(lno < binfo->start + binfo->first_free);
assert(binfo->first_free < L2G_BLOCKSIZE); assert(binfo->first_free <= L2G_BLOCKSIZE);
if (binfo->value_block[lno - binfo->start] == 0) if (binfo->value_block[lno - binfo->start] == 0)
binfo->zeroes--; binfo->zeroes--;
...@@ -761,7 +818,13 @@ l2g_expensive_set(Local_to_global *l2g, ...@@ -761,7 +818,13 @@ l2g_expensive_set(Local_to_global *l2g,
{ {
/* There is no room within this block. Insert a new block /* There is no room within this block. Insert a new block
after binfo. */ after binfo. */
FIXME; block_no = 1 + binfo - l2g->blocks;
add_block_before(l2g, block_no);
binfo = l2g->blocks + block_no;
binfo->start = lno;
binfo->value_block[0] = tno;
binfo->first_free = 1;
binfo->zeroes--;
} }
} }
else else
...@@ -769,6 +832,7 @@ l2g_expensive_set(Local_to_global *l2g, ...@@ -769,6 +832,7 @@ l2g_expensive_set(Local_to_global *l2g,
ix = sparse_locate_value(binfo, lno); ix = sparse_locate_value(binfo, lno);
if (ix < binfo->first_free && binfo->key_block[ix] == lno) if (ix < binfo->first_free && binfo->key_block[ix] == lno)
{ {
/* We found the value in this sparse block. */
assert(binfo->value_block[ix] != 0); assert(binfo->value_block[ix] != 0);
binfo->value_block[ix] = tno; binfo->value_block[ix] = tno;
} }
...@@ -776,25 +840,48 @@ l2g_expensive_set(Local_to_global *l2g, ...@@ -776,25 +840,48 @@ l2g_expensive_set(Local_to_global *l2g,
{ {
if (binfo->zeroes == 0) if (binfo->zeroes == 0)
{ {
/* Split the block to make room. */ /* Split the sparse block to make room. */
FIXME; /* IF lno > [the greatest value in the block_no = 1 + binfo - l2g->blocks;
block] THEN create a new empty add_block_before(l2g, block_no);
block and let binfo point to it binfo = l2g->blocks + block_no;
ELSE move the final lno into the
new block and let binfo point to assert(binfo[-1].first_free == L2G_BLOCKSIZE);
the old block, that now contains an
empty slot ENDIF. The ordo for if (lno > binfo[-1].key_block[L2G_BLOCKSIZE-1])
this is not good when we do many {
worst-case insertions, but that is /* Insert the mapping into the new block. */
alright, since this function is binfo->start = lno;
only used for disaster recovery. */ binfo->value_block[0] = tno;
binfo->first_free = 1;
assert(binfo->zeroes == 1 || binfo->first_free == 0); binfo->zeroes--;
return;
}
else
{
/* Move the last mapping from the block into the new block,
and enter the new mapping into the old block. */
/* Set up the new block. */
binfo->start = binfo[-1].key_block[L2G_BLOCKSIZE-1];
binfo->value_block[0] = binfo[-1].value_block[
L2G_BLOCKSIZE-1];
binfo->first_free = 1;
binfo->zeroes--;
/* Fix the old block. */
binfo--;
binfo->zeroes++;
binfo->first_free--;
/* The old block is now compact. Let the code below
enter the new mapping into it. */
}
assert(binfo->zeroes == 1);
} }
else else
sparse_compact(binfo); sparse_compact(binfo);
/* There is room for a new mapping in this block. */ /* There is room for a new mapping in this block. */
assert(binfo->zeroes > 0);
for (ix = binfo->first_free; ix > 0; --ix) for (ix = binfo->first_free; ix > 0; --ix)
{ {
assert(binfo->key_block[ix-1] != lno); assert(binfo->key_block[ix-1] != lno);
...@@ -817,7 +904,6 @@ l2g_expensive_set(Local_to_global *l2g, ...@@ -817,7 +904,6 @@ l2g_expensive_set(Local_to_global *l2g,
} }
} }
} }
#endif
/* /*
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment