Db-GTM

 view release on metacpan or  search on metacpan

GTM.pm  view on Meta::CPAN

 
   # Copies everything in dblink1 into dblink2
   &GTM::merge($dblink1,$dblink2);   

   # Copies everything in dblink1's sub-node "vendors" into dblink2
   &GTM::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 = &GTMDB::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 = &GTM::gvn2list($GVN);         # Converts a MUMPS-Global name to list
  $gvn  = &GTM::list2gvn(@name);        # Converts a list into a MUMPS Global

  # The functions &GTM::merge / &GTM::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 = &GTM::merge  ([ $gvn OR $src_db_obj ],[ $GVN OR $dst_db_obj ]);
  $status = &GTM::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 )