Db-GTM
view release on metacpan or search on metacpan
# Copies everything in dblink1 into dblink2
>M::merge($dblink1,$dblink2);
# Copies everything in dblink1's sub-node "vendors" into dblink2
>M::merge($dblink1->node("vendors"),$dblink2);
=head3 DELETING NODES
$status = kill(@node); # Destroys node and all sub-nodes
$status = kv(@node); # Destroys specified node only
$status = ks(@node); # Destroys sub-nodes only
All return nonzero on failure.
Example:
$dblink2->set("BUBBA GUMP AUTO CO.",103009);
$dblink2->set("BUBBA GUMP AUTO CO.","Address","789 Someother Ave.");
$dblink2->set("CRAZY EDDIE USED CARS",103009);
$dblink2->set("CRAZY EDDIE USED CARS","Address","999 Emporium Ave.");
$dblink2->set("PAY-AND-SPRAY",103009);
$dblink2->set("PAY-AND-SPRAY","Address","400 Sunset Bvd");
$dblink2->kill("BUBBA GUMP AUTO CO."); # destroys "Address" sub-node too
$dblink2->ks("CRAZY EDDIE USED CARS"); # destroys ONLY the 'Address' record
$dblink2->kv("PAY-AND-SPRAY"); # leaves 'Address' record intact
$dblink2->kill(); # destroys the "auto dealerships" node and all subnodes
=head3 TRANSACTIONS
GT.M and Db::GTM support the concept of "transactions". All database
changes made during a transaction are linked, meaning that either they
are all processed successfully or none of them are. If there is a
fatal error or system crash in the middle of the transaction set, none
of the set/kill operations will take effect.
$status = $dblink->txnstart(); # Begin a transaction
$status = $dblink->txnabort(); # Abort a transaction, make no changes
$status = $dblink->txncommit(); # Save all set/kills made during txn
Example:
$status = $dblink->txnstart();
$dblink->set($acctno,"CHECKING","BALANCE",($oldChkBal - $transferAmt));
$dblink->set($acctno,"SAVINGS","BALANCE", ($oldSavBal + $transferAmt));
$status = $dblink->txncommit();
From the time you initiate txnstart(), all sets/kills are queued until
you do either txncommit() or txnabort().
Note that if you have multiple GTMDB objects and only do a txnstart()
with one of them, then the others will behave normally (their writes
will take effect immediately).
Also note that until a txncommit() is performed, everyone who views
the data that has been set since a txnstart() will see the OLD data,
not the stuff that is in the process of being written.
=head3 LOCKING
$status = $dblink->lock(@name,$seconds); # Lock a database node
$status = $dblink->unlock(@name); # Unlock something locked prior
seconds: the last parameter to lock() is the number of seconds to
wait to get a lock before giving up. This is important as GT.M
reserves the use of signals for itself and using SIGALRM may
cause problems.
Specifying a seconds count of 0 will make the locking attempt
fail immediately if another lock exists.
Specifying a seconds count of -1 will make the locking attempt
wait forever for a conflicting lock to be released. This can
lead to deadlock, so use with caution.
If you specify a global name, you MUST specify a seconds count.
Bad things will happen to you if you don't.
In order to work gracefully with other processes that are attempting
to update data in the GTM datastore, you can request locks on database
nodes. Locks are advisory (meaning that it's possible to write to a
"locked" node if you don't bother to ask for your lock first). Locks
are automatically released when your process exits.
Lock on a higher-level resources conflict with lower-level ones.
Examples:
(Process 1) $db = new GTMDB("TOPNODE");
$db->lock("MYNODE","A",0); # Lock (TOPNODE.MYNODE.A)
(Process 2) $db = new GTMDB("TOPNODE");
$db->lock("MYNODE",0); # Lock (TOPNODE.MYNODE)
# Fails because process 1 has a conflicting lock
Note that you can always get locks to resources that you have previously
locked, or lock a lower level resource.
=head2 FUNCTION LIST
Conventions:
When a function takes '@name' as a parameter, or returns it as output,
@name is a list that makes up the name of a database node. Any node
can store data as well as have child nodes. See the examples above
for explicit usage. If unspecified, functions that operate on @name
will operate on the main node linked to during new()
When a function returns '$status', anything nonzero indicates failure
$db_obj = new GTMDB(@name); # Returns a link to a database node
$db_obj = >MDB::new(@name); # Same
@name = $db_obj->getprefix(); # Returns the name of the main node
$scalar = $db_obj->get(@name); # Returns data stored at a node
$scalar = $db_obj->exists(@name); # True if node has data or sub-nodes
$scalar = $db_obj->haschildren(@name); # True if node has sub-nodes
$db_obj = $db_obj->sub(@name); # Returns a link to a sub-node
$status = $db_obj->set(@name,$val); # Sets data at node to $value
$scalar = $db_obj->next(@name); # Returns next node at same level
$scalar = $db_obj->prev(@name); # Returns previous node at same level
$scalar = $db_obj->first(@name); # Returns first child node
$scalar = $db_obj->last(@name); # Returns last child node
@name = $db_obj->query(@name); # Returns next data node at any depth
@list = $db_obj->children(@name); # Returns all immediate child nodes
$status = $db_obj->kill(@name); # Destroys node and all subnodes
$status = $db_obj->ks(@name); # Destroys all sub-nodes only
$status = $db_obj->kv(@name); # Destroys current node only
$status = $dblink->txnstart(); # Begin a transaction
$status = $dblink->txnabort(); # Abort a transaction, make no changes
$status = $dblink->txncommit(); # Save all set/kills made during txn
$status = $dblink->lock(@name,$seconds); # Lock a database node
$status = $dblink->unlock(@name); # Unlock locked database node
$status = $db_obj->merge(@srcname [ ,undef,@dstname ]);
# Copies nodes in @srcname into @dstname, overwriting collisions
# if unspecified, @dstname is assumed to be the main node
$status = $db_obj->clobber(@srcname [ ,undef,@dstname ]);
# Makes @dstname an exact clone of @srcname
$db_obj->clobber() and $db_obj->merge() can take another $db_obj as a source.
$gvn = $db_obj->list2gvn(@name);
# Returns the MUMPS-Global name that is the combination of the main
# node name + the specified one.
@name = $db_obj->gvn2list($GVN); # Converts a MUMPS-Global name to list
@name = >M::gvn2list($GVN); # Converts a MUMPS-Global name to list
$gvn = >M::list2gvn(@name); # Converts a list into a MUMPS Global
# The functions >M::merge / >M::clobber can be used to copy the
# contents of one DB object into another. They take either database
# objects or GVNs (such as those returned by list2gvn()) as arguments
$status = >M::merge ([ $gvn OR $src_db_obj ],[ $GVN OR $dst_db_obj ]);
$status = >M::clobber([ $gvn OR $src_db_obj ],[ $GVN OR $dst_db_obj ]);
=head2 USING GTM AS A TIED HASH OR SCALAR
Although PERL's native support of hierarchical databases is somewhat
limited, you can use this module to tie a node of a GTM database to
a hash or scalar value.
# Ties the PERL hash variable %spzhash to the GTM node ["SPZ","foo"]
my(%spzhash); tie %spzhash, 'GTMDB', "SPZ", "foo";
# Ties the PERL scalar variable $spzsclar to the node ["SPZ","foo","bar"]
my($spzsclr); tie $spzsclr, 'GTMDB', "SPZ", "foo", "bar";
my($spzlink) = new GTMDB("SPZ","foo");
# Sets ["SPZ","foo","bar"] to 6
$spzhash{"bar"} = 6; # Equivalent to $spzlink->set("bar",6);
$spzsclr = 6; # Also equivalent...
exists $spzhash{"bar"}; # True if "bar" has data or child nodes
keys %spzhash; # A list of all child-nodes of ["SPZ","foo"]
%spzhash = (); # Equivalent to $spzlink->kill();
As a special note, the 'keys' and 'each' keywords will always return
the keys presorted in the mumps collating order. If you want to use
'tie' to store a simple flat-file hash this works fine.
Multidimensional support, or accessing child nodes is trickier:
$spzhash{"bar","baz"} = 6; # Equivalent to $spzlink->set("bar","baz",6);
keys $spzhash{"bar"}; # Syntax error
@node = ("bar","baz"); # Danger Will Robinson...
$spzhash{@node} = 6; # Does $spzlink->set(2,6);
If you wanted to get child nodes of ["SPZ","foo","bar"] this way, do:
( run in 3.233 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )