Hello people of module-authors!
I have been working on a module which will allow one to do some
relatively advanced storage and lookup mechanisms
on pure Perl object references.
The features are as follows:
1) Use perl objects as keys.
2) You may choose whether the database will retain a strong or
weak reference to either the key or the value
3) You may store a single value under multiple keys; keys may be of
mixed type
4) Reference keys and objects may optionally be deleted when their
referrant objects are destroyed
5) Store multiple value objects under 'tags' or 'attributes', these tags
themselves may be either
strings or references
6) Multiple deletion options, delete all keys/attributes
by a value, delete a value by any given key, delete
any values for a given attribute, delete an attribute lookup,
dissociate an attribute from
a value
7) Elegant debugging/dumping information, showing a lower level view of
the lookup table
8) Uniform API with two currently implemented backends (one is my XS
code, other uses Variable::Magic)
9) Unlike Hash::Util::FieldHash, this module will work with perl 5.8.8
(the version used in EL5-based distributions)
10) Decent speed, using an intel xeon E5520 CPU, i was able to acheive
200k store/sec for string keys, 150k store/sec for object keys, and 50k
store/sec for attribute lookups. At best this is still a good 6-7 times
slower than a normal perl hash, but is still
acceptable.
An example usage module (poco-keepalive) is available here:
https://github.com/mnunberg/Hash-Registry/blob/master/examples/poco-component-keepalive.pm
Implementation details ae here:
https://github.com/mnunberg/Hash-Registry/blob/master/Guts.pod
Basic API interface is here:
https://github.com/mnunberg/Hash-Registry/blob/master/api_list.txt
and of course, you should be able to determine where the rest of the
stuff is, if you wish to look into it a bit more.
Anyway, the question I wish to ask is in respect to naming this module;
I have had several ideas for naming this, all which are unacceptable;
The current name (Hash::Registry) was randomly chosen when this project
was still just hoping to be some kind of tied hash
Another idea was Data::Registry or Object::Registry, but this makes the
module sound like it's dealing with actual 'data'
rather than perl references, while the emphasis is very much on opaque
perl references (such as globrefs, etc.) rather than even trying to make
an attempt to deal with actual 'data' (that is, serialization,
inspection of object methods etc. etc.).
Another name that came up was Data::RefDB, which is a bit inelegant, and
sadly, anything with the name 'DB' in it seems to imply something of an
RDBMS or at least something with serializing and persistent storage
(while my module wants nothing to do with either).
The name that's been sticking with me for a while has been 'Prod', or
Perl Reference Object Database. But, it's a top-level namespace and
someone commented that it gives the impression of having something to do
with POD, so I'm quite lost.
Another thing to note is that I will probably want to publish a few more
modules under this namespace; at least one comes to mind, and that is
::Trigger, which will provide a common PP and XS interface for
performing various actions on C<free> magic, such as calling a CV,
deleting a hash entry or array element, or even calling a C function
(the XS implementation already provides the API and I just need to tidy
it up a bit), and would be a far higher performing substitute for common
cases of DESTROY
__END__
Synopsis:
=head1 SYNOPSIS
my $table = Hash::Registry->new();
Store a value under a simple string key, maintain the value as a weak
reference.
The string key will be deleted when the value is destroyed:
$table->store("key", $object);
Store C<$object> under a second index (C<$fh>), which is a globref;
C<$fh> will automatically be garbage collected when C<$object> is destroyed.
{
open my $fh, ">", "/foo/bar";
$table->store($fh, $object, StrongKey => 1);
}
# $fh still exists with a sole reference remaining in the table
Register an attribute type (C<foo_files>), and tag C<$fh> as being one
of C<$foo_files>,
C<$fh> is still dependent on C<$object>
# assume $fh is still in scope
$table->register_kt("foo_files");
$table->store_a(1, "foo_files", $fh);
Store another C<foo_file>
open my $fh2, ">", "/foo/baz"
$table->store_a(1, "foo_files", $fh);
# $fh2 will automatically be deleted from the table when it goes
out of scope
# because we did not specify StrongKey
Get all C<foo_file>s
my @foo_files = $table->fetch_a(1, "foo_files");
# @foo_files contains ($fh, $fh2);
Get rid of C<$object>. This can be done in one of the following ways:
# Implicit garbage collection
undef $object;
# Delete by value
$table->purge($object);
# Delete by key ($fh is still stored under the foo_keys attribute)
$table->purgeby($fh);
# remove each key for the $object value
$table->unlink("key");
$table->unlink($fh); #fh still exists under "foo" files
Get rid of C<foo_file> entries
# delete, by attribute
$table->purgeby_a(1, "foo_files");
# delete a single attribute from all entries
$table->unlink_a(1, "foo_files");
# dissociate the 'foo_files' attribtue from each entry
$table->dissoc_a(1, "foo_files", $fh);
$table->dissoc_a(1, "foo_files", $fh2);
# implicit garbage collection:
undef $fh;
undef $fh2;