The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Bot::Cobalt::DB - Locking Berkeley DBs with serialization

SYNOPSIS

  use Bot::Cobalt::DB;
  
  ## ... perhaps in a Cobalt_register ...
  my $db_path = $core->var ."/MyDatabase.db";
  $self->{DB} = Bot::Cobalt::DB->new(
    File => $db_path,
  );
  
  ## Open (and lock):
  $self->{DB}->dbopen;
  
  ## Do some work:
  $self->{DB}->put("SomeKey",
    { Some => {
        Deep => { Structure => 1, },
    }, },
  );
  
  for my $key ($self->{DB}->dbkeys) {
    my $this_hash = $self->{DB}->get($key);
  }
  
  $self->{DB}->dbclose;

DESCRIPTION

Bot::Cobalt::DB provides a simple object-oriented interface to basic DB_File (Berkeley DB 1.x) usage.

BerkDB is a fast and simple key/value store. This module uses JSON to store nested Perl data structures, providing easy database-backed storage for Bot::Cobalt plugins.

Performance will suffer miserably if you don't have JSON::XS!

Constructor

new() is used to create a new Bot::Cobalt::DB object representing your Berkeley DB:

  my $db = Bot::Cobalt::DB->new(
    File => $path_to_db,

   ## Optional arguments:
   
    # Database file mode
    Perms => $octal_mode,

    ## Locking timeout in seconds
    ## Defaults to 5s:
    Timeout => 10,
    
    ## Normally, references are serialized transparently.
    ## If Raw is enabled, no serialization filter is used and you're 
    ## on your own.
    Raw => 0,
  );

Opening and closing

Database operations should be contained within a dbopen/dbclose:

  ## open, put, close:
  $db->dbopen || croak "dbopen failure";
  $db->put($key, $data);
  $db->dbclose;
  
  ## open for read-only, read, close:
  $db->dbopen(ro => 1) || croak "dbopen failure";
  my $data = $db->get($key);
  $db->dbclose;

Methods will fail if the DB is not open.

If the DB for this object is open when the object is DESTROY'd, Bot::Cobalt::DB will attempt to close it safely.

Locking

Proper locking is done -- that means the DB is 're-tied' after a lock is granted and state cannot change between database open and lock time.

The attempt to gain a lock will time out after five seconds (and dbopen() will return boolean false).

The lock is cleared on dbclose.

If the Bot::Cobalt::DB object is destroyed, it will attempt to dbclose for you, but it is good practice to keep track of your open/close calls and attempt to close as quickly as possible.

Methods

dbopen

dbopen opens and locks the database. If 'ro => 1' is specified, this is a LOCK_SH shared (read) lock; otherwise it is a LOCK_EX exclusive (write) lock.

Try to call a dbclose as quickly as possible to reduce locking contention.

is_open

Returns a boolean value representing whether or not the DB is currently open and locked.

dbclose

dbclose closes and unlocks the database.

put

The put method adds an entry to the database:

  $db->put($key, $value);

The value can be any data structure serializable by JSON::XS; that is to say, any shallow or deep data structure NOT including blessed references.

(Yes, Storable is faster. JSON is used because it is trivially portable to any language that can interface with BerkDB.)

get

The get method retrieves a (deserialized) key.

  $db->put($key, { Some => 'hash' } );
  ## . . . later on . . .
  my $ref = $db->get($key);

del

The del method removes a key from the database.

  $db->del($key);

dbkeys

dbkeys will return a list of keys in list context, or the number of keys in the database in scalar context.

dbdump

You can serialize/export the entirety of the DB via dbdump.

  ## YAML::Syck
  my $yamlified = $db->dbdump('YAML');
  ## YAML::XS
  my $yamlified = $db->dbdump('YAMLXS');
  ## JSON (::XS or ::PP)
  my $jsonified = $db->dbdump('JSON');

See Bot::Cobalt::Serializer for more on freeze() and valid formats.

As of 2.00_24, a tool called cobalt2-dbdump is available as a simple frontend to this functionality. See cobalt2-dbdump --help

FORMAT

Bot::Cobalt::DB databases are Berkeley DB 1.x, with NULL-terminated records and values stored as JSON.

They should be fairly easy to parse in a language of your choice.

AUTHOR

Jon Portnoy <avenj@cobaltirc.org>

http://www.cobaltirc.org