r14186@rob-kinyons-powerbook58: rob | 2006-06-14 11:44:48 -0400
[dbsrgits/DBM-Deep.git] / lib / DBM / Deep / Engine.pm
index 54ec75d..73917a4 100644 (file)
@@ -16,7 +16,7 @@ use Scalar::Util ();
 #   - _get_key_subloc()
 #   - add_bucket() - where the buckets are printed
 #
-# * Every method in here assumes that the _fileobj has been appropriately
+# * Every method in here assumes that the _storage has been appropriately
 #   safeguarded. This can be anything from flock() to some sort of manual
 #   mutex. But, it's the caller's responsability to make sure that this has
 #   been done.
@@ -37,28 +37,55 @@ sub SIG_FREE     () { 'F'    }
 sub SIG_KEYS     () { 'K'    }
 sub SIG_SIZE     () {  1     }
 
+# This is the transaction ID for the HEAD
+sub HEAD () { 0 }
+
 ################################################################################
 #
 # This is new code. It is a complete rewrite of the engine based on a new API
 #
 ################################################################################
 
-sub write_value {
+sub read_value {
     my $self = shift;
-    my ($offset, $key, $value, $orig_key) = @_;
+    my ($offset, $key, $orig_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 );
+    my $tag = $self->find_blist( $offset, $dig_key ) or return;
+    return $self->get_bucket_value( $tag, $dig_key, $orig_key );
 }
 
-sub read_value {
+sub key_exists {
     my $self = shift;
-    my ($offset, $key, $orig_key) = @_;
+    my ($offset, $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 );
+    # 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 );
+}
+
+sub get_next_key {
+    my $self = shift;
+    my ($offset) = @_;
+
+    # If the previous key was not specifed, start at the top and
+    # return the first one found.
+    my $temp;
+    if ( @_ > 1 ) {
+        $temp = {
+            prev_md5    => $self->apply_digest($_[1]),
+            return_next => 0,
+        };
+    }
+    else {
+        $temp = {
+            prev_md5    => chr(0) x $self->{hash_size},
+            return_next => 1,
+        };
+    }
+
+    return $self->traverse_index( $temp, $offset, 0 );
 }
 
 sub delete_key {
@@ -72,21 +99,13 @@ sub delete_key {
     return $value;
 }
 
-sub key_exists {
+sub write_value {
     my $self = shift;
-    my ($offset, $key) = @_;
+    my ($offset, $key, $value, $orig_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 );
-}
-
-sub XXXget_next_key {
-    my $self = shift;
-    my ($offset, $prev_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 );
 }
 
 ################################################################################
@@ -116,7 +135,7 @@ sub new {
         ##
         max_buckets => 16,
 
-        fileobj => undef,
+        storage => undef,
         obj     => undef,
     }, $class;
 
@@ -153,7 +172,7 @@ sub new {
     return $self;
 }
 
-sub _fileobj { return $_[0]{fileobj} }
+sub _storage { return $_[0]{storage} }
 
 sub apply_digest {
     my $self = shift;
@@ -181,9 +200,9 @@ sub calculate_sizes {
 sub write_file_header {
     my $self = shift;
 
-    my $loc = $self->_fileobj->request_space( length( SIG_FILE ) + 33 );
+    my $loc = $self->_storage->request_space( length( SIG_FILE ) + 33 );
 
-    $self->_fileobj->print_at( $loc,
+    $self->_storage->print_at( $loc,
         SIG_FILE,
         SIG_HEADER,
         pack('N', 1),  # header version
@@ -196,7 +215,7 @@ sub write_file_header {
         pack('n', $self->{max_buckets}),
     );
 
-    $self->_fileobj->set_transaction_offset( 13 );
+    $self->_storage->set_transaction_offset( 13 );
 
     return;
 }
@@ -204,7 +223,7 @@ sub write_file_header {
 sub read_file_header {
     my $self = shift;
 
-    my $buffer = $self->_fileobj->read_at( 0, length(SIG_FILE) + 9 );
+    my $buffer = $self->_storage->read_at( 0, length(SIG_FILE) + 9 );
     return unless length($buffer);
 
     my ($file_signature, $sig_header, $header_version, $size) = unpack(
@@ -212,22 +231,22 @@ sub read_file_header {
     );
 
     unless ( $file_signature eq SIG_FILE ) {
-        $self->_fileobj->close;
+        $self->_storage->close;
         $self->_throw_error( "Signature not found -- file is not a Deep DB" );
     }
 
     unless ( $sig_header eq SIG_HEADER ) {
-        $self->_fileobj->close;
+        $self->_storage->close;
         $self->_throw_error( "Old file version found." );
     }
 
-    my $buffer2 = $self->_fileobj->read_at( undef, $size );
+    my $buffer2 = $self->_storage->read_at( undef, $size );
     my ($a1, $a2, $a3, $a4, @values) = unpack( 'N4 n A n A n', $buffer2 );
 
-    $self->_fileobj->set_transaction_offset( 13 );
+    $self->_storage->set_transaction_offset( 13 );
 
     if ( @values < 5 || grep { !defined } @values ) {
-        $self->_fileobj->close;
+        $self->_storage->close;
         $self->_throw_error("Corrupted file - bad header");
     }
 
@@ -242,7 +261,7 @@ sub setup_fh {
     my ($obj) = @_;
 
     # Need to remove use of $fh here
-    my $fh = $self->_fileobj->{fh};
+    my $fh = $self->_storage->{fh};
     flock $fh, LOCK_EX;
 
     #XXX The duplication of calculate_sizes needs to go away
@@ -255,11 +274,11 @@ sub setup_fh {
         # File is empty -- write header and master index
         ##
         if (!$bytes_read) {
-            $self->_fileobj->audit( "# Database created on" );
+            $self->_storage->audit( "# Database created on" );
 
             $self->write_file_header;
 
-            $obj->{base_offset} = $self->_fileobj->request_space(
+            $obj->{base_offset} = $self->_storage->request_space(
                 $self->tag_size( $self->{index_size} ),
             );
 
@@ -296,7 +315,7 @@ sub setup_fh {
     }
 
     #XXX We have to make sure we don't mess up when autoflush isn't turned on
-    $self->_fileobj->set_inode;
+    $self->_storage->set_inode;
 
     flock $fh, LOCK_UN;
 
@@ -317,7 +336,7 @@ sub write_tag {
     my ($offset, $sig, $content) = @_;
     my $size = length( $content );
 
-    $self->_fileobj->print_at(
+    $self->_storage->print_at(
         $offset, 
         $sig, pack($self->{data_pack}, $size), $content,
     );
@@ -340,25 +359,26 @@ sub load_tag {
     my $self = shift;
     my ($offset) = @_;
 
-    my $fileobj = $self->_fileobj;
+    my $storage = $self->_storage;
 
     my ($sig, $size) = unpack(
         "A $self->{data_pack}",
-        $fileobj->read_at( $offset, SIG_SIZE + $self->{data_size} ),
+        $storage->read_at( $offset, SIG_SIZE + $self->{data_size} ),
     );
 
     return {
         signature => $sig,
         size      => $size,   #XXX Is this even used?
+        start     => $offset,
         offset    => $offset + SIG_SIZE + $self->{data_size},
-        content   => $fileobj->read_at( undef, $size ),
+        content   => $storage->read_at( undef, $size ),
     };
 }
 
 sub find_keyloc {
     my $self = shift;
     my ($tag, $transaction_id) = @_;
-    $transaction_id = $self->_fileobj->transaction_id
+    $transaction_id = $self->_storage->transaction_id
         unless defined $transaction_id;
 
     for ( my $i = 0; $i < $self->{max_buckets}; $i++ ) {
@@ -367,13 +387,8 @@ sub find_keyloc {
             substr( $tag->{content}, $i * $self->{key_size}, $self->{key_size} ),
         );
 
-        if ( $loc == 0 ) {
-            return ( $loc, $is_deleted, $i * $self->{key_size} );
-        }
-
-        next if $transaction_id != $trans_id;
-
-        return ( $loc, $is_deleted, $i * $self->{key_size} );
+        next if $loc != HEAD && $transaction_id != $trans_id;
+        return( $loc, $is_deleted, $i * $self->{key_size} );
     }
 
     return;
@@ -400,14 +415,14 @@ sub add_bucket {
         );
     }
 
-    my $fileobj = $self->_fileobj;
+    my $storage = $self->_storage;
 
     #ACID - This is a mutation. Must only find the exact transaction
     my ($keyloc, $offset) = $self->_find_in_buckets( $tag, $md5, 1 );
 
     my @transactions;
-    if ( $fileobj->transaction_id == 0 ) {
-        @transactions = $fileobj->current_transactions;
+    if ( $storage->transaction_id == 0 ) {
+        @transactions = $storage->current_transactions;
     }
 
 #    $self->_release_space( $size, $subloc );
@@ -428,8 +443,8 @@ sub add_bucket {
             for my $trans_id ( @transactions ) {
                 my ($loc, $is_deleted, $offset2) = $self->find_keyloc( $keytag, $trans_id );
                 unless ($loc) {
-                    my $location2 = $fileobj->request_space( $old_size );
-                    $fileobj->print_at( $keytag->{offset} + $offset2,
+                    my $location2 = $storage->request_space( $old_size );
+                    $storage->print_at( $keytag->{offset} + $offset2,
                         pack($self->{long_pack}, $location2 ),
                         pack( 'C C', $trans_id, 0 ),
                     );
@@ -438,20 +453,20 @@ sub add_bucket {
             }
         }
 
-        $location = $self->_fileobj->request_space( $size );
+        $location = $self->_storage->request_space( $size );
         #XXX This needs to be transactionally-aware in terms of which keytag->{offset} to use
-        $fileobj->print_at( $keytag->{offset} + $offset,
+        $storage->print_at( $keytag->{offset} + $offset,
             pack($self->{long_pack}, $location ),
-            pack( 'C C', $fileobj->transaction_id, 0 ),
+            pack( 'C C', $storage->transaction_id, 0 ),
         );
     }
     # Adding a new md5
     else {
-        my $keyloc = $fileobj->request_space( $self->tag_size( $self->{keyloc_size} ) );
+        my $keyloc = $storage->request_space( $self->tag_size( $self->{keyloc_size} ) );
 
         # The bucket fit into list
         if ( defined $offset ) {
-            $fileobj->print_at( $tag->{offset} + $offset,
+            $storage->print_at( $tag->{offset} + $offset,
                 $md5, pack( $self->{long_pack}, $keyloc ),
             );
         }
@@ -464,15 +479,15 @@ sub add_bucket {
             $keyloc, SIG_KEYS, chr(0)x$self->{keyloc_size},
         );
 
-        $location = $self->_fileobj->request_space( $size );
-        $fileobj->print_at( $keytag->{offset},
+        $location = $self->_storage->request_space( $size );
+        $storage->print_at( $keytag->{offset},
             pack( $self->{long_pack}, $location ),
-            pack( 'C C', $fileobj->transaction_id, 0 ),
+            pack( 'C C', $storage->transaction_id, 0 ),
         );
 
         my $offset = 1;
         for my $trans_id ( @transactions ) {
-            $fileobj->print_at( $keytag->{offset} + $self->{key_size} * $offset++,
+            $storage->print_at( $keytag->{offset} + $self->{key_size} * $offset++,
                 pack( $self->{long_pack}, 0 ),
                 pack( 'C C', $trans_id, 1 ),
             );
@@ -488,10 +503,10 @@ sub _write_value {
     my $self = shift;
     my ($location, $key, $value, $orig_key) = @_;
 
-    my $fileobj = $self->_fileobj;
+    my $storage = $self->_storage;
 
     my $dbm_deep_obj = _get_dbm_object( $value );
-    if ( $dbm_deep_obj && $dbm_deep_obj->_fileobj ne $fileobj ) {
+    if ( $dbm_deep_obj && $dbm_deep_obj->_storage ne $storage ) {
         $self->_throw_error( "Cannot cross-reference. Use export() instead" );
     }
 
@@ -525,7 +540,7 @@ sub _write_value {
     ##
     # Plain key is stored AFTER value, as keys are typically fetched less often.
     ##
-    $fileobj->print_at( undef, pack($self->{data_pack}, length($key)) . $key );
+    $storage->print_at( undef, pack($self->{data_pack}, length($key)) . $key );
 
     # Internal references don't care about autobless
     return 1 if $dbm_deep_obj;
@@ -533,12 +548,12 @@ sub _write_value {
     ##
     # If value is blessed, preserve class name
     ##
-    if ( $fileobj->{autobless} ) {
+    if ( $storage->{autobless} ) {
         if ( defined( my $c = Scalar::Util::blessed($value) ) ) {
-            $fileobj->print_at( undef, chr(1), pack($self->{data_pack}, length($c)) . $c );
+            $storage->print_at( undef, chr(1), pack($self->{data_pack}, length($c)) . $c );
         }
         else {
-            $fileobj->print_at( undef, chr(0) );
+            $storage->print_at( undef, chr(0) );
         }
     }
 
@@ -554,21 +569,23 @@ sub _write_value {
         my %x = %$value;
         tie %$value, 'DBM::Deep', {
             base_offset => $location,
-            fileobj     => $fileobj,
+            storage     => $storage,
             parent      => $self->{obj},
             parent_key  => $orig_key,
         };
         %$value = %x;
+        bless $value, 'DBM::Deep::Hash' unless Scalar::Util::blessed( $value );
     }
     elsif ($r eq 'ARRAY') {
         my @x = @$value;
         tie @$value, 'DBM::Deep', {
             base_offset => $location,
-            fileobj     => $fileobj,
+            storage     => $storage,
             parent      => $self->{obj},
             parent_key  => $orig_key,
         };
         @$value = @x;
+        bless $value, 'DBM::Deep::Array' unless Scalar::Util::blessed( $value );
     }
 
     return 1;
@@ -578,13 +595,13 @@ sub split_index {
     my $self = shift;
     my ($tag, $md5, $keyloc) = @_;
 
-    my $fileobj = $self->_fileobj;
+    my $storage = $self->_storage;
 
-    my $loc = $fileobj->request_space(
+    my $loc = $storage->request_space(
         $self->tag_size( $self->{index_size} ),
     );
 
-    $fileobj->print_at( $tag->{ref_loc}, pack($self->{long_pack}, $loc) );
+    $storage->print_at( $tag->{ref_loc}, pack($self->{long_pack}, $loc) );
 
     my $index_tag = $self->write_tag(
         $loc, SIG_INDEX,
@@ -607,14 +624,14 @@ sub split_index {
         my $num = ord(substr($key, $tag->{ch} + 1, 1));
 
         if ($newloc[$num]) {
-            my $subkeys = $fileobj->read_at( $newloc[$num], $self->{bucket_list_size} );
+            my $subkeys = $storage->read_at( $newloc[$num], $self->{bucket_list_size} );
 
             # This is looking for the first empty spot
             my ($subloc, $offset) = $self->_find_in_buckets(
                 { content => $subkeys }, '',
             );
 
-            $fileobj->print_at(
+            $storage->print_at(
                 $newloc[$num] + $offset,
                 $key, pack($self->{long_pack}, $old_subloc),
             );
@@ -622,11 +639,11 @@ sub split_index {
             next;
         }
 
-        my $loc = $fileobj->request_space(
+        my $loc = $storage->request_space(
             $self->tag_size( $self->{bucket_list_size} ),
         );
 
-        $fileobj->print_at(
+        $storage->print_at(
             $index_tag->{offset} + ($num * $self->{long_size}),
             pack($self->{long_pack}, $loc),
         );
@@ -636,14 +653,14 @@ sub split_index {
             chr(0)x$self->{bucket_list_size},
         );
 
-        $fileobj->print_at( $blist_tag->{offset}, $key . pack($self->{long_pack}, $old_subloc) );
+        $storage->print_at( $blist_tag->{offset}, $key . pack($self->{long_pack}, $old_subloc) );
 
         $newloc[$num] = $blist_tag->{offset};
     }
 
     $self->_release_space(
         $self->tag_size( $self->{bucket_list_size} ),
-        $tag->{offset} - SIG_SIZE - $self->{data_size},
+        $tag->{start},
     );
 
     return 1;
@@ -653,43 +670,68 @@ sub read_from_loc {
     my $self = shift;
     my ($subloc, $orig_key) = @_;
 
-    my $fileobj = $self->_fileobj;
+    my $storage = $self->_storage;
 
-    my $signature = $fileobj->read_at( $subloc, SIG_SIZE );
+    my $signature = $storage->read_at( $subloc, SIG_SIZE );
 
     ##
     # If value is a hash or array, return new DBM::Deep object with correct offset
     ##
     if (($signature eq SIG_HASH) || ($signature eq SIG_ARRAY)) {
         #XXX This needs to be a singleton
+#        my $new_obj;
+#        my $is_autobless;
+#        if ( $signature eq SIG_HASH ) {
+#            $new_obj = {};
+#            tie %$new_obj, 'DBM::Deep', {
+#                base_offset => $subloc,
+#                storage     => $self->_storage,
+#                parent      => $self->{obj},
+#                parent_key  => $orig_key,
+#            };
+#            $is_autobless = tied(%$new_obj)->_storage->{autobless};
+#        }
+#        else {
+#            $new_obj = [];
+#            tie @$new_obj, 'DBM::Deep', {
+#                base_offset => $subloc,
+#                storage     => $self->_storage,
+#                parent      => $self->{obj},
+#                parent_key  => $orig_key,
+#            };
+#            $is_autobless = tied(@$new_obj)->_storage->{autobless};
+#        }
+#
+#        if ($is_autobless) {
+
         my $new_obj = DBM::Deep->new({
             type        => $signature,
             base_offset => $subloc,
-            fileobj     => $self->_fileobj,
+            storage     => $self->_storage,
             parent      => $self->{obj},
             parent_key  => $orig_key,
         });
 
-        if ($new_obj->_fileobj->{autobless}) {
+        if ($new_obj->_storage->{autobless}) {
             ##
             # Skip over value and plain key to see if object needs
             # to be re-blessed
             ##
-            $fileobj->increment_pointer( $self->{data_size} + $self->{index_size} );
+            $storage->increment_pointer( $self->{data_size} + $self->{index_size} );
 
-            my $size = $fileobj->read_at( undef, $self->{data_size} );
+            my $size = $storage->read_at( undef, $self->{data_size} );
             $size = unpack($self->{data_pack}, $size);
-            if ($size) { $fileobj->increment_pointer( $size ); }
+            if ($size) { $storage->increment_pointer( $size ); }
 
-            my $bless_bit = $fileobj->read_at( undef, 1 );
+            my $bless_bit = $storage->read_at( undef, 1 );
             if ( ord($bless_bit) ) {
                 my $size = unpack(
                     $self->{data_pack},
-                    $fileobj->read_at( undef, $self->{data_size} ),
+                    $storage->read_at( undef, $self->{data_size} ),
                 );
 
                 if ( $size ) {
-                    $new_obj = bless $new_obj, $fileobj->read_at( undef, $size );
+                    $new_obj = bless $new_obj, $storage->read_at( undef, $size );
                 }
             }
         }
@@ -697,11 +739,11 @@ sub read_from_loc {
         return $new_obj;
     }
     elsif ( $signature eq SIG_INTERNAL ) {
-        my $size = $fileobj->read_at( undef, $self->{data_size} );
+        my $size = $storage->read_at( undef, $self->{data_size} );
         $size = unpack($self->{data_pack}, $size);
 
         if ( $size ) {
-            my $new_loc = $fileobj->read_at( undef, $size );
+            my $new_loc = $storage->read_at( undef, $size );
             $new_loc = unpack( $self->{long_pack}, $new_loc ); 
             return $self->read_from_loc( $new_loc, $orig_key );
         }
@@ -713,10 +755,10 @@ sub read_from_loc {
     # Otherwise return actual value
     ##
     elsif ( $signature eq SIG_DATA ) {
-        my $size = $fileobj->read_at( undef, $self->{data_size} );
+        my $size = $storage->read_at( undef, $self->{data_size} );
         $size = unpack($self->{data_pack}, $size);
 
-        my $value = $size ? $fileobj->read_at( undef, $size ) : '';
+        my $value = $size ? $storage->read_at( undef, $size ) : '';
         return $value;
     }
 
@@ -769,14 +811,14 @@ sub delete_bucket {
 
     return if !$keyloc;
 
-    my $fileobj = $self->_fileobj;
+    my $storage = $self->_storage;
 
     my @transactions;
-    if ( $fileobj->transaction_id == 0 ) {
-        @transactions = $fileobj->current_transactions;
+    if ( $storage->transaction_id == 0 ) {
+        @transactions = $storage->current_transactions;
     }
 
-    if ( $fileobj->transaction_id == 0 ) {
+    if ( $storage->transaction_id == 0 ) {
         my $keytag = $self->load_tag( $keyloc );
 
         my ($subloc, $is_deleted, $offset) = $self->find_keyloc( $keytag );
@@ -789,8 +831,8 @@ sub delete_bucket {
         for my $trans_id ( @transactions ) {
             my ($loc, $is_deleted, $offset2) = $self->find_keyloc( $keytag, $trans_id );
             unless ($loc) {
-                my $location2 = $fileobj->request_space( $size );
-                $fileobj->print_at( $keytag->{offset} + $offset2,
+                my $location2 = $storage->request_space( $size );
+                $storage->print_at( $keytag->{offset} + $offset2,
                     pack($self->{long_pack}, $location2 ),
                     pack( 'C C', $trans_id, 0 ),
                 );
@@ -800,7 +842,7 @@ sub delete_bucket {
 
         $keytag = $self->load_tag( $keyloc );
         ($subloc, $is_deleted, $offset) = $self->find_keyloc( $keytag );
-        $fileobj->print_at( $keytag->{offset} + $offset,
+        $storage->print_at( $keytag->{offset} + $offset,
             substr( $keytag->{content}, $offset + $self->{key_size} ),
             chr(0) x $self->{key_size},
         );
@@ -810,9 +852,9 @@ sub delete_bucket {
 
         my ($subloc, $is_deleted, $offset) = $self->find_keyloc( $keytag );
 
-        $fileobj->print_at( $keytag->{offset} + $offset,
+        $storage->print_at( $keytag->{offset} + $offset,
             pack($self->{long_pack}, 0 ),
-            pack( 'C C', $fileobj->transaction_id, 1 ),
+            pack( 'C C', $storage->transaction_id, 1 ),
         );
     }
 
@@ -850,8 +892,8 @@ sub find_blist {
     my $tag = $self->load_tag( $offset )
         or $self->_throw_error( "INTERNAL ERROR - Cannot find tag" );
 
-    my $ch = 0;
-    while ($tag->{signature} ne SIG_BLIST) {
+    #XXX What happens when $ch >= $self->{hash_size} ??
+    for (my $ch = 0; $tag->{signature} ne SIG_BLIST; $ch++) {
         my $num = ord substr($md5, $ch, 1);
 
         my $ref_loc = $tag->{offset} + ($num * $self->{long_size});
@@ -860,11 +902,11 @@ sub find_blist {
         if (!$tag) {
             return if !$args->{create};
 
-            my $loc = $self->_fileobj->request_space(
+            my $loc = $self->_storage->request_space(
                 $self->tag_size( $self->{bucket_list_size} ),
             );
 
-            $self->_fileobj->print_at( $ref_loc, pack($self->{long_pack}, $loc) );
+            $self->_storage->print_at( $ref_loc, pack($self->{long_pack}, $loc) );
 
             $tag = $self->write_tag(
                 $loc, SIG_BLIST,
@@ -877,7 +919,7 @@ sub find_blist {
             last;
         }
 
-        $tag->{ch} = $ch++;
+        $tag->{ch} = $ch;
         $tag->{ref_loc} = $ref_loc;
     }
 
@@ -946,7 +988,7 @@ sub traverse_index {
         ##
         # Iterate through buckets, looking for a key match
         ##
-        my $transaction_id = $self->_fileobj->transaction_id;
+        my $transaction_id = $self->_storage->transaction_id;
         for (my $i = 0; $i < $self->{max_buckets}; $i++) {
             my ($key, $keyloc) = $self->_get_key_subloc( $keys, $i );
 
@@ -962,7 +1004,7 @@ sub traverse_index {
             }
             # Seek to bucket location and skip over signature
             elsif ($xxxx->{return_next}) {
-                my $fileobj = $self->_fileobj;
+                my $storage = $self->_storage;
 
                 my $keytag = $self->load_tag( $keyloc );
                 my ($subloc, $is_deleted) = $self->find_keyloc( $keytag );
@@ -972,18 +1014,18 @@ sub traverse_index {
                 next if $is_deleted;
 
                 # Skip over value to get to plain key
-                my $sig = $fileobj->read_at( $subloc, SIG_SIZE );
+                my $sig = $storage->read_at( $subloc, SIG_SIZE );
 
-                my $size = $fileobj->read_at( undef, $self->{data_size} );
+                my $size = $storage->read_at( undef, $self->{data_size} );
                 $size = unpack($self->{data_pack}, $size);
-                if ($size) { $fileobj->increment_pointer( $size ); }
+                if ($size) { $storage->increment_pointer( $size ); }
 
                 # Read in plain key and return as scalar
-                $size = $fileobj->read_at( undef, $self->{data_size} );
+                $size = $storage->read_at( undef, $self->{data_size} );
                 $size = unpack($self->{data_pack}, $size);
 
                 my $plain_key;
-                if ($size) { $plain_key = $fileobj->read_at( undef, $size); }
+                if ($size) { $plain_key = $storage->read_at( undef, $size); }
                 return $plain_key;
             }
         }
@@ -994,34 +1036,6 @@ sub traverse_index {
     return;
 }
 
-sub get_next_key {
-    ##
-    # Locate next key, given digested previous one
-    ##
-    my $self = shift;
-    my ($obj) = @_;
-
-    ##
-    # If the previous key was not specifed, start at the top and
-    # return the first one found.
-    ##
-    my $temp;
-    if ( @_ > 1 ) {
-        $temp = {
-            prev_md5    => $_[1],
-            return_next => 0,
-        };
-    }
-    else {
-        $temp = {
-            prev_md5    => chr(0) x $self->{hash_size},
-            return_next => 1,
-        };
-    }
-
-    return $self->traverse_index( $temp, $obj->_base_offset, 0 );
-}
-
 # Utilities
 
 sub _get_key_subloc {
@@ -1050,15 +1064,8 @@ sub _find_in_buckets {
             $tag->{content}, $i,
         );
 
-        my @rv = ($subloc, $i * $self->{bucket_size});
-
-        unless ( $subloc ) {
-            return @rv;
-        }
-
-        next BUCKET if $key ne $md5;
-
-        return @rv;
+        next BUCKET if $subloc && $key ne $md5;
+        return( $subloc, $i * $self->{bucket_size} );
     }
 
     return;
@@ -1070,7 +1077,7 @@ sub _release_space {
 
     my $next_loc = 0;
 
-    $self->_fileobj->print_at( $loc,
+    $self->_storage->print_at( $loc,
         SIG_FREE, 
         pack($self->{long_pack}, $size ),
         pack($self->{long_pack}, $next_loc ),
@@ -1136,12 +1143,12 @@ sub _length_needed {
             + $self->{data_size} # size for key
             + length( $key );    # length of key
 
-    if ( $is_dbm_deep && $value->_fileobj eq $self->_fileobj ) {
+    if ( $is_dbm_deep && $value->_storage eq $self->_storage ) {
         # long_size is for the internal reference
         return $len + $self->{long_size};
     }
 
-    if ( $self->_fileobj->{autobless} ) {
+    if ( $self->_storage->{autobless} ) {
         # This is for the bit saying whether or not this thing is blessed.
         $len += 1;
     }
@@ -1158,7 +1165,7 @@ sub _length_needed {
 
     # if autobless is enabled, must also take into consideration
     # the class name as it is stored after the key.
-    if ( $self->_fileobj->{autobless} ) {
+    if ( $self->_storage->{autobless} ) {
         my $c = Scalar::Util::blessed($value);
         if ( defined $c && !$is_dbm_deep ) {
             $len += $self->{data_size} + length($c);