Fixed the bug revealed by making bucketlists properly clean up after themselves
rkinyon [Thu, 27 Sep 2007 19:16:18 +0000 (19:16 +0000)]
lib/DBM/Deep/Engine.pm

index 00313d8..c5b3363 100644 (file)
@@ -564,8 +564,8 @@ sub get_txn_staleness_counter {
 
     return unpack( $StP{$STALE_SIZE},
         $self->storage->read_at(
-            $self->trans_loc + 4 + $STALE_SIZE * ($trans_id - 1),
-            4,
+            $self->trans_loc + $self->txn_bitfield_len + $STALE_SIZE * ($trans_id - 1),
+            $STALE_SIZE,
         )
     );
 }
@@ -578,7 +578,7 @@ sub inc_txn_staleness_counter {
     return unless $trans_id;
 
     $self->storage->print_at(
-        $self->trans_loc + 4 + $STALE_SIZE * ($trans_id - 1),
+        $self->trans_loc + $self->txn_bitfield_len + $STALE_SIZE * ($trans_id - 1),
         pack( $StP{$STALE_SIZE}, $self->get_txn_staleness_counter( $trans_id ) + 1 ),
     );
 }
@@ -893,12 +893,12 @@ sub _dump_file {
         'I' => DBM::Deep::Engine::Sector::Index->new({engine=>$self,offset=>1})->size,
     );
 
+    my $return = "";
     # Read the free sector chains
     my %sectors;
     foreach my $multiple ( 0 .. 2 ) {
-        my $chains_offset = $multiple * $self->byte_size;
-
-        my $old_loc = $self->chains_loc + $chains_offset;
+        $return .= "Chains($types{$multiple}):";
+        my $old_loc = $self->chains_loc + $multiple * $self->byte_size;
         while ( 1 ) {
             my $loc = unpack(
                 $StP{$self->byte_size},
@@ -912,10 +912,11 @@ sub _dump_file {
 
             $sectors{ $types{$multiple} }{ $loc } = undef;
             $old_loc = $loc + SIG_SIZE + $STALE_SIZE;
+            $return .= " $loc";
         }
+        $return .= $/;
     }
 
-    my $return = "";
     SECTOR:
     while ( $spot < $self->storage->{end} ) {
         # Read each sector in order.
@@ -931,7 +932,7 @@ sub _dump_file {
                 }
             }
 
-            die "Didn't find free sector for $spot in chains\n";
+            die "********\n$return\nDidn't find free sector for $spot in chains\n********\n";
         }
         else {
             $return .= sprintf "%08d: %s  %04d", $spot, $sector->type, $sector->size;
@@ -1497,6 +1498,8 @@ sub delete_key {
 
     my @trans_ids = $self->engine->get_running_txn_ids;
 
+    # If we're the HEAD and there are running txns, then we need to clone this value to the other
+    # transactions to preserve Isolation.
     if ( $self->engine->trans_id == 0 ) {
         if ( @trans_ids ) {
             foreach my $other_trans_id ( @trans_ids ) {
@@ -1655,6 +1658,7 @@ sub get_bucket_list {
             );
         }
 
+        $sector->clear;
         $sector->free;
 
         $sector = $blist_cache{ ord( substr( $args->{key_md5}, $i, 1 ) ) };
@@ -1789,6 +1793,13 @@ sub _init {
     return $self;
 }
 
+sub clear {
+    my $self = shift;
+    $self->engine->storage->print_at( $self->offset + $self->base_size,
+        chr(0) x ($self->size - $self->base_size), # Zero-fill the data
+    );
+}
+
 sub size {
     my $self = shift;
     unless ( $self->{size} ) {