use Scalar::Util ();
# File-wide notes:
-# * Every method in here assumes that the _storage 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.
################################################################################
-my %size_to_pack = (
- 2 => 'n',
- 4 => 'N',
- 8 => 'Q',
+# Please refer to the pack() documentation for further information
+my %StP = (
+ 1 => 'c', # Unsigned char value
+ 2 => 'n', # Unsigned short in "network" (big-endian) order
+ 4 => 'N', # Unsigned long in "network" (big-endian) order
+ 8 => 'Q', # Usigned quad (no order specified, presumably machine-dependent)
);
sub new {
}
Scalar::Util::weaken( $self->{obj} ) if $self->{obj};
- $self->{byte_pack} = $size_to_pack{ $self->{byte_size} };
+ $self->{byte_pack} = $StP{ $self->byte_size };
##
# Number of buckets per blist before another level of indexing is
$self->_write_file_header;
# 1) Create Array/Hash entry
- # 2) Create Index entry
+ my $initial_reference = DBM::Deep::Engine::Sector::Reference->new({
+ engine => $self,
+ type => $obj->_type,
+ });
+ $obj->{base_offset} = $initial_reference->offset;
- $obj->{base_offset} = $self->_storage->request_space(
- $self->_tag_size( $self->{index_size} ),
- );
-
- $self->_write_tag(
- $obj->_base_offset, $obj->_type,
- chr(0) x $self->{index_size},
- );
-
- $self->_storage->flush;
+ $self->storage->flush;
}
# Reading from an existing file
else {
$self->_calculate_sizes;
}
- #XXX We have to make sure we don't mess up when autoflush isn't turned on
- $self->_storage->set_inode;
+ # We have to make sure we don't mess up when autoflush isn't turned on
+ $self->storage->set_inode;
return 1;
}
# current hashing algorithm
#XXX Does this need to be updated with different hashing algorithms?
$self->{hash_chars_used} = (2**8);
- $self->{index_size} = $self->{hash_chars_used} * $self->{byte_size};
+ $self->{index_size} = $self->{hash_chars_used} * $self->byte_size;
- $self->{bucket_size} = $self->{hash_size} + $self->{byte_size} * 2;
+ $self->{bucket_size} = $self->{hash_size} + $self->byte_size * 2;
$self->{bucket_list_size} = $self->{max_buckets} * $self->{bucket_size};
+ $self->{data_size} = 256; # In bytes
+
return;
}
my $header_fixed = length( SIG_FILE ) + 1 + 4 + 4;
my $header_var = 16 + 1 + 1;
- my $loc = $self->_storage->request_space( $header_fixed + $header_var );
+ my $loc = $self->storage->request_space( $header_fixed + $header_var );
- $self->_storage->print_at( $loc,
+ $self->storage->print_at( $loc,
SIG_FILE,
SIG_HEADER,
pack('N', 1), # header version - at this point, we're at 9 bytes
pack('N', $header_var), # header size
# --- Above is $header_fixed. Below is $header_var
pack('N4', 0, 0, 0, 0), # currently running transaction IDs
- pack('n', $self->{byte_size}),
+ pack('n', $self->byte_size),
pack('n', $self->{max_buckets}),
);
- $self->_storage->set_transaction_offset( 13 );
+ $self->storage->set_transaction_offset( 13 );
return;
}
my $header_fixed = length( SIG_FILE ) + 1 + 4 + 4;
my $header_var = 16 + 1 + 1;
- my $buffer = $self->_storage->read_at( 0, $header_fixed );
+ my $buffer = $self->storage->read_at( 0, $header_fixed );
return unless length($buffer);
my ($file_signature, $sig_header, $header_version, $size) = unpack(
);
unless ( $file_signature eq SIG_FILE ) {
- $self->_storage->close;
+ $self->storage->close;
DBM::Deep->_throw_error( "Signature not found -- file is not a Deep DB" );
}
unless ( $sig_header eq SIG_HEADER ) {
- $self->_storage->close;
+ $self->storage->close;
DBM::Deep->_throw_error( "Old file version found." );
}
unless ( $size eq $header_var ) {
- $self->_storage->close;
+ $self->storage->close;
DBM::Deep->_throw_error( "Unexpected size found." );
}
- my $buffer2 = $self->_storage->read_at( undef, $size );
+ my $buffer2 = $self->storage->read_at( undef, $size );
# $a1-4 are the transaction IDs
my ($a1, $a2, $a3, $a4, @values) = unpack( 'N4 n n', $buffer2 );
# The transaction offset is the first thing after the fixed header section
- $self->_storage->set_transaction_offset( $header_fixed );
+ $self->storage->set_transaction_offset( $header_fixed );
if ( @values < 2 || grep { !defined } @values ) {
- $self->_storage->close;
+ $self->storage->close;
DBM::Deep->_throw_error("Corrupted file - bad header");
}
my ($offset, $sig, $content) = @_;
my $size = length( $content );
- $self->_storage->print_at(
+ $self->storage->print_at(
$offset,
$sig, pack($self->{byte_pack}, $size), $content,
);
return {
signature => $sig,
start => $offset,
- offset => $offset + SIG_SIZE + $self->{byte_size},
+ offset => $offset + SIG_SIZE + $self->byte_size,
content => $content,
is_new => 1,
};
sub _load_tag {
my $self = shift;
my ($offset) = @_;
- my $storage = $self->_storage;
+ my $storage = $self->storage;
my ($sig, $size) = unpack(
"A $self->{byte_pack}",
- $storage->read_at( $offset, SIG_SIZE + $self->{byte_size} ),
+ $storage->read_at( $offset, SIG_SIZE + $self->byte_size ),
);
return {
signature => $sig,
start => $offset,
- offset => $offset + SIG_SIZE + $self->{byte_size},
+ offset => $offset + SIG_SIZE + $self->byte_size,
content => $storage->read_at( undef, $size ),
is_new => 0,
};
sub _tag_size {
my $self = shift;
my ($size) = @_;
- return SIG_SIZE + $self->{byte_size} + $size;
+ return SIG_SIZE + $self->byte_size + $size;
}
################################################################################
-sub _storage { $_[0]{storage} }
+sub storage { $_[0]{storage} }
+sub byte_size { $_[0]{byte_size} }
+
+################################################################################
+
+package DBM::Deep::Engine::Sector::Reference;
+
+our @ISA = qw( DBM::Deep::Engine::Sector );
+
+sub _init {
+ my $self = shift;
+
+ my $engine = $self->engine;
+
+ my $leftover = $self->size - 3 - 2 * $engine->byte_size;
+
+ my $offset = $engine->storage->request_space( $self->size );
+ $engine->storage->print_at( $offset,
+ $self->type,
+ pack( $StP{1}, 0 ), # Recycled counter
+ pack( $StP{$engine->byte_size}, 0 ), # Chain loc
+ pack( $StP{$engine->byte_size}, 0 ), # Index/BList loc
+ pack( $StP{1}, 0 ), # Blessedness
+ pack( $StP{1}, 0 ), # Classname length
+ chr(0) x $leftover, # Zero-fill the data
+ );
+
+ return $offset;
+}
+
+sub type { $_[0]{type} }
+
+package DBM::Deep::Engine::Sector;
+
+sub new {
+ my $self = bless $_[1], $_[0];
+ Scalar::Util::weaken( $self->{engine} );
+ $self->{offset} = $self->_init;
+ return $self;
+}
+sub _init {}
+
+sub engine { $_[0]{engine} }
+sub offset { $_[0]{offset} }
+
+# This is in bytes
+sub size { return 256 }
1;
__END__