From: rkinyon Date: Sun, 14 Jan 2007 05:39:19 +0000 (+0000) Subject: Fixed a bug with how transactions worked across a reindex X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=65bd261b9cb3a65ce4626f0789d5bbcb28be2a6a;p=dbsrgits%2FDBM-Deep.git Fixed a bug with how transactions worked across a reindex --- diff --git a/lib/DBM/Deep/Engine.pm b/lib/DBM/Deep/Engine.pm index f2bad5a..3722aed 100644 --- a/lib/DBM/Deep/Engine.pm +++ b/lib/DBM/Deep/Engine.pm @@ -505,6 +505,24 @@ sub add_entry { $self->{entries}{$trans_id}{$loc} = undef; } +# If the buckets are being relocated because of a reindexing, the entries +# mechanism needs to be made aware of it. +sub reindex_entry { + my $self = shift; + my ($old_loc, $new_loc) = @_; + + TRANS: + while ( my ($trans_id, $locs) = each %{ $self->{entries} } ) { + foreach my $orig_loc ( keys %{ $locs } ) { + if ( $orig_loc == $old_loc ) { + delete $locs->{orig_loc}; + $locs->{$new_loc} = undef; + next TRANS; + } + } + } +} + sub clear_entries { my $self = shift; delete $self->{entries}{$self->trans_id}; @@ -1348,7 +1366,9 @@ sub get_bucket_list { }); my %blist_cache; - foreach my $md5 ( $sector->chopped_up ) { + #XXX q.v. the comments for this function. + foreach my $entry ( $sector->chopped_up ) { + my ($spot, $md5) = @{$entry}; my $idx = ord( substr( $md5, $i, 1 ) ); # XXX This is inefficient @@ -1359,7 +1379,8 @@ sub get_bucket_list { $new_index->set_entry( $idx => $blist->offset ); - $blist->write_at_next_open( $md5 ); + my $new_spot = $blist->write_at_next_open( $md5 ); + $engine->reindex_entry( $spot => $new_spot ); } # Handle the new item separately. @@ -1497,6 +1518,7 @@ sub bucket_size { return $self->{bucket_size}; } +# XXX This is such a poor hack. I need to rethink this code. sub chopped_up { my $self = shift; @@ -1504,14 +1526,13 @@ sub chopped_up { my @buckets; foreach my $idx ( 0 .. $e->max_buckets - 1 ) { - my $md5 = $e->storage->read_at( - $self->offset + $self->base_size + $idx * $self->bucket_size, $e->hash_size, - ); + my $spot = $self->offset + $self->base_size + $idx * $self->bucket_size; + my $md5 = $e->storage->read_at( $spot, $e->hash_size ); last if $md5 eq $e->blank_md5; my $rest = $e->storage->read_at( undef, $self->bucket_size - $e->hash_size ); - push @buckets, $md5 . $rest; + push @buckets, [ $spot, $md5 . $rest ]; } return @buckets; @@ -1519,15 +1540,15 @@ sub chopped_up { sub write_at_next_open { my $self = shift; - my ($md5) = @_; + my ($entry) = @_; #XXX This is such a hack! $self->{_next_open} = 0 unless exists $self->{_next_open}; - $self->engine->storage->print_at( - $self->offset + $self->base_size + $self->{_next_open}++ * $self->bucket_size, - $md5, - ); + my $spot = $self->offset + $self->base_size + $self->{_next_open}++ * $self->bucket_size; + $self->engine->storage->print_at( $spot, $entry ); + + return $spot; } sub has_md5 { diff --git a/t/33_transactions.t b/t/33_transactions.t index 0b69c05..1e6e779 100644 --- a/t/33_transactions.t +++ b/t/33_transactions.t @@ -208,4 +208,3 @@ __END__ Tests to add: * Two transactions running at the same time * Doing a clear on the head while a transaction is running -# More than just two keys