X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBM%2FDeep%2FEngine.pm;h=73917a4d9bf6614a54a4789bb47eb5670f4e67bd;hb=fb451ba69d35e7acbd996e3de8c073f6ce76d7ea;hp=54ec75da8a4892a984da0bf5a28d262bae271413;hpb=e5a9d386f8a0eeba8777a0ac98c78274baff3efb;p=dbsrgits%2FDBM-Deep.git diff --git a/lib/DBM/Deep/Engine.pm b/lib/DBM/Deep/Engine.pm index 54ec75d..73917a4 100644 --- a/lib/DBM/Deep/Engine.pm +++ b/lib/DBM/Deep/Engine.pm @@ -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);