[1068] in Coldmud discussion meeting

root meeting help first previous next last

[COLD] binarydb.patch

daemon@ATHENA.MIT.EDU (Mon Aug 19 20:20:22 1996 )

Date: Tue, 20 Aug 1996 01:58:46 +0200 (MET DST)
From: Miroslav Silovic <silovic@public.srce.hr>
To: coldstuff@cold.org


This patch should prevent most of the wild db growth. It also fixes a
nasty database dumping bug.

 IMPORTANT NOTE: binarydb.c is critical part of the driver. When I
 tested this, allocated_blocks wasn't updated right. On the other
 hand, after 50,000 random object touches, there wasn't any db
 corruption. I suppose that means that the code is safe.

The patch follows:

--------------------------------------------------------------------

*** binarydb.c	Sat Jul 13 21:32:17 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));
      }
  }
  
***************
*** 456,461 ****
--- 456,463 ----
  	    for (b = starting_block; b < starting_block + count; b++)
  		bitmap[b >> 3] |= (1 << (b & 7));
  	    last_free = b;
+             /* printf ("Object alloc: %6d, total size: %6d allocated: %d\n",starting_block,bitmap_blocks,allocated_blocks);
+ 	    fflush (stdout); */
  	    return starting_block;
  	}
  
***************
*** 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 {
--- 482,530 ----
      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 {