KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > cache > TransactionEntry


1 /*
2  * JBoss, the OpenSource J2EE webOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7 package org.jboss.cache;
8
9
10 import org.apache.commons.logging.Log;
11 import org.apache.commons.logging.LogFactory;
12 import org.jboss.cache.config.Option;
13 import org.jboss.cache.lock.IdentityLock;
14 import org.jboss.cache.lock.NodeLock;
15 import org.jboss.cache.marshall.MethodCall;
16
17 import javax.transaction.Transaction JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.LinkedHashSet JavaDoc;
22 import java.util.LinkedList JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.ListIterator JavaDoc;
25
26 /**
27  * This is the value (key being the {@link GlobalTransaction}) in the transaction table
28  * of CacheImpl.
29  * <br>A TransactionEntry maintains
30  * <ul>
31  * <li>Handle to local Transactions: there can be more than 1 local TX associated with a GlobalTransaction
32  * <li>List of modifications (Modification)
33  * <li>List of nodes that were created as part of lock acquisition. These nodes can be
34  * safely deleted when a transaction is rolled back
35  * <li>List of locks ({@link IdentityLock}) that have been acquired by
36  * this transaction so far
37  * </ul>
38  *
39  * @author <a HREF="mailto:bela@jboss.org">Bela Ban</a> Apr 14, 2003
40  * @version $Revision: 1.19 $
41  */

42 public class TransactionEntry
43 {
44
45    static Log log = LogFactory.getLog(TransactionEntry.class);
46
47    /**
48     * Local transaction
49     */

50    private Transaction JavaDoc ltx = null;
51    private Option option;
52
53    /**
54     * List<MethodCall> of modifications ({@link MethodCall}). They will be replicated on TX commit
55     */

56    private List JavaDoc<MethodCall> modification_list = new LinkedList JavaDoc<MethodCall>();
57    private List JavaDoc<MethodCall> cl_mod_list = new LinkedList JavaDoc<MethodCall>();
58
59    /**
60     * List<MethodCall>. List of compensating {@link org.jboss.cache.marshall.MethodCall} objects
61     * which revert the ones in <tt>modification_list</tt>. For each entry in the modification list,
62     * we have a corresponding entry in this list. A rollback will simply iterate over this list in
63     * reverse to undo the modifications. Note that these undo-ops will never be replicated.
64     */

65    private List JavaDoc undo_list = new LinkedList JavaDoc();
66
67    /**
68     * LinkedHashSet<IdentityLock> of locks acquired by the transaction. We use
69     * a LinkedHashSet because we need efficient Set semantics (same lock can
70     * be added multiple times) but also need guaranteed ordering for use
71     * by lock release code (see JBCCACHE-874).
72     */

73    private LinkedHashSet JavaDoc locks = new LinkedHashSet JavaDoc();
74
75    /**
76     * A list of dummy uninitialised nodes created by the cache loader interceptor to load data for a
77     * given node in this tx.
78     */

79    private List JavaDoc dummyNodesCreatedByCacheLoader;
80
81    /**
82     * List<Fqn> of nodes that have been removed by the transaction
83     */

84    private List JavaDoc<Fqn> removedNodes = new LinkedList JavaDoc<Fqn>();
85    private List JavaDoc<MethodCall> cacheListenerEvents = new LinkedList JavaDoc<MethodCall>();
86
87    /**
88     * Constructs a new TransactionEntry.
89     */

90    public TransactionEntry()
91    {
92    }
93
94    /**
95     * Adds a modification to the modification list.
96     */

97    public void addModification(MethodCall m)
98    {
99       if (m == null) return;
100       modification_list.add(m);
101    }
102
103    public void addCacheLoaderModification(MethodCall m)
104    {
105       if (m != null) cl_mod_list.add(m);
106    }
107
108
109    /**
110     * Returns all modifications.
111     */

112    public List JavaDoc<MethodCall> getModifications()
113    {
114       return modification_list;
115    }
116
117    public List JavaDoc<MethodCall> getCacheLoaderModifications()
118    {
119       return cl_mod_list;
120    }
121
122    /**
123     * Adds an undo operation to the undo list.
124     *
125     * @see #undoOperations
126     */

127    public void addUndoOperation(MethodCall m)
128    {
129       undo_list.add(m);
130    }
131
132    /**
133     * Adds the node that has been removed.
134     *
135     * @param fqn
136     */

137    public void addRemovedNode(Fqn fqn)
138    {
139       removedNodes.add(fqn);
140    }
141
142    /**
143     * Gets the list of removed nodes.
144     */

145    public List JavaDoc<Fqn> getRemovedNodes()
146    {
147       return new ArrayList JavaDoc(removedNodes);
148    }
149
150
151    /**
152     * Returns the undo operations in use.
153     * Note: This list may be concurrently modified.
154     */

155    public List JavaDoc getUndoOperations()
156    {
157       return undo_list;
158    }
159
160    /**
161     * Sets the local transaction for this entry.
162     */

163    public void setTransaction(Transaction JavaDoc tx)
164    {
165       ltx = tx;
166    }
167
168    /**
169     * Returns a local transaction associated with this TransactionEntry
170     */

171    public Transaction JavaDoc getTransaction()
172    {
173       return ltx;
174    }
175
176    /**
177     * Adds a lock to the end of the lock list, if it isn't already present.
178     */

179    public void addLock(NodeLock l)
180    {
181       if (l != null)
182       {
183          synchronized (locks)
184          {
185             locks.add(l);
186          }
187       }
188    }
189
190    /**
191     * Add multiple locks to the lock list.
192     *
193     * @param newLocks Collection<IdentityLock>
194     */

195    public void addLocks(Collection JavaDoc newLocks)
196    {
197       if (newLocks != null)
198       {
199          synchronized (locks)
200          {
201             locks.addAll(newLocks);
202          }
203       }
204    }
205
206    /**
207     * Returns the locks in use.
208     *
209     * @return a defensive copy of the internal data structure.
210     */

211    public List JavaDoc getLocks()
212    {
213       synchronized (locks)
214       {
215          return new ArrayList JavaDoc(locks);
216       }
217    }
218
219    /**
220     * Calls {@link #releaseAllLocksFIFO}.
221     *
222     * @deprecated don't think this is used anymore
223     */

224    public void releaseAllLocks(Object JavaDoc owner)
225    {
226       releaseAllLocksFIFO(owner);
227       synchronized (locks)
228       {
229          locks.clear();
230       }
231    }
232
233    /**
234     * Releases all locks held by the owner, in reverse order of creation.
235     * Clears the list of locks held.
236     */

237    public void releaseAllLocksLIFO(Object JavaDoc owner)
238    {
239
240       synchronized (locks)
241       {
242          // Copying out to an array is faster than creating an ArrayList and iterating,
243
// since list creation will just copy out to an array internally
244
IdentityLock[] lockArray = (IdentityLock[]) locks.toArray(new IdentityLock[locks.size()]);
245          for (int i = lockArray.length - 1; i >= 0; i--)
246          {
247             if (log.isTraceEnabled())
248             {
249                log.trace("releasing lock for " + lockArray[i].getFqn() + " (" + lockArray[i] + ")");
250             }
251             lockArray[i].release(owner);
252          }
253          locks.clear();
254       }
255    }
256
257    /**
258     * Releases all locks held by the owner, in order of creation.
259     * Does not clear the list of locks held.
260     */

261    public void releaseAllLocksFIFO(Object JavaDoc owner)
262    {
263       // I guess a copy would work as well
264
// This seems fairly safe though
265
synchronized (locks)
266       {
267          for (Iterator JavaDoc i = locks.iterator(); i.hasNext();)
268          {
269             IdentityLock lock = (IdentityLock) i.next();
270             lock.release(owner);
271             if (log.isTraceEnabled())
272             {
273                log.trace("releasing lock for " + lock.getFqn() + " (" + lock + ")");
274             }
275          }
276       }
277    }
278
279    /**
280     * Posts all undo operations to the CacheImpl.
281     */

282    public void undoOperations(CacheSPI cache)
283    {
284       if (log.isTraceEnabled())
285       {
286          log.trace("undoOperations " + undo_list);
287       }
288       ArrayList JavaDoc l;
289       synchronized (undo_list)
290       {
291          l = new ArrayList JavaDoc(undo_list);
292       }
293       for (ListIterator JavaDoc i = l.listIterator(l.size()); i.hasPrevious();)
294       {
295          MethodCall undo_op = (MethodCall) i.previous();
296          undo(undo_op, cache);
297       }
298    }
299
300    private void undo(MethodCall undo_op, CacheSPI cache)
301    {
302       try
303       {
304          Object JavaDoc retval = undo_op.invoke(cache);
305          if (retval instanceof Throwable JavaDoc)
306          {
307             throw (Throwable JavaDoc) retval;
308          }
309       }
310       catch (Throwable JavaDoc t)
311       {
312          log.error("undo operation failed, error=" + t);
313          log.trace(t, t);
314       }
315    }
316
317    /**
318     * Returns debug information about this transaction.
319     */

320    public String JavaDoc toString()
321    {
322       StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
323       sb.append("\nmodification_list: ").append(modification_list);
324       synchronized (undo_list)
325       {
326          sb.append("\nundo_list: ").append(undo_list);
327       }
328       synchronized (locks)
329       {
330          sb.append("\nlocks: ").append(locks);
331       }
332       return sb.toString();
333    }
334
335    public void loadUninitialisedNode(Fqn fqn)
336    {
337       if (dummyNodesCreatedByCacheLoader == null) dummyNodesCreatedByCacheLoader = new LinkedList JavaDoc();
338       dummyNodesCreatedByCacheLoader.add(fqn);
339    }
340
341    public List JavaDoc getDummyNodesCreatedByCacheLoader()
342    {
343       return dummyNodesCreatedByCacheLoader;
344    }
345
346    /**
347     * Sets a transaction-scope option override
348     *
349     * @param o
350     */

351    public void setOption(Option o)
352    {
353       this.option = o;
354    }
355
356    /**
357     * Retrieves a transaction scope option override
358     */

359    public Option getOption()
360    {
361       return this.option;
362    }
363
364    public void addCacheListenerEvents(List JavaDoc<MethodCall> cacheListenerEvents)
365    {
366       this.cacheListenerEvents.addAll(cacheListenerEvents);
367    }
368
369    public List JavaDoc<MethodCall> getCacheListenerEvents()
370    {
371       return cacheListenerEvents;
372    }
373 }
374
Popular Tags