KickJava   Java API By Example, From Geeks To Geeks.

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


1 package org.jboss.cache.interceptors;
2
3 import org.jboss.cache.Fqn;
4 import org.jboss.cache.GlobalTransaction;
5 import org.jboss.cache.Modification;
6 import org.jboss.cache.NodeSPI;
7 import org.jboss.cache.TransactionEntry;
8 import org.jboss.cache.TransactionTable;
9 import org.jboss.cache.marshall.MethodCall;
10 import org.jboss.cache.marshall.MethodDeclarations;
11
12 import javax.transaction.TransactionManager JavaDoc;
13 import java.lang.reflect.Method JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Map JavaDoc;
19 import java.util.Set JavaDoc;
20 import java.util.concurrent.ConcurrentHashMap JavaDoc;
21
22 /**
23  * Loads nodes that don't exist at the time of the call into memory from the CacheLoader.
24  * If the nodes were evicted earlier then we remove them from the cache loader after
25  * their attributes have been initialized and their children have been loaded in memory.
26  *
27  * @author <a HREF="mailto:{hmesha@novell.com}">{Hany Mesha}</a>
28  * @version $Id: ActivationInterceptor.java,v 1.48 2007/01/04 05:35:37 msurtani Exp $
29  */

30 public class ActivationInterceptor extends CacheLoaderInterceptor implements ActivationInterceptorMBean
31 {
32
33    protected TransactionManager JavaDoc tx_mgr = null;
34    protected TransactionTable tx_table = null;
35    private HashMap JavaDoc m_txActivations = new HashMap JavaDoc();
36    private long m_activations = 0;
37
38    /**
39     * List<Transaction> that we have registered for
40     */

41    protected ConcurrentHashMap JavaDoc transactions = new ConcurrentHashMap JavaDoc(16);
42    protected static final Object JavaDoc NULL = new Object JavaDoc();
43
44    public ActivationInterceptor()
45    {
46       this.useCacheStore = false;
47       isActivation = true;
48    }
49
50    /**
51     * Makes sure a node is loaded into memory before a call executes. If node is
52     * already loaded and its attributes already initialized, then remove it from
53     * the cache loader and notify the cache listeners that the node has been activated.
54     *
55     * @return
56     * @throws Throwable
57     */

58    public Object JavaDoc invoke(MethodCall m) throws Throwable JavaDoc
59    {
60
61       Fqn fqn = null;
62       Object JavaDoc[] args = m.getArgs();
63       Object JavaDoc retval;
64
65       // First call the parent class to load the node
66
retval = super.invoke(m);
67
68       // is this a node removal operation?
69
boolean removeData = false, nodeRemoved = false;
70
71       // Could be TRANSACTIONAL. If so, we register for TX completion (if we haven't done so yet)
72
if (tx_mgr != null && tx_mgr.getTransaction() != null)
73       {
74          GlobalTransaction gtx = cache.getInvocationContext().getGlobalTransaction();
75          switch (m.getMethodId())
76          {
77             case MethodDeclarations.commitMethod_id:
78                if (hasModifications(args))
79                {
80                   loader.commit(gtx);
81                   if (configuration.getExposeManagementStatistics() && getStatisticsEnabled())
82                   {
83                      Integer JavaDoc acts = (Integer JavaDoc) m_txActivations.get(gtx);
84                      if (acts != null)
85                      {
86                         m_activations = m_activations + acts;
87                      }
88                      m_txActivations.remove(gtx);
89                   }
90                }
91                break;
92             case MethodDeclarations.rollbackMethod_id:
93                if (hasModifications(args))
94                {
95                   loader.rollback(gtx);
96                   if (configuration.getExposeManagementStatistics() && getStatisticsEnabled())
97                   {
98                      m_txActivations.remove(gtx);
99                   }
100                }
101                break;
102             case MethodDeclarations.optimisticPrepareMethod_id:
103             case MethodDeclarations.prepareMethod_id:
104                prepareCacheLoader(gtx);
105                break;
106          }
107       }
108
109       // if we're here then it's not transactional
110

111       // CacheLoaderInterceptor normally doesn't load the node
112
// since CacheStoreInterceptor.put() returns the old value
113
switch (m.getMethodId())
114       {
115          case MethodDeclarations.putDataMethodLocal_id:
116          case MethodDeclarations.putDataEraseMethodLocal_id:
117          case MethodDeclarations.putKeyValMethodLocal_id:
118          case MethodDeclarations.removeKeyMethodLocal_id:
119          case MethodDeclarations.addChildMethodLocal_id:
120             fqn = (Fqn) args[1];
121             break;
122          case MethodDeclarations.getKeyValueMethodLocal_id:
123          case MethodDeclarations.getNodeMethodLocal_id:
124          case MethodDeclarations.getKeysMethodLocal_id:
125          case MethodDeclarations.getChildrenNamesMethodLocal_id:
126          case MethodDeclarations.releaseAllLocksMethodLocal_id:
127          case MethodDeclarations.printMethodLocal_id:
128             fqn = (Fqn) args[0];
129             break;
130          case MethodDeclarations.removeNodeMethodLocal_id:
131             nodeRemoved = true;
132             fqn = (Fqn) args[1];
133             break;
134          case MethodDeclarations.removeDataMethodLocal_id:
135             removeData = true;
136             fqn = (Fqn) args[1];
137             break;
138       }
139
140       synchronized (this)
141       {
142          if (fqn != null)
143          {
144             if (nodeRemoved)
145             {
146                log.trace("This is a remove operation; removing the node from the loader, no activation processing needed.");
147                loader.remove(fqn);
148             }
149             else if (removeData)
150             {
151                log.trace("This is a remove data operation; removing the data from the loader, no activation processing needed.");
152                loader.removeData(fqn);
153             }
154             else if (cache.getRoot().hasChild(fqn) && loader.exists(fqn))
155             {
156                // Remove the node from the cache loader if it exists in memory,
157
// its attributes have been initialized, its children have been loaded,
158
// AND it was found in the cache loader (nodeLoaded = true).
159
// Then notify the listeners that the node has been activated.
160
NodeSPI n = getNode(fqn);// don't load
161
// node not null and attributes have been loaded?
162
if (n != null && n.getDataLoaded())
163                {
164                   if (!n.getChildrenDirect().isEmpty())
165                   {
166                      if (allInitialized(n))
167                      {
168                         log.debug("children all initialized");
169                         remove(fqn);
170                      }
171                   }
172                   else if (loaderNoChildren(fqn))
173                   {
174                      log.debug("no children " + n);
175                      remove(fqn);
176                   }
177                }
178             }
179          }
180       }
181       return retval;
182    }
183
184    private void remove(Fqn fqn) throws Exception JavaDoc
185    {
186       cache.getNotifier().notifyNodeActivated(fqn, true, true);
187       loader.remove(fqn);
188       if (configuration.getExposeManagementStatistics() && getStatisticsEnabled())
189       {
190          m_activations++;
191       }
192    }
193
194    /**
195     * Returns true if a node has all children loaded and initialized.
196     */

197    private boolean allInitialized(NodeSPI n)
198    {
199       if (!n.getChildrenLoaded())
200       {
201          return false;
202       }
203
204       for (NodeSPI child : n.getChildrenDirect())
205       {
206          if (!child.getDataLoaded())
207          {
208             return false;
209          }
210       }
211       return true;
212    }
213
214    /**
215     * Returns true if the loader indicates no children for this node.
216     * Return false on error.
217     */

218    private boolean loaderNoChildren(Fqn fqn)
219    {
220       try
221       {
222          Set JavaDoc children_names = loader.getChildrenNames(fqn);
223          return (children_names == null);
224       }
225       catch (Exception JavaDoc e)
226       {
227          log.error("failed getting the children names for " + fqn + " from the cache loader", e);
228          return false;
229       }
230    }
231
232    public long getActivations()
233    {
234       return m_activations;
235    }
236
237    public void resetStatistics()
238    {
239       super.resetStatistics();
240       m_activations = 0;
241    }
242
243    public Map JavaDoc<String JavaDoc, Object JavaDoc> dumpStatistics()
244    {
245       Map JavaDoc<String JavaDoc, Object JavaDoc> retval = super.dumpStatistics();
246       if (retval == null)
247       {
248          retval = new HashMap JavaDoc<String JavaDoc, Object JavaDoc>();
249       }
250       retval.put("Activations", m_activations);
251       return retval;
252    }
253
254    protected boolean hasModifications(Object JavaDoc[] args)
255    {
256       int hint = 1;
257       if (args[hint] instanceof Boolean JavaDoc) return (Boolean JavaDoc) args[hint];
258       for (int i = 0; i < args.length; i++)
259       {
260          if (args[i] instanceof Boolean JavaDoc) return (Boolean JavaDoc) args[i];
261       }
262       return false;
263    }
264
265    private void prepareCacheLoader(GlobalTransaction gtx) throws Exception JavaDoc
266    {
267       List JavaDoc modifications;
268       TransactionEntry entry;
269       int txActs = 0;
270
271       entry = tx_table.get(gtx);
272       if (entry == null)
273       {
274          throw new Exception JavaDoc("entry for transaction " + gtx + " not found in transaction table");
275       }
276       modifications = entry.getCacheLoaderModifications();
277       if (modifications.size() == 0)
278       {
279          return;
280       }
281       List JavaDoc cache_loader_modifications = new ArrayList JavaDoc();
282       for (Iterator JavaDoc it = modifications.iterator(); it.hasNext();)
283       {
284          MethodCall methodCall = (MethodCall) it.next();
285          Method JavaDoc method = methodCall.getMethod();
286          Object JavaDoc[] args;
287          if (method == null)
288          {
289             throw new Exception JavaDoc("method call has no method: " + methodCall);
290          }
291          args = methodCall.getArgs();
292          switch (methodCall.getMethodId())
293          {
294             case MethodDeclarations.removeNodeMethodLocal_id:
295                // just remove it from loader, don't trigger activation processing
296
Modification mod = new Modification(Modification.ModificationType.REMOVE_NODE, (Fqn) args[1]);
297                cache_loader_modifications.add(mod);
298                break;
299             case MethodDeclarations.putDataMethodLocal_id:
300             case MethodDeclarations.putDataEraseMethodLocal_id:
301             case MethodDeclarations.putKeyValMethodLocal_id:
302                // On the way out, remove the node from the cache loader.
303
// Only remove the node if it exists in memory, its attributes have
304
// been initialized, its children have been loaded
305
// AND it was found in the cache loader (nodeLoaded = true).
306
// Then notify the listeners that the node has been activated.
307
Fqn fqn = (Fqn) args[1];
308                if (fqn != null && cache.getRoot().hasChild(fqn) && loader.exists(fqn))
309                {
310                   NodeSPI n = getNode(fqn);// don't load
311
// node not null and attributes have been loaded?
312
if (n != null && n.getDataLoaded())
313                   {
314                      // has children?
315
if (!n.getChildrenDirect().isEmpty() && allInitialized(n))
316                      {
317                         // children have been loaded, remove the node
318
addRemoveMod(cache_loader_modifications, fqn);
319                         txActs++;
320                      }
321                      // doesn't have children, check the cache loader
322
else if (loaderNoChildren(fqn))
323                      {
324                         addRemoveMod(cache_loader_modifications, fqn);
325                         txActs++;
326                      }
327                   }
328                }
329                break;
330          }
331       }
332       if (cache_loader_modifications.size() > 0)
333       {
334          loader.prepare(gtx, cache_loader_modifications, false);
335          if (configuration.getExposeManagementStatistics() && getStatisticsEnabled() && txActs > 0)
336          {
337             m_txActivations.put(gtx, txActs);
338          }
339       }
340    }
341
342    private void addRemoveMod(List JavaDoc l, Fqn fqn)
343    {
344       Modification mod = new Modification(Modification.ModificationType.REMOVE_NODE, fqn);
345       l.add(mod);
346       cache.getNotifier().notifyNodeActivated(fqn, false, true);
347    }
348
349 }
350
Popular Tags