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