You need several concurrently running programs to have simultaneous access to a DBM file.
Either use the DBM implementation's locking mechanism if it has one, lock the file with flock
, or use an auxiliary locking scheme as in Recipe 7.21.
With SDBM or NDBM, you can't do much to lock the database itself. You must devise an auxiliary locking scheme using an extra lockfile.
GDBM uses the concept of readers and writers: either many readers or one solitary writer may have a GDBM file open at any given time. You specify whether you're a reader or a writer when you open it. This can be annoying.
Version 1 of Berkeley DB gives you access to the file descriptor of the open database, allowing you to flock
it. The lock applies to the database as a whole, not to individual records. Version 2 implements its own full transaction system with locking.
Example 14.3 shows an example of locking a database using Berkeley DB. Run this repeatedly in the background to see locks granted in proper order.
#!/usr/bin/perl # dblockdemo - demo locking dbm databases use DB_File; use strict; sub LOCK_SH { 1 } # In case you don't have sub LOCK_EX { 2 } # the standard Fcntl module. You sub LOCK_NB { 4 } # should, but who can tell sub LOCK_UN { 8 } # how those chips fall? my($oldval, $fd, $db, %db, $value, $key); $key = shift || 'default'; $value = shift || 'magic'; $value .= " $$"; $db = tie(%db, 'DB_File', '/tmp/foo.db', O_CREAT|O_RDWR, 0666) or die "dbcreat /tmp/foo.db $!"; $fd = $db->fd; # need this for locking print "$$: db fd is $fd\n"; open(DB_FH, "+<&=$fd") or die "dup $!"; 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{$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{$key} = $value; $db->sync; # to flush sleep 10; flock(DB_FH, LOCK_UN); undef $db; untie %db; close(DB_FH); print "$$: Updated db to $key=$value\n";
The documentation for the standard DB_File module, also in Chapter 7 of Programming Perl; Recipe 7.11; Recipe 16.12