Added in storage of the key at the hash instead of as part of the value
rkinyon [Thu, 30 Nov 2006 03:58:40 +0000 (03:58 +0000)]
lib/DBM/Deep/Engine3.pm
t/02_hash.t

index 6c4341b..062ab8d 100644 (file)
@@ -28,9 +28,6 @@ sub SIG_FREE     () { 'F'    }
 sub SIG_KEYS     () { 'K'    }
 sub SIG_SIZE     () {  1     }
 
-# This is the transaction ID for the HEAD
-sub HEAD () { 0 }
-
 ################################################################################
 
 # Please refer to the pack() documentation for further information
@@ -107,16 +104,15 @@ sub read_value {
     my ($trans_id, $base_offset, $key) = @_;
 
     # This will be a Reference sector
-    my $sector = $self->_load_sector( $base_offset );
-    die "How did this fail (no sector for '$base_offset')?!\n" unless $sector;
+    my $sector = $self->_load_sector( $base_offset )
+        or die "How did this fail (no sector for '$base_offset')?!\n";
 
     my $key_md5 = $self->_apply_digest( $key );
 
     # XXX What should happen if this fails?
     my $blist = $sector->get_bucket_list({
         key_md5 => $key_md5,
-    });
-    die "How did this fail (no blist)?!\n" unless $blist;
+    }) or die "How did this fail (no blist)?!\n";
 
     my $value_sector = $blist->get_data_for( $key_md5 );
     return if ! $value_sector;
@@ -129,16 +125,15 @@ sub key_exists {
     my ($trans_id, $base_offset, $key) = @_;
 
     # This will be a Reference sector
-    my $sector = $self->_load_sector( $base_offset );
-    die "How did this fail (no sector for '$base_offset')?!\n" unless $sector;
+    my $sector = $self->_load_sector( $base_offset )
+        or die "How did this fail (no sector for '$base_offset')?!\n";
 
     my $key_md5 = $self->_apply_digest( $key );
 
     # XXX What should happen if this fails?
     my $blist = $sector->get_bucket_list({
         key_md5 => $key_md5,
-    });
-    die "How did this fail (no blist)?!\n" unless $blist;
+    }) or die "How did this fail (no blist)?!\n";
 
     # exists() returns 1 or '' for true/false.
     return $blist->has_md5( $key_md5 ) ? 1 : '';
@@ -148,16 +143,15 @@ sub delete_key {
     my $self = shift;
     my ($trans_id, $base_offset, $key) = @_;
 
-    my $sector = $self->_load_sector( $base_offset );
-    die "How did this fail (no sector for '$base_offset')?!\n" unless $sector;
+    my $sector = $self->_load_sector( $base_offset )
+        or die "How did this fail (no sector for '$base_offset')?!\n";
 
     my $key_md5 = $self->_apply_digest( $key );
 
     # XXX What should happen if this fails?
     my $blist = $sector->get_bucket_list({
         key_md5 => $key_md5,
-    });
-    die "How did this fail (no blist)?!\n" unless $blist;
+    }) or die "How did this fail (no blist)?!\n";
 
     return $blist->delete_md5( $key_md5 );
 }
@@ -167,8 +161,8 @@ sub write_value {
     my ($trans_id, $base_offset, $key, $value) = @_;
 
     # This will be a Reference sector
-    my $sector = $self->_load_sector( $base_offset );
-    die "How did this fail (no sector for '$base_offset')?!\n" unless $sector;
+    my $sector = $self->_load_sector( $base_offset )
+        or die "How did this fail (no sector for '$base_offset')?!\n";
 
     my $key_md5 = $self->_apply_digest( $key );
 
@@ -176,29 +170,61 @@ sub write_value {
     my $blist = $sector->get_bucket_list({
         key_md5 => $key_md5,
         create  => 1,
-    });
-    die "How did this fail (no blist)?!\n" unless $blist;
+    }) or die "How did this fail (no blist)?!\n";
 
-    my $value_sector;
+    my $class;
     if ( !defined $value ) {
-        $value_sector = DBM::Deep::Engine::Sector::Null->new({
-            engine => $self,
-            data   => $value,
-        });
+        $class = 'DBM::Deep::Engine::Sector::Null';
     }
     else {
-        $value_sector = DBM::Deep::Engine::Sector::Scalar->new({
-            engine => $self,
-            data   => $value,
-        });
+        $class = 'DBM::Deep::Engine::Sector::Scalar';
     }
 
-    $blist->write_md5( $key_md5, $value_sector->offset );
+    my $value_sector = $class->new({
+        engine => $self,
+        data   => $value,
+    });
+
+    $blist->write_md5( $key_md5, $key, $value_sector->offset );
 }
 
 sub get_next_key {
     my $self = shift;
     my ($trans_id, $base_offset) = @_;
+
+    # This will be a Reference sector
+    my $sector = $self->_load_sector( $base_offset )
+        or die "How did this fail (no sector for '$base_offset')?!\n";
+
+    return;
+
+    # This is FIRSTKEY
+    if ( @_ == 2 ) {
+#        my $blist = $sector->get_bucket_list({
+#            key_md5 => $key_md5,
+#        }) or die "How did this fail (no blist)?!\n";
+#        
+#        return $blist->get_key_for_idx( 0 );
+    }
+
+    # This is NEXTKEY
+
+    my $temp;
+    if ( @_ > 2 ) {
+        $temp = {
+            prev_md5    => $self->_apply_digest($_[2]),
+            return_next => 0,
+        };
+    }
+    else {
+        $temp = {
+            prev_md5    => $self->blank_md5,
+            return_next => 1,
+        };
+    }
+
+    #return $self->traverse_index( $temp, $_val_offset, 0 );
+    return;
 }
 
 ################################################################################
@@ -507,6 +533,7 @@ sub get_blist_loc {
 sub get_bucket_list {
     my $self = shift;
     my ($args) = @_;
+    $args ||= {};
 
     # XXX Add in check here for recycling?
 
@@ -533,10 +560,21 @@ sub get_bucket_list {
     });
 }
 
+sub get_first_key {
+    my $self = shift;
+
+    my $blist = $self->get_bucket_list();
+}
+
+sub get_key_after {
+}
+
 package DBM::Deep::Engine::Sector::BucketList;
 
 our @ISA = qw( DBM::Deep::Engine::Sector );
 
+sub idx_for_txn { return $_[1] + 1 }
+
 sub _init {
     my $self = shift;
 
@@ -560,15 +598,16 @@ sub base_size { 2 } # Sig + recycled counter
 
 sub size {
     my $self = shift;
-    my $engine = $self->engine;
-    return $self->base_size + $engine->max_buckets * $self->bucket_size; # Base + numbuckets * bucketsize
+    my $e = $self->engine;
+    return $self->base_size + $e->max_buckets * $self->bucket_size; # Base + numbuckets * bucketsize
 }
 
 sub bucket_size {
     my $self = shift;
     my $e = $self->engine;
-    my $locs_size = $e->num_txns * $e->byte_size; # Pointer to data with magic values to indicate status
-    return $e->hash_size + $locs_size;       # Hash + txn holders
+    # Key + transactions
+    my $locs_size = (1 + $e->num_txns ) * $e->byte_size;
+    return $e->hash_size + $locs_size;
 }
 
 sub has_md5 {
@@ -581,7 +620,6 @@ sub find_md5 {
     my $self = shift;
     my ($md5) = @_;
 
-    # Make sure we don't hit the fencepost error
     foreach my $idx ( 0 .. $self->engine->max_buckets - 1 ) {
         my $potential = $self->engine->storage->read_at(
             $self->offset + $self->base_size + $idx * $self->bucket_size, $self->engine->hash_size,
@@ -596,12 +634,25 @@ sub find_md5 {
 
 sub write_md5 {
     my $self = shift;
-    my ($md5, $value_loc) = @_;
+    my ($md5, $key, $value_loc) = @_;
 
     my $engine = $self->engine;
     my ($found, $idx) = $self->find_md5( $md5 );
-    $engine->storage->print_at( $self->offset + $self->base_size + $idx * $self->bucket_size,
-        $md5,                                         # The actual MD5
+    my $spot = $self->offset + $self->base_size + $idx * $self->bucket_size;
+
+    unless ($found) {
+        my $key_sector = DBM::Deep::Engine::Sector::Scalar->new({
+            engine => $self->engine,
+            data   => $key,
+        });
+
+        $engine->storage->print_at( $spot,
+            $md5,
+            $key_sector->offset,
+        );
+    }
+
+    $engine->storage->print_at( $spot + $self->engine->hash_size + $self->engine->byte_size,
         pack( $StP{$engine->byte_size}, $value_loc ), # The pointer to the data in the HEAD
     );
 }
@@ -613,10 +664,17 @@ sub delete_md5 {
     my $engine = $self->engine;
     my ($found, $idx) = $self->find_md5( $md5 );
     return 1 unless $found;
+
+    # Save the location so that we can free the data
     my $location = $self->get_location_for( $idx );
-    $engine->storage->print_at( $self->offset + $self->base_size + $idx * $self->bucket_size,
-        $self->engine->blank_md5,            # The blank MD5
-        pack( $StP{$engine->byte_size}, 0 ), # The pointer to the data in the HEAD
+
+    my $spot = $self->offset + $self->base_size + $idx * $self->bucket_size;
+    $engine->storage->print_at( $spot,
+        $engine->storage->read_at(
+            $spot + $self->bucket_size,
+            $self->bucket_size * ( $engine->num_txns - $idx - 1 ),
+        ),
+        chr(0) x $self->bucket_size,
     );
 
     return 1;
@@ -627,7 +685,8 @@ sub get_location_for {
     my ($idx) = @_;
 
     my $location = $self->engine->storage->read_at(
-        $self->offset + $self->base_size + $idx * $self->bucket_size + $self->engine->hash_size, $self->engine->byte_size,
+        $self->offset + $self->base_size + $idx * $self->bucket_size + $self->engine->hash_size + $self->engine->byte_size,
+        $self->engine->byte_size,
     );
     return unpack( $StP{$self->engine->byte_size}, $location );
 }
index 19e26de..5a6673e 100644 (file)
@@ -46,13 +46,13 @@ TODO: {
 
 delete $db->{key4};
 ok( !exists $db->{key4}, "And key4 doesn't exists anymore" );
-__END__
+
 ##
 # count keys
 ##
 
 is( scalar keys %$db, 3, "keys() works against tied hash" );
-
+__END__
 ##
 # step through keys
 ##