Added ability for ::File to read and write transaction ID
rkinyon [Tue, 11 Apr 2006 17:53:59 +0000 (17:53 +0000)]
lib/DBM/Deep/Engine.pm
lib/DBM/Deep/File.pm

index ddf16e4..df0b0e3 100644 (file)
@@ -9,6 +9,10 @@ use Fcntl qw( :DEFAULT :flock :seek );
 
 # File-wide notes:
 # * All the local($/,$\); are to protect read() and print() from -l.
+# * To add to bucket_size, make sure you modify the following:
+#   - calculate_sizes()
+#   - _get_key_subloc()
+#   - add_bucket() - where the buckets are printed
 
 ##
 # Setup file and tag signatures.  These should never change.
@@ -117,6 +121,8 @@ sub write_file_header {
         pack('S', $self->{max_buckets}),
     );
 
+    $self->_fileobj->set_transaction_offset( 13 );
+
     return;
 }
 
@@ -571,7 +577,7 @@ sub split_index {
     my $keys = $tag->{content}
              . $md5 . pack($self->{long_pack}, $newtag_loc)
                     . pack($self->{long_pack}, 0)  # size
-                    . pack($self->{long_pack}, 0); # transaction #
+                    . pack($self->{long_pack}, 0); # transaction ID
 
     my @newloc = ();
     BUCKET:
@@ -956,7 +962,7 @@ sub _get_key_subloc {
     my ($key, $subloc, $size, $transaction) = unpack(
         # This is 'a', not 'A'. Please read the pack() documentation for the
         # difference between the two and why it's important.
-        "a$self->{hash_size} $self->{long_pack} $self->{long_pack} $self->{long_pack}",
+        "a$self->{hash_size} $self->{long_pack}3",
         substr(
             $keys,
             ($idx * $self->{bucket_size}),
@@ -984,14 +990,16 @@ sub _find_in_buckets {
         my @rv = ($subloc, $i * $self->{bucket_size}, $size);
 
         unless ( $subloc ) {
-            return @zero if !$exact && @zero and $trans_id;
+            if ( !$exact && @zero and $trans_id ) {
+                @rv = ($zero[2], $zero[0] * $self->{bucket_size}, $zero[3]);
+            }
             return @rv;
         }
 
         next BUCKET if $key ne $md5;
 
         # Save off the HEAD in case we need it.
-        @zero = @rv if $transaction_id == 0;
+        @zero = ($i,$key,$subloc,$size,$transaction_id) if $transaction_id == 0;
 
         next BUCKET if $transaction_id != $trans_id;
 
index 2862ca5..f11a66a 100644 (file)
@@ -27,8 +27,8 @@ sub new {
         filter_fetch_key   => undef,
         filter_fetch_value => undef,
 
-        transaction_id     => 0,
-        transaction_offset => 0,
+        transaction_id        => 0,
+        transaction_offset    => 0,
     }, $class;
 
     # Grab the parameters we want to use
@@ -163,25 +163,76 @@ sub begin_transaction {
 
     my $fh = $self->{fh};
 
+    $self->lock;
+
+    seek( $fh, $self->{transaction_offset}, SEEK_SET );
+    my $buffer;
+    read( $fh, $buffer, 4 );
+    $buffer = unpack( 'N', $buffer );
+
+    for ( 1 .. 32 ) {
+        next if $buffer & (1 << ($_ - 1));
+        $self->{transaction_id} = $_;
+        $buffer &= (1 << $_);
+        last;
+    }
+
     seek( $fh, $self->{transaction_offset}, SEEK_SET );
+    print( $fh pack( 'N', $buffer ) );
 
-    $self->{transaction_id}++;
+    $self->unlock;
+
+    return $self->{transaction_id};
 }
 
 sub end_transaction {
     my $self = shift;
 
-#    seek( $fh, $self->{transaction_offset}, SEEK_SET );
+    my $fh = $self->{fh};
+
+    $self->lock;
+
+    seek( $fh, $self->{transaction_offset}, SEEK_SET );
+    my $buffer;
+    read( $fh, $buffer, 4 );
+    $buffer = unpack( 'N', $buffer );
+
+    # Unset $self->{transaction_id} bit
+
+    seek( $fh, $self->{transaction_offset}, SEEK_SET );
+    print( $fh pack( 'N', $buffer ) );
+
+    $self->unlock;
 
     $self->{transaction_id} = 0;
 }
 
-sub transaction_id {
+sub current_transactions {
     my $self = shift;
 
-    return $self->{transaction_id};
+    my $fh = $self->{fh};
+
+    $self->lock;
+
+    seek( $fh, $self->{transaction_offset}, SEEK_SET );
+    my $buffer;
+    read( $fh, $buffer, 4 );
+    $buffer = unpack( 'N', $buffer );
+
+    $self->unlock;
+
+    my @transactions;
+    for ( 1 .. 32 ) {
+        if ( $buffer & (1 << ($_ - 1)) ) {
+            push @transactions, $_;
+        }
+    }
+
+    return @transactions;
 }
 
+sub transaction_id { return $_[0]->{transaction_id} }
+
 #sub commit {
 #}