Difference between revisions of "Esmith::DB"
(Created page with "===NAME=== esmith::DB - virtual interface to E-Smith databases ===SYNOPSIS=== # Note: Do not instantiate this class directly. Use a subclass. # Examples in this doc...") |
(→create) |
||
(21 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
===NAME=== | ===NAME=== | ||
− | esmith::DB - virtual interface to E-Smith databases | + | '''esmith::DB''' - virtual interface to E-Smith databases<br /> |
+ | |||
+ | In a root terminal you can do the command below if you want to display the up-to-date content | ||
+ | perldoc -U esmith::DB | ||
+ | |||
+ | found on this side of the web, thanks to [http://smeserver.fr/perldoc.php?module=esmith::DB GranPa] | ||
===SYNOPSIS=== | ===SYNOPSIS=== | ||
Line 41: | Line 46: | ||
For example, there is esmith::DB::db to interface with esmith::db flatfile databases. There could also be esmith::DB::Berkeley to use Berkeley database files, or even esmith::DB::DBI. | For example, there is esmith::DB::db to interface with esmith::db flatfile databases. There could also be esmith::DB::Berkeley to use Berkeley database files, or even esmith::DB::DBI. | ||
− | Most of the methods herein are | + | Most of the methods herein are ''virtual''. They don't exist. The subclass is responsible for impelmenting them. There are a handful of concrete methods that have been implemented for you that should work with any subclass. |
====Virtual Methods==== | ====Virtual Methods==== | ||
Line 55: | Line 60: | ||
Should the $new_config_file already exist or for some reason you can't write to it, esmith::DB->error will return the reason and create() will return false. | Should the $new_config_file already exist or for some reason you can't write to it, esmith::DB->error will return the reason and create() will return false. | ||
+ | |||
+ | example for creating and using a custom database in one line: | ||
+ | my $customDB = esmith::ConfigDB->open('YOUR_DATABASE_NAME') || esmith::ConfigDB->create('YOUR_DATABASE_NAME'); | ||
+ | |||
===== open ===== | ===== open ===== | ||
Line 91: | Line 100: | ||
If a record already exists for the $key it will return false. | If a record already exists for the $key it will return false. | ||
+ | |||
+ | see also [http://wiki.contribs.org/Esmith::DB::db#creating_a_new_record that page] | ||
+ | |||
+ | |||
+ | for example (if it doesn't exist we create it) | ||
+ | my $rec = $DB->get('roundcube') || $DB->new_record('roundcube', {type => 'service'}); | ||
+ | |||
===== get ===== | ===== get ===== | ||
Line 98: | Line 114: | ||
If there's no record for the $key it will return false. | If there's no record for the $key it will return false. | ||
+ | |||
+ | for example (if it doesn't exist we create it) | ||
+ | my $rec = $DB->get('roundcube') || $DB->new_record('roundcube', {type => 'service'}); | ||
+ | |||
===== get_all ===== | ===== get_all ===== | ||
Line 103: | Line 123: | ||
Gets all the records out of the given $db as a list of esmith::DB::Record objects. | Gets all the records out of the given $db as a list of esmith::DB::Record objects. | ||
+ | |||
+ | here an example | ||
+ | |||
+ | { | ||
+ | use esmith::HostsDB; | ||
+ | $DB = esmith::HostsDB->open; | ||
+ | |||
+ | # Purge quoting chars in comments to fix bug 8723 & bug 8806 | ||
+ | foreach my $host ($DB->get_all) | ||
+ | { | ||
+ | my $comment = $host->prop('Comment'); | ||
+ | next unless $comment; | ||
+ | $comment =~ s/['"]//g; | ||
+ | $host->merge_props(Comment => $comment); | ||
+ | } | ||
+ | } | ||
==== Concrete methods ==== | ==== Concrete methods ==== | ||
Line 134: | Line 170: | ||
my $value = 'default'; | my $value = 'default'; | ||
− | + | ||
if (my $r = $db->get("foo")) | if (my $r = $db->get("foo")) | ||
{ | { | ||
Line 159: | Line 195: | ||
my $status; | my $status; | ||
− | + | ||
− | if (my $s = $db->get( | + | if (my $s = $db->get("foo")) { $status = $s->prop('status'); } |
− | + | ||
− | $status ||= | + | $status ||= 'default'; |
With this method, you can use: | With this method, you can use: | ||
Line 183: | Line 219: | ||
If the optional type option is passed, it will be used to create the record if it does not already exist. Otherwise, a non-existent record will cause this method to return an error. | If the optional type option is passed, it will be used to create the record if it does not already exist. Otherwise, a non-existent record will cause this method to return an error. | ||
Returns 0 for any errors, 1 for success. | Returns 0 for any errors, 1 for success. | ||
+ | ===== delete_prop ===== | ||
+ | my $dbkey = $db->get("$key"); | ||
+ | $dbkey->delete_prop("$prop"); | ||
+ | or | ||
+ | db->get("$key")->delete_prop("$prop"); | ||
+ | method to delete a propriety $prop of the key $key | ||
+ | |||
+ | ===== delete ===== | ||
+ | |||
+ | my $dbkey = $DB->get('$key'); | ||
+ | $dbkey->delete; | ||
+ | |||
+ | a method to delete a key | ||
+ | |||
===== keys ===== | ===== keys ===== | ||
Line 196: | Line 246: | ||
The defaults are loaded from /etc/e-smith/db/<dbname>/migrate by default, but the environment variable ESMITH_DB_DEFAULTSDIR can be set to use a different hierarchy if required. | The defaults are loaded from /etc/e-smith/db/<dbname>/migrate by default, but the environment variable ESMITH_DB_DEFAULTSDIR can be set to use a different hierarchy if required. | ||
− | The entries in | + | The entries in ''migrate'' are perl fragments which will be evaluated and so can munge anything they choose to. But, please be gentle :-) |
So you could have | So you could have | ||
Line 216: | Line 266: | ||
==== _loadDefaults ($forceReset) ==== | ==== _loadDefaults ($forceReset) ==== | ||
− | This is a private method. | + | '''This is a private method.''' |
Load the default properties for a given database. Caller can provide a flag to force resetting properties that already exist. | Load the default properties for a given database. Caller can provide a flag to force resetting properties that already exist. | ||
Line 229: | Line 279: | ||
Each of these directories is arranged as a set of subdirectories, with the directory name equal to the key for the given database. With these subdirectories are files, which are named by the properties of these database keys. | Each of these directories is arranged as a set of subdirectories, with the directory name equal to the key for the given database. With these subdirectories are files, which are named by the properties of these database keys. | ||
− | The entries in | + | The entries in ''defaults'' will be skipped if the existing key/property already exists (unless the $forceReset argument is provided). These are simple files, whose contents are the value to be used for that property. |
− | The entries in | + | The entries in ''force'' are always loaded into the given key/property. These are again simple files, like ''defaults''. |
To make this concrete, you might have: | To make this concrete, you might have: | ||
Line 237: | Line 287: | ||
/etc/e-smith/db/configuration/defaults/sshd/access | /etc/e-smith/db/configuration/defaults/sshd/access | ||
− | containing the single word | + | containing the single word ''private'', which would be the default. This value would only be used if no ''access'' property existed, or the $forceReset option is passed. |
− | You can override both | + | You can override both ''defaults'' and ''migrate'' with |
/etc/e-smith/db/configuration/force/sshd/access | /etc/e-smith/db/configuration/force/sshd/access | ||
− | containing the single word | + | containing the single word ''public'' to force the value of that property. |
==== get_value_and_delete ($key) ==== | ==== get_value_and_delete ($key) ==== | ||
Line 257: | Line 307: | ||
SME Server Developers <bugs@e-smith.com> | SME Server Developers <bugs@e-smith.com> | ||
− | |||
[[Category:Developer]] | [[Category:Developer]] | ||
− | |||
[[Category:SME Server Development Framework]] | [[Category:SME Server Development Framework]] | ||
[[Category:Development Tools]] | [[Category:Development Tools]] |
Latest revision as of 08:13, 12 August 2015
NAME
esmith::DB - virtual interface to E-Smith databases
In a root terminal you can do the command below if you want to display the up-to-date content
perldoc -U esmith::DB
found on this side of the web, thanks to GranPa
SYNOPSIS
# Note: Do not instantiate this class directly. Use a subclass. # Examples in this documentation where you see it being used directly # are merely for consistency. Substitute a subclass in our examples. use esmith::DB; my $db = esmith::DB->create($filename) or die esmith::DB->error; my $db = esmith::DB->open($filename) or die esmith::DB->error; my $db = esmith::DB->open_ro($filename) or die esmith::DB->error; my %DB = esmith::DB->as_hash($filename) or die esmith::DB->error; $db->reload; my $file = $db->file; my $record = $db->new_record($key, \%properties); my $record = $db->get($key); my @all_records = $db->get_all; my @all_records_by_prop = $db->get_all_by_prop($prop => $val); $db->set_prop($key, $prop, $value); $db->set_value($key, $value); $db->set_prop($key, $prop, $value, type => $type); $db->set_value($key, $value, create => 0);
DESCRIPTION
This module is a general interface to E-Smith's databases of various types and formats. It is not intended to be used directly, but that subclasses will implement the interface presented here to provide a single interface no matter what the underlying format.
For example, there is esmith::DB::db to interface with esmith::db flatfile databases. There could also be esmith::DB::Berkeley to use Berkeley database files, or even esmith::DB::DBI.
Most of the methods herein are virtual. They don't exist. The subclass is responsible for impelmenting them. There are a handful of concrete methods that have been implemented for you that should work with any subclass.
Virtual Methods
This is the esmith::DB interface. Subclassers are expected to implement these methods.
create
my $db = esmith::DB->create($new_config_file) || die esmith::DB->error;
Creates a brand new, empty configuration database and returns a subclass of the esmith::DB object representing it.
Should the $new_config_file already exist or for some reason you can't write to it, esmith::DB->error will return the reason and create() will return false.
example for creating and using a custom database in one line:
my $customDB = esmith::ConfigDB->open('YOUR_DATABASE_NAME') || esmith::ConfigDB->create('YOUR_DATABASE_NAME');
open
my $db = esmith::DB->open($config_file) || die esmith::DB->error
Loads an existing configuration database and returns a subclass of the esmith::DB::db object representing it.
Should the $config_file not exist or not be openable it will return false and esmith::DB->error will contain the reason.
open_ro
my $db = esmith::DB->open_ro($config_file) || die esmith::DB->error;
Like open(), but the database is read-only. new_record() and all methods which could change a record (set_prop(), merge_props(), delete(), etc...) will both throw exceptions if used.
error
my $error = esmith::DB->error;
Returns a string describing the error from the last failing method.
reload
$db->reload;
Flushes out the $db's cache (if there is one) and reloads all configuration data from disk.
file
my $file = $db->file;
File which this $db represents.
new_record
my $record = $db->new_record($key, \%properties);
Adds a new record at $key in the $db setting it to the given %properties. Returns a subclass of the esmith::DB::Record object.
If a record already exists for the $key it will return false.
see also that page
for example (if it doesn't exist we create it)
my $rec = $DB->get('roundcube') || $DB->new_record('roundcube', {type => 'service'});
get
my $record = $db->get($key);
Gets an existing record from the $db with the given $key. Returns an esmith::DB::Record object representing the data in $key.
If there's no record for the $key it will return false.
for example (if it doesn't exist we create it)
my $rec = $DB->get('roundcube') || $DB->new_record('roundcube', {type => 'service'});
get_all
my @records = $db->get_all;
Gets all the records out of the given $db as a list of esmith::DB::Record objects.
here an example
{ use esmith::HostsDB; $DB = esmith::HostsDB->open; # Purge quoting chars in comments to fix bug 8723 & bug 8806 foreach my $host ($DB->get_all) { my $comment = $host->prop('Comment'); next unless $comment; $comment =~ s/['"]//g; $host->merge_props(Comment => $comment); } }
Concrete methods
These are all implemented in terms of the esmith::DB interface and its not necessary for a subclass to implement them.
as_hash
my %db = $db->as_hash; my %db = esmith::DB->as_hash($file);
Returns the entire database as a hash of hashes. Each key is a key in the database, and the value is a hash of it's properties.
my $value = $db{some_key}{some_prop};
When used as an object method it will use the already opened database. When used as a class method it will open the given $file.
get_all_by_prop
my @records_by_prop = $db->get_all_by_prop($property => $value);
Like get_all() except it gets only those records whose $property has the given $value. For properties with multiple comma-delimited values (ie: name|val1,val2,val3), only one of the properties needs to match.
get_value
my $value = $db->get_value( $key );
Shortcut method to get the value from the record defined by the given key. Returns undef if the record does not exist.
The following code is unsafe if the key doesn't exist:
my $value = $db->get("foo")->value || 'default';
and should be:
my $value = 'default'; if (my $r = $db->get("foo")) { $value = $r->value; }
With this method, you can use:
my $value = $db->get_value("foo") || 'default';
get_prop
my $prop = $db->get_prop( $key, $prop );
Shortcut method to get a property from the record defined by the given key.
Returns undef if the record for that key doesn't exist, or the property does not exist.
The following code is unsafe if either the key or property doesn't exist:
my $status = $db->get("foo")->prop('status') || 'disabled';
and should be written as:
my $status; if (my $s = $db->get("foo")) { $status = $s->prop('status'); } $status ||= 'default';
With this method, you can use:
my $value = $db->get_prop("foo", "status") || 'default';
set_value
$db->set_value($key, $value)[, create => 1]);
Shortcut method to set a value to a key in the database without extracting the record first. If the record is not pre-existing, it will be created, unless the 'create' option is passed with a value of 0.
Returns 0 for any errors, 1 for success.
set_prop
$db->set_prop($key, $prop, $value[, type => $type]);
Shortcut method to set a property on a record without having to extract the record first.
If the optional type option is passed, it will be used to create the record if it does not already exist. Otherwise, a non-existent record will cause this method to return an error. Returns 0 for any errors, 1 for success.
delete_prop
my $dbkey = $db->get("$key"); $dbkey->delete_prop("$prop");
or
db->get("$key")->delete_prop("$prop");
method to delete a propriety $prop of the key $key
delete
my $dbkey = $DB->get('$key'); $dbkey->delete;
a method to delete a key
keys
foreach my $key ($db->keys) {
A simple convenience function to prevent having to access the config hash inside the db object (technically private), or calling map across a get_all call, which is what this is going to do. :) This method returns a list of keys to the records in the db. It does not sort.
migrate
Process the fragments in the migration queue for this database, using processTemplate.
The defaults are loaded from /etc/e-smith/db/<dbname>/migrate by default, but the environment variable ESMITH_DB_DEFAULTSDIR can be set to use a different hierarchy if required.
The entries in migrate are perl fragments which will be evaluated and so can munge anything they choose to. But, please be gentle :-)
So you could have
/etc/e-smith/db/configuration/migrate/sshd/access
which is a perl fragment which does something funky to migrate the access property from some old value to some new value.
After running all the migration scripts, and reloading the DB's data into its local cache, the private method _loadDefaults is called to set any missing default values and any forced settings.
resetToDefaults
Reset all entries to their default values, if defaults exist. This calls the internal method _loadDefaults with the forceReset flag set. It should not be used lightly!!
record_has_defaults
Returns true if there are defaults or force directories for the given record name
_loadDefaults ($forceReset)
This is a private method.
Load the default properties for a given database. Caller can provide a flag to force resetting properties that already exist.
Any forced properties will be evaluated after setting the default properties.
The defaults are loaded from the following directories in order (the environment variable ESMITH_DB_DEFAULTSDIR can be set to use a different hierarchy if required):
/etc/e-smith/db/<dbname>/defaults /etc/e-smith/db/<dbname>/force
Each of these directories is arranged as a set of subdirectories, with the directory name equal to the key for the given database. With these subdirectories are files, which are named by the properties of these database keys.
The entries in defaults will be skipped if the existing key/property already exists (unless the $forceReset argument is provided). These are simple files, whose contents are the value to be used for that property.
The entries in force are always loaded into the given key/property. These are again simple files, like defaults.
To make this concrete, you might have:
/etc/e-smith/db/configuration/defaults/sshd/access
containing the single word private, which would be the default. This value would only be used if no access property existed, or the $forceReset option is passed.
You can override both defaults and migrate with
/etc/e-smith/db/configuration/force/sshd/access
containing the single word public to force the value of that property.
get_value_and_delete ($key)
Retrieve the value of the named key, return it, and delete the record. If the key does not exist, it returns undef. This is normally called from migration code.
get_prop_and_delete ($key, $prop)
Retrieve the named property of the named key, return the value, and delete the property from the record. Returns undef if the property or key does not exist. This is normally called from migration code.
AUTHOR
SME Server Developers <bugs@e-smith.com>