Added setup_fh that handles inodes separate from open()
rkinyon [Wed, 1 Mar 2006 17:17:55 +0000 (17:17 +0000)]
lib/DBM/Deep.pm
lib/DBM/Deep/Engine.pm
t/04_array.t
t/23_misc.t
t/27_filehandle.t

index ff74226..4eab81d 100644 (file)
@@ -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;
 }
 
index 5bf80b6..a8678c2 100644 (file)
@@ -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
     ##
index cdef14e..157f1a8 100644 (file)
@@ -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" );
index 3d12cf2..5a6f179 100644 (file)
@@ -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 {
index 67e7b71..762a05c 100644 (file)
@@ -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 = <FILE>) {
 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;
+}