From: rkinyon Date: Tue, 30 Jan 2007 04:22:46 +0000 (+0000) Subject: Removed transactional staleness counter from the HEAD as it can never be stale X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=6db2a0a25083cd093e02f7b493cd1c15116f6086;p=dbsrgits%2FDBM-Deep.git Removed transactional staleness counter from the HEAD as it can never be stale --- diff --git a/lib/DBM/Deep/Engine.pm b/lib/DBM/Deep/Engine.pm index c2e4a0e..13f29fa 100644 --- a/lib/DBM/Deep/Engine.pm +++ b/lib/DBM/Deep/Engine.pm @@ -359,10 +359,10 @@ sub begin_work { } my @slots = $self->read_txn_slots; - for my $i ( 1 .. @slots ) { + for my $i ( 0 .. @slots ) { next if $slots[$i]; $slots[$i] = 1; - $self->set_trans_id( $i ); + $self->set_trans_id( $i + 1 ); last; } $self->write_txn_slots( @slots ); @@ -389,7 +389,8 @@ sub rollback { my $read_loc = $entry + $self->hash_size + $self->byte_size - + $self->trans_id * ( $self->byte_size + 4 ); + + $self->byte_size + + ($self->trans_id - 1) * ( $self->byte_size + 4 ); my $data_loc = $self->storage->read_at( $read_loc, $self->byte_size ); $data_loc = unpack( $StP{$self->byte_size}, $data_loc ); @@ -403,7 +404,7 @@ sub rollback { $self->clear_entries; my @slots = $self->read_txn_slots; - $slots[$self->trans_id] = 0; + $slots[$self->trans_id-1] = 0; $self->write_txn_slots( @slots ); $self->inc_txn_staleness_counter( $self->trans_id ); $self->set_trans_id( 0 ); @@ -427,13 +428,15 @@ sub commit { my $head_loc = $self->storage->read_at( $base, $self->byte_size ); $head_loc = unpack( $StP{$self->byte_size}, $head_loc ); + + my $spot = $base + $self->byte_size + ($self->trans_id - 1) * ( $self->byte_size + 4 ); my $trans_loc = $self->storage->read_at( - $base + $self->trans_id * ( $self->byte_size + 4 ), $self->byte_size, + $spot, $self->byte_size, ); $self->storage->print_at( $base, $trans_loc ); $self->storage->print_at( - $base + $self->trans_id * ( $self->byte_size + 4 ), + $spot, pack( $StP{$self->byte_size} . ' N', (0) x 2 ), ); @@ -445,7 +448,7 @@ sub commit { $self->clear_entries; my @slots = $self->read_txn_slots; - $slots[$self->trans_id] = 0; + $slots[$self->trans_id-1] = 0; $self->write_txn_slots( @slots ); $self->inc_txn_staleness_counter( $self->trans_id ); $self->set_trans_id( 0 ); @@ -472,7 +475,7 @@ sub write_txn_slots { sub get_running_txn_ids { my $self = shift; my @transactions = $self->read_txn_slots; - my @trans_ids = grep { $transactions[$_] } 0 .. $#transactions; + my @trans_ids = map { $_+1} grep { $transactions[$_] } 0 .. $#transactions; } sub get_txn_staleness_counter { @@ -482,13 +485,12 @@ sub get_txn_staleness_counter { # Hardcode staleness of 0 for the HEAD return 0 unless $trans_id; - my $x = unpack( 'N', + return unpack( 'N', $self->storage->read_at( - $self->trans_loc + 4 * $trans_id, + $self->trans_loc + 4 + 4 * ($trans_id - 1), 4, ) ); - return $x; } sub inc_txn_staleness_counter { @@ -499,7 +501,7 @@ sub inc_txn_staleness_counter { return unless $trans_id; $self->storage->print_at( - $self->trans_loc + 4 * $trans_id, + $self->trans_loc + 4 + 4 * ($trans_id - 1), pack( 'N', $self->get_txn_staleness_counter( $trans_id ) + 1 ), ); } @@ -551,7 +553,7 @@ sub clear_entries { my $nt = $self->num_txns; - my $header_var = 1 + 1 + 1 + 1 + 4 + 4 * $nt + 3 * $self->byte_size; + my $header_var = 1 + 1 + 1 + 1 + 4 + 4 * ($nt - 1) + 3 * $self->byte_size; my $loc = $self->storage->request_space( $header_fixed + $header_var ); @@ -568,8 +570,9 @@ sub clear_entries { pack('C', $self->data_sector_size - 1), pack('C', $nt), +#XXX This is a problem - it limits everything to 32 transactions pack('N', 0 ), # Transaction activeness bitfield - pack('N' . $nt, 0 x $nt ), # Transaction staleness counters + pack('N' . ($nt-1), 0 x ($nt-1) ), # Transaction staleness counters pack($StP{$self->byte_size}, 0), # Start of free chain (blist size) pack($StP{$self->byte_size}, 0), # Start of free chain (data size) pack($StP{$self->byte_size}, 0), # Start of free chain (index size) @@ -577,7 +580,7 @@ sub clear_entries { #XXX Set these less fragilely $self->set_trans_loc( $header_fixed + 4 ); - $self->set_chains_loc( $header_fixed + 4 + 4 + 4 * $nt ); + $self->set_chains_loc( $header_fixed + 4 + 4 + 4 * ($nt-1) ); return; } @@ -618,9 +621,6 @@ sub clear_entries { DBM::Deep->_throw_error("Corrupted file - bad header"); } - $self->set_trans_loc( $header_fixed + scalar(@values) ); - $self->set_chains_loc( $header_fixed + scalar(@values) + 4 + 4 * $self->num_txns ); - #XXX Add warnings if values weren't set right @{$self}{qw(byte_size max_buckets data_sector_size num_txns)} = @values; @@ -628,12 +628,15 @@ sub clear_entries { $self->{max_buckets} += 1; $self->{data_sector_size} += 1; - my $header_var = scalar(@values) + 4 + 4 * $self->num_txns + 3 * $self->byte_size; + my $header_var = scalar(@values) + 4 + 4 * ($self->num_txns - 1) + 3 * $self->byte_size; unless ( $size == $header_var ) { $self->storage->close; DBM::Deep->_throw_error( "Unexpected size found ($size <-> $header_var)." ); } + $self->set_trans_loc( $header_fixed + scalar(@values) ); + $self->set_chains_loc( $header_fixed + scalar(@values) + 4 + 4 * ($self->num_txns - 1) ); + return length($buffer) + length($buffer2); } } @@ -1558,8 +1561,9 @@ sub bucket_size { my $self = shift; unless ( $self->{bucket_size} ) { my $e = $self->engine; + #XXX Convert the 4 to STALE_SIZE() # Key + head (location) + transactions (location + staleness-counter) - my $location_size = $e->byte_size + $e->num_txns * ( $e->byte_size + 4 ); + my $location_size = $e->byte_size + $e->byte_size + ($e->num_txns - 1) * ($e->byte_size + 4); $self->{bucket_size} = $e->hash_size + $location_size; } return $self->{bucket_size}; @@ -1672,13 +1676,22 @@ sub write_md5 { my $loc = $spot + $engine->hash_size - + $engine->byte_size - + $args->{trans_id} * ( $engine->byte_size + 4 ); + + $engine->byte_size; - $engine->storage->print_at( $loc, - pack( $StP{$engine->byte_size}, $args->{value}->offset ), - pack( 'N', $engine->get_txn_staleness_counter( $args->{trans_id} ) ), - ); + #XXX Convert the 4 to STALE_SIZE() + if ( $args->{trans_id} ) { + $loc += $engine->byte_size + ($args->{trans_id} - 1) * ( $engine->byte_size + 4 ); + + $engine->storage->print_at( $loc, + pack( $StP{$engine->byte_size}, $args->{value}->offset ), + pack( 'N', $engine->get_txn_staleness_counter( $args->{trans_id} ) ), + ); + } + else { + $engine->storage->print_at( $loc, + pack( $StP{$engine->byte_size}, $args->{value}->offset ), + ); + } } sub mark_deleted { @@ -1695,13 +1708,23 @@ sub mark_deleted { my $loc = $spot + $engine->hash_size - + $engine->byte_size - + $args->{trans_id} * ( $engine->byte_size + 4 ); + + $engine->byte_size; + + #XXX Convert the 4 to STALE_SIZE() + if ( $args->{trans_id} ) { + $loc += $engine->byte_size + ($args->{trans_id} - 1) * ( $engine->byte_size + 4 ); + + $engine->storage->print_at( $loc, + pack( $StP{$engine->byte_size}, 1 ), # 1 is the marker for deleted + pack( 'N', $engine->get_txn_staleness_counter( $args->{trans_id} ) ), + ); + } + else { + $engine->storage->print_at( $loc, + pack( $StP{$engine->byte_size}, 1 ), # 1 is the marker for deleted + ); + } - $engine->storage->print_at( $loc, - pack( $StP{$engine->byte_size}, 1 ), # 1 is the marker for deleted - pack( 'N', $engine->get_txn_staleness_counter( $args->{trans_id} ) ), - ); } sub delete_md5 { @@ -1749,22 +1772,29 @@ sub get_data_location_for { my $spot = $self->offset + $self->base_size + $args->{idx} * $self->bucket_size + $e->hash_size - + $e->byte_size - + $args->{trans_id} * ( $e->byte_size + 4 ); + + $e->byte_size; + + #XXX Convert the 4 to STALE_SIZE() + if ( $args->{trans_id} ) { + $spot += $e->byte_size + ($args->{trans_id} - 1) * ( $e->byte_size + 4 ); + } + #XXX Convert the 4 to STALE_SIZE() my $buffer = $e->storage->read_at( $spot, $e->byte_size + 4, ); my ($loc, $staleness) = unpack( $StP{$e->byte_size} . ' N', $buffer ); - # We have found an entry that is old, so get rid of it - if ( $staleness != (my $s = $e->get_txn_staleness_counter( $args->{trans_id} ) ) ) { - $e->storage->print_at( - $spot, - pack( $StP{$e->byte_size} . ' N', (0) x 2 ), - ); - $loc = 0; + if ( $args->{trans_id} ) { + # We have found an entry that is old, so get rid of it + if ( $staleness != (my $s = $e->get_txn_staleness_counter( $args->{trans_id} ) ) ) { + $e->storage->print_at( + $spot, + pack( $StP{$e->byte_size} . ' N', (0) x 2 ), + ); + $loc = 0; + } } # If we're in a transaction and we never wrote to this location, try the diff --git a/t/35_transaction_multiple.t b/t/35_transaction_multiple.t index 901b5c0..11261fd 100644 --- a/t/35_transaction_multiple.t +++ b/t/35_transaction_multiple.t @@ -49,7 +49,7 @@ $db1->{bar} = 'foo'; ok( exists $db1->{bar}, "After DB1 set bar to foo, DB1's bar exists" ); ok( !exists $db2->{bar}, "After DB1 set bar to foo, DB2's bar doesn't exist" ); ok( !exists $db3->{bar}, "After DB1 set bar to foo, DB3's bar doesn't exist" ); - + $db2->begin_work; is( $db1->{foo}, 'bar2', "After DB2 transaction begin, DB1's foo is still bar2" );