http://www.perlmonks.org?node_id=341454

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

So I've searched, I've read pod pages and whatnot, and I'm still really confused as to what anydbm_file is for. I have a script I'm going to run on two different systems. One has DB_file and the other has several other DB types (NDBM, ODBM, SDBM) but not DB_file. I was hoping that anydbm_file would allow me to use whichever was available, but the documentation page for anydbm is very sparse, and doesn't give very good syntax or examples. Could someone elucidate for me?

Replies are listed 'Best First'.
Re: what is anydbm_file?
by graff (Chancellor) on Apr 01, 2004 at 05:32 UTC
    I share your disappointment with the terseness of the various dbm man pages in perl -- there are some serious gaps there, and it is often not that helpful to read things like "to use this module, you really should have the complete (whatever_dbm C library) manual to refer to". (Guess what I've never been able to find on the university network where I do most of my work...) Hell, just a few more examples for how to open each of the dbm flavors would be nice.

    (Update: in the years since I first posted this node, the docs have improved a lot, and easy examples are easy to find.)

    In any case, if you intend to be sharing data between the DB_file system and the NDBM/ODBM/SDBM system, you may be up a creek unless at least one of these flavors is common to both systems. As explained in the AnyDBM_File man page (in a rare display of detail), each flavor has its own file storage format and different capacity constraints, so portability of data between two DBM flavors requires that both flavors be available to a given perl installation (on one machine). On top of that, most flavors create data files that are not portable across the big-/little-endian divide -- so even if you had the same DBM module on two machines, the data would not be directly portable if the systems differ in cpu byte-order.

    But if you are writing a script such that each installation on a given machine will just be writing/reading data solely on that machine, you can start with something like the following test script, and you shouldn't have to change this to suit particular machines:

    #!/usr/bin/perl use strict; use Fcntl; use AnyDBM_File; my $preferred_dbm = $AnyDBM_File::ISA[0]; my %hash; my $dbfile = "this_is_a_test"; print "opening test_dbm using $preferred_dbm ...\n"; tie( %hash, $preferred_dbm, $dbfile, O_CREAT|O_RDWR, 0664 ) or die $!; my $i = 0; my $limit = 20000; while ( $i < $limit ) { my $x = rand; $hash{"a$i"} = $x; $i++; print "$i records stored\n" if ( $i % 2000 == 0 ); } untie %hash; print "Saved $limit records in $dbfile using $preferred_dbm\n"; %hash = (); # just to prove things work as intended tie %hash, $preferred_dbm, $dbfile, O_RDONLY, 0444; for $i ( 1 .. 20 ) { my $k = 'a' . int( rand( $limit )); print "$k = $hash{$k}\n"; } untie %hash;
    Note that the different dbm flavors have different file naming conventions -- some create one file, some create two, some add a standard file extension to the given file name, some do not.

    One last issue: the AnyDBM_File man page appears to say that at least one flavor (SDBM_File) is part of the core distribution -- another quick test you should try, just to see what's available (i.e. possible) and what's preferred is simply:

    perl -MAnyDBM_File -e 'print join $/, @AnyDBM_File::ISA, $/'
    (update: On trying that last little test myself, I may be misunderstanding how @ISA really works in AnyDBM_File. I tried it on a system where I know there's more than one flavor available -- because I've used at least two different ones there in the past -- but only NDBM_File shows up. As a side note, I noticed that using NDBM on macosx creates one file "name.db", while doing the same thing on solaris creates two files, "name.pag" and "name.dir" -- go figure... At least the test script given above worked on both systems without modification; maybe that's all that matters.)
      On trying that last little test myself, I may be misunderstanding how @ISA really works in AnyDBM_File. I tried it on a system where I know there's more than one flavor available -- because I've used at least two different ones there in the past -- but only NDBM_File shows up.
      I took a look at this, and found that when AnyDBM_File is loaded, it goes through its @ISA and and replaces it with a list containing a single entry: the first module in the original @ISA list that can be successfully loaded.
Re: what is anydbm_file?
by jZed (Prior) on Mar 31, 2004 at 23:30 UTC
    Yes AnyDBM_File will use whichever is available. If you just use 'AnyDBM_File' as the tie type, it will look for things in the order specified in the POD. But DB_File is also fairly easy to install.
    my %h; tie(%h, 'AnyDBM_File', $file, $mode, 0666) or die "Couldn't tie DBM file '$file': $!; aborting";
    That will use whatever's available selecting in the order specified in the POD if several are available. You can set the @INC for AnyDBM_File if you prefer say GDBM over NDBM.
Re: what is anydbm_file?
by Happy-the-monk (Canon) on Mar 31, 2004 at 23:29 UTC

    AnyDBM_File - provide framework for multiple DBMs   is what you're looking for, then.

    From the documentation:

    BEGIN { @AnyDBM_File::ISA = qw(DB_File GDBM_File NDBM_File) } use AnyDBM_File; use POSIX; use NDBM_File; use DB_File; tie %newhash, 'DB_File', $new_filename, O_CREAT|O_RDWR; tie %oldhash, 'NDBM_File', $old_filename, 1, 0; %newhash = %oldhash;

    Although there is not very much to see, what more is needed?

    Cheers, Sören

      I don't mean to be critical, but this is a good example of a bad post. I explicitly stated that I had read the man page for this module and that it had not helped. Restating it does about as much good as speaking loudly and slowly to foreigners.

      The 'else' that is needed is in the posts below this. For example, the man page makes no reference to the ability to select AnyDBM_File as a DB type.

      Thanks to everyone else who posted too, btw, I got just what I needed.

        Thank you for replying after all, Anonymous Monk. You said: I was hoping that anydbm_file would allow me to use whichever was available, but the documentation page for anydbm is very sparse, and doesn't give very good syntax or examples.

        In my understanding, the sniplet of the manual shows that AnyDBM_File does exactly that, allow you use all available DBM drivers. It does so with an example of it's syntax. I don't want to discuss whether it's a good example. It was sufficient to get me going.

        I am sorry I did not help you to your own gain, which I intended to do. But you failed to answer my question as well, so we could not arrive at understanding the other.

        Being a foreigner myself, I am very sorry you felt ill-treated by my post. That was definitely not intended.
        On a side note: speaking slowly sometimes helps understanding, whereas speaking loudly only helps in noisy and crowded spaces.

        Cheerio, Sören

Re: what is anydbm_file?
by Anomynous Monk (Scribe) on Apr 01, 2004 at 04:24 UTC
    AnyDBM_File is basically for backward compatibility for those using the old dbmopen instead of the new tie facility. (Of course, it's usable by tie also.) The intent is that it pick the first available from a list of DB modules. If you know anything about your requirements or the system you will run on, it's better to specify explicitly the db module you actually want.