From: rkinyon Date: Fri, 7 Apr 2006 01:31:09 +0000 (+0000) Subject: Have a header now X-Git-Tag: 0-99_01~33 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=260a80b464ba15baf32c593f0d0ea9630fe2a4cf;p=dbsrgits%2FDBM-Deep.git Have a header now --- diff --git a/lib/DBM/Deep.pm b/lib/DBM/Deep.pm index 688e936..21adc09 100644 --- a/lib/DBM/Deep.pm +++ b/lib/DBM/Deep.pm @@ -122,8 +122,6 @@ sub _init { ? $args->{root} : DBM::Deep::_::Root->new( $args ); - #XXX Right before this line, we have to set the physical parameters like - #XXX 2S vs. 4N vs. 8Q or max_buckets, etc. $self->{engine}->setup_fh( $self ); return $self; @@ -1461,6 +1459,9 @@ L for more information. B Your returned digest strings must be B the number of bytes you specify in the hash_size parameter (in this case 32). +B If you do choose to use a custom digest algorithm, you must set it +every time you access this file. Otherwise, the default (MD5) will be used. + =head1 CIRCULAR REFERENCES DBM::Deep has B support for circular references. Meaning you diff --git a/lib/DBM/Deep/Engine.pm b/lib/DBM/Deep/Engine.pm index 81135c2..3527091 100644 --- a/lib/DBM/Deep/Engine.pm +++ b/lib/DBM/Deep/Engine.pm @@ -69,11 +69,17 @@ sub new { $self->{max_buckets} = 16; } + return $self; +} + +sub calculate_sizes { + my $self = shift; + $self->{index_size} = (2**8) * $self->{long_size}; $self->{bucket_size} = $self->{hash_size} + $self->{long_size} * 2; $self->{bucket_list_size} = $self->{max_buckets} * $self->{bucket_size}; - return $self; + return; } sub write_file_header { @@ -83,10 +89,18 @@ sub write_file_header { my $fh = $obj->_fh; my $loc = $self->_request_space( - $obj, length( SIG_FILE ) + $self->{data_size}, + $obj, length( SIG_FILE ) + 12, ); seek($fh, $loc + $obj->_root->{file_offset}, SEEK_SET); - print( $fh SIG_FILE, pack('N', 0) ); + print( $fh + SIG_FILE, + pack('N', 0), + pack('S', $self->{long_size}), + pack('A', $self->{long_pack}), + pack('S', $self->{data_size}), + pack('A', $self->{data_pack}), + pack('S', $self->{max_buckets}), + ); return; } @@ -100,15 +114,21 @@ sub read_file_header { seek($fh, 0 + $obj->_root->{file_offset}, SEEK_SET); my $buffer; my $bytes_read = read( - $fh, $buffer, length(SIG_FILE) + $self->{data_size}, + $fh, $buffer, length(SIG_FILE) + 12, ); if ( $bytes_read ) { - my ($signature, $version) = unpack( 'A4 N', $buffer ); + my ($signature, $version, @values) = unpack( 'A4 N S A S A S', $buffer ); unless ($signature eq SIG_FILE) { $self->close_fh( $obj ); $obj->_throw_error("Signature not found -- file is not a Deep DB"); } + + $#values = 4; + if ( grep { !defined } @values ) { + die "DBM::Deep: Corrupted file - bad header\n"; + } + @{$self}{qw( long_size long_pack data_size data_pack max_buckets )} = @values; } return $bytes_read; @@ -123,9 +143,12 @@ sub setup_fh { my $fh = $obj->_fh; flock $fh, LOCK_EX; + #XXX The duplication of calculate_sizes needs to go away unless ( $obj->{base_offset} ) { my $bytes_read = $self->read_file_header( $obj ); + $self->calculate_sizes; + ## # File is empty -- write header and master index ## @@ -160,6 +183,9 @@ sub setup_fh { } } } + else { + $self->calculate_sizes; + } #XXX We have to make sure we don't mess up when autoflush isn't turned on unless ( $obj->_root->{inode} ) { diff --git a/t/06_error.t b/t/06_error.t index 9f3e59e..b680d82 100644 --- a/t/06_error.t +++ b/t/06_error.t @@ -19,7 +19,7 @@ print FH 'DPDB'; close FH; throws_ok { DBM::Deep->new( $filename ); -} qr/DBM::Deep: Corrupted file, no master index record/, "Fail if there's no master index record"; +} qr/DBM::Deep: Corrupted file - bad header/, "Fail if there's a bad header"; { my ($fh, $filename) = new_fh();