Alex J. G. Burzyński

NAME

CDB::TinyCDB - Perl extension for TinyCDB library to cdb databases

SYNOPSIS

  use CDB::TinyCDB;

  # open ( direct file access )
  my $cdb = CDB::TinyCDB->open( 'my.cdb' );

  # load ( loads file into memory )
  my $cdb = CDB::TinyCDB->load( 'my.cdb' );

  # returns first occurence of key in file
  print $cdb->get("key");

  # returns all records for key
  print "$_\n" for $cdb->getall("key");

  # returns last record for key
  print $cdb->getlast("key");

  # checks if key exists
  print $cdb->exists("key");

  # iterates over all entries
  while ( my ($key, $value) = $cdb->each ) {
    # same as cdb -d my.cdb, but skips null keys
    printf("+%d,%d:%s->%s\n", length($key), length($value), $key, $value);
  }

  # returns all keys (skips null keys)
  print "$_\n" for $cdb->keys;

or

  use CDB::TinyCDB;

  # open/load for updating - loads all existing records into temp file
  my $cdb = CDB::TinyCDB->open( 'my.cdb', for_update => "my.cdb.$$" );
  my $cdb = CDB::TinyCDB->load( 'my.cdb', for_update => "my.cdb.$$" );

  # add new records (allows duplicates)
  print "records added: ", $cdb->put_add( k1, 'value1'); # 1
  print "records added: ", $cdb->put_add( k1 => 'value1', k2 => 'value2' ); # 2

  # replace and remove old records
  print "records replaced: ", $cdb->put_replace( k3, 'value3'); # 0
  print "records replaced: ", $cdb->put_replace( key, 'value'); # 1

  # replace and fill with null old records
  print "records replaced: ", $cdb->put_replace0( k2, 'value3'); # 1

  # add and warn if record previously existed
  print "records added: ", $cdb->put_warn( k1, 'value4'); # 1
  # warns: Key k1 already exists - added anyway

  # checks if key exists
  print $cdb->exists("k1");

  # dies if record already existed
  eval {
      $cdb->put_insert( k1, 'value1');
  };
  if ( $@ ) {
    print "k1 wasn't added: $@\n"; # Unable to insert new record - key exists
  }
  
  # commit changes and reopen/reload db - temp file replaces my.cdb
  $cdb->finish( save_changes => 1, reopen => 1);
  # same as
  $cdb->finish();

  print $cdb->getlast("k1"); # value4 

  # finish without saving changes
  $cdb->finish( save_changes => 0 );

  # finish without reopening file
  $cdb->finish( reopen => 0 );

or

  use CDB::TinyCDB;

  # create new cdb file
  my $cdb = CDB::TinyCDB->create( 'my-new.cdb', "my-new.cdb.$$" );

  # add new records (allows duplicates)
  print "records added: ", $cdb->put_add( k1, 'value1'); # 1
  print "records added: ", $cdb->put_add( k1 => 'value1', k2 => 'value2' ); # 2

  # replace and remove old records
  print "records replaced: ", $cdb->put_replace( k3, 'value3'); # 0
  print "records replaced: ", $cdb->put_replace( key, 'value'); # 1

  # replace and fill with null old records
  print "records replaced: ", $cdb->put_replace0( k2, 'value3'); # 1

  # add and warn if record previously existed
  print "records added: ", $cdb->put_warn( k1, 'value4'); # 1
  # warns: Key k1 already exists - added anyway

  # checks if key exists
  print $cdb->exists("k1");

  # dies if record already existed
  eval {
      $cdb->put_insert( k1, 'value1');
  };
  if ( $@ ) {
    print "k1 wasn't added: $@\n"; # Unable to insert new record - key exists
  }
  
  # commit changes and reopen/reload db - temp file replaces my-new.cdb
  $cdb->finish( save_changes => 1 );
  # same as
  $cdb->finish();

  # reading is not allowed in create mode
  print $cdb->getlast("k1"); # dies

DESCRIPTION

CDB::TinyCDB is a perl extension for TinyCDB library to query and create CDB files;

Query interface

TinyCDB supports two variants of query interface - first that maps the cdb file into memory (using mmap(2) on *nixes and MapViewOfFile on Windows) and the second one which reads file directly from disk.

load (Query interface 1)

Loads the CDB into memory - designed to be efficient for multiple queries.

  my $cdb = CDB::TinyCDB->load( 'my.cdb' );

open (Query interface 2)

Opens file and acceses it using read(2) and seek(2) - designed to be efficient for single queries or if cdb file is huge.

  my $cdb = CDB::TinyCDB->open( 'my.cdb' );

Query methods

Both load and open support same query methods (even though TinyCDB doesn't support some of them in open mode).

get
  print $cdb->get("key");

Returns first occurence of key in file.

getall
  print "$_\n" for $cdb->getall("key");

Returns all records for given key.

getlast
  print $cdb->getlast("key");

Returns last record for key. Useful if there are duplicated records added by "put_add".

exists
  print $cdb->exists("key");

Returns if key exists in file.

each
  while ( my ($key, $value) = $cdb->each ) {
    printf("+%d,%d:%s->%s\n", length($key), length($value), $key, $value);
  }

Iterates over all entries in file. Maintains the current position in file, so while iterating please don't call other methods.

Note: CDB allows to have duplicated keys, so don't use it directly to create hashes.

Note: it doesn't return records with zero length keys (most likely replaced by "put_replace0").

keys
  print "$_\n" for $cdb->keys;

Returns all keys.

Note: CDB allows to have duplicated keys, so don't use it directly to create hashes.

Note: it doesn't return records with zero length keys (most likely replaced by "put_replace0").

Create interface

CDB database file is created in two steps: first, temporary file created and written to disk, and second, that temporary file is renamed to permanent place. Unix rename(2) call is atomic operation, it removes destination file if any AND renames another file in one step. This way it is guaranteed that readers will not see incomplete database. To prevent multiple simultaneous updates, locking may also be used.

Note: rename(2) requires that both files are on the same filesystem.

Create methods

In create mode no query methods can be used. The only exception is "exists", but it may significantly slow down the whole process, as it currently flushes internal buffer to disk on every call with key those hash value already exists in db.

create
  my $cdb = CDB::TinyCDB->create( 'my-new.cdb', "my-new.cdb.$$" );

Creates new cdb file (my-new.cdb) and uses temporary file until changes are committed (my-new.cdb.$$).

put_add
  print "records added: ", $cdb->put_add( k1, 'value1'); # 1
  print "records added: ", $cdb->put_add( k1 => 'value1', k2 => 'value2' ); # 2
  print "records added: ", $cdb->put_add( %hash ); # scalar keys %hash 

Adds new records and returns number of records added. No duplicate checking will be performed - allowing duplicate keys to exists.

put_replace
  print "records replaced: ", $cdb->put_replace( k3, 'value3'); # 0
  print "records replaced: ", $cdb->put_replace( key, 'value'); # 1

If the key already exists, it will be removed from the database before adding new key,value pair. This requires moving data in the file, and can be quite slow if the file is large. All matching old records will be removed this way.

Returns number of records replaced.

put_replace0
  print "records replaced: ", $cdb->put_replace0( k2, 'value3'); # 1

If the key already exists and it isn't the last record in the file, old record will be zeroed out before adding new key,value pair. This is alot faster than "put_replace", but some extra data will still be present in the file. The data -- old record -- will not be accessible by normal searches, but will appear in direct file dumps (cdb -d).

put_insert
  # dies if record already existed
  eval {
      $cdb->put_insert( k1, 'value1');
  };
  if ( $@ ) {
    print "k1 wasn't added: $@\n"; # Unable to insert new record - key exists
  }
  

Add key,value pair only if such key does not exists in a database. Note that since query (see "get" above) will find first added record, this mode is somewhat useless (but allows to reduce database size in case of repeated keys). This is the same as calling "exists" followed by "put_add" if the key was not found.

put_warn
  print "records added: ", $cdb->put_warn( k1, 'value4'); # 1
  # warns: Key k1 already exists - added anyway

Add key,value pair unconditionally, but also check if this key already exists. This is equivalent of calling "exists", printing a warning if key exists, and unconditionally followed by "put_add".

finish
  $cdb->finish();

Commits changes and renames temp file into chosen CDB file. Allows to abort changes when called like this:

  $cdb->finish( save_changes => 0 );

Update interface

Although TinyCDB doesn't support updating already existent files CDB::TinyCDB provides inteface to do so.

  my $cdb = CDB::TinyCDB->open( 'my.cdb', for_update => "my.cdb.$$" );
  my $cdb = CDB::TinyCDB->load( 'my.cdb', for_update => "my.cdb.$$" );

Depending on the query method used CDB will be reopened or reloaded after changes are committed.

On startup it loads all existing records into temp file, where new records will be added. Until changes are committed the query methods will be used against the old file.

Update query methods

get
getall
getlast
exists
each
keys

Allows querying the old file - for all above please see "Query methods".

Note: "exists" however will check against temp file.

Update create methods

put_add
put_replace
put_replace0
put_insert
put_warn

Add new records - for all above please see "Create methods".

finish
  $cdb->finish();

Commits changes and renames temp file into chosen CDB file, which will be then reopened/reloaded.

Allows to abort changes with:

  $cdb->finish( save_changes => 0 );

Allows to abort file reloading with:

  $cdb->finish( reopen => 0 );

Note: both params can be used together in single call.

EXPORT

None by default.

TinyCDB INSTALLATION

Please see README file if you need to install it from sources.

SEE ALSO

CDB_File

Use tied hashes for accessing cdb files - doesn't require external libraries.

http://www.corpit.ru/mjt/tinycdb.html

TinyCDB home page. Some methods description were copied from there.

AUTHOR

Alex J. G. Burzyński, <ajgb@cpan.org>

COPYRIGHT AND LICENSE

Copyright (C) 2010 by Alex J. G. Burzyński

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.10.0 or, at your option, any later version of Perl 5 you may have available.