NAME

ObjStore - Perl extension for ObjectStore ODMS

SYNOPSIS

  use ObjStore;

  $osdir = ObjStore->schema_dir;
  my $DB = ObjStore::Database->open($osdir . "/perltest.db", 0, 0666);

  try_update {
      $top = $DB->root('megabase', $DB->newHV('dict'));
      for (my $x=1; $x < 1000000000; $x++) {
	  $top->{$x} = {
	      id => $x,
	      m1 => "I will not talk in ObjectStore/Perl class.",
	      m2 => "I will read the documentation.",
	  };
      }
  };
  print "[Abort] $@\n" if $@;

DESCRIPTION

[Run peek on one of our databases so people understand the simplicity that comes from not having a rigid schema.]

OBJECTSTORE PHILOSOPHY

ObjectStore is outrageously powerful and sophisticated. It actually does way too much for the average get-the-job-done programmer. The theme of this interface to ObjectStore is simplicity and easy of use. The performance of raw ObjectStore is so good that even with a gunky perl layer, benchmarks will find relational databases left on the bookshelf.

Specifically, the interface is optimized for flexibility, then memory performance, then speed. If you really want speed, wait till Perl5 gets access to pthreads. Or see the TODO list about dynamic linking additional C++ objects.

TRANSACTIONS

1. You cannot access persistent data outside of a transaction. Care must be taken that all persistent variables go out of scope before transactions complete.

    {
	my $var;
	try_update {
	    $var = $DB->root('top');
	};
    }      # $var destroy causes ObjStore exception

2. It is impractical to use 'read' transactions because collections include embedded cursors. You cannot be able to iterate over collections without modifying the cursors in the database. This should be construed as a bug in perl. As a work around, read transactions are implemented with the abort_only transaction mode. This mode allows you to modify the database but will not commit the changes.

REFERENCE COUNTING

It is not practical to simply make perl types persistent. Values in the database have different requirements than transient values and require a custom solution.

1. All data allocated in the database is reference counted separately from transient data.

2. You cannot take a reference to a scalar value.

CONTAINERS

There are a few considerations when creating a container: which segment, which symantics, and which representation.

HASHES

$DB->newHV('array');
$DB->newHV('dict');

my $seg = $DB->create_segment;
$seg->newHV('array');
$seg->newHV('dict');

Array representations have one caveat: if they need to resize, any transient references you might have will become pointers to random memory. This case actually doesn''t come up very often. To mess up, you need to go through these contortions:

my $top = $DB->newTiedHV('array');
my $dict = $top->{dict} = $DB->newHV('dict');
for (1..14) { $top->{$_} = $_; }   # cause resize of $top

$dict->{foo} = 'bar';              # $dict points to random OOPS!

$dict = $top->{dict};              # now $dict OK
$dict->{foo} = 'bar';              # OK

SACKS

$DB->newSack('array');

Sacks are sequential access containers. They support the following methods:

void $sack->a($element);
void $sack->r($element);
int  $sack->contains($element);
SV*  $sack->first();
SV*  $sack->next();
void $sack->bless('classname');

Not very feature-ful, are they? You''d think you would get a big efficiency win! In fact, they are only a little better than hashes. Sacks are really just a stop-gap until Larry and friends figure out how to do tied arrays.

AUTHOR

Joshua Pritikin, pritikin@mindspring.com

SEE ALSO

ObjectStore Documentation