$value = $self->_storage->{filter_store_value}->( $value );
}
- $self->_engine->write_value( $self->_base_offset, $key, $value, $orig_key );
+ $self->_engine->write_value( $self->_storage->transaction_id, $self->_base_offset, $key, $value, $orig_key );
$self->unlock();
##
$self->lock( LOCK_SH );
- my $result = $self->_engine->read_value( $self->_base_offset, $key, $orig_key );
+ my $result = $self->_engine->read_value( $self->_storage->transaction_id, $self->_base_offset, $key, $orig_key );
$self->unlock();
##
# Delete bucket
##
- my $value = $self->_engine->delete_key( $self->_base_offset, $key, $orig_key );
+ my $value = $self->_engine->delete_key( $self->_storage->transaction_id, $self->_base_offset, $key, $orig_key );
if (defined $value && !ref($value) && $self->_storage->{filter_fetch_value}) {
$value = $self->_storage->{filter_fetch_value}->($value);
##
$self->lock( LOCK_SH );
- my $result = $self->_engine->key_exists( $self->_base_offset, $key );
+ my $result = $self->_engine->key_exists( $self->_storage->transaction_id, $self->_base_offset, $key );
$self->unlock();
while ( $key ) {
# Retrieve the key before deleting because we depend on next_key
my $next_key = $self->next_key( $key );
- $self->_engine->delete_key( $self->_base_offset, $key, $key );
+ $self->_engine->delete_key( $self->_storage->transaction_id, $self->_base_offset, $key, $key );
$key = $next_key;
}
}
else {
my $size = $self->FETCHSIZE;
for my $key ( 0 .. $size - 1 ) {
- $self->_engine->delete_key( $self->_base_offset, $key, $key );
+ $self->_engine->delete_key( $self->_storage->transaction_id, $self->_base_offset, $key, $key );
}
$self->STORESIZE( 0 );
}
sub read_value {
my $self = shift;
- my ($offset, $key, $orig_key) = @_;
+ my ($trans_id, $offset, $key, $orig_key) = @_;
- my $dig_key = $self->apply_digest( $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 );
}
sub key_exists {
my $self = shift;
- my ($offset, $key) = @_;
+ my ($trans_id, $offset, $key) = @_;
- my $dig_key = $self->apply_digest( $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 get_next_key {
my $self = shift;
- my ($offset) = @_;
+ my ($trans_id, $offset) = @_;
# If the previous key was not specifed, start at the top and
# return the first one found.
my $temp;
- if ( @_ > 1 ) {
+ if ( @_ > 2 ) {
$temp = {
- prev_md5 => $self->apply_digest($_[1]),
+ prev_md5 => $self->_apply_digest($_[2]),
return_next => 0,
};
}
sub delete_key {
my $self = shift;
- my ($offset, $key, $orig_key) = @_;
+ my ($trans_id, $offset, $key, $orig_key) = @_;
- my $dig_key = $self->apply_digest( $key );
+ my $dig_key = $self->_apply_digest( $key );
my $tag = $self->find_blist( $offset, $dig_key ) or return;
my $value = $self->get_bucket_value( $tag, $dig_key, $orig_key );
$self->delete_bucket( $tag, $dig_key, $orig_key );
sub write_value {
my $self = shift;
- my ($offset, $key, $value, $orig_key) = @_;
+ my ($trans_id, $offset, $key, $value, $orig_key) = @_;
- my $dig_key = $self->apply_digest( $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 );
}
sub _storage { return $_[0]{storage} }
-sub apply_digest {
+sub _apply_digest {
my $self = shift;
return $self->{digest}->(@_);
}
}
}
- #XXX Write this
- $self->_write_value({
- tag => $key_tag,
- value => $value,
+ my $value_loc = $self->_storage->request_space(
+ $self->_length_needed( $value, $key ),
+ );
+
+ $self->_add_key_offset({
+ tag => $key_tag,
+ trans_id => $trans_id,
+ loc => $value_loc,
});
+ $self->_write_value( $value_loc, $key, $value, $key );
+
return 1;
}
my $self = shift;
my ($args) = @_;
+ use Data::Dumper;warn Dumper $args;
+
my $key_tag = $self->load_tag( $args->{offset} );
my @head;
my $bucket_tag = $self->load_tag( $args->{offset} )
or $self->_throw_error( "INTERNAL ERROR - Cannot find tag" );
- # $bucket_tag->{ref_loc} and $bucket_tag->{ch} are used in split_index()
-
#XXX What happens when $ch >= $self->{hash_size} ??
for (my $ch = 0; $bucket_tag->{signature} ne SIG_BLIST; $ch++) {
my $num = ord substr($args->{key_md5}, $ch, 1);
return( $keytag_loc, $bucket_tag );
}
else {
+ my ($key, $subloc, $index);
BUCKET:
for ( my $i = 0; $i < $self->{max_buckets}; $i++ ) {
- my ($key, $subloc) = $self->_get_key_subloc(
+ ($key, $subloc) = $self->_get_key_subloc(
$bucket_tag->{content}, $i,
);
next BUCKET if $subloc && $key ne $args->{key_md5};
- #XXX Right here, I need to create a new value, if I can
- return( $subloc, $bucket_tag );
+
+ # Keep track of where we are, in case we need to create a new
+ # entry.
+ $index = $i;
+ last;
}
- # Right here, it looks like split_index needs to happen
- # What happens here?
+
+ # Either we have a subloc to return or we don't want to create a new
+ # entry. Either way, we need to return now.
+ return ($subloc, $bucket_tag) if $subloc || !$args->{create};
+
+ my $keytag_loc = $self->_storage->request_space(
+ $self->tag_size( $self->{keyloc_size} ),
+ );
+
+ # There's space left in this bucket
+ if ( defined $index ) {
+ substr( $bucket_tag->{content}, $index * $self->{key_size}, $self->{key_size} ) =
+ $args->{key_md5} . pack( "$self->{long_pack}", $keytag_loc );
+
+ $self->_storage->print_at( $bucket_tag->{offset}, $bucket_tag->{content} );
+ }
+ # We need to split the index
+ else {
+ $self->split_index( $bucket_tag, $args->{key_md5}, $keytag_loc );
+ }
+
+ $self->write_tag(
+ $keytag_loc, SIG_KEYS,
+ chr(0)x$self->{keyloc_size},
+ );
+
+ return( $keytag_loc, $bucket_tag );
}
return;
substr( $args->{tag}{content}, $i * $self->{key_size}, $self->{key_size} ) = pack(
"$self->{long_pack} C C",
$loc, $trans_id, 1,
- )
+ );
}
}
return 1;
}
-sub _write_value {
+sub _add_key_offset {
my $self = shift;
my ($args) = @_;
+ my $is_changed;
+ for ( my $i = 0; $i < $self->{max_buckets}; $i++ ) {
+ my ($loc, $trans_id, $is_deleted) = unpack(
+ "$self->{long_pack} C C",
+ substr( $args->{tag}{content}, $i * $self->{key_size}, $self->{key_size} ),
+ );
+ if ( $trans_id == $args->{trans_id} || (!$loc && !$is_deleted) ) {
+ substr( $args->{tag}{content}, $i * $self->{key_size}, $self->{key_size} ) = pack(
+ "$self->{long_pack} C C",
+ $args->{loc}, $args->{trans_id}, 0,
+ );
+ $is_changed = 1;
+ last;
+ }
+ }
+
+ if ( $is_changed ) {
+ $self->_storage->print_at(
+ $args->{tag}{offset}, $args->{tag}{content},
+ );
+ }
+ else {
+ die "Why didn't _add_key_offset() change something?!\n";
+ }
+
+ return 1;
}
sub setup_fh {
##
$self->lock( $self->LOCK_SH );
- my $result = $self->_engine->get_next_key($self->_base_offset);
+ my $result = $self->_engine->get_next_key($self->_storage->transaction_id, $self->_base_offset);
$self->unlock();
##
$self->lock( $self->LOCK_SH );
- my $result = $self->_engine->get_next_key( $self->_base_offset, $prev_key );
+ my $result = $self->_engine->get_next_key( $self->_storage->transaction_id, $self->_base_offset, $prev_key );
$self->unlock();