Added 16 bytes to the header prepping for transaction staleness counters
rkinyon [Thu, 21 Dec 2006 05:39:15 +0000 (05:39 +0000)]
lib/DBM/Deep/Engine3.pm

index 15a8022..524bf09 100644 (file)
@@ -319,14 +319,14 @@ sub begin_work {
         DBM::Deep->_throw_error( "Cannot begin_work within a transaction" );
     }
 
-    my @slots = $self->read_transaction_slots;
+    my @slots = $self->read_txn_slots;
     for my $i ( 1 .. @slots ) {
         next if $slots[$i];
         $slots[$i] = 1;
         $self->set_trans_id( $i );
         last;
     }
-    $self->write_transaction_slots( @slots );
+    $self->write_txn_slots( @slots );
 
     if ( !$self->trans_id ) {
         DBM::Deep->_throw_error( "Cannot begin_work - no available transactions" );
@@ -363,9 +363,9 @@ sub rollback {
 
     $self->clear_entries;
 
-    my @slots = $self->read_transaction_slots;
+    my @slots = $self->read_txn_slots;
     $slots[$self->trans_id] = 0;
-    $self->write_transaction_slots( @slots );
+    $self->write_txn_slots( @slots );
     $self->set_trans_id( 0 );
 
     return 1;
@@ -406,26 +406,36 @@ sub commit {
 
     $self->clear_entries;
 
-    my @slots = $self->read_transaction_slots;
+    my @slots = $self->read_txn_slots;
     $slots[$self->trans_id] = 0;
-    $self->write_transaction_slots( @slots );
+    $self->write_txn_slots( @slots );
     $self->set_trans_id( 0 );
 
     return 1;
 }
 
-sub read_transaction_slots {
+sub read_txn_slots {
     my $self = shift;
-    return split '', unpack( "b32", $self->storage->read_at( $self->trans_loc, 4 ) );
+    return split '', unpack( 'b32',
+        $self->storage->read_at(
+            $self->trans_loc, 4,
+        )
+    );
 }
 
-sub write_transaction_slots {
+sub write_txn_slots {
     my $self = shift;
     $self->storage->print_at( $self->trans_loc,
-        pack( "b32", join('', @_) ),
+        pack( 'b32', join('', @_) ),
     );
 }
 
+sub get_running_txn_ids {
+    my $self = shift;
+    my @transactions = $self->read_txn_slots;
+    my @trans_ids = grep { $transactions[$_] } 0 .. $#transactions;
+}
+
 sub get_entries {
     my $self = shift;
     return [ keys %{ $self->{entries}{$self->trans_id} ||= {} } ];
@@ -455,7 +465,7 @@ sub clear_entries {
     sub _write_file_header {
         my $self = shift;
 
-        my $header_var = 1 + 1 + 4 + 2 * $self->byte_size;
+        my $header_var = 1 + 1 + 4 + 4 * $self->num_txns + 2 * $self->byte_size;
 
         my $loc = $self->storage->request_space( $header_fixed + $header_var );
 
@@ -467,13 +477,14 @@ sub clear_entries {
             # --- Above is $header_fixed. Below is $header_var
             pack('C', $self->byte_size),
             pack('C', $self->max_buckets),
-            pack('N', 0 ),                   # Running transactions
+            pack('N', 0 ),                   # Transaction cctiveness bitfield
+            pack('N' . $self->num_txns, 0 ), # Transaction staleness counters
             pack($StP{$self->byte_size}, 0), # Start of free chain (blist size)
             pack($StP{$self->byte_size}, 0), # Start of free chain (data size)
         );
 
         $self->set_trans_loc( $header_fixed + 2 );
-        $self->set_chains_loc( $header_fixed + 6 );
+        $self->set_chains_loc( $header_fixed + 2 + 4 + 4 * $self->num_txns );
 
         return;
     }
@@ -502,7 +513,7 @@ sub clear_entries {
         my @values = unpack( 'C C', $buffer2 );
 
         $self->set_trans_loc( $header_fixed + 2 );
-        $self->set_chains_loc( $header_fixed + 6 );
+        $self->set_chains_loc( $header_fixed + 2 + 4 + 4 * $self->num_txns );
 
         if ( @values < 2 || grep { !defined } @values ) {
             $self->storage->close;
@@ -512,7 +523,7 @@ sub clear_entries {
         #XXX Add warnings if values weren't set right
         @{$self}{qw(byte_size max_buckets)} = @values;
 
-        my $header_var = 1 + 1 + 4 + 2 * $self->byte_size;
+        my $header_var = 1 + 1 + 4 + 4 * $self->num_txns + 2 * $self->byte_size;
         unless ( $size eq $header_var ) {
             $self->storage->close;
             DBM::Deep->_throw_error( "Unexpected size found ($size <-> $header_var)." );
@@ -984,8 +995,7 @@ sub write_data {
         }
     }
     else {
-        my @transactions = $self->engine->read_transaction_slots;
-        my @trans_ids = grep { $transactions[$_] } 0 .. $#transactions;
+        my @trans_ids = $self->engine->get_running_txn_ids;
         if ( $blist->{found} ) {
             if ( @trans_ids ) {
                 my $old_value = $blist->get_data_for;
@@ -1042,8 +1052,7 @@ sub delete_key {
     my $old_value = $location && $self->engine->_load_sector( $location );
 
     if ( $self->engine->trans_id == 0 ) {
-        my @transactions = $self->engine->read_transaction_slots;
-        my @trans_ids = grep { $transactions[$_] } 0 .. $#transactions;
+        my @trans_ids = $self->engine->get_running_txn_ids;
         if ( @trans_ids ) {
             foreach my $other_trans_id ( @trans_ids ) {
                 next if $blist->get_data_location_for({ trans_id => $other_trans_id, allow_head => 0 });