From: rkinyon Date: Wed, 1 Mar 2006 17:17:55 +0000 (+0000) Subject: Added setup_fh that handles inodes separate from open() X-Git-Tag: 0-99_01~105 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=70b5542878eb8e2e68692982806ab90c7879e0c7;p=dbsrgits%2FDBM-Deep.git Added setup_fh that handles inodes separate from open() --- diff --git a/lib/DBM/Deep.pm b/lib/DBM/Deep.pm index ff74226..4eab81d 100644 --- a/lib/DBM/Deep.pm +++ b/lib/DBM/Deep.pm @@ -137,7 +137,7 @@ sub _init { ? $args->{root} : DBM::Deep::_::Root->new( $args ); - if (!defined($self->_fh)) { $self->{engine}->open( $self ); } + $self->{engine}->setup_fh( $self ); return $self; } @@ -181,8 +181,11 @@ sub lock { # double-check file inode, in case another process # has optimize()d our file while we were waiting. if ($stats[1] != $self->_root->{inode}) { - $self->{engine}->open( $self ); # re-open + $self->{engine}->close( $self ); + $self->{engine}->setup_fh( $self ); flock($self->_fh, $type); # re-lock + + # This may not be necessary after re-opening $self->_root->{end} = (stat($self->_fh))[7]; # re-end } } @@ -374,8 +377,8 @@ sub optimize { $self->unlock(); $self->{engine}->close( $self ); - $self->{engine}->open( $self ); - + $self->{engine}->setup_fh( $self ); + return 1; } diff --git a/lib/DBM/Deep/Engine.pm b/lib/DBM/Deep/Engine.pm index 5bf80b6..a8678c2 100644 --- a/lib/DBM/Deep/Engine.pm +++ b/lib/DBM/Deep/Engine.pm @@ -67,13 +67,29 @@ sub set_digest { _precalc_sizes(); } +sub setup_fh { + my $self = shift; + my ($obj) = @_; + + $self->open( $obj ) if !defined $obj->_fh; + + #XXX Is {end} busted? Can't we just seek( $fh, 0, SEEK_END ) ? + unless ( $obj->_root->{inode} ) { + my @stats = stat($obj->_fh); + $obj->_root->{inode} = $stats[1]; + $obj->_root->{end} = $stats[7]; + } + + return 1; +} + sub open { ## # Open a fh to the database, create if nonexistent. # Make sure file signature matches DBM::Deep spec. ## my $self = shift; - my $obj = shift; + my ($obj) = @_; if (defined($obj->_fh)) { $self->close( $obj ); } @@ -125,10 +141,6 @@ sub open { my $old_af = $|; $| = 1; $| = $old_af; select $old_fh; - my @stats = stat($fh); - $obj->_root->{inode} = $stats[1]; - $obj->_root->{end} = $stats[7]; - return 1; } @@ -140,10 +152,6 @@ sub open { return $obj->_throw_error("Signature not found -- file is not a Deep DB"); } - my @stats = stat($fh); - $obj->_root->{inode} = $stats[1]; - $obj->_root->{end} = $stats[7]; - ## # Get our type from master index signature ## diff --git a/t/04_array.t b/t/04_array.t index cdef14e..157f1a8 100644 --- a/t/04_array.t +++ b/t/04_array.t @@ -200,9 +200,6 @@ is($db->[0], "elem first"); is($db->[1], "elem last"); is($returned[0], "middle ABC"); -# These tests verify that the hash methods cannot be called on arraytypes. -# They will be removed once the ARRAY and HASH types are refactored into their own classes. - $db->[0] = [ 1 .. 3 ]; $db->[1] = { a => 'foo' }; is( $db->[0]->length, 3, "Reuse of same space with array successful" ); diff --git a/t/23_misc.t b/t/23_misc.t index 3d12cf2..5a6f179 100644 --- a/t/23_misc.t +++ b/t/23_misc.t @@ -18,7 +18,6 @@ is( $db->{key1}, "value1", "Value set correctly" ); # Testing to verify that the close() will occur if open is called on an open DB. #XXX WOW is this hacky ... $db->_get_self->{engine}->open( $db->_get_self ); - is( $db->{key1}, "value1", "Value still set after re-open" ); throws_ok { diff --git a/t/27_filehandle.t b/t/27_filehandle.t index 67e7b71..762a05c 100644 --- a/t/27_filehandle.t +++ b/t/27_filehandle.t @@ -2,26 +2,30 @@ # DBM::Deep Test ## use strict; -use Test::More tests => 9; +use Test::More tests => 10; use Test::Exception; use DBM::Deep; -open(FILE, "t/27_filehandle.t.db") || die("Can't open t/27_filehandle.t.db\n"); +{ + open(FILE, "t/27_filehandle.t.db") || die("Can't open t/27_filehandle.t.db\n"); -my $db; + my $db; -# test if we can open and read a db using its filehandle + # test if we can open and read a db using its filehandle -ok(($db = DBM::Deep->new(fh => *FILE)), "open db in filehandle"); -ok($db->{hash}->{foo}->[1] eq 'b', "and get at stuff in the database"); -throws_ok { - $db->{foo} = 1; -} qr/Cannot write to a readonly filehandle/, "Can't write to a read-only filehandle"; -ok( !$db->exists( 'foo' ), "foo doesn't exist" ); + ok(($db = DBM::Deep->new(fh => *FILE)), "open db in filehandle"); + ok($db->{hash}->{foo}->[1] eq 'b', "and get at stuff in the database"); + throws_ok { + $db->{foo} = 1; + } qr/Cannot write to a readonly filehandle/, "Can't write to a read-only filehandle"; + ok( !$db->exists( 'foo' ), "foo doesn't exist" ); -undef $db; -close(FILE); + my $db_obj = $db->_get_self; + ok( $db_obj->_root->{inode}, "The inode has been set" ); + + close(FILE); +} # now the same, but with an offset into the file. Use the database that's # embedded in the test for the DATA filehandle. First, find the database ... @@ -32,12 +36,20 @@ while(my $line = ) { my $offset = tell(FILE); close(FILE); -open(FILE, "t/28_DATA.t"); -ok(($db = DBM::Deep->new(fh => *FILE, file_offset => $offset)), "open db in filehandle with offset"); -ok($db->{hash}->{foo}->[1] eq 'b', "and get at stuff in the database"); +{ + open(FILE, "t/28_DATA.t"); + + my $db; -ok( !$db->exists( 'foo' ), "foo doesn't exist yet" ); -throws_ok { - $db->{foo} = 1; -} qr/Cannot write to a readonly filehandle/, "Can't write to a read-only filehandle"; -ok( !$db->exists( 'foo' ), "foo doesn't exist" ); + ok(($db = DBM::Deep->new(fh => *FILE, file_offset => $offset)), "open db in filehandle with offset"); + + ok($db->{hash}->{foo}->[1] eq 'b', "and get at stuff in the database"); + + ok( !$db->exists( 'foo' ), "foo doesn't exist yet" ); + throws_ok { + $db->{foo} = 1; + } qr/Cannot write to a readonly filehandle/, "Can't write to a read-only filehandle"; + ok( !$db->exists( 'foo' ), "foo doesn't exist" ); + + close FILE; +}