.\" Automatically generated by Pod::Man 4.09 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .if !\nF .nr F 0 .if \nF>0 \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "DBM::Deep::Cookbook 3pm" .TH DBM::Deep::Cookbook 3pm "2018-05-23" "perl v5.26.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBM::Deep::Cookbook \- Cookbook for DBM::Deep .SH "DESCRIPTION" .IX Header "DESCRIPTION" This is the Cookbook for DBM::Deep. It contains useful tips and tricks, plus some examples of how to do common tasks. .SH "RECIPES" .IX Header "RECIPES" .SS "Unicode data" .IX Subsection "Unicode data" If possible, it is highly recommended that you upgrade your database to version 2 (using the \fIutils/upgrade_db.pl\fR script in the \s-1CPAN\s0 distribution), in order to use Unicode. .PP If your databases are still shared by perl installations with older DBM::Deep versions, you can use filters to encode strings on the fly: .PP .Vb 7 \& my $db = DBM::Deep\->new( ... ); \& my $encode_sub = sub { my $s = shift; utf8::encode($s); $s }; \& my $decode_sub = sub { my $s = shift; utf8::decode($s); $s }; \& $db\->set_filter( \*(Aqstore_value\*(Aq => $encode_sub ); \& $db\->set_filter( \*(Aqfetch_value\*(Aq => $decode_sub ); \& $db\->set_filter( \*(Aqstore_key\*(Aq => $encode_sub ); \& $db\->set_filter( \*(Aqfetch_key\*(Aq => $decode_sub ); .Ve .PP A previous version of this cookbook recommended using \&\f(CW\*(C`binmode $db\->_fh, ":utf8"\*(C'\fR, but that is \fInot\fR a good idea, as it could easily corrupt the database. .SS "Real-time Encryption Example" .IX Subsection "Real-time Encryption Example" \&\fB\s-1NOTE\s0\fR: This is just an example of how to write a filter. This most definitely should \fB\s-1NOT\s0\fR be taken as a proper way to write a filter that does encryption. (Furthermore, it fails to take Unicode into account.) .PP Here is a working example that uses the \fICrypt::Blowfish\fR module to do real-time encryption / decryption of keys & values with DBM::Deep Filters. Please visit for more on \fICrypt::Blowfish\fR. You'll also need the \fICrypt::CBC\fR module. .PP .Vb 3 \& use DBM::Deep; \& use Crypt::Blowfish; \& use Crypt::CBC; \& \& my $cipher = Crypt::CBC\->new({ \& \*(Aqkey\*(Aq => \*(Aqmy secret key\*(Aq, \& \*(Aqcipher\*(Aq => \*(AqBlowfish\*(Aq, \& \*(Aqiv\*(Aq => \*(Aq$KJh#(}q\*(Aq, \& \*(Aqregenerate_key\*(Aq => 0, \& \*(Aqpadding\*(Aq => \*(Aqspace\*(Aq, \& \*(Aqprepend_iv\*(Aq => 0 \& }); \& \& my $db = DBM::Deep\->new( \& file => "foo\-encrypt.db", \& filter_store_key => \e&my_encrypt, \& filter_store_value => \e&my_encrypt, \& filter_fetch_key => \e&my_decrypt, \& filter_fetch_value => \e&my_decrypt, \& ); \& \& $db\->{key1} = "value1"; \& $db\->{key2} = "value2"; \& print "key1: " . $db\->{key1} . "\en"; \& print "key2: " . $db\->{key2} . "\en"; \& \& undef $db; \& exit; \& \& sub my_encrypt { \& return $cipher\->encrypt( $_[0] ); \& } \& sub my_decrypt { \& return $cipher\->decrypt( $_[0] ); \& } .Ve .SS "Real-time Compression Example" .IX Subsection "Real-time Compression Example" Here is a working example that uses the \fICompress::Zlib\fR module to do real-time compression / decompression of keys & values with DBM::Deep Filters. Please visit for more on \fICompress::Zlib\fR. .PP .Vb 2 \& use DBM::Deep; \& use Compress::Zlib; \& \& my $db = DBM::Deep\->new( \& file => "foo\-compress.db", \& filter_store_key => \e&my_compress, \& filter_store_value => \e&my_compress, \& filter_fetch_key => \e&my_decompress, \& filter_fetch_value => \e&my_decompress, \& ); \& \& $db\->{key1} = "value1"; \& $db\->{key2} = "value2"; \& print "key1: " . $db\->{key1} . "\en"; \& print "key2: " . $db\->{key2} . "\en"; \& \& undef $db; \& exit; \& \& sub my_compress { \& my $s = shift; \& utf8::encode($s); \& return Compress::Zlib::memGzip( $s ) ; \& } \& sub my_decompress { \& my $s = Compress::Zlib::memGunzip( shift ) ; \& utf8::decode($s); \& return $s; \& } .Ve .PP \&\fBNote:\fR Filtering of keys only applies to hashes. Array \*(L"keys\*(R" are actually numerical index numbers, and are not filtered. .SH "Custom Digest Algorithm" .IX Header "Custom Digest Algorithm" DBM::Deep by default uses the \fIMessage Digest 5\fR (\s-1MD5\s0) algorithm for hashing keys. However you can override this, and use another algorithm (such as \s-1SHA\-256\s0) or even write your own. But please note that DBM::Deep currently expects zero collisions, so your algorithm has to be \fIperfect\fR, so to speak. Collision detection may be introduced in a later version. .PP You can specify a custom digest algorithm by passing it into the parameter list for \fInew()\fR, passing a reference to a subroutine as the 'digest' parameter, and the length of the algorithm's hashes (in bytes) as the 'hash_size' parameter. Here is a working example that uses a 256\-bit hash from the \&\fIDigest::SHA256\fR module. Please see for more information. .PP The value passed to your digest function will be encoded as \s-1UTF\-8\s0 if the database is in version 2 format or higher. .PP .Vb 2 \& use DBM::Deep; \& use Digest::SHA256; \& \& my $context = Digest::SHA256::new(256); \& \& my $db = DBM::Deep\->new( \& filename => "foo\-sha.db", \& digest => \e&my_digest, \& hash_size => 32, \& ); \& \& $db\->{key1} = "value1"; \& $db\->{key2} = "value2"; \& print "key1: " . $db\->{key1} . "\en"; \& print "key2: " . $db\->{key2} . "\en"; \& \& undef $db; \& exit; \& \& sub my_digest { \& return substr( $context\->hash($_[0]), 0, 32 ); \& } .Ve .PP \&\fBNote:\fR Your returned digest strings must be \fB\s-1EXACTLY\s0\fR the number of bytes you specify in the hash_size parameter (in this case 32). Undefined behavior will occur otherwise. .PP \&\fBNote:\fR If you do choose to use a custom digest algorithm, you must set it every time you access this file. Otherwise, the default (\s-1MD5\s0) will be used. .SH "PERFORMANCE" .IX Header "PERFORMANCE" Because DBM::Deep is a conncurrent datastore, every change is flushed to disk immediately and every read goes to disk. This means that DBM::Deep functions at the speed of disk (generally 10\-20ms) vs. the speed of \s-1RAM\s0 (generally 50\-70ns), or at least 150\-200x slower than the comparable in-memory datastructure in Perl. .PP There are several techniques you can use to speed up how DBM::Deep functions. .IP "\(bu" 4 Put it on a ramdisk .Sp The easiest and quickest mechanism to making DBM::Deep run faster is to create a ramdisk and locate the DBM::Deep file there. Doing this as an option may become a feature of DBM::Deep, assuming there is a good ramdisk wrapper on \s-1CPAN.\s0 .IP "\(bu" 4 Work at the tightest level possible .Sp It is much faster to assign the level of your db that you are working with to an intermediate variable than to re-look it up every time. Thus .Sp .Vb 4 \& # BAD \& while ( my ($k, $v) = each %{$db\->{foo}{bar}{baz}} ) { \& ... \& } \& \& # GOOD \& my $x = $db\->{foo}{bar}{baz}; \& while ( my ($k, $v) = each %$x ) { \& ... \& } .Ve .IP "\(bu" 4 Make your file as tight as possible .Sp If you know that you are not going to use more than 65K in your database, consider using the \f(CW\*(C`pack_size => \*(Aqsmall\*(Aq\*(C'\fR option. This will instruct DBM::Deep to use 16bit addresses, meaning that the seek times will be less. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fIDBM::Deep\fR\|(3), \fIDigest::MD5\fR\|(3), \fIDigest::SHA256\fR\|(3), \&\fICrypt::Blowfish\fR\|(3), \fICompress::Zlib\fR\|(3)