KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > cache > interceptors > OptimisticLockingInterceptor


1 /*
2  * JBoss, Home of Professional Open Source
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

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 JavaDoc;
22 import java.util.Collection JavaDoc;
23 import java.util.Iterator JavaDoc;
24
25 /**
26  * Locks nodes during transaction boundaries
27  *
28  * @author <a HREF="mailto:manik@jboss.org">Manik Surtani (manik@jboss.org)</a>
29  * @author <a HREF="mailto:stevew@jofti.com">Steve Woodcock (stevew@jofti.com)</a>
30  */

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 JavaDoc invoke(MethodCall m) throws Throwable JavaDoc
42    {
43       // bypass for buddy group org metod calls.
44
if (MethodDeclarations.isBuddyGroupOrganisationMethod(m.getMethodId())) return super.invoke(m);
45
46       InvocationContext ctx = cache.getInvocationContext();
47       Object JavaDoc retval = null;
48       Method JavaDoc meth = m.getMethod();
49
50       // bail out if _lock() is being called on the tree cache... this should never be called with o/l enabled.
51
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 JavaDoc("failed to get global transaction");
66          }
67          //we are interested in the prepare/commit/rollback
68

69          //methods we are interested in are prepare/commit
70
//this is irrespective of whether we are local or remote
71
switch (m.getMethodId())
72          {
73             case MethodDeclarations.optimisticPrepareMethod_id:
74                //try and acquire the locks - before passing on
75
try
76                {
77                   if (log.isDebugEnabled()) log.debug("Calling lockNodes() with gtx " + ctx.getGlobalTransaction());
78                   lockNodes(gtx);
79                }
80                catch (Throwable JavaDoc e)
81                {
82                   log.debug("Caught exception attempting to lock nodes ", e);
83                   //we have failed - set to rollback and throw exception
84
try
85                   {
86                      unlock(gtx);
87                   }
88                   catch (Throwable JavaDoc t)
89                   {
90                      // we have failed to unlock - now what?
91
log.fatal("Failed to unlock on prepare ", t);
92                   }
93                   throw e;
94
95                }
96                // locks have acquired so lets pass on up
97
retval = super.invoke(m);
98                break;
99             case MethodDeclarations.commitMethod_id:
100             case MethodDeclarations.rollbackMethod_id:
101                // we need to let the stack run its commits first -
102
// we unlock last - even if an exception occurs
103
try
104                {
105                   retval = super.invoke(m);
106                   unlock(gtx);
107                }
108                catch (Throwable JavaDoc t)
109                {
110                   log.debug("exception encountered on " + meth + " running unlock ", t);
111                   try
112                   {
113                      unlock(gtx);
114                   }
115                   catch (Throwable JavaDoc ct)
116                   {
117                      log.fatal("Failed to unlock on " + meth, t);
118                   }
119                   throw t;
120                }
121                break;
122             default:
123                //we do not care
124
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 JavaDoc lockNodes(GlobalTransaction gtx) throws Exception JavaDoc
139    {
140       TransactionWorkspace workspace = getTransactionWorkspace(gtx);
141       log.debug("locking nodes");
142
143       // should be an ordered list
144
Collection JavaDoc nodes = workspace.getNodes().values();
145
146       for (Iterator JavaDoc 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