close() -> _close()
[dbsrgits/DBM-Deep.git] / lib / DBM / Deep.pm
1 package DBM::Deep;
2
3 ##
4 # DBM::Deep
5 #
6 # Description:
7 #       Multi-level database module for storing hash trees, arrays and simple
8 #       key/value pairs into FTP-able, cross-platform binary database files.
9 #
10 #       Type `perldoc DBM::Deep` for complete documentation.
11 #
12 # Usage Examples:
13 #       my %db;
14 #       tie %db, 'DBM::Deep', 'my_database.db'; # standard tie() method
15 #       
16 #       my $db = new DBM::Deep( 'my_database.db' ); # preferred OO method
17 #
18 #       $db->{my_scalar} = 'hello world';
19 #       $db->{my_hash} = { larry => 'genius', hashes => 'fast' };
20 #       $db->{my_array} = [ 1, 2, 3, time() ];
21 #       $db->{my_complex} = [ 'hello', { perl => 'rules' }, 42, 99 ];
22 #       push @{$db->{my_array}}, 'another value';
23 #       my @key_list = keys %{$db->{my_hash}};
24 #       print "This module " . $db->{my_complex}->[1]->{perl} . "!\n";
25 #
26 # Copyright:
27 #       (c) 2002-2005 Joseph Huckaby.  All Rights Reserved.
28 #       This program is free software; you can redistribute it and/or 
29 #       modify it under the same terms as Perl itself.
30 ##
31
32 use strict;
33
34 use FileHandle;
35 use Fcntl qw/:flock/;
36 use Digest::MD5 ();
37 use Scalar::Util ();
38 use vars qw/$VERSION/;
39
40 $VERSION = "0.96";
41
42 ##
43 # Set to 4 and 'N' for 32-bit offset tags (default).  Theoretical limit of 4 GB per file.
44 #       (Perl must be compiled with largefile support for files > 2 GB)
45 #
46 # Set to 8 and 'Q' for 64-bit offsets.  Theoretical limit of 16 XB per file.
47 #       (Perl must be compiled with largefile and 64-bit long support)
48 ##
49 #my $LONG_SIZE = 4;
50 #my $LONG_PACK = 'N';
51
52 ##
53 # Set to 4 and 'N' for 32-bit data length prefixes.  Limit of 4 GB for each key/value.
54 # Upgrading this is possible (see above) but probably not necessary.  If you need
55 # more than 4 GB for a single key or value, this module is really not for you :-)
56 ##
57 #my $DATA_LENGTH_SIZE = 4;
58 #my $DATA_LENGTH_PACK = 'N';
59 my ($LONG_SIZE, $LONG_PACK, $DATA_LENGTH_SIZE, $DATA_LENGTH_PACK);
60
61 ##
62 # Maximum number of buckets per list before another level of indexing is done.
63 # Increase this value for slightly greater speed, but larger database files.
64 # DO NOT decrease this value below 16, due to risk of recursive reindex overrun.
65 ##
66 my $MAX_BUCKETS = 16;
67
68 ##
69 # Better not adjust anything below here, unless you're me :-)
70 ##
71
72 ##
73 # Setup digest function for keys
74 ##
75 my ($DIGEST_FUNC, $HASH_SIZE);
76 #my $DIGEST_FUNC = \&Digest::MD5::md5;
77
78 ##
79 # Precalculate index and bucket sizes based on values above.
80 ##
81 #my $HASH_SIZE = 16;
82 my ($INDEX_SIZE, $BUCKET_SIZE, $BUCKET_LIST_SIZE);
83
84 set_digest();
85 #set_pack();
86 #precalc_sizes();
87
88 ##
89 # Setup file and tag signatures.  These should never change.
90 ##
91 sub SIG_FILE  () { 'DPDB' }
92 sub SIG_HASH  () { 'H' }
93 sub SIG_ARRAY () { 'A' }
94 sub SIG_NULL  () { 'N' }
95 sub SIG_DATA  () { 'D' }
96 sub SIG_INDEX () { 'I' }
97 sub SIG_BLIST () { 'B' }
98 sub SIG_SIZE  () {  1  }
99
100 ##
101 # Setup constants for users to pass to new()
102 ##
103 sub TYPE_HASH  () { return SIG_HASH; }
104 sub TYPE_ARRAY () { return SIG_ARRAY; }
105
106 sub new {
107         ##
108         # Class constructor method for Perl OO interface.
109         # Calls tie() and returns blessed reference to tied hash or array,
110         # providing a hybrid OO/tie interface.
111         ##
112         my $class = shift;
113         my $args;
114         if (scalar(@_) > 1) { $args = {@_}; }
115         else { $args = { file => shift }; }
116         
117         ##
118         # Check if we want a tied hash or array.
119         ##
120         my $self;
121         if (defined($args->{type}) && $args->{type} eq TYPE_ARRAY) {
122                 tie @$self, $class, %$args;
123         }
124         else {
125                 tie %$self, $class, %$args;
126         }
127
128         return bless $self, $class;
129 }
130
131 {
132     my @outer_params = qw( type base_offset );
133     sub _init {
134         ##
135         # Setup $self and bless into this class.
136         ##
137         my $class = shift;
138         my $args = shift;
139
140         my $self = {
141             type => TYPE_HASH,
142             base_offset => length(SIG_FILE),
143             root => {
144                 file => undef,
145                 fh => undef,
146                 end => 0,
147                 links => 0,
148                 autoflush => undef,
149                 locking => undef,
150                 volatile => undef,
151                 debug => undef,
152                 mode => 'r+',
153                 filter_store_key => undef,
154                 filter_store_value => undef,
155                 filter_fetch_key => undef,
156                 filter_fetch_value => undef,
157                 autobless => undef,
158                 locked => 0,
159                 %$args,
160             },
161         };
162
163         bless $self, $class;
164
165         foreach my $outer_parm ( @outer_params ) {
166             next unless exists $args->{$outer_parm};
167             $self->{$outer_parm} = $args->{$outer_parm}
168         }
169         
170         if ( exists $args->{root} ) {
171             $self->{root} = $args->{root};
172         }
173         else {
174             # This is cleanup based on the fact that the $args
175             # coming in is for both the root and non-root items
176             delete $self->root->{$_} for @outer_params;
177         }
178         $self->root->{links}++;
179
180         if (!defined($self->fh)) { $self->_open(); }
181
182         return $self;
183     }
184 }
185
186 sub _get_self { tied( %{$_[0]} ) || $_[0] }
187
188 sub TIEHASH {
189     ##
190     # Tied hash constructor method, called by Perl's tie() function.
191     ##
192     my $class = shift;
193     my $args;
194     if (scalar(@_) > 1) { $args = {@_}; }
195     #XXX This use of ref() is bad and is a bug
196     elsif (ref($_[0])) { $args = $_[0]; }
197     else { $args = { file => shift }; }
198
199     return $class->_init($args);
200 }
201
202 sub TIEARRAY {
203 ##
204 # Tied array constructor method, called by Perl's tie() function.
205 ##
206 my $class = shift;
207 my $args;
208 if (scalar(@_) > 1) { $args = {@_}; }
209     #XXX This use of ref() is bad and is a bug
210         elsif (ref($_[0])) { $args = $_[0]; }
211         else { $args = { file => shift }; }
212         
213         return $class->_init($args);
214 }
215
216 sub DESTROY {
217         ##
218         # Class deconstructor.  Close file handle if there are no more refs.
219         ##
220     my $self = _get_self($_[0]);
221     return unless $self;
222         
223         $self->root->{links}--;
224         
225         if (!$self->root->{links}) {
226                 $self->_close();
227         }
228 }
229
230 sub _open {
231         ##
232         # Open a FileHandle to the database, create if nonexistent.
233         # Make sure file signature matches DeepDB spec.
234         ##
235     my $self = _get_self($_[0]);
236
237         if (defined($self->fh)) { $self->_close(); }
238         
239         if (!(-e $self->root->{file}) && $self->root->{mode} eq 'r+') {
240                 my $temp = FileHandle->new( $self->root->{file}, 'w' );
241                 undef $temp;
242         }
243         
244     #XXX Convert to set_fh()
245         $self->root->{fh} = FileHandle->new( $self->root->{file}, $self->root->{mode} );
246         if (! defined($self->fh)) {
247                 return $self->throw_error("Cannot open file: " . $self->root->{file} . ": $!");
248         }
249
250     binmode $self->fh; # for win32
251     if ($self->root->{autoflush}) {
252         $self->fh->autoflush();
253     }
254     
255     my $signature;
256     seek($self->fh, 0, 0);
257     my $bytes_read = $self->fh->read($signature, length(SIG_FILE));
258     
259     ##
260     # File is empty -- write signature and master index
261     ##
262     if (!$bytes_read) {
263         seek($self->fh, 0, 0);
264         $self->fh->print(SIG_FILE);
265         $self->root->{end} = length(SIG_FILE);
266         $self->create_tag($self->base_offset, $self->type, chr(0) x $INDEX_SIZE);
267
268         my $plain_key = "[base]";
269         $self->fh->print( pack($DATA_LENGTH_PACK, length($plain_key)) . $plain_key );
270         $self->root->{end} += $DATA_LENGTH_SIZE + length($plain_key);
271         $self->fh->flush();
272
273         return 1;
274     }
275     
276     ##
277     # Check signature was valid
278     ##
279     unless ($signature eq SIG_FILE) {
280         $self->_close();
281         return $self->throw_error("Signature not found -- file is not a Deep DB");
282     }
283
284     $self->root->{end} = (stat($self->fh))[7];
285         
286     ##
287     # Get our type from master index signature
288     ##
289     my $tag = $self->load_tag($self->base_offset);
290 #XXX This is a problem - need to verify type, not override it!
291 #XXX We probably also want to store the hash algorithm name, not assume anything
292 #XXX Convert to set_type() when one is written
293     $self->{type} = $tag->{signature};
294         
295     return 1;
296 }
297
298 sub _close {
299         ##
300         # Close database FileHandle
301         ##
302     my $self = _get_self($_[0]);
303         undef $self->root->{fh};
304 }
305
306 sub create_tag {
307         ##
308         # Given offset, signature and content, create tag and write to disk
309         ##
310         my ($self, $offset, $sig, $content) = @_;
311         my $size = length($content);
312         
313         seek($self->fh, $offset, 0);
314         $self->fh->print( $sig . pack($DATA_LENGTH_PACK, $size) . $content );
315         
316         if ($offset == $self->root->{end}) {
317                 $self->root->{end} += SIG_SIZE + $DATA_LENGTH_SIZE + $size;
318         }
319         
320         return {
321                 signature => $sig,
322                 size => $size,
323                 offset => $offset + SIG_SIZE + $DATA_LENGTH_SIZE,
324                 content => $content
325         };
326 }
327
328 sub load_tag {
329         ##
330         # Given offset, load single tag and return signature, size and data
331         ##
332         my $self = shift;
333         my $offset = shift;
334         
335         seek($self->fh, $offset, 0);
336         if ($self->fh->eof()) { return; }
337         
338         my $sig;
339         $self->fh->read($sig, SIG_SIZE);
340         
341         my $size;
342         $self->fh->read($size, $DATA_LENGTH_SIZE);
343         $size = unpack($DATA_LENGTH_PACK, $size);
344         
345         my $buffer;
346         $self->fh->read($buffer, $size);
347         
348         return {
349                 signature => $sig,
350                 size => $size,
351                 offset => $offset + SIG_SIZE + $DATA_LENGTH_SIZE,
352                 content => $buffer
353         };
354 }
355
356 sub index_lookup {
357         ##
358         # Given index tag, lookup single entry in index and return .
359         ##
360         my $self = shift;
361         my ($tag, $index) = @_;
362
363         my $location = unpack($LONG_PACK, substr($tag->{content}, $index * $LONG_SIZE, $LONG_SIZE) );
364         if (!$location) { return; }
365         
366         return $self->load_tag( $location );
367 }
368
369 sub add_bucket {
370         ##
371         # Adds one key/value pair to bucket list, given offset, MD5 digest of key,
372         # plain (undigested) key and value.
373         ##
374         my $self = shift;
375         my ($tag, $md5, $plain_key, $value) = @_;
376         my $keys = $tag->{content};
377         my $location = 0;
378         my $result = 2;
379
380     my $is_dbm_deep = eval { $value->isa( 'DBM::Deep' ) };
381         my $internal_ref = $is_dbm_deep && ($value->root eq $self->root);
382
383         ##
384         # Iterate through buckets, seeing if this is a new entry or a replace.
385         ##
386         for (my $i=0; $i<$MAX_BUCKETS; $i++) {
387                 my $key = substr($keys, $i * $BUCKET_SIZE, $HASH_SIZE);
388                 my $subloc = unpack($LONG_PACK, substr($keys, ($i * $BUCKET_SIZE) + $HASH_SIZE, $LONG_SIZE));
389                 if (!$subloc) {
390                         ##
391                         # Found empty bucket (end of list).  Populate and exit loop.
392                         ##
393                         $result = 2;
394                         
395                         if ($internal_ref) { $location = $value->base_offset; }
396                         else { $location = $self->root->{end}; }
397                         
398                         seek($self->fh, $tag->{offset} + ($i * $BUCKET_SIZE), 0);
399                         $self->fh->print( $md5 . pack($LONG_PACK, $location) );
400                         last;
401                 }
402                 elsif ($md5 eq $key) {
403                         ##
404                         # Found existing bucket with same key.  Replace with new value.
405                         ##
406                         $result = 1;
407                         
408                         if ($internal_ref) {
409                                 $location = $value->base_offset;
410                                 seek($self->fh, $tag->{offset} + ($i * $BUCKET_SIZE), 0);
411                                 $self->fh->print( $md5 . pack($LONG_PACK, $location) );
412                         }
413                         else {
414                                 seek($self->fh, $subloc + SIG_SIZE, 0);
415                                 my $size;
416                                 $self->fh->read($size, $DATA_LENGTH_SIZE); $size = unpack($DATA_LENGTH_PACK, $size);
417                                 
418                                 ##
419                                 # If value is a hash, array, or raw value with equal or less size, we can
420                                 # reuse the same content area of the database.  Otherwise, we have to create
421                                 # a new content area at the EOF.
422                                 ##
423                                 my $actual_length;
424                 my $r = Scalar::Util::reftype( $value ) || '';
425                 if ( $r eq 'HASH' || $r eq 'ARRAY' ) { $actual_length = $INDEX_SIZE; }
426                                 else { $actual_length = length($value); }
427                                 
428                                 if ($actual_length <= $size) {
429                                         $location = $subloc;
430                                 }
431                                 else {
432                                         $location = $self->root->{end};
433                                         seek($self->fh, $tag->{offset} + ($i * $BUCKET_SIZE) + $HASH_SIZE, 0);
434                                         $self->fh->print( pack($LONG_PACK, $location) );
435                                 }
436                         }
437                         last;
438                 }
439         } # i loop
440         
441         ##
442         # If this is an internal reference, return now.
443         # No need to write value or plain key
444         ##
445         if ($internal_ref) {
446         return $result;
447     }
448         
449         ##
450         # If bucket didn't fit into list, split into a new index level
451         ##
452         if (!$location) {
453                 seek($self->fh, $tag->{ref_loc}, 0);
454                 $self->fh->print( pack($LONG_PACK, $self->root->{end}) );
455                 
456                 my $index_tag = $self->create_tag($self->root->{end}, SIG_INDEX, chr(0) x $INDEX_SIZE);
457                 my @offsets = ();
458                 
459                 $keys .= $md5 . pack($LONG_PACK, 0);
460                 
461                 for (my $i=0; $i<=$MAX_BUCKETS; $i++) {
462                         my $key = substr($keys, $i * $BUCKET_SIZE, $HASH_SIZE);
463                         if ($key) {
464                                 my $old_subloc = unpack($LONG_PACK, substr($keys, ($i * $BUCKET_SIZE) + $HASH_SIZE, $LONG_SIZE));
465                                 my $num = ord(substr($key, $tag->{ch} + 1, 1));
466                                 
467                                 if ($offsets[$num]) {
468                                         my $offset = $offsets[$num] + SIG_SIZE + $DATA_LENGTH_SIZE;
469                                         seek($self->fh, $offset, 0);
470                                         my $subkeys;
471                                         $self->fh->read($subkeys, $BUCKET_LIST_SIZE);
472                                         
473                                         for (my $k=0; $k<$MAX_BUCKETS; $k++) {
474                                                 my $subloc = unpack($LONG_PACK, substr($subkeys, ($k * $BUCKET_SIZE) + $HASH_SIZE, $LONG_SIZE));
475                                                 if (!$subloc) {
476                                                         seek($self->fh, $offset + ($k * $BUCKET_SIZE), 0);
477                                                         $self->fh->print( $key . pack($LONG_PACK, $old_subloc || $self->root->{end}) );
478                                                         last;
479                                                 }
480                                         } # k loop
481                                 }
482                                 else {
483                                         $offsets[$num] = $self->root->{end};
484                                         seek($self->fh, $index_tag->{offset} + ($num * $LONG_SIZE), 0);
485                                         $self->fh->print( pack($LONG_PACK, $self->root->{end}) );
486                                         
487                                         my $blist_tag = $self->create_tag($self->root->{end}, SIG_BLIST, chr(0) x $BUCKET_LIST_SIZE);
488                                         
489                                         seek($self->fh, $blist_tag->{offset}, 0);
490                                         $self->fh->print( $key . pack($LONG_PACK, $old_subloc || $self->root->{end}) );
491                                 }
492                         } # key is real
493                 } # i loop
494                 
495                 $location ||= $self->root->{end};
496         } # re-index bucket list
497         
498         ##
499         # Seek to content area and store signature, value and plaintext key
500         ##
501         if ($location) {
502                 my $content_length;
503                 seek($self->fh, $location, 0);
504                 
505                 ##
506                 # Write signature based on content type, set content length and write actual value.
507                 ##
508         my $r = Scalar::Util::reftype($value) || '';
509                 if ($r eq 'HASH') {
510                         $self->fh->print( TYPE_HASH );
511                         $self->fh->print( pack($DATA_LENGTH_PACK, $INDEX_SIZE) . chr(0) x $INDEX_SIZE );
512                         $content_length = $INDEX_SIZE;
513                 }
514                 elsif ($r eq 'ARRAY') {
515                         $self->fh->print( TYPE_ARRAY );
516                         $self->fh->print( pack($DATA_LENGTH_PACK, $INDEX_SIZE) . chr(0) x $INDEX_SIZE );
517                         $content_length = $INDEX_SIZE;
518                 }
519                 elsif (!defined($value)) {
520                         $self->fh->print( SIG_NULL );
521                         $self->fh->print( pack($DATA_LENGTH_PACK, 0) );
522                         $content_length = 0;
523                 }
524                 else {
525                         $self->fh->print( SIG_DATA );
526                         $self->fh->print( pack($DATA_LENGTH_PACK, length($value)) . $value );
527                         $content_length = length($value);
528                 }
529                 
530                 ##
531                 # Plain key is stored AFTER value, as keys are typically fetched less often.
532                 ##
533                 $self->fh->print( pack($DATA_LENGTH_PACK, length($plain_key)) . $plain_key );
534                 
535                 ##
536                 # If value is blessed, preserve class name
537                 ##
538                 my $value_class = Scalar::Util::blessed($value);
539                 if ($self->root->{autobless} && defined $value_class && $value_class ne 'DBM::Deep' ) {
540             ##
541             # Blessed ref -- will restore later
542             ##
543             $self->fh->print( chr(1) );
544             $self->fh->print( pack($DATA_LENGTH_PACK, length($value_class)) . $value_class );
545             $content_length += 1;
546             $content_length += $DATA_LENGTH_SIZE + length($value_class);
547                 }
548                 
549                 ##
550                 # If this is a new content area, advance EOF counter
551                 ##
552                 if ($location == $self->root->{end}) {
553                         $self->root->{end} += SIG_SIZE;
554                         $self->root->{end} += $DATA_LENGTH_SIZE + $content_length;
555                         $self->root->{end} += $DATA_LENGTH_SIZE + length($plain_key);
556                 }
557                 
558                 ##
559                 # If content is a hash or array, create new child DeepDB object and
560                 # pass each key or element to it.
561                 ##
562                 if ($r eq 'HASH') {
563                         my $branch = DBM::Deep->new(
564                                 type => TYPE_HASH,
565                                 base_offset => $location,
566                                 root => $self->root,
567                         );
568                         foreach my $key (keys %{$value}) {
569                                 $branch->{$key} = $value->{$key};
570                         }
571                 }
572                 elsif ($r eq 'ARRAY') {
573                         my $branch = DBM::Deep->new(
574                                 type => TYPE_ARRAY,
575                                 base_offset => $location,
576                                 root => $self->root,
577                         );
578                         my $index = 0;
579                         foreach my $element (@{$value}) {
580                                 $branch->[$index] = $element;
581                                 $index++;
582                         }
583                 }
584                 
585                 return $result;
586         }
587         
588         return $self->throw_error("Fatal error: indexing failed -- possibly due to corruption in file");
589 }
590
591 sub get_bucket_value {
592         ##
593         # Fetch single value given tag and MD5 digested key.
594         ##
595         my $self = shift;
596         my ($tag, $md5) = @_;
597         my $keys = $tag->{content};
598         
599         ##
600         # Iterate through buckets, looking for a key match
601         ##
602     BUCKET:
603         for (my $i=0; $i<$MAX_BUCKETS; $i++) {
604                 my $key = substr($keys, $i * $BUCKET_SIZE, $HASH_SIZE);
605                 my $subloc = unpack($LONG_PACK, substr($keys, ($i * $BUCKET_SIZE) + $HASH_SIZE, $LONG_SIZE));
606
607                 if (!$subloc) {
608                         ##
609                         # Hit end of list, no match
610                         ##
611                         return;
612                 }
613
614         if ( $md5 ne $key ) {
615             next BUCKET;
616         }
617
618         ##
619         # Found match -- seek to offset and read signature
620         ##
621         my $signature;
622         seek($self->fh, $subloc, 0);
623         $self->fh->read($signature, SIG_SIZE);
624         
625         ##
626         # If value is a hash or array, return new DeepDB object with correct offset
627         ##
628         if (($signature eq TYPE_HASH) || ($signature eq TYPE_ARRAY)) {
629             my $obj = DBM::Deep->new(
630                 type => $signature,
631                 base_offset => $subloc,
632                 root => $self->root
633             );
634             
635             if ($self->root->{autobless}) {
636                 ##
637                 # Skip over value and plain key to see if object needs
638                 # to be re-blessed
639                 ##
640                 seek($self->fh, $DATA_LENGTH_SIZE + $INDEX_SIZE, 1);
641                 
642                 my $size;
643                 $self->fh->read($size, $DATA_LENGTH_SIZE); $size = unpack($DATA_LENGTH_PACK, $size);
644                 if ($size) { seek($self->fh, $size, 1); }
645                 
646                 my $bless_bit;
647                 $self->fh->read($bless_bit, 1);
648                 if (ord($bless_bit)) {
649                     ##
650                     # Yes, object needs to be re-blessed
651                     ##
652                     my $class_name;
653                     $self->fh->read($size, $DATA_LENGTH_SIZE); $size = unpack($DATA_LENGTH_PACK, $size);
654                     if ($size) { $self->fh->read($class_name, $size); }
655                     if ($class_name) { $obj = bless( $obj, $class_name ); }
656                 }
657             }
658             
659             return $obj;
660         }
661         
662         ##
663         # Otherwise return actual value
664         ##
665         elsif ($signature eq SIG_DATA) {
666             my $size;
667             my $value = '';
668             $self->fh->read($size, $DATA_LENGTH_SIZE); $size = unpack($DATA_LENGTH_PACK, $size);
669             if ($size) { $self->fh->read($value, $size); }
670             return $value;
671         }
672         
673         ##
674         # Key exists, but content is null
675         ##
676         else { return; }
677         } # i loop
678
679         return;
680 }
681
682 sub delete_bucket {
683         ##
684         # Delete single key/value pair given tag and MD5 digested key.
685         ##
686         my $self = shift;
687         my ($tag, $md5) = @_;
688         my $keys = $tag->{content};
689         
690         ##
691         # Iterate through buckets, looking for a key match
692         ##
693     BUCKET:
694         for (my $i=0; $i<$MAX_BUCKETS; $i++) {
695                 my $key = substr($keys, $i * $BUCKET_SIZE, $HASH_SIZE);
696                 my $subloc = unpack($LONG_PACK, substr($keys, ($i * $BUCKET_SIZE) + $HASH_SIZE, $LONG_SIZE));
697
698                 if (!$subloc) {
699                         ##
700                         # Hit end of list, no match
701                         ##
702                         return;
703                 }
704
705         if ( $md5 ne $key ) {
706             next BUCKET;
707         }
708
709         ##
710         # Matched key -- delete bucket and return
711         ##
712         seek($self->fh, $tag->{offset} + ($i * $BUCKET_SIZE), 0);
713         $self->fh->print( substr($keys, ($i+1) * $BUCKET_SIZE ) );
714         $self->fh->print( chr(0) x $BUCKET_SIZE );
715         
716         return 1;
717         } # i loop
718
719         return;
720 }
721
722 sub bucket_exists {
723         ##
724         # Check existence of single key given tag and MD5 digested key.
725         ##
726         my $self = shift;
727         my ($tag, $md5) = @_;
728         my $keys = $tag->{content};
729         
730         ##
731         # Iterate through buckets, looking for a key match
732         ##
733     BUCKET:
734         for (my $i=0; $i<$MAX_BUCKETS; $i++) {
735                 my $key = substr($keys, $i * $BUCKET_SIZE, $HASH_SIZE);
736                 my $subloc = unpack($LONG_PACK, substr($keys, ($i * $BUCKET_SIZE) + $HASH_SIZE, $LONG_SIZE));
737
738                 if (!$subloc) {
739                         ##
740                         # Hit end of list, no match
741                         ##
742                         return;
743                 }
744
745         if ( $md5 ne $key ) {
746             next BUCKET;
747         }
748
749         ##
750         # Matched key -- return true
751         ##
752         return 1;
753         } # i loop
754
755         return;
756 }
757
758 sub find_bucket_list {
759         ##
760         # Locate offset for bucket list, given digested key
761         ##
762         my $self = shift;
763         my $md5 = shift;
764         
765         ##
766         # Locate offset for bucket list using digest index system
767         ##
768         my $ch = 0;
769         my $tag = $self->load_tag($self->base_offset);
770         if (!$tag) { return; }
771         
772         while ($tag->{signature} ne SIG_BLIST) {
773                 $tag = $self->index_lookup($tag, ord(substr($md5, $ch, 1)));
774                 if (!$tag) { return; }
775                 $ch++;
776         }
777         
778         return $tag;
779 }
780
781 sub traverse_index {
782         ##
783         # Scan index and recursively step into deeper levels, looking for next key.
784         ##
785     my ($self, $offset, $ch, $force_return_next) = @_;
786     $force_return_next = undef unless $force_return_next;
787         
788         my $tag = $self->load_tag( $offset );
789         
790         if ($tag->{signature} ne SIG_BLIST) {
791                 my $content = $tag->{content};
792                 my $start;
793                 if ($self->{return_next}) { $start = 0; }
794                 else { $start = ord(substr($self->{prev_md5}, $ch, 1)); }
795                 
796                 for (my $index = $start; $index < 256; $index++) {
797                         my $subloc = unpack($LONG_PACK, substr($content, $index * $LONG_SIZE, $LONG_SIZE) );
798                         if ($subloc) {
799                                 my $result = $self->traverse_index( $subloc, $ch + 1, $force_return_next );
800                                 if (defined($result)) { return $result; }
801                         }
802                 } # index loop
803                 
804                 $self->{return_next} = 1;
805         } # tag is an index
806         
807         elsif ($tag->{signature} eq SIG_BLIST) {
808                 my $keys = $tag->{content};
809                 if ($force_return_next) { $self->{return_next} = 1; }
810                 
811                 ##
812                 # Iterate through buckets, looking for a key match
813                 ##
814                 for (my $i=0; $i<$MAX_BUCKETS; $i++) {
815                         my $key = substr($keys, $i * $BUCKET_SIZE, $HASH_SIZE);
816                         my $subloc = unpack($LONG_PACK, substr($keys, ($i * $BUCKET_SIZE) + $HASH_SIZE, $LONG_SIZE));
817         
818                         if (!$subloc) {
819                                 ##
820                                 # End of bucket list -- return to outer loop
821                                 ##
822                                 $self->{return_next} = 1;
823                                 last;
824                         }
825                         elsif ($key eq $self->{prev_md5}) {
826                                 ##
827                                 # Located previous key -- return next one found
828                                 ##
829                                 $self->{return_next} = 1;
830                                 next;
831                         }
832                         elsif ($self->{return_next}) {
833                                 ##
834                                 # Seek to bucket location and skip over signature
835                                 ##
836                                 seek($self->fh, $subloc + SIG_SIZE, 0);
837                                 
838                                 ##
839                                 # Skip over value to get to plain key
840                                 ##
841                                 my $size;
842                                 $self->fh->read($size, $DATA_LENGTH_SIZE); $size = unpack($DATA_LENGTH_PACK, $size);
843                                 if ($size) { seek($self->fh, $size, 1); }
844                                 
845                                 ##
846                                 # Read in plain key and return as scalar
847                                 ##
848                                 my $plain_key;
849                                 $self->fh->read($size, $DATA_LENGTH_SIZE); $size = unpack($DATA_LENGTH_PACK, $size);
850                                 if ($size) { $self->fh->read($plain_key, $size); }
851                                 
852                                 return $plain_key;
853                         }
854                 } # bucket loop
855                 
856                 $self->{return_next} = 1;
857         } # tag is a bucket list
858         
859         return;
860 }
861
862 sub get_next_key {
863         ##
864         # Locate next key, given digested previous one
865         ##
866     my $self = _get_self($_[0]);
867         
868         $self->{prev_md5} = $_[1] ? $_[1] : undef;
869         $self->{return_next} = 0;
870         
871         ##
872         # If the previous key was not specifed, start at the top and
873         # return the first one found.
874         ##
875         if (!$self->{prev_md5}) {
876                 $self->{prev_md5} = chr(0) x $HASH_SIZE;
877                 $self->{return_next} = 1;
878         }
879         
880         return $self->traverse_index( $self->base_offset, 0 );
881 }
882
883 sub lock {
884         ##
885         # If db locking is set, flock() the db file.  If called multiple
886         # times before unlock(), then the same number of unlocks() must
887         # be called before the lock is released.
888         ##
889     my $self = _get_self($_[0]);
890         my $type = $_[1];
891     $type = LOCK_EX unless defined $type;
892         
893         if ($self->root->{locking}) {
894                 if (!$self->root->{locked}) { flock($self->fh, $type); }
895                 $self->root->{locked}++;
896         }
897 }
898
899 sub unlock {
900         ##
901         # If db locking is set, unlock the db file.  See note in lock()
902         # regarding calling lock() multiple times.
903         ##
904     my $self = _get_self($_[0]);
905         
906         if ($self->root->{locking} && $self->root->{locked} > 0) {
907                 $self->root->{locked}--;
908                 if (!$self->root->{locked}) { flock($self->fh, LOCK_UN); }
909         }
910 }
911
912 #XXX These uses of ref() need verified
913 sub copy_node {
914         ##
915         # Copy single level of keys or elements to new DB handle.
916         # Recurse for nested structures
917         ##
918     my $self = _get_self($_[0]);
919         my $db_temp = $_[1];
920
921         if ($self->type eq TYPE_HASH) {
922                 my $key = $self->first_key();
923                 while ($key) {
924                         my $value = $self->get($key);
925                         if (!ref($value)) { $db_temp->{$key} = $value; }
926                         else {
927                                 my $type = $value->type;
928                                 if ($type eq TYPE_HASH) { $db_temp->{$key} = {}; }
929                                 else { $db_temp->{$key} = []; }
930                                 $value->copy_node( $db_temp->{$key} );
931                         }
932                         $key = $self->next_key($key);
933                 }
934         }
935         else {
936                 my $length = $self->length();
937                 for (my $index = 0; $index < $length; $index++) {
938                         my $value = $self->get($index);
939                         if (!ref($value)) { $db_temp->[$index] = $value; }
940             #XXX NO tests for this code
941                         else {
942                                 my $type = $value->type;
943                                 if ($type eq TYPE_HASH) { $db_temp->[$index] = {}; }
944                                 else { $db_temp->[$index] = []; }
945                                 $value->copy_node( $db_temp->[$index] );
946                         }
947                 }
948         }
949 }
950
951 sub export {
952         ##
953         # Recursively export into standard Perl hashes and arrays.
954         ##
955     my $self = _get_self($_[0]);
956         
957         my $temp;
958         if ($self->type eq TYPE_HASH) { $temp = {}; }
959         elsif ($self->type eq TYPE_ARRAY) { $temp = []; }
960         
961         $self->lock();
962         $self->copy_node( $temp );
963         $self->unlock();
964         
965         return $temp;
966 }
967
968 sub import {
969         ##
970         # Recursively import Perl hash/array structure
971         ##
972     #XXX This use of ref() seems to be ok
973         if (!ref($_[0])) { return; } # Perl calls import() on use -- ignore
974         
975     my $self = _get_self($_[0]);
976         my $struct = $_[1];
977         
978     #XXX This use of ref() seems to be ok
979         if (!ref($struct)) {
980                 ##
981                 # struct is not a reference, so just import based on our type
982                 ##
983                 shift @_;
984                 
985                 if ($self->type eq TYPE_HASH) { $struct = {@_}; }
986                 elsif ($self->type eq TYPE_ARRAY) { $struct = [@_]; }
987         }
988         
989     my $r = Scalar::Util::reftype($struct) || '';
990         if ($r eq "HASH" && $self->type eq TYPE_HASH) {
991                 foreach my $key (keys %$struct) { $self->put($key, $struct->{$key}); }
992         }
993         elsif ($r eq "ARRAY" && $self->type eq TYPE_ARRAY) {
994                 $self->push( @$struct );
995         }
996         else {
997                 return $self->throw_error("Cannot import: type mismatch");
998         }
999         
1000         return 1;
1001 }
1002
1003 sub optimize {
1004         ##
1005         # Rebuild entire database into new file, then move
1006         # it back on top of original.
1007         ##
1008     my $self = _get_self($_[0]);
1009         if ($self->root->{links} > 1) {
1010                 return $self->throw_error("Cannot optimize: reference count is greater than 1");
1011         }
1012         
1013         my $db_temp = DBM::Deep->new(
1014                 file => $self->root->{file} . '.tmp',
1015                 type => $self->type
1016         );
1017         if (!$db_temp) {
1018                 return $self->throw_error("Cannot optimize: failed to open temp file: $!");
1019         }
1020         
1021         $self->lock();
1022         $self->copy_node( $db_temp );
1023         undef $db_temp;
1024         
1025         ##
1026         # Attempt to copy user, group and permissions over to new file
1027         ##
1028         my @stats = stat($self->fh);
1029         my $perms = $stats[2] & 07777;
1030         my $uid = $stats[4];
1031         my $gid = $stats[5];
1032         chown( $uid, $gid, $self->root->{file} . '.tmp' );
1033         chmod( $perms, $self->root->{file} . '.tmp' );
1034         
1035     # q.v. perlport for more information on this variable
1036     if ( $^O eq 'MSWin32' ) {
1037                 ##
1038                 # Potential race condition when optmizing on Win32 with locking.
1039                 # The Windows filesystem requires that the filehandle be closed 
1040                 # before it is overwritten with rename().  This could be redone
1041                 # with a soft copy.
1042                 ##
1043                 $self->unlock();
1044                 $self->_close();
1045         }
1046         
1047         if (!rename $self->root->{file} . '.tmp', $self->root->{file}) {
1048                 unlink $self->root->{file} . '.tmp';
1049                 $self->unlock();
1050                 return $self->throw_error("Optimize failed: Cannot copy temp file over original: $!");
1051         }
1052         
1053         $self->unlock();
1054         $self->_close();
1055         $self->_open();
1056         
1057         return 1;
1058 }
1059
1060 sub clone {
1061         ##
1062         # Make copy of object and return
1063         ##
1064     my $self = _get_self($_[0]);
1065         
1066         return DBM::Deep->new(
1067                 type => $self->type,
1068                 base_offset => $self->base_offset,
1069                 root => $self->root
1070         );
1071 }
1072
1073 {
1074     my %is_legal_filter = map {
1075         $_ => ~~1,
1076     } qw(
1077         store_key store_value
1078         fetch_key fetch_value
1079     );
1080
1081     sub set_filter {
1082         ##
1083         # Setup filter function for storing or fetching the key or value
1084         ##
1085         my $self = _get_self($_[0]);
1086         my $type = lc $_[1];
1087         my $func = $_[2] ? $_[2] : undef;
1088         
1089         if ( $is_legal_filter{$type} ) {
1090             $self->root->{"filter_$type"} = $func;
1091             return 1;
1092         }
1093
1094         return;
1095     }
1096 }
1097
1098 ##
1099 # Accessor methods
1100 ##
1101
1102 sub root {
1103         ##
1104         # Get access to the root structure
1105         ##
1106     my $self = _get_self($_[0]);
1107         return $self->{root};
1108 }
1109
1110 sub fh {
1111         ##
1112         # Get access to the raw FileHandle
1113         ##
1114     #XXX It will be useful, though, when we split out HASH and ARRAY
1115     my $self = _get_self($_[0]);
1116         return $self->root->{fh};
1117 }
1118
1119 sub type {
1120         ##
1121         # Get type of current node (TYPE_HASH or TYPE_ARRAY)
1122         ##
1123     my $self = _get_self($_[0]);
1124         return $self->{type};
1125 }
1126
1127 sub base_offset {
1128         ##
1129         # Get base_offset of current node (TYPE_HASH or TYPE_ARRAY)
1130         ##
1131     my $self = _get_self($_[0]);
1132         return $self->{base_offset};
1133 }
1134
1135 sub error {
1136         ##
1137         # Get last error string, or undef if no error
1138         ##
1139         return $_[0]
1140         ? ( _get_self($_[0])->{root}->{error} or undef )
1141         : $@;
1142 }
1143
1144 ##
1145 # Utility methods
1146 ##
1147
1148 sub throw_error {
1149         ##
1150         # Store error string in self
1151         ##
1152     my $self = _get_self($_[0]);
1153         my $error_text = $_[1];
1154         
1155         $self->root->{error} = $error_text;
1156         
1157         unless ($self->root->{debug}) {
1158         die "DBM::Deep: $error_text\n";
1159     }
1160
1161     warn "DBM::Deep: $error_text\n";
1162         return;
1163 }
1164
1165 sub clear_error {
1166         ##
1167         # Clear error state
1168         ##
1169     my $self = _get_self($_[0]);
1170         
1171         undef $self->root->{error};
1172 }
1173
1174 sub precalc_sizes {
1175         ##
1176         # Precalculate index, bucket and bucket list sizes
1177         ##
1178
1179     #XXX I don't like this ...
1180     set_pack() unless defined $LONG_SIZE;
1181
1182         $INDEX_SIZE = 256 * $LONG_SIZE;
1183         $BUCKET_SIZE = $HASH_SIZE + $LONG_SIZE;
1184         $BUCKET_LIST_SIZE = $MAX_BUCKETS * $BUCKET_SIZE;
1185 }
1186
1187 sub set_pack {
1188         ##
1189         # Set pack/unpack modes (see file header for more)
1190         ##
1191     my ($long_s, $long_p, $data_s, $data_p) = @_;
1192
1193     $LONG_SIZE = $long_s ? $long_s : 4;
1194     $LONG_PACK = $long_p ? $long_p : 'N';
1195
1196     $DATA_LENGTH_SIZE = $data_s ? $data_s : 4;
1197     $DATA_LENGTH_PACK = $data_p ? $data_p : 'N';
1198
1199         precalc_sizes();
1200 }
1201
1202 sub set_digest {
1203         ##
1204         # Set key digest function (default is MD5)
1205         ##
1206     my ($digest_func, $hash_size) = @_;
1207
1208     $DIGEST_FUNC = $digest_func ? $digest_func : \&Digest::MD5::md5;
1209     $HASH_SIZE = $hash_size ? $hash_size : 16;
1210
1211         precalc_sizes();
1212 }
1213
1214 ##
1215 # tie() methods (hashes and arrays)
1216 ##
1217
1218 sub STORE {
1219         ##
1220         # Store single hash key/value or array element in database.
1221         ##
1222     my $self = _get_self($_[0]);
1223         my $key = ($self->root->{filter_store_key} && $self->type eq TYPE_HASH) ? $self->root->{filter_store_key}->($_[1]) : $_[1];
1224     #XXX What is ref() checking here?
1225         my $value = ($self->root->{filter_store_value} && !ref($_[2])) ? $self->root->{filter_store_value}->($_[2]) : $_[2];
1226         
1227         my $unpacked_key = $key;
1228         if (($self->type eq TYPE_ARRAY) && ($key =~ /^\d+$/)) { $key = pack($LONG_PACK, $key); }
1229         my $md5 = $DIGEST_FUNC->($key);
1230         
1231         ##
1232         # Make sure file is open
1233         ##
1234         if (!defined($self->fh) && !$self->_open()) {
1235                 return;
1236         }
1237         
1238         ##
1239         # Request exclusive lock for writing
1240         ##
1241         $self->lock( LOCK_EX );
1242
1243         ##
1244         # If locking is enabled, set 'end' parameter again, in case another
1245         # DB instance appended to our file while we were unlocked.
1246         ##
1247         if ($self->root->{locking} || $self->root->{volatile}) {
1248                 $self->root->{end} = (stat($self->fh))[7];
1249         }
1250         
1251         ##
1252         # Locate offset for bucket list using digest index system
1253         ##
1254         my $tag = $self->load_tag($self->base_offset);
1255         if (!$tag) {
1256                 $tag = $self->create_tag($self->base_offset, SIG_INDEX, chr(0) x $INDEX_SIZE);
1257         }
1258         
1259         my $ch = 0;
1260         while ($tag->{signature} ne SIG_BLIST) {
1261                 my $num = ord(substr($md5, $ch, 1));
1262                 my $new_tag = $self->index_lookup($tag, $num);
1263                 if (!$new_tag) {
1264                         my $ref_loc = $tag->{offset} + ($num * $LONG_SIZE);
1265                         seek($self->fh, $ref_loc, 0);
1266                         $self->fh->print( pack($LONG_PACK, $self->root->{end}) );
1267                         
1268                         $tag = $self->create_tag($self->root->{end}, SIG_BLIST, chr(0) x $BUCKET_LIST_SIZE);
1269                         $tag->{ref_loc} = $ref_loc;
1270                         $tag->{ch} = $ch;
1271                         last;
1272                 }
1273                 else {
1274                         my $ref_loc = $tag->{offset} + ($num * $LONG_SIZE);
1275                         $tag = $new_tag;
1276                         $tag->{ref_loc} = $ref_loc;
1277                         $tag->{ch} = $ch;
1278                 }
1279                 $ch++;
1280         }
1281         
1282         ##
1283         # Add key/value to bucket list
1284         ##
1285         my $result = $self->add_bucket( $tag, $md5, $key, $value );
1286         
1287         ##
1288         # If this object is an array, and bucket was not a replace, and key is numerical,
1289         # and index is equal or greater than current length, advance length variable.
1290         ##
1291         if (($result == 2) && ($self->type eq TYPE_ARRAY) && ($unpacked_key =~ /^\d+$/) && ($unpacked_key >= $self->FETCHSIZE())) {
1292                 $self->STORESIZE( $unpacked_key + 1 );
1293         }
1294         
1295         $self->unlock();
1296
1297         return $result;
1298 }
1299
1300 sub FETCH {
1301         ##
1302         # Fetch single value or element given plain key or array index
1303         ##
1304     my $self = _get_self($_[0]);
1305
1306     my $key = $_[1];
1307     if ( $self->type eq TYPE_HASH ) {
1308         if ( my $filter = $self->root->{filter_store_key} ) {
1309             $key = $filter->( $key );
1310         }
1311     }
1312     elsif ( $self->type eq TYPE_ARRAY ) { 
1313         if ( $key =~ /^\d+$/ ) {
1314             $key = pack($LONG_PACK, $key);
1315         }
1316     }
1317
1318         my $md5 = $DIGEST_FUNC->($key);
1319
1320         ##
1321         # Make sure file is open
1322         ##
1323         if (!defined($self->fh)) { $self->_open(); }
1324         
1325         ##
1326         # Request shared lock for reading
1327         ##
1328         $self->lock( LOCK_SH );
1329         
1330         my $tag = $self->find_bucket_list( $md5 );
1331         if (!$tag) {
1332                 $self->unlock();
1333                 return;
1334         }
1335         
1336         ##
1337         # Get value from bucket list
1338         ##
1339         my $result = $self->get_bucket_value( $tag, $md5 );
1340         
1341         $self->unlock();
1342         
1343     #XXX What is ref() checking here?
1344         return ($result && !ref($result) && $self->root->{filter_fetch_value}) ? $self->root->{filter_fetch_value}->($result) : $result;
1345 }
1346
1347 sub DELETE {
1348         ##
1349         # Delete single key/value pair or element given plain key or array index
1350         ##
1351     my $self = _get_self($_[0]);
1352         my $key = ($self->root->{filter_store_key} && $self->type eq TYPE_HASH) ? $self->root->{filter_store_key}->($_[1]) : $_[1];
1353         
1354         my $unpacked_key = $key;
1355         if (($self->type eq TYPE_ARRAY) && ($key =~ /^\d+$/)) { $key = pack($LONG_PACK, $key); }
1356         my $md5 = $DIGEST_FUNC->($key);
1357
1358         ##
1359         # Make sure file is open
1360         ##
1361         if (!defined($self->fh)) { $self->_open(); }
1362         
1363         ##
1364         # Request exclusive lock for writing
1365         ##
1366         $self->lock( LOCK_EX );
1367         
1368         my $tag = $self->find_bucket_list( $md5 );
1369         if (!$tag) {
1370                 $self->unlock();
1371                 return;
1372         }
1373         
1374         ##
1375         # Delete bucket
1376         ##
1377         my $result = $self->delete_bucket( $tag, $md5 );
1378         
1379         ##
1380         # If this object is an array and the key deleted was on the end of the stack,
1381         # decrement the length variable.
1382         ##
1383         if ($result && ($self->type eq TYPE_ARRAY) && ($unpacked_key == $self->FETCHSIZE() - 1)) {
1384                 $self->STORESIZE( $unpacked_key );
1385         }
1386         
1387         $self->unlock();
1388         
1389         return $result;
1390 }
1391
1392 sub EXISTS {
1393         ##
1394         # Check if a single key or element exists given plain key or array index
1395         ##
1396     my $self = _get_self($_[0]);
1397         my $key = ($self->root->{filter_store_key} && $self->type eq TYPE_HASH) ? $self->root->{filter_store_key}->($_[1]) : $_[1];
1398         
1399         if (($self->type eq TYPE_ARRAY) && ($key =~ /^\d+$/)) { $key = pack($LONG_PACK, $key); }
1400         my $md5 = $DIGEST_FUNC->($key);
1401
1402         ##
1403         # Make sure file is open
1404         ##
1405         if (!defined($self->fh)) { $self->_open(); }
1406         
1407         ##
1408         # Request shared lock for reading
1409         ##
1410         $self->lock( LOCK_SH );
1411         
1412         my $tag = $self->find_bucket_list( $md5 );
1413         
1414         ##
1415         # For some reason, the built-in exists() function returns '' for false
1416         ##
1417         if (!$tag) {
1418                 $self->unlock();
1419                 return '';
1420         }
1421         
1422         ##
1423         # Check if bucket exists and return 1 or ''
1424         ##
1425         my $result = $self->bucket_exists( $tag, $md5 ) || '';
1426         
1427         $self->unlock();
1428         
1429         return $result;
1430 }
1431
1432 sub CLEAR {
1433         ##
1434         # Clear all keys from hash, or all elements from array.
1435         ##
1436     my $self = _get_self($_[0]);
1437
1438         ##
1439         # Make sure file is open
1440         ##
1441         if (!defined($self->fh)) { $self->_open(); }
1442         
1443         ##
1444         # Request exclusive lock for writing
1445         ##
1446         $self->lock( LOCK_EX );
1447         
1448         seek($self->fh, $self->base_offset, 0);
1449         if ($self->fh->eof()) {
1450                 $self->unlock();
1451                 return;
1452         }
1453         
1454         $self->create_tag($self->base_offset, $self->type, chr(0) x $INDEX_SIZE);
1455         
1456         $self->unlock();
1457         
1458         return 1;
1459 }
1460
1461 sub FIRSTKEY {
1462         ##
1463         # Locate and return first key (in no particular order)
1464         ##
1465     my $self = _get_self($_[0]);
1466         if ($self->type ne TYPE_HASH) {
1467                 return $self->throw_error("FIRSTKEY method only supported for hashes");
1468         }
1469
1470         ##
1471         # Make sure file is open
1472         ##
1473         if (!defined($self->fh)) { $self->_open(); }
1474         
1475         ##
1476         # Request shared lock for reading
1477         ##
1478         $self->lock( LOCK_SH );
1479         
1480         my $result = $self->get_next_key();
1481         
1482         $self->unlock();
1483         
1484         return ($result && $self->root->{filter_fetch_key}) ? $self->root->{filter_fetch_key}->($result) : $result;
1485 }
1486
1487 sub NEXTKEY {
1488         ##
1489         # Return next key (in no particular order), given previous one
1490         ##
1491     my $self = _get_self($_[0]);
1492         if ($self->type ne TYPE_HASH) {
1493                 return $self->throw_error("NEXTKEY method only supported for hashes");
1494         }
1495         my $prev_key = ($self->root->{filter_store_key} && $self->type eq TYPE_HASH) ? $self->root->{filter_store_key}->($_[1]) : $_[1];
1496         my $prev_md5 = $DIGEST_FUNC->($prev_key);
1497
1498         ##
1499         # Make sure file is open
1500         ##
1501         if (!defined($self->fh)) { $self->_open(); }
1502         
1503         ##
1504         # Request shared lock for reading
1505         ##
1506         $self->lock( LOCK_SH );
1507         
1508         my $result = $self->get_next_key( $prev_md5 );
1509         
1510         $self->unlock();
1511         
1512         return ($result && $self->root->{filter_fetch_key}) ? $self->root->{filter_fetch_key}->($result) : $result;
1513 }
1514
1515 ##
1516 # The following methods are for arrays only
1517 ##
1518
1519 sub FETCHSIZE {
1520         ##
1521         # Return the length of the array
1522         ##
1523     my $self = _get_self($_[0]);
1524         if ($self->type ne TYPE_ARRAY) {
1525                 return $self->throw_error("FETCHSIZE method only supported for arrays");
1526         }
1527         
1528         my $SAVE_FILTER = $self->root->{filter_fetch_value};
1529         $self->root->{filter_fetch_value} = undef;
1530         
1531         my $packed_size = $self->FETCH('length');
1532         
1533         $self->root->{filter_fetch_value} = $SAVE_FILTER;
1534         
1535         if ($packed_size) { return int(unpack($LONG_PACK, $packed_size)); }
1536         else { return 0; } 
1537 }
1538
1539 sub STORESIZE {
1540         ##
1541         # Set the length of the array
1542         ##
1543     my $self = _get_self($_[0]);
1544         if ($self->type ne TYPE_ARRAY) {
1545                 return $self->throw_error("STORESIZE method only supported for arrays");
1546         }
1547         my $new_length = $_[1];
1548         
1549         my $SAVE_FILTER = $self->root->{filter_store_value};
1550         $self->root->{filter_store_value} = undef;
1551         
1552         my $result = $self->STORE('length', pack($LONG_PACK, $new_length));
1553         
1554         $self->root->{filter_store_value} = $SAVE_FILTER;
1555         
1556         return $result;
1557 }
1558
1559 sub POP {
1560         ##
1561         # Remove and return the last element on the array
1562         ##
1563     my $self = _get_self($_[0]);
1564         if ($self->type ne TYPE_ARRAY) {
1565                 return $self->throw_error("POP method only supported for arrays");
1566         }
1567         my $length = $self->FETCHSIZE();
1568         
1569         if ($length) {
1570                 my $content = $self->FETCH( $length - 1 );
1571                 $self->DELETE( $length - 1 );
1572                 return $content;
1573         }
1574         else {
1575                 return;
1576         }
1577 }
1578
1579 sub PUSH {
1580         ##
1581         # Add new element(s) to the end of the array
1582         ##
1583     my $self = _get_self(shift);
1584         if ($self->type ne TYPE_ARRAY) {
1585                 return $self->throw_error("PUSH method only supported for arrays");
1586         }
1587         my $length = $self->FETCHSIZE();
1588         
1589         while (my $content = shift @_) {
1590                 $self->STORE( $length, $content );
1591                 $length++;
1592         }
1593 }
1594
1595 sub SHIFT {
1596         ##
1597         # Remove and return first element on the array.
1598         # Shift over remaining elements to take up space.
1599         ##
1600     my $self = _get_self($_[0]);
1601         if ($self->type ne TYPE_ARRAY) {
1602                 return $self->throw_error("SHIFT method only supported for arrays");
1603         }
1604         my $length = $self->FETCHSIZE();
1605         
1606         if ($length) {
1607                 my $content = $self->FETCH( 0 );
1608                 
1609                 ##
1610                 # Shift elements over and remove last one.
1611                 ##
1612                 for (my $i = 0; $i < $length - 1; $i++) {
1613                         $self->STORE( $i, $self->FETCH($i + 1) );
1614                 }
1615                 $self->DELETE( $length - 1 );
1616                 
1617                 return $content;
1618         }
1619         else {
1620                 return;
1621         }
1622 }
1623
1624 sub UNSHIFT {
1625         ##
1626         # Insert new element(s) at beginning of array.
1627         # Shift over other elements to make space.
1628         ##
1629     my $self = _get_self($_[0]);shift @_;
1630         if ($self->type ne TYPE_ARRAY) {
1631                 return $self->throw_error("UNSHIFT method only supported for arrays");
1632         }
1633         my @new_elements = @_;
1634         my $length = $self->FETCHSIZE();
1635         my $new_size = scalar @new_elements;
1636         
1637         if ($length) {
1638                 for (my $i = $length - 1; $i >= 0; $i--) {
1639                         $self->STORE( $i + $new_size, $self->FETCH($i) );
1640                 }
1641         }
1642         
1643         for (my $i = 0; $i < $new_size; $i++) {
1644                 $self->STORE( $i, $new_elements[$i] );
1645         }
1646 }
1647
1648 sub SPLICE {
1649         ##
1650         # Splices section of array with optional new section.
1651         # Returns deleted section, or last element deleted in scalar context.
1652         ##
1653     my $self = _get_self($_[0]);shift @_;
1654         if ($self->type ne TYPE_ARRAY) {
1655                 return $self->throw_error("SPLICE method only supported for arrays");
1656         }
1657         my $length = $self->FETCHSIZE();
1658         
1659         ##
1660         # Calculate offset and length of splice
1661         ##
1662         my $offset = shift || 0;
1663         if ($offset < 0) { $offset += $length; }
1664         
1665         my $splice_length;
1666         if (scalar @_) { $splice_length = shift; }
1667         else { $splice_length = $length - $offset; }
1668         if ($splice_length < 0) { $splice_length += ($length - $offset); }
1669         
1670         ##
1671         # Setup array with new elements, and copy out old elements for return
1672         ##
1673         my @new_elements = @_;
1674         my $new_size = scalar @new_elements;
1675         
1676         my @old_elements = ();
1677         for (my $i = $offset; $i < $offset + $splice_length; $i++) {
1678                 push @old_elements, $self->FETCH( $i );
1679         }
1680         
1681         ##
1682         # Adjust array length, and shift elements to accomodate new section.
1683         ##
1684     if ( $new_size != $splice_length ) {
1685         if ($new_size > $splice_length) {
1686             for (my $i = $length - 1; $i >= $offset + $splice_length; $i--) {
1687                 $self->STORE( $i + ($new_size - $splice_length), $self->FETCH($i) );
1688             }
1689         }
1690         else {
1691             for (my $i = $offset + $splice_length; $i < $length; $i++) {
1692                 $self->STORE( $i + ($new_size - $splice_length), $self->FETCH($i) );
1693             }
1694             for (my $i = 0; $i < $splice_length - $new_size; $i++) {
1695                 $self->DELETE( $length - 1 );
1696                 $length--;
1697             }
1698         }
1699         }
1700         
1701         ##
1702         # Insert new elements into array
1703         ##
1704         for (my $i = $offset; $i < $offset + $new_size; $i++) {
1705                 $self->STORE( $i, shift @new_elements );
1706         }
1707         
1708         ##
1709         # Return deleted section, or last element in scalar context.
1710         ##
1711         return wantarray ? @old_elements : $old_elements[-1];
1712 }
1713
1714 #XXX We don't need to define it.
1715 #XXX It will be useful, though, when we split out HASH and ARRAY
1716 #sub EXTEND {
1717         ##
1718         # Perl will call EXTEND() when the array is likely to grow.
1719         # We don't care, but include it for compatibility.
1720         ##
1721 #}
1722
1723 ##
1724 # Public method aliases
1725 ##
1726 *put = *store = *STORE;
1727 *get = *fetch = *FETCH;
1728 *delete = *DELETE;
1729 *exists = *EXISTS;
1730 *clear = *CLEAR;
1731 *first_key = *FIRSTKEY;
1732 *next_key = *NEXTKEY;
1733 *length = *FETCHSIZE;
1734 *pop = *POP;
1735 *push = *PUSH;
1736 *shift = *SHIFT;
1737 *unshift = *UNSHIFT;
1738 *splice = *SPLICE;
1739
1740 1;
1741
1742 __END__
1743
1744 =head1 NAME
1745
1746 DBM::Deep - A pure perl multi-level hash/array DBM
1747
1748 =head1 SYNOPSIS
1749
1750   use DBM::Deep;
1751   my $db = DBM::Deep->new( "foo.db" );
1752   
1753   $db->{key} = 'value'; # tie() style
1754   print $db->{key};
1755   
1756   $db->put('key', 'value'); # OO style
1757   print $db->get('key');
1758   
1759   # true multi-level support
1760   $db->{my_complex} = [
1761         'hello', { perl => 'rules' }, 
1762         42, 99 ];
1763
1764 =head1 DESCRIPTION
1765
1766 A unique flat-file database module, written in pure perl.  True 
1767 multi-level hash/array support (unlike MLDBM, which is faked), hybrid 
1768 OO / tie() interface, cross-platform FTPable files, and quite fast.  Can 
1769 handle millions of keys and unlimited hash levels without significant 
1770 slow-down.  Written from the ground-up in pure perl -- this is NOT a 
1771 wrapper around a C-based DBM.  Out-of-the-box compatibility with Unix, 
1772 Mac OS X and Windows.
1773
1774 =head1 INSTALLATION
1775
1776 Hopefully you are using CPAN's excellent Perl module, which will download
1777 and install the module for you.  If not, get the tarball, and run these 
1778 commands:
1779
1780         tar zxf DBM-Deep-*
1781         cd DBM-Deep-*
1782         perl Makefile.PL
1783         make
1784         make test
1785         make install
1786
1787 =head1 SETUP
1788
1789 Construction can be done OO-style (which is the recommended way), or using 
1790 Perl's tie() function.  Both are examined here.
1791
1792 =head2 OO CONSTRUCTION
1793
1794 The recommended way to construct a DBM::Deep object is to use the new()
1795 method, which gets you a blessed, tied hash or array reference.
1796
1797         my $db = DBM::Deep->new( "foo.db" );
1798
1799 This opens a new database handle, mapped to the file "foo.db".  If this
1800 file does not exist, it will automatically be created.  DB files are 
1801 opened in "r+" (read/write) mode, and the type of object returned is a
1802 hash, unless otherwise specified (see L<OPTIONS> below).
1803
1804
1805
1806 You can pass a number of options to the constructor to specify things like
1807 locking, autoflush, etc.  This is done by passing an inline hash:
1808
1809         my $db = DBM::Deep->new(
1810                 file => "foo.db",
1811                 locking => 1,
1812                 autoflush => 1
1813         );
1814
1815 Notice that the filename is now specified I<inside> the hash with
1816 the "file" parameter, as opposed to being the sole argument to the 
1817 constructor.  This is required if any options are specified.
1818 See L<OPTIONS> below for the complete list.
1819
1820
1821
1822 You can also start with an array instead of a hash.  For this, you must
1823 specify the C<type> parameter:
1824
1825         my $db = DBM::Deep->new(
1826                 file => "foo.db",
1827                 type => DBM::Deep->TYPE_ARRAY
1828         );
1829
1830 B<Note:> Specifing the C<type> parameter only takes effect when beginning
1831 a new DB file.  If you create a DBM::Deep object with an existing file, the
1832 C<type> will be loaded from the file header, and ignored if it is passed
1833 to the constructor.
1834
1835 =head2 TIE CONSTRUCTION
1836
1837 Alternatively, you can create a DBM::Deep handle by using Perl's built-in
1838 tie() function.  This is not ideal, because you get only a basic, tied hash 
1839 (or array) which is not blessed, so you can't call any functions on it.
1840
1841         my %hash;
1842         tie %hash, "DBM::Deep", "foo.db";
1843         
1844         my @array;
1845         tie @array, "DBM::Deep", "bar.db";
1846
1847 As with the OO constructor, you can replace the DB filename parameter with
1848 a hash containing one or more options (see L<OPTIONS> just below for the
1849 complete list).
1850
1851         tie %hash, "DBM::Deep", {
1852                 file => "foo.db",
1853                 locking => 1,
1854                 autoflush => 1
1855         };
1856
1857 =head2 OPTIONS
1858
1859 There are a number of options that can be passed in when constructing your
1860 DBM::Deep objects.  These apply to both the OO- and tie- based approaches.
1861
1862 =over
1863
1864 =item * file
1865
1866 Filename of the DB file to link the handle to.  You can pass a full absolute
1867 filesystem path, partial path, or a plain filename if the file is in the 
1868 current working directory.  This is a required parameter.
1869
1870 =item * mode
1871
1872 File open mode (read-only, read-write, etc.) string passed to Perl's FileHandle
1873 module.  This is an optional parameter, and defaults to "r+" (read/write).
1874 B<Note:> If the default (r+) mode is selected, the file will also be auto-
1875 created if it doesn't exist.
1876
1877 =item * type
1878
1879 This parameter specifies what type of object to create, a hash or array.  Use
1880 one of these two constants: C<DBM::Deep-E<gt>TYPE_HASH> or C<DBM::Deep-E<gt>TYPE_ARRAY>.
1881 This only takes effect when beginning a new file.  This is an optional 
1882 parameter, and defaults to C<DBM::Deep-E<gt>TYPE_HASH>.
1883
1884 =item * locking
1885
1886 Specifies whether locking is to be enabled.  DBM::Deep uses Perl's Fnctl flock()
1887 function to lock the database in exclusive mode for writes, and shared mode for
1888 reads.  Pass any true value to enable.  This affects the base DB handle I<and 
1889 any child hashes or arrays> that use the same DB file.  This is an optional 
1890 parameter, and defaults to 0 (disabled).  See L<LOCKING> below for more.
1891
1892 =item * autoflush
1893
1894 Specifies whether autoflush is to be enabled on the underlying FileHandle.  
1895 This obviously slows down write operations, but is required if you may have 
1896 multiple processes accessing the same DB file (also consider enable I<locking> 
1897 or at least I<volatile>).  Pass any true value to enable.  This is an optional 
1898 parameter, and defaults to 0 (disabled).
1899
1900 =item * volatile
1901
1902 If I<volatile> mode is enabled, DBM::Deep will stat() the DB file before each
1903 STORE() operation.  This is required if an outside force may change the size of
1904 the file between transactions.  Locking also implicitly enables volatile.  This
1905 is useful if you want to use a different locking system or write your own.  Pass
1906 any true value to enable.  This is an optional parameter, and defaults to 0 
1907 (disabled).
1908
1909 =item * autobless
1910
1911 If I<autobless> mode is enabled, DBM::Deep will preserve blessed hashes, and
1912 restore them when fetched.  This is an B<experimental> feature, and does have
1913 side-effects.  Basically, when hashes are re-blessed into their original
1914 classes, they are no longer blessed into the DBM::Deep class!  So you won't be
1915 able to call any DBM::Deep methods on them.  You have been warned.
1916 This is an optional parameter, and defaults to 0 (disabled).
1917
1918 =item * filter_*
1919
1920 See L<FILTERS> below.
1921
1922 =item * debug
1923
1924 Setting I<debug> mode will make all errors non-fatal, dump them out to
1925 STDERR, and continue on.  This is for debugging purposes only, and probably
1926 not what you want.  This is an optional parameter, and defaults to 0 (disabled).
1927
1928 =item * fh
1929
1930 Instead of passing a file path, you can instead pass a handle to an pre-opened
1931 filehandle.  Note: Beware of using the magick *DATA handle, as this actually 
1932 contains your entire Perl script, as well as the data following the __DATA__
1933 marker.  This will not work, because DBM::Deep uses absolute seek()s into the
1934 file.  Instead, consider reading *DATA into an IO::Scalar handle, then passing
1935 in that.
1936
1937 =back
1938
1939 =head1 TIE INTERFACE
1940
1941 With DBM::Deep you can access your databases using Perl's standard hash/array
1942 syntax.  Because all DBM::Deep objects are I<tied> to hashes or arrays, you can treat
1943 them as such.  DBM::Deep will intercept all reads/writes and direct them to the right
1944 place -- the DB file.  This has nothing to do with the L<TIE CONSTRUCTION> 
1945 section above.  This simply tells you how to use DBM::Deep using regular hashes 
1946 and arrays, rather than calling functions like C<get()> and C<put()> (although those 
1947 work too).  It is entirely up to you how to want to access your databases.
1948
1949 =head2 HASHES
1950
1951 You can treat any DBM::Deep object like a normal Perl hash reference.  Add keys,
1952 or even nested hashes (or arrays) using standard Perl syntax:
1953
1954         my $db = DBM::Deep->new( "foo.db" );
1955         
1956         $db->{mykey} = "myvalue";
1957         $db->{myhash} = {};
1958         $db->{myhash}->{subkey} = "subvalue";
1959
1960         print $db->{myhash}->{subkey} . "\n";
1961
1962 You can even step through hash keys using the normal Perl C<keys()> function:
1963
1964         foreach my $key (keys %$db) {
1965                 print "$key: " . $db->{$key} . "\n";
1966         }
1967
1968 Remember that Perl's C<keys()> function extracts I<every> key from the hash and
1969 pushes them onto an array, all before the loop even begins.  If you have an 
1970 extra large hash, this may exhaust Perl's memory.  Instead, consider using 
1971 Perl's C<each()> function, which pulls keys/values one at a time, using very 
1972 little memory:
1973
1974         while (my ($key, $value) = each %$db) {
1975                 print "$key: $value\n";
1976         }
1977
1978 Please note that when using C<each()>, you should always pass a direct
1979 hash reference, not a lookup.  Meaning, you should B<never> do this:
1980
1981         # NEVER DO THIS
1982         while (my ($key, $value) = each %{$db->{foo}}) { # BAD
1983
1984 This causes an infinite loop, because for each iteration, Perl is calling
1985 FETCH() on the $db handle, resulting in a "new" hash for foo every time, so
1986 it effectively keeps returning the first key over and over again. Instead, 
1987 assign a temporary variable to C<$db->{foo}>, then pass that to each().
1988
1989 =head2 ARRAYS
1990
1991 As with hashes, you can treat any DBM::Deep object like a normal Perl array
1992 reference.  This includes inserting, removing and manipulating elements, 
1993 and the C<push()>, C<pop()>, C<shift()>, C<unshift()> and C<splice()> functions.
1994 The object must have first been created using type C<DBM::Deep-E<gt>TYPE_ARRAY>, 
1995 or simply be a nested array reference inside a hash.  Example:
1996
1997         my $db = DBM::Deep->new(
1998                 file => "foo-array.db",
1999                 type => DBM::Deep->TYPE_ARRAY
2000         );
2001         
2002         $db->[0] = "foo";
2003         push @$db, "bar", "baz";
2004         unshift @$db, "bah";
2005         
2006         my $last_elem = pop @$db; # baz
2007         my $first_elem = shift @$db; # bah
2008         my $second_elem = $db->[1]; # bar
2009         
2010         my $num_elements = scalar @$db;
2011
2012 =head1 OO INTERFACE
2013
2014 In addition to the I<tie()> interface, you can also use a standard OO interface
2015 to manipulate all aspects of DBM::Deep databases.  Each type of object (hash or
2016 array) has its own methods, but both types share the following common methods: 
2017 C<put()>, C<get()>, C<exists()>, C<delete()> and C<clear()>.
2018
2019 =over
2020
2021 =item * put()
2022
2023 Stores a new hash key/value pair, or sets an array element value.  Takes two
2024 arguments, the hash key or array index, and the new value.  The value can be
2025 a scalar, hash ref or array ref.  Returns true on success, false on failure.
2026
2027         $db->put("foo", "bar"); # for hashes
2028         $db->put(1, "bar"); # for arrays
2029
2030 =item * get()
2031
2032 Fetches the value of a hash key or array element.  Takes one argument: the hash
2033 key or array index.  Returns a scalar, hash ref or array ref, depending on the 
2034 data type stored.
2035
2036         my $value = $db->get("foo"); # for hashes
2037         my $value = $db->get(1); # for arrays
2038
2039 =item * exists()
2040
2041 Checks if a hash key or array index exists.  Takes one argument: the hash key 
2042 or array index.  Returns true if it exists, false if not.
2043
2044         if ($db->exists("foo")) { print "yay!\n"; } # for hashes
2045         if ($db->exists(1)) { print "yay!\n"; } # for arrays
2046
2047 =item * delete()
2048
2049 Deletes one hash key/value pair or array element.  Takes one argument: the hash
2050 key or array index.  Returns true on success, false if not found.  For arrays,
2051 the remaining elements located after the deleted element are NOT moved over.
2052 The deleted element is essentially just undefined, which is exactly how Perl's
2053 internal arrays work.  Please note that the space occupied by the deleted 
2054 key/value or element is B<not> reused again -- see L<UNUSED SPACE RECOVERY> 
2055 below for details and workarounds.
2056
2057         $db->delete("foo"); # for hashes
2058         $db->delete(1); # for arrays
2059
2060 =item * clear()
2061
2062 Deletes B<all> hash keys or array elements.  Takes no arguments.  No return 
2063 value.  Please note that the space occupied by the deleted keys/values or 
2064 elements is B<not> reused again -- see L<UNUSED SPACE RECOVERY> below for 
2065 details and workarounds.
2066
2067         $db->clear(); # hashes or arrays
2068
2069 =back
2070
2071 =head2 HASHES
2072
2073 For hashes, DBM::Deep supports all the common methods described above, and the 
2074 following additional methods: C<first_key()> and C<next_key()>.
2075
2076 =over
2077
2078 =item * first_key()
2079
2080 Returns the "first" key in the hash.  As with built-in Perl hashes, keys are 
2081 fetched in an undefined order (which appears random).  Takes no arguments, 
2082 returns the key as a scalar value.
2083
2084         my $key = $db->first_key();
2085
2086 =item * next_key()
2087
2088 Returns the "next" key in the hash, given the previous one as the sole argument.
2089 Returns undef if there are no more keys to be fetched.
2090
2091         $key = $db->next_key($key);
2092
2093 =back
2094
2095 Here are some examples of using hashes:
2096
2097         my $db = DBM::Deep->new( "foo.db" );
2098         
2099         $db->put("foo", "bar");
2100         print "foo: " . $db->get("foo") . "\n";
2101         
2102         $db->put("baz", {}); # new child hash ref
2103         $db->get("baz")->put("buz", "biz");
2104         print "buz: " . $db->get("baz")->get("buz") . "\n";
2105         
2106         my $key = $db->first_key();
2107         while ($key) {
2108                 print "$key: " . $db->get($key) . "\n";
2109                 $key = $db->next_key($key);     
2110         }
2111         
2112         if ($db->exists("foo")) { $db->delete("foo"); }
2113
2114 =head2 ARRAYS
2115
2116 For arrays, DBM::Deep supports all the common methods described above, and the 
2117 following additional methods: C<length()>, C<push()>, C<pop()>, C<shift()>, 
2118 C<unshift()> and C<splice()>.
2119
2120 =over
2121
2122 =item * length()
2123
2124 Returns the number of elements in the array.  Takes no arguments.
2125
2126         my $len = $db->length();
2127
2128 =item * push()
2129
2130 Adds one or more elements onto the end of the array.  Accepts scalars, hash 
2131 refs or array refs.  No return value.
2132
2133         $db->push("foo", "bar", {});
2134
2135 =item * pop()
2136
2137 Fetches the last element in the array, and deletes it.  Takes no arguments.
2138 Returns undef if array is empty.  Returns the element value.
2139
2140         my $elem = $db->pop();
2141
2142 =item * shift()
2143
2144 Fetches the first element in the array, deletes it, then shifts all the 
2145 remaining elements over to take up the space.  Returns the element value.  This 
2146 method is not recommended with large arrays -- see L<LARGE ARRAYS> below for 
2147 details.
2148
2149         my $elem = $db->shift();
2150
2151 =item * unshift()
2152
2153 Inserts one or more elements onto the beginning of the array, shifting all 
2154 existing elements over to make room.  Accepts scalars, hash refs or array refs.  
2155 No return value.  This method is not recommended with large arrays -- see 
2156 <LARGE ARRAYS> below for details.
2157
2158         $db->unshift("foo", "bar", {});
2159
2160 =item * splice()
2161
2162 Performs exactly like Perl's built-in function of the same name.  See L<perldoc 
2163 -f splice> for usage -- it is too complicated to document here.  This method is
2164 not recommended with large arrays -- see L<LARGE ARRAYS> below for details.
2165
2166 =back
2167
2168 Here are some examples of using arrays:
2169
2170         my $db = DBM::Deep->new(
2171                 file => "foo.db",
2172                 type => DBM::Deep->TYPE_ARRAY
2173         );
2174         
2175         $db->push("bar", "baz");
2176         $db->unshift("foo");
2177         $db->put(3, "buz");
2178         
2179         my $len = $db->length();
2180         print "length: $len\n"; # 4
2181         
2182         for (my $k=0; $k<$len; $k++) {
2183                 print "$k: " . $db->get($k) . "\n";
2184         }
2185         
2186         $db->splice(1, 2, "biz", "baf");
2187         
2188         while (my $elem = shift @$db) {
2189                 print "shifted: $elem\n";
2190         }
2191
2192 =head1 LOCKING
2193
2194 Enable automatic file locking by passing a true value to the C<locking> 
2195 parameter when constructing your DBM::Deep object (see L<SETUP> above).
2196
2197         my $db = DBM::Deep->new(
2198                 file => "foo.db",
2199                 locking => 1
2200         );
2201
2202 This causes DBM::Deep to C<flock()> the underlying FileHandle object with exclusive 
2203 mode for writes, and shared mode for reads.  This is required if you have 
2204 multiple processes accessing the same database file, to avoid file corruption.  
2205 Please note that C<flock()> does NOT work for files over NFS.  See L<DB OVER 
2206 NFS> below for more.
2207
2208 =head2 EXPLICIT LOCKING
2209
2210 You can explicitly lock a database, so it remains locked for multiple 
2211 transactions.  This is done by calling the C<lock()> method, and passing an 
2212 optional lock mode argument (defaults to exclusive mode).  This is particularly 
2213 useful for things like counters, where the current value needs to be fetched, 
2214 then incremented, then stored again.
2215
2216         $db->lock();
2217         my $counter = $db->get("counter");
2218         $counter++;
2219         $db->put("counter", $counter);
2220         $db->unlock();
2221
2222         # or...
2223         
2224         $db->lock();
2225         $db->{counter}++;
2226         $db->unlock();
2227
2228 You can pass C<lock()> an optional argument, which specifies which mode to use
2229 (exclusive or shared).  Use one of these two constants: C<DBM::Deep-E<gt>LOCK_EX> 
2230 or C<DBM::Deep-E<gt>LOCK_SH>.  These are passed directly to C<flock()>, and are the 
2231 same as the constants defined in Perl's C<Fcntl> module.
2232
2233         $db->lock( DBM::Deep->LOCK_SH );
2234         # something here
2235         $db->unlock();
2236
2237 If you want to implement your own file locking scheme, be sure to create your
2238 DBM::Deep objects setting the C<volatile> option to true.  This hints to DBM::Deep
2239 that the DB file may change between transactions.  See L<LOW-LEVEL ACCESS> 
2240 below for more.
2241
2242 =head1 IMPORTING/EXPORTING
2243
2244 You can import existing complex structures by calling the C<import()> method,
2245 and export an entire database into an in-memory structure using the C<export()>
2246 method.  Both are examined here.
2247
2248 =head2 IMPORTING
2249
2250 Say you have an existing hash with nested hashes/arrays inside it.  Instead of
2251 walking the structure and adding keys/elements to the database as you go, 
2252 simply pass a reference to the C<import()> method.  This recursively adds 
2253 everything to an existing DBM::Deep object for you.  Here is an example:
2254
2255         my $struct = {
2256                 key1 => "value1",
2257                 key2 => "value2",
2258                 array1 => [ "elem0", "elem1", "elem2" ],
2259                 hash1 => {
2260                         subkey1 => "subvalue1",
2261                         subkey2 => "subvalue2"
2262                 }
2263         };
2264         
2265         my $db = DBM::Deep->new( "foo.db" );
2266         $db->import( $struct );
2267         
2268         print $db->{key1} . "\n"; # prints "value1"
2269
2270 This recursively imports the entire C<$struct> object into C<$db>, including 
2271 all nested hashes and arrays.  If the DBM::Deep object contains exsiting data,
2272 keys are merged with the existing ones, replacing if they already exist.  
2273 The C<import()> method can be called on any database level (not just the base 
2274 level), and works with both hash and array DB types.
2275
2276
2277
2278 B<Note:> Make sure your existing structure has no circular references in it.
2279 These will cause an infinite loop when importing.
2280
2281 =head2 EXPORTING
2282
2283 Calling the C<export()> method on an existing DBM::Deep object will return 
2284 a reference to a new in-memory copy of the database.  The export is done 
2285 recursively, so all nested hashes/arrays are all exported to standard Perl
2286 objects.  Here is an example:
2287
2288         my $db = DBM::Deep->new( "foo.db" );
2289         
2290         $db->{key1} = "value1";
2291         $db->{key2} = "value2";
2292         $db->{hash1} = {};
2293         $db->{hash1}->{subkey1} = "subvalue1";
2294         $db->{hash1}->{subkey2} = "subvalue2";
2295         
2296         my $struct = $db->export();
2297         
2298         print $struct->{key1} . "\n"; # prints "value1"
2299
2300 This makes a complete copy of the database in memory, and returns a reference
2301 to it.  The C<export()> method can be called on any database level (not just 
2302 the base level), and works with both hash and array DB types.  Be careful of 
2303 large databases -- you can store a lot more data in a DBM::Deep object than an 
2304 in-memory Perl structure.
2305
2306
2307
2308 B<Note:> Make sure your database has no circular references in it.
2309 These will cause an infinite loop when exporting.
2310
2311 =head1 FILTERS
2312
2313 DBM::Deep has a number of hooks where you can specify your own Perl function
2314 to perform filtering on incoming or outgoing data.  This is a perfect
2315 way to extend the engine, and implement things like real-time compression or
2316 encryption.  Filtering applies to the base DB level, and all child hashes / 
2317 arrays.  Filter hooks can be specified when your DBM::Deep object is first 
2318 constructed, or by calling the C<set_filter()> method at any time.  There are 
2319 four available filter hooks, described below:
2320
2321 =over
2322
2323 =item * filter_store_key
2324
2325 This filter is called whenever a hash key is stored.  It 
2326 is passed the incoming key, and expected to return a transformed key.
2327
2328 =item * filter_store_value
2329
2330 This filter is called whenever a hash key or array element is stored.  It 
2331 is passed the incoming value, and expected to return a transformed value.
2332
2333 =item * filter_fetch_key
2334
2335 This filter is called whenever a hash key is fetched (i.e. via 
2336 C<first_key()> or C<next_key()>).  It is passed the transformed key,
2337 and expected to return the plain key.
2338
2339 =item * filter_fetch_value
2340
2341 This filter is called whenever a hash key or array element is fetched.  
2342 It is passed the transformed value, and expected to return the plain value.
2343
2344 =back
2345
2346 Here are the two ways to setup a filter hook:
2347
2348         my $db = DBM::Deep->new(
2349                 file => "foo.db",
2350                 filter_store_value => \&my_filter_store,
2351                 filter_fetch_value => \&my_filter_fetch
2352         );
2353         
2354         # or...
2355         
2356         $db->set_filter( "filter_store_value", \&my_filter_store );
2357         $db->set_filter( "filter_fetch_value", \&my_filter_fetch );
2358
2359 Your filter function will be called only when dealing with SCALAR keys or
2360 values.  When nested hashes and arrays are being stored/fetched, filtering
2361 is bypassed.  Filters are called as static functions, passed a single SCALAR 
2362 argument, and expected to return a single SCALAR value.  If you want to
2363 remove a filter, set the function reference to C<undef>:
2364
2365         $db->set_filter( "filter_store_value", undef );
2366
2367 =head2 REAL-TIME ENCRYPTION EXAMPLE
2368
2369 Here is a working example that uses the I<Crypt::Blowfish> module to 
2370 do real-time encryption / decryption of keys & values with DBM::Deep Filters.
2371 Please visit L<http://search.cpan.org/search?module=Crypt::Blowfish> for more 
2372 on I<Crypt::Blowfish>.  You'll also need the I<Crypt::CBC> module.
2373
2374         use DBM::Deep;
2375         use Crypt::Blowfish;
2376         use Crypt::CBC;
2377         
2378         my $cipher = Crypt::CBC->new({
2379                 'key'             => 'my secret key',
2380                 'cipher'          => 'Blowfish',
2381                 'iv'              => '$KJh#(}q',
2382                 'regenerate_key'  => 0,
2383                 'padding'         => 'space',
2384                 'prepend_iv'      => 0
2385         });
2386         
2387         my $db = DBM::Deep->new(
2388                 file => "foo-encrypt.db",
2389                 filter_store_key => \&my_encrypt,
2390                 filter_store_value => \&my_encrypt,
2391                 filter_fetch_key => \&my_decrypt,
2392                 filter_fetch_value => \&my_decrypt,
2393         );
2394         
2395         $db->{key1} = "value1";
2396         $db->{key2} = "value2";
2397         print "key1: " . $db->{key1} . "\n";
2398         print "key2: " . $db->{key2} . "\n";
2399         
2400         undef $db;
2401         exit;
2402         
2403         sub my_encrypt {
2404                 return $cipher->encrypt( $_[0] );
2405         }
2406         sub my_decrypt {
2407                 return $cipher->decrypt( $_[0] );
2408         }
2409
2410 =head2 REAL-TIME COMPRESSION EXAMPLE
2411
2412 Here is a working example that uses the I<Compress::Zlib> module to do real-time
2413 compression / decompression of keys & values with DBM::Deep Filters.
2414 Please visit L<http://search.cpan.org/search?module=Compress::Zlib> for 
2415 more on I<Compress::Zlib>.
2416
2417         use DBM::Deep;
2418         use Compress::Zlib;
2419         
2420         my $db = DBM::Deep->new(
2421                 file => "foo-compress.db",
2422                 filter_store_key => \&my_compress,
2423                 filter_store_value => \&my_compress,
2424                 filter_fetch_key => \&my_decompress,
2425                 filter_fetch_value => \&my_decompress,
2426         );
2427         
2428         $db->{key1} = "value1";
2429         $db->{key2} = "value2";
2430         print "key1: " . $db->{key1} . "\n";
2431         print "key2: " . $db->{key2} . "\n";
2432         
2433         undef $db;
2434         exit;
2435         
2436         sub my_compress {
2437                 return Compress::Zlib::memGzip( $_[0] ) ;
2438         }
2439         sub my_decompress {
2440                 return Compress::Zlib::memGunzip( $_[0] ) ;
2441         }
2442
2443 B<Note:> Filtering of keys only applies to hashes.  Array "keys" are
2444 actually numerical index numbers, and are not filtered.
2445
2446 =head1 ERROR HANDLING
2447
2448 Most DBM::Deep methods return a true value for success, and call die() on
2449 failure.  You can wrap calls in an eval block to catch the die.  Also, the 
2450 actual error message is stored in an internal scalar, which can be fetched by 
2451 calling the C<error()> method.
2452
2453         my $db = DBM::Deep->new( "foo.db" ); # create hash
2454         eval { $db->push("foo"); }; # ILLEGAL -- push is array-only call
2455         
2456         print $db->error(); # prints error message
2457
2458 You can then call C<clear_error()> to clear the current error state.
2459
2460         $db->clear_error();
2461
2462 If you set the C<debug> option to true when creating your DBM::Deep object,
2463 all errors are considered NON-FATAL, and dumped to STDERR.  This is only
2464 for debugging purposes.
2465
2466 =head1 LARGEFILE SUPPORT
2467
2468 If you have a 64-bit system, and your Perl is compiled with both LARGEFILE
2469 and 64-bit support, you I<may> be able to create databases larger than 2 GB.
2470 DBM::Deep by default uses 32-bit file offset tags, but these can be changed
2471 by calling the static C<set_pack()> method before you do anything else.
2472
2473         DBM::Deep::set_pack(8, 'Q');
2474
2475 This tells DBM::Deep to pack all file offsets with 8-byte (64-bit) quad words 
2476 instead of 32-bit longs.  After setting these values your DB files have a 
2477 theoretical maximum size of 16 XB (exabytes).
2478
2479
2480
2481 B<Note:> Changing these values will B<NOT> work for existing database files.
2482 Only change this for new files, and make sure it stays set consistently 
2483 throughout the file's life.  If you do set these values, you can no longer 
2484 access 32-bit DB files.  You can, however, call C<set_pack(4, 'N')> to change 
2485 back to 32-bit mode.
2486
2487
2488
2489 B<Note:> I have not personally tested files > 2 GB -- all my systems have 
2490 only a 32-bit Perl.  However, I have received user reports that this does 
2491 indeed work!
2492
2493 =head1 LOW-LEVEL ACCESS
2494
2495 If you require low-level access to the underlying FileHandle that DBM::Deep uses,
2496 you can call the C<fh()> method, which returns the handle:
2497
2498         my $fh = $db->fh();
2499
2500 This method can be called on the root level of the datbase, or any child
2501 hashes or arrays.  All levels share a I<root> structure, which contains things
2502 like the FileHandle, a reference counter, and all your options you specified
2503 when you created the object.  You can get access to this root structure by 
2504 calling the C<root()> method.
2505
2506         my $root = $db->root();
2507
2508 This is useful for changing options after the object has already been created,
2509 such as enabling/disabling locking, volatile or debug modes.  You can also
2510 store your own temporary user data in this structure (be wary of name 
2511 collision), which is then accessible from any child hash or array.
2512
2513 =head1 CUSTOM DIGEST ALGORITHM
2514
2515 DBM::Deep by default uses the I<Message Digest 5> (MD5) algorithm for hashing
2516 keys.  However you can override this, and use another algorithm (such as SHA-256)
2517 or even write your own.  But please note that DBM::Deep currently expects zero 
2518 collisions, so your algorithm has to be I<perfect>, so to speak.
2519 Collision detection may be introduced in a later version.
2520
2521
2522
2523 You can specify a custom digest algorithm by calling the static C<set_digest()> 
2524 function, passing a reference to a subroutine, and the length of the algorithm's 
2525 hashes (in bytes).  This is a global static function, which affects ALL DBM::Deep 
2526 objects.  Here is a working example that uses a 256-bit hash from the 
2527 I<Digest::SHA256> module.  Please see 
2528 L<http://search.cpan.org/search?module=Digest::SHA256> for more.
2529
2530         use DBM::Deep;
2531         use Digest::SHA256;
2532         
2533         my $context = Digest::SHA256::new(256);
2534         
2535         DBM::Deep::set_digest( \&my_digest, 32 );
2536         
2537         my $db = DBM::Deep->new( "foo-sha.db" );
2538         
2539         $db->{key1} = "value1";
2540         $db->{key2} = "value2";
2541         print "key1: " . $db->{key1} . "\n";
2542         print "key2: " . $db->{key2} . "\n";
2543         
2544         undef $db;
2545         exit;
2546         
2547         sub my_digest {
2548                 return substr( $context->hash($_[0]), 0, 32 );
2549         }
2550
2551 B<Note:> Your returned digest strings must be B<EXACTLY> the number
2552 of bytes you specify in the C<set_digest()> function (in this case 32).
2553
2554 =head1 CIRCULAR REFERENCES
2555
2556 DBM::Deep has B<experimental> support for circular references.  Meaning you
2557 can have a nested hash key or array element that points to a parent object.
2558 This relationship is stored in the DB file, and is preserved between sessions.
2559 Here is an example:
2560
2561         my $db = DBM::Deep->new( "foo.db" );
2562         
2563         $db->{foo} = "bar";
2564         $db->{circle} = $db; # ref to self
2565         
2566         print $db->{foo} . "\n"; # prints "foo"
2567         print $db->{circle}->{foo} . "\n"; # prints "foo" again
2568
2569 One catch is, passing the object to a function that recursively walks the
2570 object tree (such as I<Data::Dumper> or even the built-in C<optimize()> or
2571 C<export()> methods) will result in an infinite loop.  The other catch is, 
2572 if you fetch the I<key> of a circular reference (i.e. using the C<first_key()> 
2573 or C<next_key()> methods), you will get the I<target object's key>, not the 
2574 ref's key.  This gets even more interesting with the above example, where 
2575 the I<circle> key points to the base DB object, which technically doesn't 
2576 have a key.  So I made DBM::Deep return "[base]" as the key name in that 
2577 special case.
2578
2579 =head1 CAVEATS / ISSUES / BUGS
2580
2581 This section describes all the known issues with DBM::Deep.  It you have found
2582 something that is not listed here, please send e-mail to L<jhuckaby@cpan.org>.
2583
2584 =head2 UNUSED SPACE RECOVERY
2585
2586 One major caveat with DBM::Deep is that space occupied by existing keys and
2587 values is not recovered when they are deleted.  Meaning if you keep deleting
2588 and adding new keys, your file will continuously grow.  I am working on this,
2589 but in the meantime you can call the built-in C<optimize()> method from time to 
2590 time (perhaps in a crontab or something) to recover all your unused space.
2591
2592         $db->optimize(); # returns true on success
2593
2594 This rebuilds the ENTIRE database into a new file, then moves it on top of
2595 the original.  The new file will have no unused space, thus it will take up as
2596 little disk space as possible.  Please note that this operation can take 
2597 a long time for large files, and you need enough disk space to temporarily hold 
2598 2 copies of your DB file.  The temporary file is created in the same directory 
2599 as the original, named with a ".tmp" extension, and is deleted when the 
2600 operation completes.  Oh, and if locking is enabled, the DB is automatically 
2601 locked for the entire duration of the copy.
2602
2603
2604
2605 B<WARNING:> Only call optimize() on the top-level node of the database, and 
2606 make sure there are no child references lying around.  DBM::Deep keeps a reference 
2607 counter, and if it is greater than 1, optimize() will abort and return undef.
2608
2609 =head2 AUTOVIVIFICATION
2610
2611 Unfortunately, autovivification doesn't work with tied hashes.  This appears to 
2612 be a bug in Perl's tie() system, as I<Jakob Schmidt> encountered the very same 
2613 issue with his I<DWH_FIle> module (see L<http://search.cpan.org/search?module=DWH_File>),
2614 and it is also mentioned in the BUGS section for the I<MLDBM> module <see 
2615 L<http://search.cpan.org/search?module=MLDBM>).  Basically, on a new db file,
2616 this does not work:
2617
2618         $db->{foo}->{bar} = "hello";
2619
2620 Since "foo" doesn't exist, you cannot add "bar" to it.  You end up with "foo"
2621 being an empty hash.  Try this instead, which works fine:
2622
2623         $db->{foo} = { bar => "hello" };
2624
2625 As of Perl 5.8.7, this bug still exists.  I have walked very carefully through
2626 the execution path, and Perl indeed passes an empty hash to the STORE() method.
2627 Probably a bug in Perl.
2628
2629 =head2 FILE CORRUPTION
2630
2631 The current level of error handling in DBM::Deep is minimal.  Files I<are> checked
2632 for a 32-bit signature when opened, but other corruption in files can cause
2633 segmentation faults.  DBM::Deep may try to seek() past the end of a file, or get
2634 stuck in an infinite loop depending on the level of corruption.  File write
2635 operations are not checked for failure (for speed), so if you happen to run
2636 out of disk space, DBM::Deep will probably fail in a bad way.  These things will 
2637 be addressed in a later version of DBM::Deep.
2638
2639 =head2 DB OVER NFS
2640
2641 Beware of using DB files over NFS.  DBM::Deep uses flock(), which works well on local
2642 filesystems, but will NOT protect you from file corruption over NFS.  I've heard 
2643 about setting up your NFS server with a locking daemon, then using lockf() to 
2644 lock your files, but your milage may vary there as well.  From what I 
2645 understand, there is no real way to do it.  However, if you need access to the 
2646 underlying FileHandle in DBM::Deep for using some other kind of locking scheme like 
2647 lockf(), see the L<LOW-LEVEL ACCESS> section above.
2648
2649 =head2 COPYING OBJECTS
2650
2651 Beware of copying tied objects in Perl.  Very strange things can happen.  
2652 Instead, use DBM::Deep's C<clone()> method which safely copies the object and 
2653 returns a new, blessed, tied hash or array to the same level in the DB.
2654
2655         my $copy = $db->clone();
2656
2657 =head2 LARGE ARRAYS
2658
2659 Beware of using C<shift()>, C<unshift()> or C<splice()> with large arrays.
2660 These functions cause every element in the array to move, which can be murder
2661 on DBM::Deep, as every element has to be fetched from disk, then stored again in
2662 a different location.  This may be addressed in a later version.
2663
2664 =head1 PERFORMANCE
2665
2666 This section discusses DBM::Deep's speed and memory usage.
2667
2668 =head2 SPEED
2669
2670 Obviously, DBM::Deep isn't going to be as fast as some C-based DBMs, such as 
2671 the almighty I<BerkeleyDB>.  But it makes up for it in features like true
2672 multi-level hash/array support, and cross-platform FTPable files.  Even so,
2673 DBM::Deep is still pretty fast, and the speed stays fairly consistent, even
2674 with huge databases.  Here is some test data:
2675         
2676         Adding 1,000,000 keys to new DB file...
2677         
2678         At 100 keys, avg. speed is 2,703 keys/sec
2679         At 200 keys, avg. speed is 2,642 keys/sec
2680         At 300 keys, avg. speed is 2,598 keys/sec
2681         At 400 keys, avg. speed is 2,578 keys/sec
2682         At 500 keys, avg. speed is 2,722 keys/sec
2683         At 600 keys, avg. speed is 2,628 keys/sec
2684         At 700 keys, avg. speed is 2,700 keys/sec
2685         At 800 keys, avg. speed is 2,607 keys/sec
2686         At 900 keys, avg. speed is 2,190 keys/sec
2687         At 1,000 keys, avg. speed is 2,570 keys/sec
2688         At 2,000 keys, avg. speed is 2,417 keys/sec
2689         At 3,000 keys, avg. speed is 1,982 keys/sec
2690         At 4,000 keys, avg. speed is 1,568 keys/sec
2691         At 5,000 keys, avg. speed is 1,533 keys/sec
2692         At 6,000 keys, avg. speed is 1,787 keys/sec
2693         At 7,000 keys, avg. speed is 1,977 keys/sec
2694         At 8,000 keys, avg. speed is 2,028 keys/sec
2695         At 9,000 keys, avg. speed is 2,077 keys/sec
2696         At 10,000 keys, avg. speed is 2,031 keys/sec
2697         At 20,000 keys, avg. speed is 1,970 keys/sec
2698         At 30,000 keys, avg. speed is 2,050 keys/sec
2699         At 40,000 keys, avg. speed is 2,073 keys/sec
2700         At 50,000 keys, avg. speed is 1,973 keys/sec
2701         At 60,000 keys, avg. speed is 1,914 keys/sec
2702         At 70,000 keys, avg. speed is 2,091 keys/sec
2703         At 80,000 keys, avg. speed is 2,103 keys/sec
2704         At 90,000 keys, avg. speed is 1,886 keys/sec
2705         At 100,000 keys, avg. speed is 1,970 keys/sec
2706         At 200,000 keys, avg. speed is 2,053 keys/sec
2707         At 300,000 keys, avg. speed is 1,697 keys/sec
2708         At 400,000 keys, avg. speed is 1,838 keys/sec
2709         At 500,000 keys, avg. speed is 1,941 keys/sec
2710         At 600,000 keys, avg. speed is 1,930 keys/sec
2711         At 700,000 keys, avg. speed is 1,735 keys/sec
2712         At 800,000 keys, avg. speed is 1,795 keys/sec
2713         At 900,000 keys, avg. speed is 1,221 keys/sec
2714         At 1,000,000 keys, avg. speed is 1,077 keys/sec
2715
2716 This test was performed on a PowerMac G4 1gHz running Mac OS X 10.3.2 & Perl 
2717 5.8.1, with an 80GB Ultra ATA/100 HD spinning at 7200RPM.  The hash keys and 
2718 values were between 6 - 12 chars in length.  The DB file ended up at 210MB.  
2719 Run time was 12 min 3 sec.
2720
2721 =head2 MEMORY USAGE
2722
2723 One of the great things about DBM::Deep is that it uses very little memory.
2724 Even with huge databases (1,000,000+ keys) you will not see much increased
2725 memory on your process.  DBM::Deep relies solely on the filesystem for storing
2726 and fetching data.  Here is output from I</usr/bin/top> before even opening a
2727 database handle:
2728
2729           PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME COMMAND
2730         22831 root      11   0  2716 2716  1296 R     0.0  0.2   0:07 perl
2731
2732 Basically the process is taking 2,716K of memory.  And here is the same 
2733 process after storing and fetching 1,000,000 keys:
2734
2735           PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME COMMAND
2736         22831 root      14   0  2772 2772  1328 R     0.0  0.2  13:32 perl
2737
2738 Notice the memory usage increased by only 56K.  Test was performed on a 700mHz 
2739 x86 box running Linux RedHat 7.2 & Perl 5.6.1.
2740
2741 =head1 DB FILE FORMAT
2742
2743 In case you were interested in the underlying DB file format, it is documented
2744 here in this section.  You don't need to know this to use the module, it's just 
2745 included for reference.
2746
2747 =head2 SIGNATURE
2748
2749 DBM::Deep files always start with a 32-bit signature to identify the file type.
2750 This is at offset 0.  The signature is "DPDB" in network byte order.  This is
2751 checked when the file is opened.
2752
2753 =head2 TAG
2754
2755 The DBM::Deep file is in a I<tagged format>, meaning each section of the file
2756 has a standard header containing the type of data, the length of data, and then 
2757 the data itself.  The type is a single character (1 byte), the length is a 
2758 32-bit unsigned long in network byte order, and the data is, well, the data.
2759 Here is how it unfolds:
2760
2761 =head2 MASTER INDEX
2762
2763 Immediately after the 32-bit file signature is the I<Master Index> record.  
2764 This is a standard tag header followed by 1024 bytes (in 32-bit mode) or 2048 
2765 bytes (in 64-bit mode) of data.  The type is I<H> for hash or I<A> for array, 
2766 depending on how the DBM::Deep object was constructed.
2767
2768
2769
2770 The index works by looking at a I<MD5 Hash> of the hash key (or array index 
2771 number).  The first 8-bit char of the MD5 signature is the offset into the 
2772 index, multipled by 4 in 32-bit mode, or 8 in 64-bit mode.  The value of the 
2773 index element is a file offset of the next tag for the key/element in question,
2774 which is usually a I<Bucket List> tag (see below).
2775
2776
2777
2778 The next tag I<could> be another index, depending on how many keys/elements
2779 exist.  See L<RE-INDEXING> below for details.
2780
2781 =head2 BUCKET LIST
2782
2783 A I<Bucket List> is a collection of 16 MD5 hashes for keys/elements, plus 
2784 file offsets to where the actual data is stored.  It starts with a standard 
2785 tag header, with type I<B>, and a data size of 320 bytes in 32-bit mode, or 
2786 384 bytes in 64-bit mode.  Each MD5 hash is stored in full (16 bytes), plus
2787 the 32-bit or 64-bit file offset for the I<Bucket> containing the actual data.
2788 When the list fills up, a I<Re-Index> operation is performed (See 
2789 L<RE-INDEXING> below).
2790
2791 =head2 BUCKET
2792
2793 A I<Bucket> is a tag containing a key/value pair (in hash mode), or a
2794 index/value pair (in array mode).  It starts with a standard tag header with
2795 type I<D> for scalar data (string, binary, etc.), or it could be a nested
2796 hash (type I<H>) or array (type I<A>).  The value comes just after the tag
2797 header.  The size reported in the tag header is only for the value, but then,
2798 just after the value is another size (32-bit unsigned long) and then the plain 
2799 key itself.  Since the value is likely to be fetched more often than the plain 
2800 key, I figured it would be I<slightly> faster to store the value first.
2801
2802
2803
2804 If the type is I<H> (hash) or I<A> (array), the value is another I<Master Index>
2805 record for the nested structure, where the process begins all over again.
2806
2807 =head2 RE-INDEXING
2808
2809 After a I<Bucket List> grows to 16 records, its allocated space in the file is
2810 exhausted.  Then, when another key/element comes in, the list is converted to a 
2811 new index record.  However, this index will look at the next char in the MD5 
2812 hash, and arrange new Bucket List pointers accordingly.  This process is called 
2813 I<Re-Indexing>.  Basically, a new index tag is created at the file EOF, and all 
2814 17 (16 + new one) keys/elements are removed from the old Bucket List and 
2815 inserted into the new index.  Several new Bucket Lists are created in the 
2816 process, as a new MD5 char from the key is being examined (it is unlikely that 
2817 the keys will all share the same next char of their MD5s).
2818
2819
2820
2821 Because of the way the I<MD5> algorithm works, it is impossible to tell exactly
2822 when the Bucket Lists will turn into indexes, but the first round tends to 
2823 happen right around 4,000 keys.  You will see a I<slight> decrease in 
2824 performance here, but it picks back up pretty quick (see L<SPEED> above).  Then 
2825 it takes B<a lot> more keys to exhaust the next level of Bucket Lists.  It's 
2826 right around 900,000 keys.  This process can continue nearly indefinitely -- 
2827 right up until the point the I<MD5> signatures start colliding with each other, 
2828 and this is B<EXTREMELY> rare -- like winning the lottery 5 times in a row AND 
2829 getting struck by lightning while you are walking to cash in your tickets.  
2830 Theoretically, since I<MD5> hashes are 128-bit values, you I<could> have up to 
2831 340,282,366,921,000,000,000,000,000,000,000,000,000 keys/elements (I believe 
2832 this is 340 unodecillion, but don't quote me).
2833
2834 =head2 STORING
2835
2836 When a new key/element is stored, the key (or index number) is first ran through 
2837 I<Digest::MD5> to get a 128-bit signature (example, in hex: 
2838 b05783b0773d894396d475ced9d2f4f6).  Then, the I<Master Index> record is checked
2839 for the first char of the signature (in this case I<b>).  If it does not exist,
2840 a new I<Bucket List> is created for our key (and the next 15 future keys that 
2841 happen to also have I<b> as their first MD5 char).  The entire MD5 is written 
2842 to the I<Bucket List> along with the offset of the new I<Bucket> record (EOF at
2843 this point, unless we are replacing an existing I<Bucket>), where the actual 
2844 data will be stored.
2845
2846 =head2 FETCHING
2847
2848 Fetching an existing key/element involves getting a I<Digest::MD5> of the key 
2849 (or index number), then walking along the indexes.  If there are enough 
2850 keys/elements in this DB level, there might be nested indexes, each linked to 
2851 a particular char of the MD5.  Finally, a I<Bucket List> is pointed to, which 
2852 contains up to 16 full MD5 hashes.  Each is checked for equality to the key in 
2853 question.  If we found a match, the I<Bucket> tag is loaded, where the value and 
2854 plain key are stored.
2855
2856
2857
2858 Fetching the plain key occurs when calling the I<first_key()> and I<next_key()>
2859 methods.  In this process the indexes are walked systematically, and each key
2860 fetched in increasing MD5 order (which is why it appears random).   Once the
2861 I<Bucket> is found, the value is skipped the plain key returned instead.  
2862 B<Note:> Do not count on keys being fetched as if the MD5 hashes were 
2863 alphabetically sorted.  This only happens on an index-level -- as soon as the 
2864 I<Bucket Lists> are hit, the keys will come out in the order they went in -- 
2865 so it's pretty much undefined how the keys will come out -- just like Perl's 
2866 built-in hashes.
2867
2868 =head1 AUTHOR
2869
2870 Joseph Huckaby, L<jhuckaby@cpan.org>
2871
2872 Special thanks to Adam Sah and Rich Gaushell!  You know why :-)
2873
2874 =head1 SEE ALSO
2875
2876 perltie(1), Tie::Hash(3), Digest::MD5(3), Fcntl(3), flock(2), lockf(3), nfs(5),
2877 Digest::SHA256(3), Crypt::Blowfish(3), Compress::Zlib(3)
2878
2879 =head1 LICENSE
2880
2881 Copyright (c) 2002-2005 Joseph Huckaby.  All Rights Reserved.
2882 This is free software, you may use it and distribute it under the
2883 same terms as Perl itself.
2884
2885 =cut