[1070] in Coldmud discussion meeting
[COLD] Final patch (that's take 2)
daemon@ATHENA.MIT.EDU (Mon Aug 19 21:02:28 1996
)
Date: Tue, 20 Aug 1996 02:24:35 +0200 (MET DST)
From: Miroslav Silovic <silovic@public.srce.hr>
To: coldstuff@cold.org
I fixed allocated_blocks here, and tested again (rather heavy-duty
test, so I tend to take this version of binarydb.c as reliable). The
fragmentation remained under 40% (about 1/3 of the blocks were free
when it stabilized, which means that the Scott's group should remain
under 18MB after the initial growth). This is about as good as
standard [gn]dbm does. It should perform better in certain cases (like
when most of the objects don't get changed too often, or when there
are not too much size variations). I tested what I think is the worst
case.
-----------------------------------------------------------------
*** binarydb.c Sat Jul 13 21:32:17 1996
--- ../../../Genesis-1.0p10/src/binarydb.c Tue Aug 20 02:18:30 1996
***************
*** 325,334 ****
if (fseek(dump_db_file, BLOCK_OFFSET (start), SEEK_SET))
panic("fseek(\"%s\") in copy: %s", dump_db_file, strerror(errno));
! for (i=0; i<blocks; i+=16) {
fread (buf, 1, BLOCK_SIZE, database_file);
fwrite (buf, 1, BLOCK_SIZE, dump_db_file);
! dump_bitmap[i >> 3] &= ~(1 << (i&7));
}
}
--- 325,334 ----
if (fseek(dump_db_file, BLOCK_OFFSET (start), SEEK_SET))
panic("fseek(\"%s\") in copy: %s", dump_db_file, strerror(errno));
! for (i=0; i<blocks; i++) {
fread (buf, 1, BLOCK_SIZE, database_file);
fwrite (buf, 1, BLOCK_SIZE, dump_db_file);
! dump_bitmap[(start+i) >> 3] &= ~(1 << ((start+i)&7));
}
}
***************
*** 453,458 ****
--- 453,459 ----
if (count == blocks_needed) {
/* Mark these blocks taken and return the starting block. */
+ allocated_blocks+=count;
for (b = starting_block; b < starting_block + count; b++)
bitmap[b >> 3] |= (1 << (b & 7));
last_free = b;
***************
*** 480,500 ****
return 1;
}
Int db_put(Obj *obj, Long objnum)
{
off_t old_offset, new_offset;
! Int old_size, new_size = size_object(obj);
db_is_dirty();
-
if (lookup_retrieve_objnum(objnum, &old_offset, &old_size)) {
! if (NEEDED(new_size, BLOCK_SIZE) > NEEDED(old_size, BLOCK_SIZE)) {
! db_unmark(LOGICAL_BLOCK(old_offset), old_size);
! new_offset = BLOCK_OFFSET(db_alloc(new_size));
! } else {
if (dump_db_file)
! dump_copy (LOGICAL_BLOCK(old_offset),
! NEEDED(old_size, BLOCK_SIZE));
new_offset = old_offset;
}
} else {
--- 481,529 ----
return 1;
}
+ Int check_free_blocks(Int blocks_needed, Int b)
+ {
+ Int count;
+
+ if (b >= bitmap_blocks)
+ return 0;
+ for (count = 0; count < blocks_needed; count++) {
+ if (bitmap[b >> 3] & (1 << (b & 7)))
+ break;
+ b++;
+ if (b >= bitmap_blocks)
+ break;
+ }
+ return count == blocks_needed;
+ }
+
Int db_put(Obj *obj, Long objnum)
{
off_t old_offset, new_offset;
! Int old_size, new_size = size_object(obj), tmp1, tmp2;
db_is_dirty();
if (lookup_retrieve_objnum(objnum, &old_offset, &old_size)) {
! if ((tmp1=NEEDED(new_size, BLOCK_SIZE)) > (tmp2=NEEDED(old_size, BLOCK_SIZE))) {
! /* check for the possible realloc */
! if (check_free_blocks(tmp1 - tmp2, LOGICAL_BLOCK(old_offset)+tmp2)) {
! /* no, we don't have to move, just overwrite */
! if (dump_db_file)
! dump_copy (LOGICAL_BLOCK(old_offset), tmp1);
! db_mark(LOGICAL_BLOCK(old_offset) + tmp2,
! BLOCK_SIZE * (tmp1 - tmp2));
! new_offset = old_offset;
! } else {
! db_unmark(LOGICAL_BLOCK(old_offset), old_size);
! new_offset = BLOCK_OFFSET(db_alloc(new_size));
! }
! } else {
if (dump_db_file)
! dump_copy (LOGICAL_BLOCK(old_offset), tmp2);
! if (tmp1 < tmp2) {
! db_unmark(LOGICAL_BLOCK(old_offset) + tmp1,
! BLOCK_SIZE * (tmp2 - tmp1));
! }
new_offset = old_offset;
}
} else {