Skip to main content

Transactions and Locking

The following topics are discussed in this section:

Controlling Transactions

The Native SDK provides the following methods to control transactions:

  • Iris.tCommit() — commits one level of transaction.

  • Iris.tStart() — starts a transaction (which may be a nested transaction).

  • Iris.getotalevel() — returns an int value indicating the current transaction level (0 if not in a transaction).

  • Iris.tRollback() — rolls back all open transactions in the session.

  • Iris.tRollbackOne() — rolls back the current level transaction only. If this is a nested transaction, any higher-level transactions will not be rolled back.

The following example starts three levels of nested transaction, setting the value of a different node in each transaction level. All three nodes are printed to prove that they have values. The example then rolls back the second and third levels and commits the first level. All three nodes are printed again to prove that only the first node still has a value.

Controlling Transactions: Using three levels of nested transaction
  const node = 'myGlobal';
  console.log('Set three values in three different transaction levels:');
  for (let i=1; i<4; i++) {
    irisjs.tStart();
    let lvl = irisjs.getTLevel()
    irisjs.set(('Value'+lvl), node, lvl);
    let val = '<valueless>'
    if (irisjs.isDefined(node,lvl)%10 > 0) val = irisjs.get(node,lvl);
    console.log('  ' + node + '(' + i + ') = ' + val + ' (tLevel is ' + lvl + ')');
  }
// Prints: Set three values in three different transaction levels:
//         myGlobal(1) = Value1 (tLevel is 1)
//         myGlobal(2) = Value2 (tLevel is 2)
//         myGlobal(3) = Value3 (tLevel is 3)

  console.log('Roll back two levels and commit the level 1 transaction:');
  let act = ['  tRollbackOne','  tRollbackOne','       tCommit'];
  for (let i=3; i>0; i--) {
    if (i>1) {irisjs.tRollbackOne();} else {irisjs.tCommit();}
    let val = '<valueless>'
    if (irisjs.isDefined(node,i)%10 > 0) val = irisjs.getString(node,i);
    console.log(act[3-i]+' (tLevel='+irisjs.getTLevel()+'): '+node+'('+i+') = '+val);
  }

// Prints: Roll back two levels and commit the level 1 transaction:
//           tRollbackOne (tLevel=2): myGlobal(3) = <valueless>
//           tRollbackOne (tLevel=1): myGlobal(2) = <valueless>
//                tCommit (tLevel=0): myGlobal(1) = Value1

Acquiring and Releasing Locks

The following methods of class Iris are used to acquire and release locks. Both methods take a lockMode argument to specify whether the lock is shared or exclusive:

  • Iris.lock() — Takes lockMode, timeout, lockReference, and subscripts arguments, and locks the node. The lockMode argument specifies whether any previously held locks should be released. This method will time out after a predefined interval if the lock cannot be acquired.

  • Iris.unlock() — Takes lockMode, lockReference, and subscripts arguments, and releases the lock on a node.

The following argument values can be used:

  • lockMode — combination of the following chars, S for shared lock, E for escalating lock, or SE for shared and escalating. Default is empty string (exclusive and non-escalating).

  • lockReference — a string starting with a circumflex (^) followed by the global name (for example, ^myGlobal, not just myGlobal). Unlike the globalName parameter used by most methods, the lockReference parameter must be prefixed by a circumflex. Only lock() and unlock() use lockReference instead of globalName.

  • timeout — number of seconds to wait to acquire the lock before timing out.

Note:

You can use the Management Portal to examine locks. Go to System Operation > Locks to see a list of the locked items on your system.

Using Locks in a Transaction

This section demonstrates incremental locking within a transaction, using the methods previously described (see “Controlling Transactions” and “Acquiring and Releasing Locks”). You can see a list of the locked items on your system by opening the Management Portal and going to System Operation > Locks. The calls to alert() in the following code will pause execution so that you can look at the list whenever it changes.

There are two ways to release all currently held locks:

  • Iris.releaseAllLocks() — releases all locks currently held by this connection.

  • When the close() method of the connection object is called, it releases all locks and other connection resources.

The following examples demonstrate the various lock and release methods.

Using incremental locking in transactions
  irisjs.set('exclusive node','nodeOne');
  irisjs.set('shared node','nodeTwo');

// unlike global names, lock references *must* start with circumflex
  const nodeOneRef = '^nodeOne';
  const nodeTwoRef = '^nodeTwo';

  try {
    irisjs.tStart();
    irisjs.lock('E',10,nodeOneRef,''); // lock nodeOne exclusively
    irisjs.lock('S',10,nodeTwoRef,''); // lock nodeTwo shared
    console.log('Exclusive lock on nodeOne and shared lock on nodeTwo');

    alert('Press return to release locks individually');
    irisjs.unlock('D',nodeOneRef,''); // release nodeOne after transaction
    irisjs.unlock('I',nodeTwoRef,''); // release nodeTwo immediately

    alert('Press return to commit transaction');
    irisjs.tCommit();
  }
  catch { console.log('error'); }

Using non-incremental locking in transactions
// lock nodeOne non-incremental, nodeTwo shared non-incremental
  irisjs.lock('',10,nodeOneRef,'');

  alert('Exclusive lock on nodeOne, return to lock nodeOne non-incrementally');
  irisjs.lock('S',10,nodeTwoRef,'');

  alert('Verify that only nodeTwo is now locked, then press return');

Using releaseAllLocks() in transactions to release all incremental locks
// lock nodeOne shared incremental, nodeTwo exclusive incremental
  irisjs.lock('SE',10,nodeOneRef,'');
  irisjs.lock('E',10,nodeTwoRef,'');

  alert('Two locks are held (one with lock count 2), return to release both locks');
  irisjs.releaseAllLocks();

  alert('Verify both locks have been released, then press return');

FeedbackOpens in a new tab