Package org.jboss.cache.interceptors

Source Code of org.jboss.cache.interceptors.ActivationInterceptor

package org.jboss.cache.interceptors;

import org.jboss.cache.Fqn;
import org.jboss.cache.InvocationContext;
import org.jboss.cache.Modification;
import org.jboss.cache.Node;
import org.jboss.cache.NodeSPI;
import org.jboss.cache.marshall.MethodCall;
import org.jboss.cache.marshall.MethodDeclarations;
import org.jboss.cache.transaction.GlobalTransaction;
import org.jboss.cache.transaction.TransactionEntry;
import org.jboss.cache.transaction.TransactionTable;
import org.jgroups.Address;

import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
* Loads nodes that don't exist at the time of the call into memory from the CacheLoader.
* If the nodes were evicted earlier then we remove them from the cache loader after
* their attributes have been initialized and their children have been loaded in memory.
*
* @author <a href="mailto:{hmesha@novell.com}">{Hany Mesha}</a>
* @version $Id: ActivationInterceptor.java 4986 2008-01-04 16:55:01Z manik.surtani@jboss.com $
*/
public class ActivationInterceptor extends CacheLoaderInterceptor implements ActivationInterceptorMBean
{

   protected TransactionManager tx_mgr = null;
   protected TransactionTable tx_table = null;
   private HashMap m_txActivations = new HashMap();
   private long m_activations = 0;

   /**
    * List<Transaction> that we have registered for
    */
   protected ConcurrentHashMap transactions = new ConcurrentHashMap(16);
   protected static final Object NULL = new Object();

   public ActivationInterceptor()
   {
      initLogger();
      isActivation = true;
      useCacheStore = false;
   }

   @Override
   protected Object handleRemoveDataMethod(InvocationContext ctx, GlobalTransaction tx, Fqn fqn, boolean createUndoOps) throws Throwable
   {
      Object returnValue = super.handleRemoveDataMethod(ctx, tx, fqn, createUndoOps);
      if (trace)
         log.trace("This is a remove data operation; removing the data from the loader, no activation processing needed.");
      loader.removeData(fqn);
      return returnValue;
   }

   @Override
   protected Object handleRemoveNodeMethod(InvocationContext ctx, GlobalTransaction tx, Fqn fqn, boolean createUndoOps) throws Throwable
   {
      Object returnValue = super.handleRemoveNodeMethod(ctx, tx, fqn, createUndoOps);
      if (trace)
         log.trace("This is a remove operation; removing the node from the loader, no activation processing needed.");
      loader.remove(fqn);
      return returnValue;
   }

   @Override
   protected Object handlePrintMethod(InvocationContext ctx, Fqn fqn) throws Throwable
   {
      Object returnValue = super.handlePrintMethod(ctx, fqn);
      removeNodeFromCacheLoader(ctx, fqn);
      return returnValue;
   }

   @Override
   protected Object handleReleaseAllLocksMethod(InvocationContext ctx, Fqn fqn) throws Throwable
   {
      Object returnValue = super.handleReleaseAllLocksMethod(ctx, fqn);
      removeNodeFromCacheLoader(ctx, fqn);
      return returnValue;
   }

   @Override
   protected Object handleGetChildrenNamesMethod(InvocationContext ctx, Fqn fqn) throws Throwable
   {
      Object returnValue = super.handleGetChildrenNamesMethod(ctx, fqn);
      removeNodeFromCacheLoader(ctx, fqn);
      return returnValue;
   }

   @Override
   protected Object handleGetKeysMethod(InvocationContext ctx, Fqn fqn) throws Throwable
   {
      Object returnValue = super.handleGetKeysMethod(ctx, fqn);
      removeNodeFromCacheLoader(ctx, fqn);
      return returnValue;
   }

   @Override
   protected Object handleGetNodeMethod(InvocationContext ctx, Fqn fqn) throws Throwable
   {
      Object returnValue = super.handleGetNodeMethod(ctx, fqn);
      removeNodeFromCacheLoader(ctx, fqn);
      return returnValue;
   }

   @Override
   protected Object handleGetKeyValueMethod(InvocationContext ctx, Fqn fqn, Object key, boolean sendNodeEvent) throws Throwable
   {
      Object returnValue = super.handleGetKeyValueMethod(ctx, fqn, key, sendNodeEvent);
      removeNodeFromCacheLoader(ctx, fqn);
      return returnValue;
   }

   @Override
   protected Object handleAddChildMethod(InvocationContext ctx, GlobalTransaction tx, Fqn parentFqn, Object childName, Node cn, boolean createUndoOps) throws Throwable
   {
      Object returnValue = super.handleAddChildMethod(ctx, tx, parentFqn, childName, cn, createUndoOps);
      removeNodeFromCacheLoader(ctx, parentFqn);
      return returnValue;
   }

   @Override
   protected Object handlePutForExternalReadMethod(InvocationContext ctx, GlobalTransaction tx, Fqn fqn, Object key, Object value) throws Throwable
   {
      Object returnValue = super.handlePutForExternalReadMethod(ctx, tx, fqn, key, value);
      removeNodeFromCacheLoader(ctx, fqn);
      return returnValue;
   }

   @Override
   protected Object handlePutDataMethod(InvocationContext ctx, GlobalTransaction tx, Fqn fqn, Map data, boolean createUndoOps) throws Throwable
   {
      Object returnValue = super.handlePutDataMethod(ctx, tx, fqn, data, createUndoOps);
      removeNodeFromCacheLoader(ctx, fqn);
      return returnValue;
   }

   @Override
   protected Object handlePutKeyValueMethod(InvocationContext ctx, GlobalTransaction gtx, Fqn fqn, Object key, Object value, boolean createUndoOps) throws Throwable
   {
      Object returnValue = super.handlePutKeyValueMethod(ctx, gtx, fqn, key, value, createUndoOps);
      removeNodeFromCacheLoader(ctx, fqn);
      return returnValue;
   }

   @Override
   protected Object handleRemoveKeyMethod(InvocationContext ctx, GlobalTransaction tx, Fqn fqn, Object key, boolean createUndoOps) throws Throwable
   {
      Object returnValue = super.handleRemoveKeyMethod(ctx, tx, fqn, key, createUndoOps);
      removeNodeFromCacheLoader(ctx, fqn);
      return returnValue;
   }

   @Override
   protected Object handlePutDataEraseMethod(InvocationContext ctx, GlobalTransaction gt, Fqn fqn, Map newData, boolean createUndoOps, boolean eraseContents) throws Throwable
   {
      Object returnValue = super.handlePutDataEraseMethod(ctx, gt, fqn, newData, createUndoOps, eraseContents);
      removeNodeFromCacheLoader(ctx, fqn);
      return returnValue;
   }

   /**
    * Remove the node from the cache loader if it exists in memory,
    * its attributes have been initialized, its children have been loaded,
    * AND it was found in the cache loader (nodeLoaded = true).
    * Then notify the listeners that the node has been activated.
    */
   private void removeNodeFromCacheLoader(InvocationContext ctx, Fqn fqn) throws Throwable
   {
      NodeSPI n;
      if (((n = peekNode(ctx, fqn, false, true, false)) != null) && n.isDataLoaded() && loader.exists(fqn))
      {
         // node not null and attributes have been loaded?
         if (!n.getChildrenDirect().isEmpty())
         {
            if (allInitialized(n))
            {
               log.debug("children all initialized");
               remove(ctx, fqn);
            }
         }
         else if (loaderNoChildren(fqn))
         {
            if (log.isDebugEnabled()) log.debug("no children " + n);
            remove(ctx, fqn);
         }
      }
   }

   @Override
   protected Object handleOptimisticPrepareMethod(InvocationContext ctx, GlobalTransaction gtx, List modifications, Map data, Address address, boolean onePhaseCommit) throws Throwable
   {
      Object retval = nextInterceptor(ctx);
      if (inTransaction())
      {
         prepareCacheLoader(ctx);
      }
      return retval;
   }

   private boolean inTransaction()
         throws SystemException
   {
      return tx_mgr != null && tx_mgr.getTransaction() != null;
   }

   @Override
   protected Object handlePrepareMethod(InvocationContext ctx, GlobalTransaction gtx, List modification, Address coordinator, boolean onePhaseCommit) throws Throwable
   {
      Object retval = nextInterceptor(ctx);
      if (inTransaction())
      {
         prepareCacheLoader(ctx);
      }
      return retval;
   }

   private void remove(InvocationContext ctx, Fqn fqn) throws Exception
   {
      cache.getNotifier().notifyNodeActivated(fqn, true, Collections.emptyMap(), ctx);
      loader.remove(fqn);
      if (configuration.getExposeManagementStatistics() && getStatisticsEnabled())
      {
         m_activations++;
      }
   }

   /**
    * Returns true if a node has all children loaded and initialized.
    */
   private boolean allInitialized(NodeSPI<?, ?> n)
   {
      if (!n.isChildrenLoaded())
      {
         return false;
      }
      for (NodeSPI child : n.getChildrenDirect())
      {
         if (!child.isDataLoaded())
         {
            return false;
         }
      }
      return true;

   }

   /**
    * Returns true if the loader indicates no children for this node.
    * Return false on error.
    */
   private boolean loaderNoChildren(Fqn fqn)
   {
      try
      {
         Set children_names = loader.getChildrenNames(fqn);
         return (children_names == null);
      }
      catch (Exception e)
      {
         log.error("failed getting the children names for " + fqn + " from the cache loader", e);
         return false;
      }
   }

   public long getActivations()
   {
      return m_activations;
   }

   @Override
   public void resetStatistics()
   {
      super.resetStatistics();
      m_activations = 0;
   }

   @Override
   public Map<String, Object> dumpStatistics()
   {
      Map<String, Object> retval = super.dumpStatistics();
      if (retval == null)
      {
         retval = new HashMap<String, Object>();
      }
      retval.put("Activations", m_activations);
      return retval;
   }

   private void prepareCacheLoader(InvocationContext ctx) throws Exception
   {
      List<MethodCall> modifications;
      TransactionEntry entry;
      int txActs = 0;
      GlobalTransaction gtx = ctx.getGlobalTransaction();

      entry = tx_table.get(gtx);
      if (entry == null)
      {
         throw new Exception("entry for transaction " + gtx + " not found in transaction table");
      }
      modifications = entry.getCacheLoaderModifications();
      if (modifications.size() == 0)
      {
         return;
      }
      List cache_loader_modifications = new ArrayList();
      for (MethodCall methodCall : modifications)
      {
         Method method = methodCall.getMethod();
         Object[] args;
         if (method == null)
         {
            throw new Exception("method call has no method: " + methodCall);
         }
         args = methodCall.getArgs();
         switch (methodCall.getMethodId())
         {
            case MethodDeclarations.removeNodeMethodLocal_id:
               // just remove it from loader, don't trigger activation processing
               Modification mod = new Modification(Modification.ModificationType.REMOVE_NODE, (Fqn) args[1]);
               cache_loader_modifications.add(mod);
               break;
            case MethodDeclarations.putDataMethodLocal_id:
            case MethodDeclarations.putDataEraseMethodLocal_id:
            case MethodDeclarations.putKeyValMethodLocal_id:
               // On the way out, remove the node from the cache loader.
               // Only remove the node if it exists in memory, its attributes have
               // been initialized, its children have been loaded
               // AND it was found in the cache loader (nodeLoaded = true).
               // Then notify the listeners that the node has been activated.
               Fqn fqn = (Fqn) args[1];
               if (fqn != null && peekNode(ctx, fqn, false, false, false) != null && loader.exists(fqn))
               {
                  NodeSPI n = peekNode(ctx, fqn, false, true, false);// don't load
                  // node not null and attributes have been loaded?
                  if (n != null && n.isDataLoaded())
                  {
                     // has children?
                     if (!n.getChildrenDirect().isEmpty() && allInitialized(n))
                     {
                        // children have been loaded, remove the node
                        addRemoveMod(ctx, cache_loader_modifications, fqn, n.getDataDirect());
                        txActs++;
                     }
                     // doesn't have children, check the cache loader
                     else if (loaderNoChildren(fqn))
                     {
                        addRemoveMod(ctx, cache_loader_modifications, fqn, n.getDataDirect());
                        txActs++;
                     }
                  }
               }
               break;
         }
      }
      if (cache_loader_modifications.size() > 0)
      {
         loader.prepare(gtx, cache_loader_modifications, false);
         if (configuration.getExposeManagementStatistics() && getStatisticsEnabled() && txActs > 0)
         {
            m_txActivations.put(gtx, txActs);
         }
      }
   }

   private void addRemoveMod(InvocationContext ctx, List l, Fqn fqn, Map data)
   {
      Modification mod = new Modification(Modification.ModificationType.REMOVE_NODE, fqn);
      l.add(mod);
      cache.getNotifier().notifyNodeActivated(fqn, false, data, ctx);
   }

}
TOP

Related Classes of org.jboss.cache.interceptors.ActivationInterceptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.