|
Summary: Performing distributed and 'local' transactions on space/cache instances.
OverviewYou can group cache operations into a single transaction. Because the GigaSpaces cache is potentially a distributed resource, there is a distinction between distributed transactions and local transactions. The distributed transactions use the Jini Transaction Manager.
In this case your transaction may span across multiple different cache instances. The cache instance may be clustered using the replicated or partitioned schema. You should use the Jini Transaction Manager to provide you a distributed transaction when your application needs to interact with multiple spaces as part of the same transaction. In many cases the application need to interact only one cache instance or with one of the partitions or with one of the replicated cache instances when using a transaction. In this case, you should use the Local Transaction Manager (com.j_spaces.core.client.LocalTransactionManager; see Javadoc), which ensures ACID transaction when interacting with a single space. When running the cache in remote mode, the LocalTransactionManager may provide better performance than the Jini Transaction Manager since there are several remote calls that are saved. When running the cache in embedded mode and using the Local Transaction Manager there are no remote calls involved. In this case the Local Transaction Manager is the preferred transaction manager.
The following sections will describe how to use transactions with the map interface: Creating Transaction MangerTo create Jini Transaction Manger: TransactionManager trManager = (TransactionManager)LookupFinder.find(
null, // service name
new Class[] { net.jini.core.transaction.server.TransactionManager.class },
// service class name
null, // service attributes
"localhost", // unicast lookup host
null, // lookup groups
10*1000 // timeout 10 seconds
);
Starting Jini Transaction ManagerStart the Jini Transaction Manager by running <GigaSpaces Root>\bin\startJiniTX_Mahalo. Alternatively, you can start the Jini Transaction Manager embedded within the container process in the following ways:
Committing and Aborting the Jini TransactionWhen using the Jini transaction Manager you should consider using the Transaction.commit(long waitFor) and Transaction.abort(long waitFor) methods - This will return acknowledgement to the caller application only after the transaction Commit or Abort operation has been fully completed by all transaction participants or until the timeout period expired. When using the Transaction.abort() and Transaction.commit() the client get the acknowledgement immediately after the abort or commit call without waiting for all transaction participates to complete. This may lead to inconsistency. The waitFor parameter timeout allows you to choose the maximum amount of time you would like to wait for the transaction to be completed by all participates. This behavior will not happen when using the Local Transaction Manager, since the client gets acknowledgement for the commit/abort operation only after the space has completed the commit/abort processing.
To create Local Transaction Manger: IMap cache = (IMap)CacheFinder.find( url );
LocalTransactionManager trManager = (LocalTransactionManager)
LocalTransactionManager.getInstance(cache);
Create a TransactionYou should use the transaction manager object with the TransactionFactory to generate a new transaction object: Transaction.Created tCreated =TransactionFactory.create(trManager, 1000 * 60); txn = tCreated.transaction;
Bind the Transaction to the Cache proxyCall the IMap.setTransaction(Transaction) on the IMap object that represents the cache. The transaction object, obtained from the TransactionFactory, is passed as an argument into the setTransaction(). cache.setTransaction(txn); Once the transaction is started and bound to the IMap instance all IMap operations are encapsulated in the same transaction. You may perform all map operations as usual, but to make these visible to other clients you should complete the transaction by calling the commit operation: txn.commit(10000); To cancel the operation conducted you should call the abort command: txn.abort(10000); To invalidate the transaction object bound to the IMap instance you should call the IMap. setTransaction() again passing null as an argument. When using the IMap.setTransaction() the transaction is defined implicitly on all the objects used with this IMap instance – i.e. the IMap is not thread safe when performing transactional operations – all threads sharing the same IMap instance share the same transaction. If you have multi-threaded applications and require each thread to have a different transaction, you should generate a different IMap instance per thread. ExampleThe following code example demonstrates how to use the LocalTransactionManager with the Map API. For a full running example and code walkthrough see the Quick guide and the Examples folder. package com.j_spaces.examples.hellomap; import com.j_spaces.core.client.FinderException; import com.j_spaces.map.CacheFinder; import com.j_spaces.map.IMap; import com.j_spaces.core.client.LocalTransactionManager; import net.jini.core.transaction.Transaction; import net.jini.core.transaction.TransactionFactory; public class HelloWorldTransaction { public static void main(String[] args) { say("\nWelcome to GigaSpaces Map-Transaction HelloWorld"); say("This example writes to cache using a transaction..."); if ( args.length != 1 ) { say("Usage: <spaceURL>"); say("<protocol>://host:port/containername/spacename"); System.exit(1); } try { // find the space with RMI, the Jini lookup or connect to an // embedded instance say("Connect to " + args[0] ); IMap mapspace = (IMap)CacheFinder.find("jini://*/*/mySpace"); if ( mapspace == null ) { say("Cache not found: " + args[0]); System.exit(-1); } say("Connected successfully ! "); // Local transactions are the preferred way // to work with a single space say("Create local transaction-manager..."); LocalTransactionManager trManager = (LocalTransactionManager) LocalTransactionManager.getInstance(mapspace); Transaction txn = null; // Transactionfactory lease will expire after one minute // (automatic abort / rollback) Transaction.Created tCreated = TransactionFactory.create(trManager, 1000 * 60); txn = tCreated.transaction; // put an object into map and commit the transaction say("Putentry under transaction..."); mapspace.setTransaction(txn); Message message1 = new Message("one"); mapspace.put("1", message1); say("Commit transaction..."); txn.commit( ); mapspace.setTransaction( null ); say("Look for entry..."); Message result1 = (Message)mapspace.get("1"); if( result1 != null) say("map key 1:" + result1.string1); else say("Entry not in space !"); System.exit(0); } catch( FinderException ex ) { ex.printStackTrace(); say("Could not find cache: " + args[0]); say("Please check that GigaSpaces Server is running."); } catch (Exception e) { e.printStackTrace(); } } public static void say(String msg) { System.out.println(msg); } } |
(works on Firefox 2 and Internet Explorer 7)