http://qs321.pair.com?node_id=989260

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

I'm kind of confused in trying to use BerkeleyDB with an environnement

Here is the simplest example I could figure out:

# creating a dummy db first use DB_File; tie my %h, "DB_File", "/tmp/test.db"; $h{foo} = "bar"; untie %h; # now trying to read it use BerkeleyDB; my $db = new BerkeleyDB::Hash -Env => BerkeleyDB::Env->new(-Home => "/tmp"), -Filename => "test.db" or die "could not open database";

This always raises the "could not open database" exception.

What am I missing?

Replies are listed 'Best First'.
Re: can't manage to use BerkeleyDB::Env
by Anonymous Monk on Aug 23, 2012 at 10:23 UTC

    What am I missing?

    Don't mix DB_File with BerkeleyDB, DB_File doesn't use any Env

      Ok. Well, to tell the whole story I only used DB_File in this simple example.

      The thing is that I already have a db which I know has an environnement in it (I've already opened it with an other perl program). What I wanted to do was to retrieve some data from its Env, so I wanted to explore a bit the structure of an BerkeleyDB::Env class.

      So I tried to create a "detached" env:

      use BerkeleyDB; my $env = new BerkeleyDB::Env -Home => "/tmp" or die "could not create env";

      And then I do raise the "could not create" exception.

      Shouldn't it be possible to create a brand new environnement, detached from any database?

        Well, according to the docs, it is, provided you follow the docs (use flags)
        #!/usr/bin/perl -- use strict; use warnings; use Data::Dump; use BerkeleyDB; for my $opts ( [], [-Flags => DB_CREATE| DB_INIT_CDB | DB_INIT_MPOOL] + ){ my $env = BerkeleyDB::Env->new( -Home => './home', @$opts, ) or warn "cannot open environment: $BerkeleyDB::Error\n"; dd $env, [ glob './home/*' ]; } __END__

        On first run it doesn't exist, so first try, without flags, fails -- you need flags to initialize

        $ perl berkeleydb.env.pl cannot open environment: No such file or directory (undef, []) ( bless([12346044], "BerkeleyDB::Env"), [ "./home/__db.001", "./home/__db.002", "./home/__db.003", "./home/__db.004", ], )

        On second run both tries work, because its already initialized

        $ perl berkeleydb.env.pl ( bless([10087228], "BerkeleyDB::Env"), [ "./home/__db.001", "./home/__db.002", "./home/__db.003", "./home/__db.004", ], ) ( bless([12336228], "BerkeleyDB::Env"), [ "./home/__db.001", "./home/__db.002", "./home/__db.003", "./home/__db.004", ], )
Re: can't manage to use BerkeleyDB::Env
by flexvault (Monsignor) on Aug 23, 2012 at 14:24 UTC

    grondilu,

    This is a code snippet from a working program, to show you how to use the 'BerkeleyDB::Env'. Think of the environment as a holding directory, where related databases are stored, and the related BerkeleyDB internal files and cache are stored. I wouldn't use '/tmp' since it's world readable, but that's your call.

    I pulled a lot of unrelated testing out, so it may not compile, but you'll be in the ballpark. This shows with the default cache size, but I usually 16MB in production.

    One important thing, I left the 'Fcntl' in to help you think about the potential for race conditions. I use an extra file to lock the BerkeleyDB environment before using the BerkeleyDB calls. Without it, you are suspect to many race conditions. If you are going to run in single user mode, you don't need it. But for multi-user or multi-tasking you'll save yourself a lot of headaches. BerkeleyDB is very fast and you don't notice any overhead with the extra flocks.

    use strict; + use BerkeleyDB; our %Session = (); use Fcntl qw( :flock ); my $DBHome = "/home/FlexBase/"; system("rm /home/FlexBase/*"); ## Temporary for testing our $filename = "/home/FlexBase/TestBDB"; use constant CACHE => '1048576'; my $Cachesize = CACHE; our $env = new BerkeleyDB::Env ( -Home => '/home/FlexBase', -Cachesize => CACHE, -Flags => DB_INIT_MPOOL|DB_INIT_CDB|DB_CREATE ) or die "cannot open ENV: $! $BerkeleyDB::Error\n"; our %Pyr = (); our $db1 = tie %Pyr, 'BerkeleyDB::Btree', ( -Filename => "$filename", -Env => $env, # -Pagesize => 4096, ## Use of this makes the Berk +eleyDB operate worst! -Flags => DB_CREATE );

    If you super search on BerkeleyDB, you'll find some examples of subroutines that show the external locking and some timing information.

    Good Luck!

    "Well done is better than well said." - Benjamin Franklin

      Thanks. That should definitely help.