r14235@Rob-Kinyons-PowerBook: rob | 2006-06-14 22:24:47 -0400
rkinyon [Thu, 15 Jun 2006 20:06:06 +0000 (20:06 +0000)]
 Moving further along

lib/DBM/Deep.pm
lib/DBM/Deep/Engine.pm
lib/DBM/Deep/Engine2.pm
lib/DBM/Deep/Hash.pm

index aa23179..97a592f 100644 (file)
@@ -492,7 +492,7 @@ sub STORE {
         $value = $self->_storage->{filter_store_value}->( $value );
     }
 
-    $self->_engine->write_value( $self->_base_offset, $key, $value, $orig_key );
+    $self->_engine->write_value( $self->_storage->transaction_id, $self->_base_offset, $key, $value, $orig_key );
 
     $self->unlock();
 
@@ -512,7 +512,7 @@ sub FETCH {
     ##
     $self->lock( LOCK_SH );
 
-    my $result = $self->_engine->read_value( $self->_base_offset, $key, $orig_key );
+    my $result = $self->_engine->read_value( $self->_storage->transaction_id, $self->_base_offset, $key, $orig_key );
 
     $self->unlock();
 
@@ -553,7 +553,7 @@ sub DELETE {
     ##
     # Delete bucket
     ##
-    my $value = $self->_engine->delete_key( $self->_base_offset, $key, $orig_key );
+    my $value = $self->_engine->delete_key( $self->_storage->transaction_id, $self->_base_offset, $key, $orig_key );
 
     if (defined $value && !ref($value) && $self->_storage->{filter_fetch_value}) {
         $value = $self->_storage->{filter_fetch_value}->($value);
@@ -576,7 +576,7 @@ sub EXISTS {
     ##
     $self->lock( LOCK_SH );
 
-    my $result = $self->_engine->key_exists( $self->_base_offset, $key );
+    my $result = $self->_engine->key_exists( $self->_storage->transaction_id, $self->_base_offset, $key );
 
     $self->unlock();
 
@@ -616,14 +616,14 @@ sub CLEAR {
         while ( $key ) {
             # Retrieve the key before deleting because we depend on next_key
             my $next_key = $self->next_key( $key );
-            $self->_engine->delete_key( $self->_base_offset, $key, $key );
+            $self->_engine->delete_key( $self->_storage->transaction_id, $self->_base_offset, $key, $key );
             $key = $next_key;
         }
     }
     else {
         my $size = $self->FETCHSIZE;
         for my $key ( 0 .. $size - 1 ) {
-            $self->_engine->delete_key( $self->_base_offset, $key, $key );
+            $self->_engine->delete_key( $self->_storage->transaction_id, $self->_base_offset, $key, $key );
         }
         $self->STORESIZE( 0 );
     }
index 73917a4..c430e6d 100644 (file)
@@ -48,18 +48,18 @@ sub HEAD () { 0 }
 
 sub read_value {
     my $self = shift;
-    my ($offset, $key, $orig_key) = @_;
+    my ($trans_id, $offset, $key, $orig_key) = @_;
 
-    my $dig_key = $self->apply_digest( $key );
+    my $dig_key = $self->_apply_digest( $key );
     my $tag = $self->find_blist( $offset, $dig_key ) or return;
     return $self->get_bucket_value( $tag, $dig_key, $orig_key );
 }
 
 sub key_exists {
     my $self = shift;
-    my ($offset, $key) = @_;
+    my ($trans_id, $offset, $key) = @_;
 
-    my $dig_key = $self->apply_digest( $key );
+    my $dig_key = $self->_apply_digest( $key );
     # exists() returns the empty string, not undef
     my $tag = $self->find_blist( $offset, $dig_key ) or return '';
     return $self->bucket_exists( $tag, $dig_key, $key );
@@ -67,14 +67,14 @@ sub key_exists {
 
 sub get_next_key {
     my $self = shift;
-    my ($offset) = @_;
+    my ($trans_id, $offset) = @_;
 
     # If the previous key was not specifed, start at the top and
     # return the first one found.
     my $temp;
-    if ( @_ > 1 ) {
+    if ( @_ > 2 ) {
         $temp = {
-            prev_md5    => $self->apply_digest($_[1]),
+            prev_md5    => $self->_apply_digest($_[2]),
             return_next => 0,
         };
     }
@@ -90,9 +90,9 @@ sub get_next_key {
 
 sub delete_key {
     my $self = shift;
-    my ($offset, $key, $orig_key) = @_;
+    my ($trans_id, $offset, $key, $orig_key) = @_;
 
-    my $dig_key = $self->apply_digest( $key );
+    my $dig_key = $self->_apply_digest( $key );
     my $tag = $self->find_blist( $offset, $dig_key ) or return;
     my $value = $self->get_bucket_value( $tag, $dig_key, $orig_key );
     $self->delete_bucket( $tag, $dig_key, $orig_key );
@@ -101,9 +101,9 @@ sub delete_key {
 
 sub write_value {
     my $self = shift;
-    my ($offset, $key, $value, $orig_key) = @_;
+    my ($trans_id, $offset, $key, $value, $orig_key) = @_;
 
-    my $dig_key = $self->apply_digest( $key );
+    my $dig_key = $self->_apply_digest( $key );
     my $tag = $self->find_blist( $offset, $dig_key, { create => 1 } );
     return $self->add_bucket( $tag, $dig_key, $key, $value, undef, $orig_key );
 }
@@ -174,7 +174,7 @@ sub new {
 
 sub _storage { return $_[0]{storage} }
 
-sub apply_digest {
+sub _apply_digest {
     my $self = shift;
     return $self->{digest}->(@_);
 }
index 9940165..bdeb0f1 100644 (file)
@@ -227,12 +227,18 @@ sub write_value {
         }
     }
 
-    #XXX Write this
-    $self->_write_value({
-        tag    => $key_tag,
-        value  => $value,
+    my $value_loc = $self->_storage->request_space( 
+        $self->_length_needed( $value, $key ),
+    );
+
+    $self->_add_key_offset({
+        tag      => $key_tag,
+        trans_id => $trans_id,
+        loc      => $value_loc,
     });
 
+    $self->_write_value( $value_loc, $key, $value, $key );
+
     return 1;
 }
 
@@ -240,6 +246,8 @@ sub _find_value_offset {
     my $self = shift;
     my ($args) = @_;
 
+    use Data::Dumper;warn Dumper $args;
+
     my $key_tag = $self->load_tag( $args->{offset} );
 
     my @head;
@@ -269,8 +277,6 @@ sub _find_key_offset {
     my $bucket_tag = $self->load_tag( $args->{offset} )
         or $self->_throw_error( "INTERNAL ERROR - Cannot find tag" );
 
-    # $bucket_tag->{ref_loc} and $bucket_tag->{ch} are used in split_index()
-
     #XXX What happens when $ch >= $self->{hash_size} ??
     for (my $ch = 0; $bucket_tag->{signature} ne SIG_BLIST; $ch++) {
         my $num = ord substr($args->{key_md5}, $ch, 1);
@@ -322,18 +328,47 @@ sub _find_key_offset {
         return( $keytag_loc, $bucket_tag );
     }
     else {
+        my ($key, $subloc, $index);
         BUCKET:
         for ( my $i = 0; $i < $self->{max_buckets}; $i++ ) {
-            my ($key, $subloc) = $self->_get_key_subloc(
+            ($key, $subloc) = $self->_get_key_subloc(
                 $bucket_tag->{content}, $i,
             );
 
             next BUCKET if $subloc && $key ne $args->{key_md5};
-            #XXX Right here, I need to create a new value, if I can
-            return( $subloc, $bucket_tag );
+
+            # Keep track of where we are, in case we need to create a new
+            # entry.
+            $index = $i;
+            last;
         }
-        # Right here, it looks like split_index needs to happen
-        # What happens here?
+
+        # Either we have a subloc to return or we don't want to create a new
+        # entry. Either way, we need to return now.
+        return ($subloc, $bucket_tag) if $subloc || !$args->{create};
+
+        my $keytag_loc = $self->_storage->request_space(
+            $self->tag_size( $self->{keyloc_size} ),
+        );
+
+        # There's space left in this bucket
+        if ( defined $index ) {
+            substr( $bucket_tag->{content}, $index * $self->{key_size}, $self->{key_size} ) =
+                $args->{key_md5} . pack( "$self->{long_pack}", $keytag_loc );
+
+            $self->_storage->print_at( $bucket_tag->{offset}, $bucket_tag->{content} );
+        }
+        # We need to split the index
+        else {
+            $self->split_index( $bucket_tag, $args->{key_md5}, $keytag_loc );
+        }
+
+        $self->write_tag(
+            $keytag_loc, SIG_KEYS,
+            chr(0)x$self->{keyloc_size},
+        );
+
+        return( $keytag_loc, $bucket_tag );
     }
 
     return;
@@ -362,7 +397,7 @@ sub _mark_as_deleted {
             substr( $args->{tag}{content}, $i * $self->{key_size}, $self->{key_size} ) = pack(
                 "$self->{long_pack} C C",
                 $loc, $trans_id, 1,
-            )
+            );
         }
     }
 
@@ -419,11 +454,37 @@ sub _remove_key_offset {
     return 1;
 }
 
-sub _write_value {
+sub _add_key_offset {
     my $self = shift;
     my ($args) = @_;
 
+    my $is_changed;
+    for ( my $i = 0; $i < $self->{max_buckets}; $i++ ) {
+        my ($loc, $trans_id, $is_deleted) = unpack(
+            "$self->{long_pack} C C",
+            substr( $args->{tag}{content}, $i * $self->{key_size}, $self->{key_size} ),
+        );
 
+        if ( $trans_id == $args->{trans_id} || (!$loc && !$is_deleted) ) {
+            substr( $args->{tag}{content}, $i * $self->{key_size}, $self->{key_size} ) = pack(
+                "$self->{long_pack} C C",
+                $args->{loc}, $args->{trans_id}, 0,
+            );
+            $is_changed = 1;
+            last;
+        }
+    }
+
+    if ( $is_changed ) {
+        $self->_storage->print_at(
+            $args->{tag}{offset}, $args->{tag}{content},
+        );
+    }
+    else {
+        die "Why didn't _add_key_offset() change something?!\n";
+    }
+
+    return 1;
 }
 
 sub setup_fh {
index 65775b8..9ce962a 100644 (file)
@@ -92,7 +92,7 @@ sub FIRSTKEY {
        ##
        $self->lock( $self->LOCK_SH );
        
-       my $result = $self->_engine->get_next_key($self->_base_offset);
+       my $result = $self->_engine->get_next_key($self->_storage->transaction_id, $self->_base_offset);
        
        $self->unlock();
        
@@ -116,7 +116,7 @@ sub NEXTKEY {
        ##
        $self->lock( $self->LOCK_SH );
        
-       my $result = $self->_engine->get_next_key( $self->_base_offset, $prev_key );
+       my $result = $self->_engine->get_next_key( $self->_storage->transaction_id, $self->_base_offset, $prev_key );
        
        $self->unlock();