[jboss-cvs] JBossCache/src/org/jboss/cache/interceptors ...
Manik Surtani
msurtani at jboss.com
Tue Oct 31 12:10:46 EST 2006
User: msurtani
Date: 06/10/31 12:10:46
Modified: src/org/jboss/cache/interceptors Tag:
Branch_JBossCache_1_4_0
PessimisticLockInterceptor.java
Log:
JBCACHE-794
Revision Changes Path
No revision
No revision
1.20.2.1 +183 -152 JBossCache/src/org/jboss/cache/interceptors/PessimisticLockInterceptor.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: PessimisticLockInterceptor.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/interceptors/PessimisticLockInterceptor.java,v
retrieving revision 1.20
retrieving revision 1.20.2.1
diff -u -b -r1.20 -r1.20.2.1
--- PessimisticLockInterceptor.java 6 Jun 2006 10:17:14 -0000 1.20
+++ PessimisticLockInterceptor.java 31 Oct 2006 17:10:46 -0000 1.20.2.1
@@ -35,31 +35,35 @@
* current method and unlock when the method returns.
*
* @author Bela Ban
- * @version $Id: PessimisticLockInterceptor.java,v 1.20 2006/06/06 10:17:14 msurtani Exp $
+ * @version $Id: PessimisticLockInterceptor.java,v 1.20.2.1 2006/10/31 17:10:46 msurtani Exp $
*/
-public class PessimisticLockInterceptor extends Interceptor {
- TransactionTable tx_table=null;
+public class PessimisticLockInterceptor extends Interceptor
+{
+ TransactionTable tx_table = null;
- /** Map<Object, java.util.List>. Keys = threads, values = lists of locks held by that thread */
+ /**
+ * Map<Object, java.util.List>. Keys = threads, values = lists of locks held by that thread
+ */
Map lock_table;
private long lock_acquisition_timeout;
- public void setCache(TreeCache cache) {
+ public void setCache(TreeCache cache)
+ {
super.setCache(cache);
- tx_table=cache.getTransactionTable();
- lock_table=cache.getLockTable();
- lock_acquisition_timeout=cache.getLockAcquisitionTimeout();
+ tx_table = cache.getTransactionTable();
+ lock_table = cache.getLockTable();
+ lock_acquisition_timeout = cache.getLockAcquisitionTimeout();
}
-
- public Object invoke(MethodCall call) throws Throwable {
+ public Object invoke(MethodCall call) throws Throwable
+ {
JBCMethodCall m = (JBCMethodCall) call;
- Fqn fqn=null;
- int lock_type=DataNode.LOCK_TYPE_NONE;
- long lock_timeout=lock_acquisition_timeout;
- Object[] args=m.getArgs();
+ Fqn fqn = null;
+ int lock_type = DataNode.LOCK_TYPE_NONE;
+ long lock_timeout = lock_acquisition_timeout;
+ Object[] args = m.getArgs();
InvocationContext ctx = getInvocationContext();
if (log.isTraceEnabled()) log.trace("PessimisticLockInterceptor invoked for method " + m);
@@ -85,9 +89,9 @@
* (keyed by TX) */
// List locks=null;
- boolean recursive=false;
- boolean createIfNotExists=false;
-
+ boolean recursive = false;
+ boolean createIfNotExists = false;
+ boolean zeroLockTimeout = false; // only used if the call is an evict() call. See JBCACHE-794
// 1. Determine the type of lock (read, write, or none) depending on the method. If no lock is required, invoke
// the method, then return immediately
@@ -98,26 +102,27 @@
case MethodDeclarations.putDataEraseMethodLocal_id:
case MethodDeclarations.putKeyValMethodLocal_id:
case MethodDeclarations.putFailFastKeyValueMethodLocal_id:
- createIfNotExists=true;
- fqn=(Fqn)args[1];
- lock_type=DataNode.LOCK_TYPE_WRITE;
- if(m.getMethodId() == MethodDeclarations.putFailFastKeyValueMethodLocal_id)
- lock_timeout=((Long)args[5]).longValue();
+ createIfNotExists = true;
+ fqn = (Fqn) args[1];
+ lock_type = DataNode.LOCK_TYPE_WRITE;
+ if (m.getMethodId() == MethodDeclarations.putFailFastKeyValueMethodLocal_id)
+ lock_timeout = ((Long) args[5]).longValue();
break;
case MethodDeclarations.removeNodeMethodLocal_id:
- fqn=(Fqn)args[1];
- lock_type=DataNode.LOCK_TYPE_WRITE;
- recursive=true; // remove node and *all* child nodes
+ fqn = (Fqn) args[1];
+ lock_type = DataNode.LOCK_TYPE_WRITE;
+ recursive = true; // remove node and *all* child nodes
break;
case MethodDeclarations.removeKeyMethodLocal_id:
case MethodDeclarations.removeDataMethodLocal_id:
case MethodDeclarations.addChildMethodLocal_id:
- fqn=(Fqn)args[1];
- lock_type=DataNode.LOCK_TYPE_WRITE;
+ fqn = (Fqn) args[1];
+ lock_type = DataNode.LOCK_TYPE_WRITE;
break;
case MethodDeclarations.evictNodeMethodLocal_id:
- fqn=(Fqn)args[0];
- lock_type=DataNode.LOCK_TYPE_WRITE;
+ zeroLockTimeout = true;
+ fqn = (Fqn) args[0];
+ lock_type = DataNode.LOCK_TYPE_WRITE;
break;
case MethodDeclarations.getKeyValueMethodLocal_id:
case MethodDeclarations.getNodeMethodLocal_id:
@@ -125,13 +130,13 @@
case MethodDeclarations.getChildrenNamesMethodLocal_id:
case MethodDeclarations.releaseAllLocksMethodLocal_id:
case MethodDeclarations.printMethodLocal_id:
- fqn=(Fqn)args[0];
- lock_type=DataNode.LOCK_TYPE_READ;
+ fqn = (Fqn) args[0];
+ lock_type = DataNode.LOCK_TYPE_READ;
break;
case MethodDeclarations.lockMethodLocal_id:
- fqn=(Fqn)args[0];
- lock_type=((Integer)args[1]).intValue();
- recursive=((Boolean)args[2]).booleanValue();
+ fqn = (Fqn) args[0];
+ lock_type = ((Integer) args[1]).intValue();
+ recursive = ((Boolean) args[2]).booleanValue();
break;
case MethodDeclarations.commitMethod_id:
// commit propagated up from the tx interceptor
@@ -141,7 +146,7 @@
// rollback propagated up from the tx interceptor
rollback(ctx.getGlobalTransaction());
break;
- default :
+ default:
if (isOnePhaseCommitPrepareMehod(m))
{
// commit propagated up from the tx interceptor
@@ -154,30 +159,34 @@
// If no TX: add each acquired lock to the list of locks for this method (locks)
// If TX: [merge code from TransactionInterceptor]: register with TxManager, on commit/rollback,
// release the locks for the given TX
- if(fqn != null) {
- if(createIfNotExists) {
- do {
- lock(fqn, ctx.getGlobalTransaction(), lock_type, recursive, lock_timeout, createIfNotExists);
+ if (fqn != null)
+ {
+ if (createIfNotExists)
+ {
+ do
+ {
+ lock(fqn, ctx.getGlobalTransaction(), lock_type, recursive, zeroLockTimeout ? 0 : lock_timeout, createIfNotExists);
}
- while(!cache.exists(fqn)); // keep trying until we have the lock (fixes concurrent remove())
+ while (!cache.exists(fqn)); // keep trying until we have the lock (fixes concurrent remove())
// terminates successfully, or with (Timeout)Exception
}
else
- lock(fqn, ctx.getGlobalTransaction(), lock_type, recursive, lock_timeout, createIfNotExists);
+ lock(fqn, ctx.getGlobalTransaction(), lock_type, recursive, zeroLockTimeout ? 0 : lock_timeout, createIfNotExists);
}
- else {
- if(log.isTraceEnabled())
+ else
+ {
+ if (log.isTraceEnabled())
log.trace("bypassed locking as method " + m.getName() + "() doesn't require locking");
}
- if(m.getMethodId() == MethodDeclarations.lockMethodLocal_id)
+ if (m.getMethodId() == MethodDeclarations.lockMethodLocal_id)
return null;
return super.invoke(m);
}
-
/**
* Locks a given node.
+ *
* @param fqn
* @param gtx
* @param lock_type DataNode.LOCK_TYPE_READ, DataNode.LOCK_TYPE_WRITE or DataNode.LOCK_TYPE_NONE
@@ -185,89 +194,106 @@
*/
private void lock(Fqn fqn, GlobalTransaction gtx, int lock_type, boolean recursive,
long lock_timeout, boolean createIfNotExists)
- throws TimeoutException, LockingException, InterruptedException {
+ throws TimeoutException, LockingException, InterruptedException
+ {
DataNode n;
DataNode child_node;
Object child_name;
Thread currentThread = Thread.currentThread();
- Object owner = (gtx != null) ? (Object)gtx : currentThread;
+ Object owner = (gtx != null) ? (Object) gtx : currentThread;
int treeNodeSize;
- boolean acquired=false;
+ boolean acquired = false;
if (log.isTraceEnabled()) log.trace("Attempting to lock node " + fqn + " for owner " + owner);
- if(fqn == null) {
+ if (fqn == null)
+ {
log.error("fqn is null - this should not be the case");
return;
}
- if((treeNodeSize=fqn.size()) == 0)
+ if ((treeNodeSize = fqn.size()) == 0)
return;
- if(cache.getIsolationLevelClass() == IsolationLevel.NONE)
- lock_type=DataNode.LOCK_TYPE_NONE;
+ if (cache.getIsolationLevelClass() == IsolationLevel.NONE)
+ lock_type = DataNode.LOCK_TYPE_NONE;
- n=cache.getRoot();
- for(int i=0; i < treeNodeSize; i++) {
- child_name=fqn.get(i);
- child_node=(DataNode) n.getOrCreateChild(child_name, gtx, createIfNotExists);
- if(child_node == null) {
- if(log.isTraceEnabled())
+ n = cache.getRoot();
+ for (int i = 0; i < treeNodeSize; i++)
+ {
+ child_name = fqn.get(i);
+ child_node = (DataNode) n.getOrCreateChild(child_name, gtx, createIfNotExists);
+ if (child_node == null)
+ {
+ if (log.isTraceEnabled())
log.trace("failed to find or create child " + child_name + " of node " + n.getFqn());
return;
}
- if(lock_type == DataNode.LOCK_TYPE_NONE) {
+ if (lock_type == DataNode.LOCK_TYPE_NONE)
+ {
// acquired=false;
- n=child_node;
+ n = child_node;
continue;
}
- else {
- if(lock_type == DataNode.LOCK_TYPE_WRITE && i == (treeNodeSize - 1)) {
- acquired=child_node.acquire(owner, lock_timeout, DataNode.LOCK_TYPE_WRITE);
+ else
+ {
+ if (lock_type == DataNode.LOCK_TYPE_WRITE && i == (treeNodeSize - 1))
+ {
+ acquired = child_node.acquire(owner, lock_timeout, DataNode.LOCK_TYPE_WRITE);
}
- else {
- acquired=child_node.acquire(owner, lock_timeout, DataNode.LOCK_TYPE_READ);
+ else
+ {
+ acquired = child_node.acquire(owner, lock_timeout, DataNode.LOCK_TYPE_READ);
}
}
- if(acquired) {
- if(gtx != null) {
+ if (acquired)
+ {
+ if (gtx != null)
+ {
// add the lock to the list of locks maintained for this transaction
// (needed for release of locks on commit or rollback)
cache.getTransactionTable().addLock(gtx, child_node.getLock());
}
- else {
- IdentityLock l=child_node.getLock();
+ else
+ {
+ IdentityLock l = child_node.getLock();
List locks = getLocks(currentThread);
- if(!locks.contains(l))
+ if (!locks.contains(l))
locks.add(l);
}
}
- if(recursive && i == (treeNodeSize - 1)) {
- Set acquired_locks=child_node.acquireAll(owner, lock_timeout, lock_type);
- if(acquired_locks.size() > 0) {
- if(gtx != null) {
+ if (recursive && i == (treeNodeSize - 1))
+ {
+ Set acquired_locks = child_node.acquireAll(owner, lock_timeout, lock_type);
+ if (acquired_locks.size() > 0)
+ {
+ if (gtx != null)
+ {
cache.getTransactionTable().addLocks(gtx, acquired_locks);
}
- else {
+ else
+ {
List locks = getLocks(currentThread);
locks.addAll(acquired_locks);
}
}
}
- n=child_node;
+ n = child_node;
}
}
- private List getLocks(Thread currentThread) {
+ private List getLocks(Thread currentThread)
+ {
// This sort of looks like a get/put race condition, but
// since we key off the Thread, it's not
- List locks = (List)lock_table.get(currentThread);
- if (locks == null) {
+ List locks = (List) lock_table.get(currentThread);
+ if (locks == null)
+ {
locks = Collections.synchronizedList(new LinkedList());
lock_table.put(currentThread, locks);
}
@@ -278,15 +304,16 @@
private void createNodes(Fqn fqn, GlobalTransaction gtx)
{
int treeNodeSize;
- if ((treeNodeSize=fqn.size()) == 0) return;
- DataNode n=cache.getRoot();
- for(int i=0; i < treeNodeSize; i++)
- {
- Object child_name=fqn.get(i);
- DataNode child_node=(DataNode) n.getOrCreateChild(child_name, gtx, true);
- if(child_node == null)
+ if ((treeNodeSize = fqn.size()) == 0) return;
+ DataNode n = cache.getRoot();
+ for (int i = 0; i < treeNodeSize; i++)
{
- if(log.isTraceEnabled()) log.trace("failed to find or create child " + child_name + " of node " + n.getFqn());
+ Object child_name = fqn.get(i);
+ DataNode child_node = (DataNode) n.getOrCreateChild(child_name, gtx, true);
+ if (child_node == null)
+ {
+ if (log.isTraceEnabled())
+ log.trace("failed to find or create child " + child_name + " of node " + n.getFqn());
return;
}
n = child_node;
@@ -296,14 +323,17 @@
/**
* Remove all locks held by <tt>tx</tt>, remove the transaction from the transaction table
+ *
* @param gtx
*/
- private void commit(GlobalTransaction gtx) {
- if(log.isTraceEnabled())
+ private void commit(GlobalTransaction gtx)
+ {
+ if (log.isTraceEnabled())
log.trace("committing cache with gtx " + gtx);
- TransactionEntry entry=tx_table.get(gtx);
- if(entry == null) {
+ TransactionEntry entry = tx_table.get(gtx);
+ if (entry == null)
+ {
log.error("entry for transaction " + gtx + " not found (maybe already committed)");
return;
}
@@ -311,8 +341,8 @@
// Let's do it in stack style, LIFO
entry.releaseAllLocksLIFO(gtx);
- Transaction ltx=entry.getTransaction();
- if(log.isTraceEnabled())
+ Transaction ltx = entry.getTransaction();
+ if (log.isTraceEnabled())
log.trace("removing local transaction " + ltx + " and global transaction " + gtx);
tx_table.remove(ltx);
tx_table.remove(gtx);
@@ -330,15 +360,17 @@
*
* @param tx
*/
- private void rollback(GlobalTransaction tx) {
+ private void rollback(GlobalTransaction tx)
+ {
List undo_ops;
- TransactionEntry entry=tx_table.get(tx);
+ TransactionEntry entry = tx_table.get(tx);
MethodCall undo_op;
- if(log.isTraceEnabled())
+ if (log.isTraceEnabled())
log.trace("called to rollback cache with GlobalTransaction=" + tx);
- if(entry == null) {
+ if (entry == null)
+ {
log.error("entry for transaction " + tx + " not found (transaction has possibly already been rolled back)");
return;
}
@@ -361,14 +393,13 @@
// }
// }
-
// 3. Finally, release all locks held by this TX
// Let's do it in stack style, LIFO
// Note that the lock could have been released already so don't panic.
entry.releaseAllLocksLIFO(tx);
- Transaction ltx=entry.getTransaction();
- if(log.isTraceEnabled())
+ Transaction ltx = entry.getTransaction();
+ if (log.isTraceEnabled())
log.trace("removing local transaction " + ltx + " and global transaction " + tx);
tx_table.remove(ltx);
tx_table.remove(tx);
More information about the jboss-cvs-commits
mailing list