1 7 package org.jboss.cache.interceptors; 8 9 import org.jboss.cache.CacheException; 10 import org.jboss.cache.CacheSPI; 11 import org.jboss.cache.GlobalTransaction; 12 import org.jboss.cache.InvocationContext; 13 import org.jboss.cache.NodeSPI; 14 import org.jboss.cache.TransactionEntry; 15 import org.jboss.cache.lock.NodeLock; 16 import org.jboss.cache.marshall.MethodCall; 17 import org.jboss.cache.marshall.MethodDeclarations; 18 import org.jboss.cache.optimistic.TransactionWorkspace; 19 import org.jboss.cache.optimistic.WorkspaceNode; 20 21 import java.lang.reflect.Method ; 22 import java.util.Collection ; 23 import java.util.Iterator ; 24 25 31 public class OptimisticLockingInterceptor extends OptimisticInterceptor 32 { 33 private long lockAcquisitionTimeout; 34 35 public void setCache(CacheSPI cache) 36 { 37 super.setCache(cache); 38 lockAcquisitionTimeout = cache.getConfiguration().getLockAcquisitionTimeout(); 39 } 40 41 public Object invoke(MethodCall m) throws Throwable 42 { 43 if (MethodDeclarations.isBuddyGroupOrganisationMethod(m.getMethodId())) return super.invoke(m); 45 46 InvocationContext ctx = cache.getInvocationContext(); 47 Object retval = null; 48 Method meth = m.getMethod(); 49 50 if (m.getMethodId() == MethodDeclarations.lockMethodLocal_id) 52 { 53 log.warn("OptimisticLockingInterceptor intercepted a call to CacheImpl._lock(). " + 54 "This should NEVER be called if optimistic locking is used!! " + 55 "Not allowing this call to proceed further down the chain."); 56 return retval; 57 } 58 59 if (ctx.getTransaction() != null) 60 { 61 GlobalTransaction gtx = ctx.getGlobalTransaction(); 62 63 if (gtx == null) 64 { 65 throw new Exception ("failed to get global transaction"); 66 } 67 69 switch (m.getMethodId()) 72 { 73 case MethodDeclarations.optimisticPrepareMethod_id: 74 try 76 { 77 if (log.isDebugEnabled()) log.debug("Calling lockNodes() with gtx " + ctx.getGlobalTransaction()); 78 lockNodes(gtx); 79 } 80 catch (Throwable e) 81 { 82 log.debug("Caught exception attempting to lock nodes ", e); 83 try 85 { 86 unlock(gtx); 87 } 88 catch (Throwable t) 89 { 90 log.fatal("Failed to unlock on prepare ", t); 92 } 93 throw e; 94 95 } 96 retval = super.invoke(m); 98 break; 99 case MethodDeclarations.commitMethod_id: 100 case MethodDeclarations.rollbackMethod_id: 101 try 104 { 105 retval = super.invoke(m); 106 unlock(gtx); 107 } 108 catch (Throwable t) 109 { 110 log.debug("exception encountered on " + meth + " running unlock ", t); 111 try 112 { 113 unlock(gtx); 114 } 115 catch (Throwable ct) 116 { 117 log.fatal("Failed to unlock on " + meth, t); 118 } 119 throw t; 120 } 121 break; 122 default: 123 retval = super.invoke(m); 125 break; 126 } 127 128 } 129 else 130 { 131 throw new CacheException("not in a transaction"); 132 } 133 134 return retval; 135 } 136 137 138 private Object lockNodes(GlobalTransaction gtx) throws Exception 139 { 140 TransactionWorkspace workspace = getTransactionWorkspace(gtx); 141 log.debug("locking nodes"); 142 143 Collection nodes = workspace.getNodes().values(); 145 146 for (Iterator it = nodes.iterator(); it.hasNext();) 147 { 148 WorkspaceNode workspaceNode = (WorkspaceNode) it.next(); 149 NodeSPI node = workspaceNode.getNode(); 150 151 boolean acquired = node.getLock().acquire(gtx, lockAcquisitionTimeout, NodeLock.LockType.WRITE); 152 if (acquired) 153 { 154 if (log.isTraceEnabled()) log.trace("acquired lock on node " + node.getFqn()); 155 cache.getTransactionTable().addLock(gtx, node.getLock()); 156 } 157 else 158 { 159 throw new CacheException("unable to acquire lock on node " + node.getFqn()); 160 } 161 162 } 163 return null; 164 165 } 166 167 168 private void unlock(GlobalTransaction gtx) 169 { 170 TransactionEntry entry = txTable.get(gtx); 171 entry.releaseAllLocksFIFO(gtx); 172 } 173 174 } 175 | Popular Tags |