Converted to using an object for each file sector type
rkinyon [Mon, 27 Nov 2006 03:38:52 +0000 (03:38 +0000)]
lib/DBM/Deep/Engine3.pm

index 6ac7093..bef1d7c 100644 (file)
@@ -9,7 +9,7 @@ our $VERSION = q(0.99_03);
 use Scalar::Util ();
 
 # File-wide notes:
-# * Every method in here assumes that the _storage has been appropriately
+# * Every method in here assumes that the storage has been appropriately
 #   safeguarded. This can be anything from flock() to some sort of manual
 #   mutex. But, it's the caller's responsability to make sure that this has
 #   been done.
@@ -33,10 +33,12 @@ sub HEAD () { 0 }
 
 ################################################################################
 
-my %size_to_pack = (
-    2 => 'n',
-    4 => 'N',
-    8 => 'Q',
+# Please refer to the pack() documentation for further information
+my %StP = (
+    1 => 'c', # Unsigned char value
+    2 => 'n', # Unsigned short in "network" (big-endian) order
+    4 => 'N', # Unsigned long in "network" (big-endian) order
+    8 => 'Q', # Usigned quad (no order specified, presumably machine-dependent)
 );
 
 sub new {
@@ -76,7 +78,7 @@ sub new {
     }
     Scalar::Util::weaken( $self->{obj} ) if $self->{obj};
 
-    $self->{byte_pack} = $size_to_pack{ $self->{byte_size} };
+    $self->{byte_pack} = $StP{ $self->byte_size };
 
     ##
     # Number of buckets per blist before another level of indexing is
@@ -141,18 +143,13 @@ sub setup_fh {
             $self->_write_file_header;
 
             # 1) Create Array/Hash entry
-            # 2) Create Index entry
+            my $initial_reference = DBM::Deep::Engine::Sector::Reference->new({
+                engine => $self,
+                type   => $obj->_type,
+            });
+            $obj->{base_offset} = $initial_reference->offset;
 
-            $obj->{base_offset} = $self->_storage->request_space(
-                $self->_tag_size( $self->{index_size} ),
-            );
-
-            $self->_write_tag(
-                $obj->_base_offset, $obj->_type,
-                chr(0) x $self->{index_size},
-            );
-
-            $self->_storage->flush;
+            $self->storage->flush;
         }
         # Reading from an existing file
         else {
@@ -171,8 +168,8 @@ sub setup_fh {
         $self->_calculate_sizes;
     }
 
-    #XXX We have to make sure we don't mess up when autoflush isn't turned on
-    $self->_storage->set_inode;
+    # We have to make sure we don't mess up when autoflush isn't turned on
+    $self->storage->set_inode;
 
     return 1;
 }
@@ -186,11 +183,13 @@ sub _calculate_sizes {
     # current hashing algorithm
     #XXX Does this need to be updated with different hashing algorithms?
     $self->{hash_chars_used}  = (2**8);
-    $self->{index_size}       = $self->{hash_chars_used} * $self->{byte_size};
+    $self->{index_size}       = $self->{hash_chars_used} * $self->byte_size;
 
-    $self->{bucket_size}      = $self->{hash_size} + $self->{byte_size} * 2;
+    $self->{bucket_size}      = $self->{hash_size} + $self->byte_size * 2;
     $self->{bucket_list_size} = $self->{max_buckets} * $self->{bucket_size};
 
+    $self->{data_size}        = 256; # In bytes
+
     return;
 }
 
@@ -200,20 +199,20 @@ sub _write_file_header {
     my $header_fixed = length( SIG_FILE ) + 1 + 4 + 4;
     my $header_var = 16 + 1 + 1;
 
-    my $loc = $self->_storage->request_space( $header_fixed + $header_var );
+    my $loc = $self->storage->request_space( $header_fixed + $header_var );
 
-    $self->_storage->print_at( $loc,
+    $self->storage->print_at( $loc,
         SIG_FILE,
         SIG_HEADER,
         pack('N', 1),  # header version - at this point, we're at 9 bytes
         pack('N', $header_var), # header size
         # --- Above is $header_fixed. Below is $header_var
         pack('N4', 0, 0, 0, 0),  # currently running transaction IDs
-        pack('n', $self->{byte_size}),
+        pack('n', $self->byte_size),
         pack('n', $self->{max_buckets}),
     );
 
-    $self->_storage->set_transaction_offset( 13 );
+    $self->storage->set_transaction_offset( 13 );
 
     return;
 }
@@ -224,7 +223,7 @@ sub _read_file_header {
     my $header_fixed = length( SIG_FILE ) + 1 + 4 + 4;
     my $header_var = 16 + 1 + 1;
 
-    my $buffer = $self->_storage->read_at( 0, $header_fixed );
+    my $buffer = $self->storage->read_at( 0, $header_fixed );
     return unless length($buffer);
 
     my ($file_signature, $sig_header, $header_version, $size) = unpack(
@@ -232,29 +231,29 @@ sub _read_file_header {
     );
 
     unless ( $file_signature eq SIG_FILE ) {
-        $self->_storage->close;
+        $self->storage->close;
         DBM::Deep->_throw_error( "Signature not found -- file is not a Deep DB" );
     }
 
     unless ( $sig_header eq SIG_HEADER ) {
-        $self->_storage->close;
+        $self->storage->close;
         DBM::Deep->_throw_error( "Old file version found." );
     }
 
     unless ( $size eq $header_var ) {
-        $self->_storage->close;
+        $self->storage->close;
         DBM::Deep->_throw_error( "Unexpected size found." );
     }
 
-    my $buffer2 = $self->_storage->read_at( undef, $size );
+    my $buffer2 = $self->storage->read_at( undef, $size );
     # $a1-4 are the transaction IDs
     my ($a1, $a2, $a3, $a4, @values) = unpack( 'N4 n n', $buffer2 );
 
     # The transaction offset is the first thing after the fixed header section
-    $self->_storage->set_transaction_offset( $header_fixed );
+    $self->storage->set_transaction_offset( $header_fixed );
 
     if ( @values < 2 || grep { !defined } @values ) {
-        $self->_storage->close;
+        $self->storage->close;
         DBM::Deep->_throw_error("Corrupted file - bad header");
     }
 
@@ -269,7 +268,7 @@ sub _write_tag {
     my ($offset, $sig, $content) = @_;
     my $size = length( $content );
 
-    $self->_storage->print_at(
+    $self->storage->print_at(
         $offset, 
         $sig, pack($self->{byte_pack}, $size), $content,
     );
@@ -279,7 +278,7 @@ sub _write_tag {
     return {
         signature => $sig,
         start     => $offset,
-        offset    => $offset + SIG_SIZE + $self->{byte_size},
+        offset    => $offset + SIG_SIZE + $self->byte_size,
         content   => $content,
         is_new    => 1,
     };
@@ -288,17 +287,17 @@ sub _write_tag {
 sub _load_tag {
     my $self = shift;
     my ($offset) = @_;
-    my $storage = $self->_storage;
+    my $storage = $self->storage;
 
     my ($sig, $size) = unpack(
         "A $self->{byte_pack}",
-        $storage->read_at( $offset, SIG_SIZE + $self->{byte_size} ),
+        $storage->read_at( $offset, SIG_SIZE + $self->byte_size ),
     );
 
     return {
         signature => $sig,
         start     => $offset,
-        offset    => $offset + SIG_SIZE + $self->{byte_size},
+        offset    => $offset + SIG_SIZE + $self->byte_size,
         content   => $storage->read_at( undef, $size ),
         is_new    => 0,
     };
@@ -307,12 +306,58 @@ sub _load_tag {
 sub _tag_size {
     my $self = shift;
     my ($size) = @_;
-    return SIG_SIZE + $self->{byte_size} + $size;
+    return SIG_SIZE + $self->byte_size + $size;
 }
 
 ################################################################################
 
-sub _storage { $_[0]{storage} }
+sub storage { $_[0]{storage} }
+sub byte_size { $_[0]{byte_size} }
+
+################################################################################
+
+package DBM::Deep::Engine::Sector::Reference;
+
+our @ISA = qw( DBM::Deep::Engine::Sector );
+
+sub _init {
+    my $self = shift;
+
+    my $engine = $self->engine;
+
+    my $leftover = $self->size - 3 - 2 * $engine->byte_size;
+
+    my $offset = $engine->storage->request_space( $self->size );
+    $engine->storage->print_at( $offset,
+        $self->type,
+        pack( $StP{1}, 0 ),                  # Recycled counter
+        pack( $StP{$engine->byte_size}, 0 ), # Chain loc
+        pack( $StP{$engine->byte_size}, 0 ), # Index/BList loc
+        pack( $StP{1}, 0 ),                  # Blessedness
+        pack( $StP{1}, 0 ),                  # Classname length
+        chr(0) x $leftover,                  # Zero-fill the data
+    );
+
+    return $offset;
+}
+
+sub type { $_[0]{type} }
+
+package DBM::Deep::Engine::Sector;
+
+sub new {
+    my $self = bless $_[1], $_[0];
+    Scalar::Util::weaken( $self->{engine} );
+    $self->{offset} = $self->_init;
+    return $self;
+}
+sub _init {}
+
+sub engine { $_[0]{engine} }
+sub offset { $_[0]{offset} }
+
+# This is in bytes
+sub size { return 256 }
 
 1;
 __END__