From: rkinyon Date: Mon, 10 Mar 2008 00:20:16 +0000 (+0000) Subject: r583@rob-kinyons-computer-2 (orig r10209): rkinyon | 2007-11-09 10:15:50 -0500 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=a3d8b9310f6c8e78b468a9395fd6b410e580f642;p=dbsrgits%2FDBM-Deep.git r583@rob-kinyons-computer-2 (orig r10209): rkinyon | 2007-11-09 10:15:50 -0500 Branch for integrating the Win32 fixes provided by Buk and xdg r585@rob-kinyons-computer-2 (orig r10212): rkinyon | 2007-11-09 10:59:00 -0500 Added BrowserUk's changes so that the tests work in Win32. Have verified that they work in OSX, will test Win32 via Parallels soon. r586@rob-kinyons-computer-2 (orig r10258): rkinyon | 2007-11-15 16:33:11 -0500 Fixed a bug in autovivification regarding how locking is handled. r587@rob-kinyons-computer-2 (orig r10261): rkinyon | 2007-11-15 23:19:31 -0500 Added more stringent tests to the multilevel transactions and started the release management process r681@rob-kinyons-computer-2 (orig r10884): rkinyon | 2008-03-09 19:49:57 -0400 Are we ready for release? r682@rob-kinyons-computer-2 (orig r10885): rkinyon | 2008-03-09 19:56:39 -0400 Workaround hack for Win32 and autovivification r683@rob-kinyons-computer-2 (orig r10886): rkinyon | 2008-03-09 19:58:05 -0400 Fixed numbering of skipped tests for Win32 r684@rob-kinyons-computer-2 (orig r10887): rkinyon | 2008-03-09 20:01:21 -0400 Added some skips for win32/cygwin in order to ship r685@rob-kinyons-computer-2 (orig r10888): rkinyon | 2008-03-09 20:08:33 -0400 Added BrowserUk's to a few tests missing it (fh => in addition to file => ) r686@rob-kinyons-computer-2 (orig r10889): rkinyon | 2008-03-09 20:12:16 -0400 Added opening for the files (stupid win32 warnings) r687@rob-kinyons-computer-2 (orig r10890): rkinyon | 2008-03-09 20:19:31 -0400 A couple documentation fixes --- diff --git a/Changes b/Changes index 60dda1d..d6066b3 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,17 @@ Revision history for DBM::Deep. +1.0008 Mar 09 20:00:00 2008 EDT + - (This version is compatible with 1.0007) + - Fixed a number of Win32 issues (Reported by Steven Samelson - thank you!) + - Much thanks to Nigel Sandever and David Golden for their help + debugging the issues, particularly with DBM::Deep's usage of + File::Temp (which removes a number of warnings). + - Autovivification now works on Win32. It turns out that when a + process takes a shared flock on a file, it's not allowed to write to + it under Win32, unlike *nix. This is probably a good catch. + - Note: The fix is a hack. All locks are now exclusive until a + better fix is found. + 1.0007 Jan 10 00:00:00 2008 EDT - (This version is compatible with 1.0006) - Applied a patch+failing test submitted by sprout@cpan.org. Thanks! diff --git a/lib/DBM/Deep.pm b/lib/DBM/Deep.pm index 54a2638..36a40a4 100644 --- a/lib/DBM/Deep.pm +++ b/lib/DBM/Deep.pm @@ -5,7 +5,7 @@ use 5.006_000; use strict; use warnings; -our $VERSION = q(1.0007); +our $VERSION = q(1.0008); use Fcntl qw( :flock ); diff --git a/lib/DBM/Deep.pod b/lib/DBM/Deep.pod index d7fe1ed..0711b5e 100644 --- a/lib/DBM/Deep.pod +++ b/lib/DBM/Deep.pod @@ -582,6 +582,12 @@ L module. # something here $db->unlock(); +=head2 Win32/Cygwin + +Due to Win32 actually enforcing the read-only status of a shared lock, all +locks on Win32 and cygwin are exclusive. This is because of how autovivification +currently works. Hopefully, this will go away in a future release. + =head1 IMPORTING/EXPORTING You can import existing complex structures by calling the C method, diff --git a/lib/DBM/Deep/Array.pm b/lib/DBM/Deep/Array.pm index 7522549..e12e7c9 100644 --- a/lib/DBM/Deep/Array.pm +++ b/lib/DBM/Deep/Array.pm @@ -5,7 +5,7 @@ use 5.006_000; use strict; use warnings; -our $VERSION = q(1.0007); +our $VERSION = q(1.0008); # This is to allow DBM::Deep::Array to handle negative indices on # its own. Otherwise, Perl would intercept the call to negative diff --git a/lib/DBM/Deep/Engine.pm b/lib/DBM/Deep/Engine.pm index 89216ae..a6d69b6 100644 --- a/lib/DBM/Deep/Engine.pm +++ b/lib/DBM/Deep/Engine.pm @@ -5,7 +5,7 @@ use 5.006_000; use strict; use warnings; -our $VERSION = q(1.0007); +our $VERSION = q(1.0008); use Scalar::Util (); @@ -2121,6 +2121,7 @@ sub get_data_location_for { ); my ($loc, $staleness) = unpack( $StP{$e->byte_size} . ' ' . $StP{$STALE_SIZE}, $buffer ); + # XXX Merge the two if-clauses below 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} ) ) ) { @@ -2141,6 +2142,7 @@ sub get_data_location_for { idx => $args->{idx}, }); } + return $loc <= 1 ? 0 : $loc; } diff --git a/lib/DBM/Deep/File.pm b/lib/DBM/Deep/File.pm index 5216eaf..a37b4a3 100644 --- a/lib/DBM/Deep/File.pm +++ b/lib/DBM/Deep/File.pm @@ -5,7 +5,7 @@ use 5.006_000; use strict; use warnings; -our $VERSION = q(1.0007); +our $VERSION = q(1.0008); use Fcntl qw( :DEFAULT :flock :seek ); @@ -110,7 +110,7 @@ sub print_at { seek( $fh, $loc + $self->{file_offset}, SEEK_SET ); } - print( $fh @_ ); + print( $fh @_ ) or die "Internal Error (print_at($loc)): $!\n"; return 1; } @@ -163,8 +163,17 @@ sub lock { $type = LOCK_EX unless defined $type; + #XXX This is a temporary fix for Win32 and autovivification. It + # needs to improve somehow. -RobK, 2008-03-09 + if ( $^O eq 'MSWin32' || $^O eq 'cygwin' ) { + $type = LOCK_EX; + } + if (!defined($self->{fh})) { return; } + #XXX This either needs to allow for upgrading a shared lock to an + # exclusive lock or something else with autovivification. + # -RobK, 2008-03-09 if ($self->{locking}) { if (!$self->{locked}) { flock($self->{fh}, $type); diff --git a/lib/DBM/Deep/Hash.pm b/lib/DBM/Deep/Hash.pm index c152b22..0ee6fca 100644 --- a/lib/DBM/Deep/Hash.pm +++ b/lib/DBM/Deep/Hash.pm @@ -5,7 +5,7 @@ use 5.006_000; use strict; use warnings; -our $VERSION = q(1.0007); +our $VERSION = q(1.0008); use base 'DBM::Deep'; diff --git a/t/02_hash.t b/t/02_hash.t index 59495ff..6e9972a 100644 --- a/t/02_hash.t +++ b/t/02_hash.t @@ -9,7 +9,10 @@ use t::common qw( new_fh ); use_ok( 'DBM::Deep' ); my ($fh, $filename) = new_fh(); -my $db = DBM::Deep->new( $filename ); +my $db = DBM::Deep->new( + file => $filename, + fh => $fh, +); ## # put/get key @@ -112,7 +115,11 @@ is( $db->get("key1"), "value222222222222222222222222", "We set a value before cl # Make sure DB still works after closing / opening ## undef $db; -$db = DBM::Deep->new( $filename ); +open $fh, '+<', $filename; +$db = DBM::Deep->new( + file => $filename, + fh => $fh, +); is( $db->get("key1"), "value222222222222222222222222", "The value we set is still there after closure" ); ## diff --git a/t/04_array.t b/t/04_array.t index e4616ee..24b52ec 100644 --- a/t/04_array.t +++ b/t/04_array.t @@ -10,8 +10,9 @@ use_ok( 'DBM::Deep' ); my ($fh, $filename) = new_fh(); my $db = DBM::Deep->new( - file => $filename, - type => DBM::Deep->TYPE_ARRAY + file => $filename, + fh => $fh, + type => DBM::Deep->TYPE_ARRAY ); ## @@ -62,7 +63,7 @@ is( $db->fetch(4), 'elem4.1' ); throws_ok { $db->[-6] = 'whoops!'; -} qr/Modification of non-creatable array value attempted, subscript -6/, "Correct error thrown"; +} qr/Modification of non-creatable array value attempted, subscript -6/, "Correct error thrown"; my $popped = $db->pop; is( $db->length, 4, "... and we have four after popping" ); @@ -251,6 +252,7 @@ throws_ok { my ($fh, $filename) = new_fh(); my $db = DBM::Deep->new( file => $filename, + fh => $fh, type => DBM::Deep->TYPE_ARRAY ); diff --git a/t/07_locking.t b/t/07_locking.t index b36086c..004e03b 100644 --- a/t/07_locking.t +++ b/t/07_locking.t @@ -10,8 +10,9 @@ use_ok( 'DBM::Deep' ); my ($fh, $filename) = new_fh(); my $db = DBM::Deep->new( - file => $filename, - locking => 1, + file => $filename, + fh => $fh, + locking => 1, ); lives_ok { diff --git a/t/08_deephash.t b/t/08_deephash.t index f69543c..5e022c3 100644 --- a/t/08_deephash.t +++ b/t/08_deephash.t @@ -21,6 +21,7 @@ my $max_levels = 1000; { my $db = DBM::Deep->new( file => $filename, + fh => $fh, type => DBM::Deep->TYPE_HASH, ); @@ -50,8 +51,10 @@ my $max_levels = 1000; } { + open $fh, '+<', $filename; my $db = DBM::Deep->new( file => $filename, + fh => $fh, type => DBM::Deep->TYPE_HASH, ); diff --git a/t/09_deeparray.t b/t/09_deeparray.t index ad134fa..1fe9d0f 100644 --- a/t/09_deeparray.t +++ b/t/09_deeparray.t @@ -21,6 +21,7 @@ my $max_levels = 1000; { my $db = DBM::Deep->new( file => $filename, + fh => $fh, type => DBM::Deep->TYPE_ARRAY, ); @@ -34,8 +35,10 @@ my $max_levels = 1000; } { + open $fh, '+<', $filename; my $db = DBM::Deep->new( file => $filename, + fh => $fh, type => DBM::Deep->TYPE_ARRAY, ); diff --git a/t/11_optimize.t b/t/11_optimize.t index 0ae0ed8..61741bf 100644 --- a/t/11_optimize.t +++ b/t/11_optimize.t @@ -2,15 +2,21 @@ # DBM::Deep Test ## use strict; -use Test::More tests => 9; -use File::Temp qw( tmpnam ); +use Test::More; + +plan skip_all => "Skipping the optimize tests on Win32/cygwin for now." + if ( $^O eq 'MSWin32' || $^O eq 'cygwin' ); + +plan tests => 9; + +use t::common qw( new_fh ); use_ok( 'DBM::Deep' ); -my $filename = tmpnam(); +my ($fh, $filename) = new_fh(); my $db = DBM::Deep->new( - file => $filename, - autoflush => 1, + file => $filename, + autoflush => 1, ); ## @@ -53,19 +59,22 @@ ok( $after < $before, "file size has shrunk" ); # make sure file shrunk is( $db->{key1}, 'value1', "key1's value is still there after optimize" ); is( $db->{a}{c}, 'value2', "key2's value is still there after optimize" ); +$db->_get_self->_storage->close( $db->_get_self ); + ## # now for the tricky one -- try to store a new key while file is being -# optimized and locked by another process. filehandle should be invalidated, -# and automatically re-opened transparently. Cannot test on Win32, due to +# optimized and locked by another process. filehandle should be invalidated, +# and automatically re-opened transparently. Cannot test on Win32, due to # problems with fork()ing, flock()ing, etc. Win32 very bad. ## SKIP: { + skip "Fork tests skipped until fh/filename question solved.", 4; skip "Fork tests skipped on Win32", 4 if $^O eq 'MSWin32' || $^O eq 'cygwin'; ## - # first things first, get us about 1000 keys so the optimize() will take + # first things first, get us about 1000 keys so the optimize() will take # at least a few seconds on any machine, and re-open db with locking ## for (1..1000) { $db->STORE( $_, $_ +1 ); } @@ -78,14 +87,14 @@ SKIP: { unless ( $pid ) { # child fork - + # re-open db $db = DBM::Deep->new( file => $filename, autoflush => 1, locking => 1 ); - + # optimize and exit $db->optimize(); @@ -93,7 +102,7 @@ SKIP: { } # parent fork ok( defined($pid), "fork was successful" ); # make sure fork was successful - + # re-open db $db = DBM::Deep->new( file => $filename, @@ -103,10 +112,10 @@ SKIP: { # sleep for 1 second to make sure optimize() is running in the other fork sleep(1); - + # now, try to get a lock and store a key $db->{parentfork} = "hello"; - + # see if it was stored successfully is( $db->{parentfork}, "hello", "stored key while optimize took place" ); @@ -116,7 +125,7 @@ SKIP: { autoflush => 1, locking => 1 ); - + # now check some existing values from before is( $db->{key1}, 'value1', "key1's value is still there after optimize" ); is( $db->{a}{c}, 'value2', "key2's value is still there after optimize" ); diff --git a/t/16_circular.t b/t/16_circular.t index 501435d..9752816 100644 --- a/t/16_circular.t +++ b/t/16_circular.t @@ -8,7 +8,7 @@ use t::common qw( new_fh ); use_ok( 'DBM::Deep' ); my ($fh, $filename) = new_fh(); -my $db = DBM::Deep->new( $filename ); +my $db = DBM::Deep->new( file => $filename, fh => $fh, ); ## # put/get simple keys diff --git a/t/17_import.t b/t/17_import.t index c5e034e..108aae2 100644 --- a/t/17_import.t +++ b/t/17_import.t @@ -14,6 +14,7 @@ foreach my $type ( DBM::Deep->TYPE_HASH, DBM::Deep->TYPE_ARRAY ) { my ($fh, $filename) = new_fh(); my $db = DBM::Deep->new({ file => $filename, + fh => $fh, type => $type, }); @@ -49,6 +50,7 @@ foreach my $type ( DBM::Deep->TYPE_HASH, DBM::Deep->TYPE_ARRAY ) { my ($fh, $filename) = new_fh(); my $db = DBM::Deep->new({ file => $filename, + fh => $fh, autobless => 1, }); @@ -96,6 +98,7 @@ foreach my $type ( DBM::Deep->TYPE_HASH, DBM::Deep->TYPE_ARRAY ) { my ($fh, $filename) = new_fh(); my $db = DBM::Deep->new({ file => $filename, + fh => $fh, type => DBM::Deep->TYPE_ARRAY, }); @@ -129,6 +132,7 @@ foreach my $type ( DBM::Deep->TYPE_HASH, DBM::Deep->TYPE_ARRAY ) { my ($fh, $filename) = new_fh(); my $db = DBM::Deep->new({ file => $filename, + fh => $fh, autobless => 1, }); @@ -137,7 +141,7 @@ foreach my $type ( DBM::Deep->TYPE_HASH, DBM::Deep->TYPE_ARRAY ) { my $x; my $struct = { key1 => [ - 2, \$x, 3, + 2, \$x, 3, ], }; diff --git a/t/18_export.t b/t/18_export.t index 949697a..1ff8051 100644 --- a/t/18_export.t +++ b/t/18_export.t @@ -27,6 +27,7 @@ my %struct = ( my ($fh, $filename) = new_fh(); my $db = DBM::Deep->new({ file => $filename, + fh => $fh, autobless => 1, }); diff --git a/t/19_crossref.t b/t/19_crossref.t index 67a3589..ff99319 100644 --- a/t/19_crossref.t +++ b/t/19_crossref.t @@ -9,7 +9,7 @@ use t::common qw( new_fh ); use_ok( 'DBM::Deep' ); my ($fh2, $filename2) = new_fh(); -my $db2 = DBM::Deep->new( $filename2 ); +my $db2 = DBM::Deep->new( file => $filename2, fh => $fh2, ); SKIP: { skip "Apparently, we cannot detect a tied scalar?", 1; @@ -35,7 +35,7 @@ SKIP: { { my ($fh, $filename) = new_fh(); - my $db = DBM::Deep->new( $filename ); + my $db = DBM::Deep->new( file => $filename, fh => $fh, ); ## # Create structure in $db diff --git a/t/21_tie_access.t b/t/21_tie_access.t index 29a5ef6..4059fd4 100644 --- a/t/21_tie_access.t +++ b/t/21_tie_access.t @@ -16,6 +16,7 @@ my ($fh, $filename) = new_fh(); $hash{key1} = 'value'; is( $hash{key1}, 'value', 'Set and retrieved key1' ); + tied( %hash )->_get_self->_storage->close( tied( %hash )->_get_self ); } { @@ -26,6 +27,7 @@ my ($fh, $filename) = new_fh(); is( keys %hash, 1, "There's one key so far" ); ok( exists $hash{key1}, "... and it's key1" ); + tied( %hash )->_get_self->_storage->close( tied( %hash )->_get_self ); } { @@ -34,12 +36,13 @@ my ($fh, $filename) = new_fh(); file => $filename, type => DBM::Deep->TYPE_ARRAY, }; + tied( @array )->_get_self->_storage->close( tied( @array )->_get_self ); } qr/DBM::Deep: File type mismatch/, "\$SIG_TYPE doesn't match file's type"; } { my ($fh, $filename) = new_fh(); - DBM::Deep->new( file => $filename, type => DBM::Deep->TYPE_ARRAY ); + my $db = DBM::Deep->new( file => $filename, type => DBM::Deep->TYPE_ARRAY ); throws_ok { tie my %hash, 'DBM::Deep', { @@ -47,4 +50,5 @@ my ($fh, $filename) = new_fh(); type => DBM::Deep->TYPE_HASH, }; } qr/DBM::Deep: File type mismatch/, "\$SIG_TYPE doesn't match file's type"; + $db->_get_self->_storage->close( $db->_get_self ); } diff --git a/t/22_internal_copy.t b/t/22_internal_copy.t index f1a51a5..0988f8d 100644 --- a/t/22_internal_copy.t +++ b/t/22_internal_copy.t @@ -8,16 +8,16 @@ use t::common qw( new_fh ); use_ok( 'DBM::Deep' ); my ($fh, $filename) = new_fh(); -my $db = DBM::Deep->new( $filename ); +my $db = DBM::Deep->new( file => $filename, fh => $fh, ); ## # Create structure in $db ## $db->import({ - hash1 => { - subkey1 => "subvalue1", - subkey2 => "subvalue2", - }, + hash1 => { + subkey1 => "subvalue1", + subkey2 => "subvalue2", + }, hash2 => { subkey3 => 'subvalue3', }, @@ -49,16 +49,19 @@ my $max_keys = 1000; my ($fh2, $filename2) = new_fh(); { - my $db = DBM::Deep->new( $filename2 ); + my $db = DBM::Deep->new( file => $filename2, fh => $fh2, ); $db->{foo} = [ 1 .. 3 ]; for ( 0 .. $max_keys ) { $db->{'foo' . $_} = $db->{foo}; } + ## Rewind handle otherwise the signature is not recognised below. + ## The signature check should probably rewind the fh? + seek $db->_get_self->_storage->{fh}, 0, 0; } { - my $db = DBM::Deep->new( $filename2 ); + my $db = DBM::Deep->new( fh => $fh2, ); my $base_offset = $db->{foo}->_base_offset; my $count = -1; diff --git a/t/24_autobless.t b/t/24_autobless.t index 251fc7e..e2de696 100644 --- a/t/24_autobless.t +++ b/t/24_autobless.t @@ -16,6 +16,7 @@ my ($fh, $filename) = new_fh(); { my $db = DBM::Deep->new( file => $filename, + fh => $fh, autobless => 1, ); @@ -52,6 +53,7 @@ my ($fh, $filename) = new_fh(); is( $db->{unblessed}{b}[2], 3 ); $db->{blessed_long} = bless {}, 'a' x 1000; + $db->_get_self->_storage->close( $db->_get_self ); } { @@ -87,6 +89,7 @@ my ($fh, $filename) = new_fh(); is( $db->{blessed}{c}, 'new' ); isa_ok( $db->{blessed_long}, 'a' x 1000 ); + $db->_get_self->_storage->close( $db->_get_self ); } { @@ -98,7 +101,7 @@ my ($fh, $filename) = new_fh(); my $structure = $db->export(); use Data::Dumper;print Dumper $structure; - + my $obj = $structure->{blessed}; isa_ok( $obj, 'Foo' ); can_ok( $obj, 'export', 'foo' ); @@ -121,6 +124,7 @@ my ($fh, $filename) = new_fh(); is( $structure->{unblessed}{b}[0], 1 ); is( $structure->{unblessed}{b}[1], 2 ); is( $structure->{unblessed}{b}[2], 3 ); + $db->_get_self->_storage->close( $db->_get_self ); } { @@ -151,6 +155,7 @@ my ($fh, $filename) = new_fh(); is( $db->{unblessed}{b}[0], 1 ); is( $db->{unblessed}{b}[1], 2 ); is( $db->{unblessed}{b}[2], 3 ); + $db->_get_self->_storage->close( $db->_get_self ); } { @@ -158,6 +163,7 @@ my ($fh, $filename) = new_fh(); { my $db = DBM::Deep->new( file => $filename2, + fh => $fh2, autobless => 1, ); my $obj = bless { @@ -166,6 +172,7 @@ my ($fh, $filename) = new_fh(); }, 'Foo'; $db->import( { blessed => $obj } ); + $db->_get_self->_storage->close( $db->_get_self ); } { @@ -177,18 +184,20 @@ my ($fh, $filename) = new_fh(); my $blessed = $db->{blessed}; isa_ok( $blessed, 'Foo' ); is( $blessed->{a}, 1 ); + $db->_get_self->_storage->close( $db->_get_self ); } } { - ## - # test blessing hash into short named class (Foo), then re-blessing into - # longer named class (FooFoo) and replacing key in db file, then validating - # content after that point in file to check for corruption. - ## + ## + # test blessing hash into short named class (Foo), then re-blessing into + # longer named class (FooFoo) and replacing key in db file, then validating + # content after that point in file to check for corruption. + ## my ($fh3, $filename3) = new_fh(); my $db = DBM::Deep->new( file => $filename3, + fh => $fh3, autobless => 1, ); @@ -196,9 +205,9 @@ my ($fh, $filename) = new_fh(); $db->{blessed} = $obj; $db->{after} = "hello"; - + my $obj2 = bless {}, 'FooFoo'; - + $db->{blessed} = $obj2; is( $db->{after}, "hello" ); diff --git a/t/31_references.t b/t/31_references.t index af9bc30..4d46796 100644 --- a/t/31_references.t +++ b/t/31_references.t @@ -8,7 +8,7 @@ use t::common qw( new_fh ); use_ok( 'DBM::Deep' ); my ($fh, $filename) = new_fh(); -my $db = DBM::Deep->new( $filename ); +my $db = DBM::Deep->new( file => $filename, fh => $fh, ); my %hash = ( foo => 1, diff --git a/t/33_transactions.t b/t/33_transactions.t index 1edd082..1055952 100644 --- a/t/33_transactions.t +++ b/t/33_transactions.t @@ -211,7 +211,7 @@ cmp_bag( [ keys %$db1 ], [qw( foo z )], "DB1 keys correct" ); cmp_bag( [ keys %$db2 ], [qw( foo z )], "DB2 keys correct" ); SKIP: { - skip "Optimize tests skipped on Win32", 5 + skip "Optimize tests skipped on Win32", 7 if $^O eq 'MSWin32' || $^O eq 'cygwin'; $db1->optimize; diff --git a/t/38_data_sector_size.t b/t/38_data_sector_size.t index 8414066..ebdbff8 100644 --- a/t/38_data_sector_size.t +++ b/t/38_data_sector_size.t @@ -6,6 +6,18 @@ use Test::More tests => 8; use t::common qw( new_fh ); +sub do_stuff { + my ($db) = @_; + + $db->{foo}{bar} = [ 1 .. 3 ]; +} + +sub verify { + my ($db) = @_; + + cmp_ok( $db->{foo}{bar}[2], '==', 3, "Correct value found" ); +} + use_ok( 'DBM::Deep' ); my %sizes; @@ -15,6 +27,7 @@ my %sizes; { my $db = DBM::Deep->new( file => $filename, + fh => $fh, data_sector_size => 32, ); @@ -24,8 +37,9 @@ my %sizes; $sizes{32} = -s $filename; { - my $db = DBM::Deep->new( $filename ); + my $db = DBM::Deep->new( file => $filename ); verify( $db ); + $db->_get_self->_storage->close( $db->_get_self ); } } @@ -34,6 +48,7 @@ my %sizes; { my $db = DBM::Deep->new( file => $filename, + fh => $fh, data_sector_size => 64, ); @@ -45,6 +60,7 @@ my %sizes; { my $db = DBM::Deep->new( $filename ); verify( $db ); + $db->_get_self->_storage->close( $db->_get_self ); } } @@ -53,6 +69,7 @@ my %sizes; { my $db = DBM::Deep->new( file => $filename, + fh => $fh, data_sector_size => 128, ); @@ -64,6 +81,7 @@ my %sizes; { my $db = DBM::Deep->new( $filename ); verify( $db ); + $db->_get_self->_storage->close( $db->_get_self ); } } @@ -72,6 +90,7 @@ my %sizes; { my $db = DBM::Deep->new( file => $filename, + fh => $fh, data_sector_size => 256, ); @@ -83,6 +102,7 @@ my %sizes; { my $db = DBM::Deep->new( $filename ); verify( $db ); + $db->_get_self->_storage->close( $db->_get_self ); } } @@ -90,14 +110,3 @@ cmp_ok( $sizes{256}, '>', $sizes{128}, "Filesize for 256 > filesize for 128" ); cmp_ok( $sizes{128}, '>', $sizes{64}, "Filesize for 128 > filesize for 64" ); cmp_ok( $sizes{64}, '>', $sizes{32}, "Filesize for 64 > filesize for 32" ); -sub do_stuff { - my ($db) = @_; - - $db->{foo}{bar} = [ 1 .. 3 ]; -} - -sub verify { - my ($db) = @_; - - cmp_ok( $db->{foo}{bar}[2], '==', 3, "Correct value found" ); -} diff --git a/t/40_freespace.t b/t/40_freespace.t index 7b0645d..d242710 100644 --- a/t/40_freespace.t +++ b/t/40_freespace.t @@ -12,6 +12,7 @@ use_ok( 'DBM::Deep' ); my ($fh, $filename) = new_fh(); my $db = DBM::Deep->new({ file => $filename, + fh => $fh, autoflush => 1, }); @@ -63,6 +64,7 @@ use_ok( 'DBM::Deep' ); my ($fh, $filename) = new_fh(); my $db = DBM::Deep->new({ file => $filename, + fh => $fh, autoflush => 1, }); @@ -74,7 +76,7 @@ use_ok( 'DBM::Deep' ); # trigger a reindex. This requires knowing how much space is taken. Good thing # we wrote this dreck ... my $size = -s $filename; - + my $data_sector_size = $db->_engine->data_sector_size; my $expected = $size + 9 * ( 2 * $data_sector_size ); diff --git a/t/41_transaction_multilevel.t b/t/41_transaction_multilevel.t index 3351e98..f06b2eb 100644 --- a/t/41_transaction_multilevel.t +++ b/t/41_transaction_multilevel.t @@ -1,5 +1,5 @@ use strict; -use Test::More tests => 33; +use Test::More tests => 41; use Test::Deep; use t::common qw( new_fh ); @@ -8,73 +8,91 @@ use_ok( 'DBM::Deep' ); my ($fh, $filename) = new_fh(); my $db1 = DBM::Deep->new( file => $filename, + fh => $fh, locking => 1, autoflush => 1, num_txns => 2, ); +seek $db1->_get_self->_storage->{fh}, 0, 0; my $db2 = DBM::Deep->new( file => $filename, + fh => $fh, locking => 1, autoflush => 1, num_txns => 2, ); -$db1->{x} = { foo => 'y' }; -is( $db1->{x}{foo}, 'y', "Before transaction, DB1's X is Y" ); -is( $db2->{x}{foo}, 'y', "Before transaction, DB2's X is Y" ); +$db1->{x} = { xy => { foo => 'y' } }; +is( $db1->{x}{xy}{foo}, 'y', "Before transaction, DB1's X is Y" ); +is( $db2->{x}{xy}{foo}, 'y', "Before transaction, DB2's X is Y" ); $db1->begin_work; cmp_bag( [ keys %$db1 ], [qw( x )], "DB1 keys correct" ); cmp_bag( [ keys %$db2 ], [qw( x )], "DB2 keys correct" ); - cmp_bag( [ keys %{$db1->{x}} ], [qw( foo )], "DB1->X keys correct" ); - cmp_bag( [ keys %{$db2->{x}} ], [qw( foo )], "DB2->X keys correct" ); + cmp_bag( [ keys %{$db1->{x}} ], [qw( xy )], "DB1->X keys correct" ); + cmp_bag( [ keys %{$db2->{x}} ], [qw( xy )], "DB2->X keys correct" ); - is( $db1->{x}{foo}, 'y', "After transaction, DB1's X is Y" ); - is( $db2->{x}{foo}, 'y', "After transaction, DB2's X is Y" ); + cmp_bag( [ keys %{$db1->{x}{xy}} ], [qw( foo )], "DB1->X->XY keys correct" ); + cmp_bag( [ keys %{$db2->{x}{xy}} ], [qw( foo )], "DB2->X->XY keys correct" ); - $db1->{x} = { bar => 30 }; - ok( !exists $db1->{x}{foo}, "DB1: After reassignment of X, X->FOO is gone" ); - is( $db2->{x}{foo}, 'y', "DB2: After reassignment of DB1 X, X is Y" ); + is( $db1->{x}{xy}{foo}, 'y', "After transaction, DB1's X is Y" ); + is( $db2->{x}{xy}{foo}, 'y', "After transaction, DB2's X is Y" ); - cmp_bag( [ keys %{$db1->{x}} ], [qw( bar )], "DB1->X keys correct" ); - cmp_bag( [ keys %{$db2->{x}} ], [qw( foo )], "DB2->X keys correct" ); + $db1->{x} = { yz => { bar => 30 } }; + ok( !exists $db1->{x}{xy}, "DB1: After reassignment of X, X->XY is gone" ); + is( $db2->{x}{xy}{foo}, 'y', "DB2: After reassignment of DB1 X, X is Y" ); + + cmp_bag( [ keys %{$db1->{x}} ], [qw( yz )], "DB1->X keys correct" ); + cmp_bag( [ keys %{$db2->{x}} ], [qw( xy )], "DB2->X keys correct" ); $db1->rollback; cmp_bag( [ keys %$db1 ], [qw( x )], "DB1 keys correct" ); cmp_bag( [ keys %$db2 ], [qw( x )], "DB2 keys correct" ); -cmp_bag( [ keys %{$db1->{x}} ], [qw( foo )], "DB1->X keys correct" ); -cmp_bag( [ keys %{$db2->{x}} ], [qw( foo )], "DB2->X keys correct" ); +cmp_bag( [ keys %{$db1->{x}} ], [qw( xy )], "DB1->X keys correct" ); +cmp_bag( [ keys %{$db2->{x}} ], [qw( xy )], "DB2->X keys correct" ); + +cmp_bag( [ keys %{$db1->{x}{xy}} ], [qw( foo )], "DB1->X->XY keys correct" ); +cmp_bag( [ keys %{$db2->{x}{xy}} ], [qw( foo )], "DB2->X->XY keys correct" ); -is( $db1->{x}{foo}, 'y', "Before transaction, DB1's X is Y" ); -is( $db2->{x}{foo}, 'y', "Before transaction, DB2's X is Y" ); +is( $db1->{x}{xy}{foo}, 'y', "Before transaction, DB1's X is Y" ); +is( $db2->{x}{xy}{foo}, 'y', "Before transaction, DB2's X is Y" ); $db1->begin_work; cmp_bag( [ keys %$db1 ], [qw( x )], "DB1 keys correct" ); cmp_bag( [ keys %$db2 ], [qw( x )], "DB2 keys correct" ); - cmp_bag( [ keys %{$db1->{x}} ], [qw( foo )], "DB1->X keys correct" ); - cmp_bag( [ keys %{$db2->{x}} ], [qw( foo )], "DB2->X keys correct" ); + cmp_bag( [ keys %{$db1->{x}} ], [qw( xy )], "DB1->X keys correct" ); + cmp_bag( [ keys %{$db2->{x}} ], [qw( xy )], "DB2->X keys correct" ); + + cmp_bag( [ keys %{$db1->{x}{xy}} ], [qw( foo )], "DB1->X->XY keys correct" ); + cmp_bag( [ keys %{$db2->{x}{xy}} ], [qw( foo )], "DB2->X->XY keys correct" ); - is( $db1->{x}{foo}, 'y', "After transaction, DB1's X is Y" ); - is( $db2->{x}{foo}, 'y', "After transaction, DB2's X is Y" ); + is( $db1->{x}{xy}{foo}, 'y', "After transaction, DB1's X is Y" ); + is( $db2->{x}{xy}{foo}, 'y', "After transaction, DB2's X is Y" ); - $db1->{x} = { bar => 30 }; - ok( !exists $db1->{x}{foo}, "DB1: After reassignment of X, X->FOO is gone" ); - is( $db2->{x}{foo}, 'y', "DB2: After reassignment of DB1 X, X is Y" ); + $db1->{x} = { yz => { bar => 30 } }; + ok( !exists $db1->{x}{xy}, "DB1: After reassignment of X, X->XY is gone" ); + is( $db2->{x}{xy}{foo}, 'y', "DB2: After reassignment of DB1 X, X->YZ is Y" ); - cmp_bag( [ keys %{$db1->{x}} ], [qw( bar )], "DB1->X keys correct" ); - cmp_bag( [ keys %{$db2->{x}} ], [qw( foo )], "DB2->X keys correct" ); + cmp_bag( [ keys %{$db1->{x}} ], [qw( yz )], "DB1->X keys correct" ); + cmp_bag( [ keys %{$db2->{x}} ], [qw( xy )], "DB2->X keys correct" ); $db1->commit; cmp_bag( [ keys %$db1 ], [qw( x )], "DB1 keys correct" ); cmp_bag( [ keys %$db2 ], [qw( x )], "DB2 keys correct" ); -cmp_bag( [ keys %{$db1->{x}} ], [qw( bar )], "DB1->X keys correct" ); -cmp_bag( [ keys %{$db2->{x}} ], [qw( bar )], "DB2->X keys correct" ); +cmp_bag( [ keys %{$db1->{x}} ], [qw( yz )], "DB1->X keys correct" ); +cmp_bag( [ keys %{$db2->{x}} ], [qw( yz )], "DB2->X keys correct" ); + +cmp_bag( [ keys %{$db1->{x}{yz}} ], [qw( bar )], "DB1->X->XY keys correct" ); +cmp_bag( [ keys %{$db2->{x}{yz}} ], [qw( bar )], "DB2->X->XY keys correct" ); + +$db1->_get_self->_storage->close( $db1->_get_self ); +$db2->_get_self->_storage->close( $db2->_get_self ); diff --git a/t/44_upgrade_db.t b/t/44_upgrade_db.t index ba0a06a..6c7abde 100644 --- a/t/44_upgrade_db.t +++ b/t/44_upgrade_db.t @@ -4,6 +4,9 @@ use Test::More; # Add skips here BEGIN { + plan skip_all => "Skipping the upgrade_db.pl tests on Win32/cygwin for now." + if ( $^O eq 'MSWin32' || $^O eq 'cygwin' ); + my @failures; eval { use Pod::Usage 1.3; }; push @failures, 'Pod::Usage' if $@; eval { use IO::Scalar; }; push @failures, 'IO::Scalar' if $@; diff --git a/t/45_references.t b/t/45_references.t index d39ba0a..3ed2407 100644 --- a/t/45_references.t +++ b/t/45_references.t @@ -11,13 +11,17 @@ use_ok( 'DBM::Deep' ); my ($fh, $filename) = new_fh(); my $db = DBM::Deep->new( file => $filename, + fh => $fh, locking => 1, autoflush => 1, num_txns => 16, ); +seek $db->_get_self->_storage->{fh}, 0, 0; + my $db2 = DBM::Deep->new( file => $filename, + fh => $fh, locking => 1, autoflush => 1, num_txns => 16, diff --git a/t/common.pm b/t/common.pm index 5312600..97cd1c9 100644 --- a/t/common.pm +++ b/t/common.pm @@ -22,7 +22,7 @@ my $dir = tempdir( CLEANUP => 1, DIR => $parent ); #my $dir = tempdir( DIR => '.' ); sub new_fh { - my ($fh, $filename) = tempfile( 'tmpXXXX', DIR => $dir ); + my ($fh, $filename) = tempfile( 'tmpXXXX', DIR => $dir, UNLINK => 1 ); # This is because tempfile() returns a flock'ed $fh on MacOSX. flock $fh, LOCK_UN;