Paranoid::BerkeleyDB(3p)

NAME
Paranoid::BerkeleyDB -- BerkeleyDB concurrent-access Object

VERSION
$Id: BerkeleyDB.pm,v 0.82 2009/03/17 23:50:52 acorliss Exp $

SYNOPSIS
  use Paranoid::BerkeleyDB;

  $db = Paranoid::BerkeleyDB->new(DbDir => '/tmp', DbName => 'foo.db');
  $rv = $db->addDb($dbname);

  $val = $db->getVal($key);
  $val = $db->getVal($key, $dbname);

  $rv = $db->setVal($key, $val);
  $rv = $db->setVal($key, $val, $dbname);

  @keys = $db->getKeys();
  @keys = $db->getKeys($dbname);
  @keys = $db->getKeys(undef, \&sub);
  @keys = $db->getKeys($dbname, \&sub);

  $db->purgeDb();
  $db->purgeDb($dbname);

  @dbs = $db->listDbs();

  # Close environment & databases
  $db = undef;

DESCRIPTION
This provides a OO-based wrapper for BerkeleyDB that creates concurrent-access BerkeleyDB databases. Each object can have multiple databases, but all databases within an object will use a single shared environment. To make this multiprocess safe an external lock file is used with only one process at a time allowed to hold an exclusive write lock, even if the write is intended for a different database.

Databases and environments are created using the defaults for both the environment and the databases. This won't be the highest performance implementation for BerkeleyDB, but it should be the safest and most robust.

Limitations: all keys and all values must be valid strings. That means that attempting to set a valid key's associated value to undef will fail to add that key to the database. In fact, if the an existing key is assigned a undefined value it will be deleted from the database.

NOTE Many versions of BerkeleyDB liberaries that provide concurrent access are buggy as all hell. I can vouch that as of 4.6.21 most of those problems have gone away. In a nutshell, if you get errors about running out of lockers the problem is likely in the db libraries themselves, not in this module.

SUBROUTINES/METHODS

  new
  $db = Paranoid::BerkeleyDB->new(DbDir => '/tmp', DbName => 'foo.db');

This class method is the object instantiator. Two arguments are required: DbDir which is the path to the directory where the database files will be stored, and DbName which is the filename of the database itself. If DbDir doesn't exist it will be created for you automatically.

This method will create a BerkeleyDB Environment and will support multiprocess transactions.

Any errors in the operation will be stored in Paranoid::ERROR.

  addDb
  $rv = $db->addDb($dbname);

This method adds another database to the current object and environment. Calling this method does require an exclusive write lock to the database to prevent race conditions.

Any errors in the operation will be stored in Paranoid::ERROR.

  getVal
  $val = $db->getVal($key);
  $val = $db->getVal($key, $dbname);

This method retrieves the associated string to the passed key. Called with one argument the method uses the default database. Otherwise, a second argument specifying the specific database is required.

Requesting a non-existent key or from a nonexistent database will result in an undef being returned. In the case of the latter an error message will also be set in Paranoid::ERROR.

  setVal
  $rv = $db->setVal($key, $val);
  $rv = $db->setVal($key, $val, $dbname);

This method adds or updates an associative pair. If the passed value is undef the key is deleted from the database. If no database is explicitly named it is assumed that the default database is the one to work on.

Requesting a non-existent key or from a nonexistent database will result in an undef being returned. In the case of the latter an error message will also be set in Paranoid::ERROR.

  getKeys
  @keys = $db->getKeys();
  @keys = $db->getKeys($dbname);
  @keys = $db->getKeys(undef, \&sub);
  @keys = $db->getKeys($dbname, \&sub);

If this method is called without the optional subroutine reference it will return all the keys in the hash in hash order. If a subroutine reference is called it will be called as each key/value pair is iterated over with three arguments:

    &$subRef($self, $key, $value);

with $self being a handle to the current Paranoid::BerkeleyDB object. You may use this object handle to perform other database operations as needed.

  purgeDb
  $db->purgeDb();
  $db->purgeDb($dbname);

This method purges all associative pairs from the designated database. If no database name was passed then the default database will be used. This method returns the number of records purged, or a -1 if an invalid database was requested.

  listDbs
  @dbs = $db->listDbs();

This method returns a list of databases accessible by this object.

DEPENDENCIES

o   Paranoid

o   Paranoid::Debug

o   Paranoid::Filesystem

o   Paranoid::Lockfile

o   BerkeleyDB

BUGS AND LIMITATIONS
Due to the excessive reliance on lockfiles meant to prevent race conditions with other processes, this won't be the fastest db access if you're rapidly creating, destroying, and re-creating objects. If you're keeping an object around for extended use it should be reasonable.

If you have multiple dbs accessible via one object (and environment) you do need to remember that there is only one global write lock per environment. So, even if other processes need to access a different db that what is being written to, they'll have to wait until the write lock is released.

Finally, no provisions have been made to allow tuning of the BerkeleyDB environment. If the defaults don't work well for your workloads don't use this module.

End sum: this module should be safe and reliable, but not necessarily high-performing, especially with workloads with a high write-to-read transaction ratio.

HISTORY
None as of yet.

AUTHOR
Arthur Corliss (corliss@digitalmages.com)

LICENSE AND COPYRIGHT
This software is licensed under the same terms as Perl, itself. Please see http://dev.perl.org/licenses/ for more information.

(c) 2005, Arthur Corliss (corliss@digitalmages.com)