7.2.8 DB_File - Access to Berkeley DBuse DB_File; # brackets in following code indicate optional arguments [$X =] tie %hash, "DB_File", $filename [, $flags, $mode, $DB_HASH]; [$X =] tie %hash, "DB_File", $filename, $flags, $mode, $DB_BTREE; [$X =] tie @array, "DB_File", $filename, $flags, $mode, $DB_RECNO; $status = $X->del($key [, $flags]); $status = $X->put($key, $value [, $flags]); $status = $X->get($key, $value [, $flags]); $status = $X->seq($key, $value [, $flags]); $status = $X->sync([$flags]); $status = $X->fd; untie %hash; untie @array; DB_File is the most flexible of the DBM-style tie modules. It allows Perl programs to make use of the facilities provided by Berkeley DB (not included). If you intend to use this module you should really have a copy of the Berkeley DB manual page at hand. The interface defined here mirrors the Berkeley DB interface closely. Berkeley DB is a C library that provides a consistent interface to a number of database formats. DB_File provides an interface to all three of the database (file) types currently supported by Berkeley DB. The file types are:
7.2.8.1 How does DB_File interface to Berkeley DB?
DB_File gives access to Berkeley DB files using Perl's
tie
function. This allows DB_File to access Berkeley DB files using either a
hash (for In addition to the tie interface, it is also possible to use most of the functions provided in the Berkeley DB API. 7.2.8.2 Differences from Berkeley DBBerkeley DB uses the function dbopen (3) to open or create a database. Below is the C prototype for dbopen (3). DB * dbopen (const char *file, int flags, int mode, DBTYPE type, const void *openinfo)
The This interface is handled slightly differently in DB_File. Here is an equivalent call using DB_File. tie %array, "DB_File", $filename, $flags, $mode, $DB_HASH;
The
In the example above
The keys allowed in each of these predefined references are limited to
the names used in the equivalent C structure. So, for example, the
To change one of these elements, just assign to it like this: $DB_HASH->{cachesize} = 10_000; 7.2.8.3 Array offsets
In order to make 7.2.8.4 In-memory databases
Berkeley DB allows the creation of in-memory databases by using use strict; use Fcntl; use DB_File; my ($k, $v, %hash); tie(%hash, 'DB_File', undef, O_RDWR|O_CREAT, 0, $DB_BTREE) or die "can't tie DB_File: $!": foreach $k (keys %ENV) { $hash{$k} = $ENV{$k}; } # this will now come out in sorted lexical order # without the overhead of sorting the keys while (($k,$v) = each %hash) { print "$k=$v\n"; } 7.2.8.5 Using the Berkeley DB interface directlyIn addition to accessing Berkeley DB using a tied hash or array, you can also make direct use of most functions defined in the Berkeley DB documentation. To do this you need to remember the return value from tie , or use the tied function to get at it yourself later on. $db = tie %hash, "DB_File", "filename"; Once you have done that, you can access the Berkeley DB API functions directly. $db->put($key, $value, R_NOOVERWRITE); # invoke the DB "put" function
All the functions defined in the
dbopen
(3) manpage are available
except for
All the constants defined in the dbopen manpage are also available. Below is a list of the functions available. (The comments only tell you the differences from the C version.)
7.2.8.6 Examples
Here are a few examples. First, using use DB_File; use Fcntl; tie %h, "DB_File", "hashed", O_RDWR|O_CREAT, 0644, $DB_HASH; # Add a key/value pair to the file $h{apple} = "orange"; # Check for value of a key print "No, we have some bananas.\n" if $h{banana}; # Delete delete $h{"apple"}; untie %h;
Here is an example using use DB_File; use Fcntl; sub Compare { my ($key1, $key2) = @_; "\L$key1" cmp "\L$key2"; } $DB_BTREE->{compare} = 'Compare'; tie %h, 'DB_File', "tree", O_RDWR|O_CREAT, 0644, $DB_BTREE; # Add a key/value pair to the file $h{Wall} = 'Larry'; $h{Smith} = 'John'; $h{mouse} = 'mickey'; $h{duck} = 'donald'; # Delete delete $h{duck}; # Cycle through the keys printing them in order. # Note it is not necessary to sort the keys as # the btree will have kept them in order automatically. while ($key = each %h) { print "$key\n" } untie %h; The preceding code yields this output: mouse Smith Wall
Next, an example using my(@line, $number); $number = 10; use Fcntl; use DB_File; tie(@line, "DB_File", "/tmp/text", O_RDWR|O_CREAT, 0644, $DB_RECNO) or die "can't tie file: $!"; $line[$number - 1] = "this is a new line $number"; Here's an example of updating a file in place: use Fcntl; use DB_File; tie(@file, 'DB_File', "/tmp/sample", O_RDWR, 0644, $DB_RECNO) or die "can't update /tmp/sample: $!"; print "line #3 was ", $file[2], "\n"; $file[2] = `date`; untie @file; Note that the tied array interface is incomplete, causing some operations on the resulting array to fail in strange ways. See the discussion of tied arrays in Chapter 5 . Some object methods are provided to avoid this. Here's an example of reading a file backward: use DB_File; use Fcntl; $H = tie(@h, "DB_File", $file, O_RDWR, 0640, $DB_RECNO) or die "Cannot open file $file: $!\n"; # print the records in reverse order for ($i = $H->length - 1; $i >= 0; --$i) { print "$i: $h[$i]\n"; } untie @h; 7.2.8.7 Locking databases
Concurrent access of a read-write database by several parties requires
that each use some kind of locking. Here's an example that uses the
use Fcntl; use DB_File; use strict; sub LOCK_SH { 1 } sub LOCK_EX { 2 } sub LOCK_NB { 4 } sub LOCK_UN { 8 } my($oldval, $fd, $db_obj, %db_hash, $value, $key); $key = shift || 'default'; $value = shift || 'magic'; $value .= " $$"; $db_obj = tie(%db_hash, 'DB_File', '/tmp/foo.db', O_CREAT|O_RDWR, 0644) or die "dbcreat /tmp/foo.db $!"; $fd = $db_obj->fd; print "$$: db fd is $fd\n"; open(DB_FH, "+<&=$fd") or die "fdopen $!"; unless (flock (DB_FH, LOCK_SH | LOCK_NB)) { print "$$: CONTENTION; can't read during write update! Waiting for read lock ($!) ...."; unless (flock (DB_FH, LOCK_SH)) { die "flock: $!" } } print "$$: Read lock granted\n"; $oldval = $db_hash{$key}; print "$$: Old value was $oldval\n"; flock(DB_FH, LOCK_UN); unless (flock (DB_FH, LOCK_EX | LOCK_NB)) { print "$$: CONTENTION; must have exclusive lock! Waiting for write lock ($!) ...."; unless (flock (DB_FH, LOCK_EX)) { die "flock: $!" } } print "$$: Write lock granted\n"; $db_hash{$key} = $value; sleep 10; $db_obj->sync(); # to flush flock(DB_FH, LOCK_UN); undef $db_obj; # removing the last reference to the DB # closes it. Closing DB_FH is implicit. untie %db_hash; print "$$: Updated db to $key=$value\n"; 7.2.8.8 See alsoRelated manpages: dbopen (3), hash (3), recno (3), btree (3). Berkeley DB is available from these locations: |
|