use strict;
use warnings FATAL => 'all';
+no warnings 'recursion';
use base qw( DBM::Deep::Engine );
use DBM::Deep::Sector::File ();
use DBM::Deep::Storage::File ();
+sub sector_type { 'DBM::Deep::Sector::File' }
+sub iterator_class { 'DBM::Deep::Iterator::File' }
+
my $STALE_SIZE = 2;
+# Setup file and tag signatures. These should never change.
+sub SIG_FILE () { 'DPDB' }
+sub SIG_HEADER () { 'h' }
+sub SIG_NULL () { 'N' }
+sub SIG_DATA () { 'D' }
+sub SIG_INDEX () { 'I' }
+sub SIG_BLIST () { 'B' }
+sub SIG_FREE () { 'F' }
+sub SIG_SIZE () { 1 }
+# SIG_HASH and SIG_ARRAY are defined in DBM::Deep::Engine
+
# Please refer to the pack() documentation for further information
my %StP = (
1 => 'C', # Unsigned char value (no order needed as it's just one byte)
=head1 PURPOSE
-This is the engine for use with L<DBM::Deep::Storage::File/>.
+This is the engine for use with L<DBM::Deep::Storage::File>.
=head1 EXTERNAL METHODS
my ($obj, $key) = @_;
# This will be a Reference sector
- my $sector = DBM::Deep::Sector::File->load( $self, $obj->_base_offset )
+ my $sector = $self->load_sector( $obj->_base_offset )
or return;
if ( $sector->staleness != $obj->_staleness ) {
my ($obj) = @_;
# This will be a Reference sector
- my $sector = DBM::Deep::Sector::File->load( $self, $obj->_base_offset )
+ my $sector = $self->load_sector( $obj->_base_offset )
or DBM::Deep->_throw_error( "How did get_classname fail (no sector for '$obj')?!" );
if ( $sector->staleness != $obj->_staleness ) {
my ($obj, $old_key, $new_key) = @_;
# This will be a Reference sector
- my $sector = DBM::Deep::Sector::File->load( $self, $obj->_base_offset )
+ my $sector = $self->load_sector( $obj->_base_offset )
or DBM::Deep->_throw_error( "How did make_reference fail (no sector for '$obj')?!" );
if ( $sector->staleness != $obj->_staleness ) {
return;
}
+# exists returns '', not undefined.
sub key_exists {
my $self = shift;
my ($obj, $key) = @_;
# This will be a Reference sector
- my $sector = DBM::Deep::Sector::File->load( $self, $obj->_base_offset )
+ my $sector = $self->load_sector( $obj->_base_offset )
or return '';
if ( $sector->staleness != $obj->_staleness ) {
my $self = shift;
my ($obj, $key) = @_;
- my $sector = DBM::Deep::Sector::File->load( $self, $obj->_base_offset )
+ my $sector = $self->load_sector( $obj->_base_offset )
or return;
if ( $sector->staleness != $obj->_staleness ) {
}
# This will be a Reference sector
- my $sector = DBM::Deep::Sector::File->load( $self, $obj->_base_offset )
+ my $sector = $self->load_sector( $obj->_base_offset )
or DBM::Deep->_throw_error( "Cannot write to a deleted spot in DBM::Deep." );
if ( $sector->staleness != $obj->_staleness ) {
}
#XXX Can this use $loc?
- my $value_sector = DBM::Deep::Sector::File->load( $self, $tmpvar->_base_offset );
+ my $value_sector = $self->load_sector( $tmpvar->_base_offset );
$sector->write_data({
key => $key,
key_md5 => $self->_apply_digest( $key ),
value => $value_sector,
});
- # This code is to make sure we write all the values in the $value to the
- # disk and to make sure all changes to $value after the assignment are
- # reflected on disk. This may be counter-intuitive at first, but it is
- # correct dwimmery.
- # NOTE - simply tying $value won't perform a STORE on each value. Hence,
- # the copy to a temp value.
- if ( $r eq 'ARRAY' ) {
- my @temp = @$value;
- tie @$value, 'DBM::Deep', {
- base_offset => $value_sector->offset,
- staleness => $value_sector->staleness,
- storage => $self->storage,
- engine => $self,
- };
- @$value = @temp;
- bless $value, 'DBM::Deep::Array' unless Scalar::Util::blessed( $value );
- }
- elsif ( $r eq 'HASH' ) {
- my %temp = %$value;
- tie %$value, 'DBM::Deep', {
- base_offset => $value_sector->offset,
- staleness => $value_sector->staleness,
- storage => $self->storage,
- engine => $self,
- };
-
- %$value = %temp;
- bless $value, 'DBM::Deep::Hash' unless Scalar::Util::blessed( $value );
- }
+ $self->_descend( $value, $value_sector );
return 1;
}
$self->storage->print_at( $read_loc, pack( $StP{$self->byte_size}, 0 ) );
if ( $data_loc > 1 ) {
- DBM::Deep::Sector::File->load( $self, $data_loc )->free;
+ $self->load_sector( $data_loc )->free;
}
}
);
if ( $head_loc > 1 ) {
- DBM::Deep::Sector::File->load( $self, $head_loc )->free;
+ $self->load_sector( $head_loc )->free;
}
}
=over 4
-=item * storage
-
=item * byte_size
=item * hash_size
=cut
-sub storage { $_[0]{storage} }
sub byte_size { $_[0]{byte_size} }
sub hash_size { $_[0]{hash_size} }
sub hash_chars { $_[0]{hash_chars} }
sub chains_loc { $_[0]{chains_loc} }
sub set_chains_loc { $_[0]{chains_loc} = $_[1] }
-sub cache { $_[0]{cache} ||= {} }
-sub clear_cache { %{$_[0]->cache} = () }
+sub supports {
+ shift;
+ my ($feature) = @_;
+
+ return 1 if $feature eq 'transactions';
+ return if $feature eq 'singletones';
+ return;
+}
+
+sub clear {
+ my $self = shift;
+ my $obj = shift;
+
+ my $sector = $self->load_sector( $obj->_base_offset )
+ or return;
+
+ return unless $sector->staleness == $obj->_staleness;
+
+ $sector->clear;
+
+ return;
+}
=head2 _dump_file()
SECTOR:
while ( $spot < $self->storage->{end} ) {
# Read each sector in order.
- my $sector = DBM::Deep::Sector::File->load( $self, $spot );
+ my $sector = $self->load_sector( $spot );
if ( !$sector ) {
# Find it in the free-sectors that were found already
foreach my $type ( keys %sectors ) {