From: octo Date: Thu, 7 Apr 2005 15:21:58 +0000 (+0000) Subject: First try to design a new interface for persistent data. X-Git-Tag: Release-0.8.0~20^2~48 X-Git-Url: https://git.octo.it/?p=onis.git;a=commitdiff_plain;h=0c821f460c673ffda10cbdb2acf9c25b18d54d64 First try to design a new interface for persistent data. --- diff --git a/lib/Onis/Data/Persistent.pm b/lib/Onis/Data/Persistent.pm new file mode 100644 index 0000000..73df88f --- /dev/null +++ b/lib/Onis/Data/Persistent.pm @@ -0,0 +1,137 @@ +package Onis::Data::Persistent; + +use strict; +use warnings; + +use Carp qw(confess); + +=head1 NAME + +Onis::Data::Persistent - Interface for storage backends + +=head1 DESCRIPTION + +Abstraction layer for modules that act as a backend and are able to store +internal data for longer than one run.. + +=cut + +use Onis::Config qw#get_config get_checksum#; + +@Onis::Data::Persistent::EXPORT_OK = qw##; +@Onis::Data::Persistent::ISA = ('Exporter'); + +our $StoreModule = 'None'; + +=head1 CONFIGURATION OPTIONS + +Since this is a B the options are very few. One, to be specific. See +your favorite backend's documentation on it's options.. + +=over 4 + +=item B + +Selects the storage module to use. Defaults to I which is a dummy module +that doesn't do anything with the data.. (Other than storing it internally..) +Currently implemented options are: + + None (todo) + Storable (maybe) + GDBM/SDBM (todo) + MySQL (todo) + PostgreSQL (maybe) + +=back + +=cut + +if (get_config ('storage_module')) +{ + $StoreModule = ucfirst (lc (get_config ('storage_module'))); +} + +{ + my $mod_name = "Onis::Data::Persistent::$StoreModule"; + + eval qq(use $mod_name;); + + if ($@) + { + print STDERR $/, __FILE__, ": Could not load storage module ``$StoreModule''. Are you sure it exists?"; + exit (1); + } + + unshift (@Onis::Data::Persistent::ISA, $mod_name); +} + +=head1 INTERFACE + +The child-modules have to provide the following interface: + +=over 4 + +=item Bnew> (I<$name>, I<$key_name>, I<@field_names>) + +This is the constructor for the objects that will hold the data. Some modules +may need a name for each field, and this is where plugins have to give the name +of each field. This is particularly important for backends using relational +databeses. I<$name> is merely a name for that variable or, in the database +world - a table. The name must be unique for each calling method's namespace. + +Since this is a constructor it returns an object. The object "knows" the folling methods: + +=item B<$data-Eput> (I<$name>, I<$key>, I<@fields>) + +Stores the given values in the data structure. How this is done is described +below in L. Doesn't return anything. The number of entries +in I<@fields> has to match the number of entries in I<@field_names> when +creating the object using B. + +=item B<$data-Eget> (I<$name>, I<$key>) + +Returns the data associated with the given I<$name>/I<$key> pair or an empty +list if no data has been stored under this tupel before.. + +=back + +=head1 INTERNALS + +The B and B methods can be found in the +B module. Other modules are encouraged to inherit +from that module, but don't need to. The data is stored as follows: The object +that's returned to the caller is actually a hash with this layout: + + %object = + ( + data => + { + key0 => [ qw(field0 field1 field2 ...) ], + key1 => [ qw(field0 field1 field2 ...) ], + key2 => [ qw(field0 field1 field2 ...) ], + ... + } + ); + +The actual data is not directly stored under I<%object> so database backends +can store metadata there (table name, credentials, whatever..). + +=head1 FURTHER CONSIDERATIONS + +Backend modules will probably read the entire data at startup and save +everything at the end. Another strategy might be reading (at least trying to) +an entry when it's first tried to B.. + +Another problem might be if/when a module needs a list of keys. I think almost +all plugins need this.. I'll probably add a B method to which you can +tell which field to use for sorting.. That might make it a lot easier for +database-backends.. + +=head1 AUTHOR + +Florian octo Forster, L. Any comments welcome as long as I +haven't started implementing this ;) + +=cut + +exit (0);