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
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;
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 : '';
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 );
}
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 );
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;
}
################################################################################
sub get_bucket_list {
my $self = shift;
my ($args) = @_;
+ $args ||= {};
# XXX Add in check here for recycling?
});
}
+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;
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 {
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,
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
);
}
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;
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 );
}