[jboss-cvs] JBossCache/src/org/jboss/cache/interceptors ...

Manik Surtani manik at jboss.org
Fri Mar 30 10:02:09 EDT 2007


  User: msurtani
  Date: 07/03/30 10:02:09

  Modified:    src/org/jboss/cache/interceptors  
                        OptimisticReplicationInterceptor.java
                        OptimisticNodeInterceptor.java
  Log:
  Final refactorings
  
  Revision  Changes    Path
  1.37      +6 -4      JBossCache/src/org/jboss/cache/interceptors/OptimisticReplicationInterceptor.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: OptimisticReplicationInterceptor.java
  ===================================================================
  RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/interceptors/OptimisticReplicationInterceptor.java,v
  retrieving revision 1.36
  retrieving revision 1.37
  diff -u -b -r1.36 -r1.37
  --- OptimisticReplicationInterceptor.java	29 Mar 2007 16:02:58 -0000	1.36
  +++ OptimisticReplicationInterceptor.java	30 Mar 2007 14:02:09 -0000	1.37
  @@ -264,7 +264,7 @@
               // get the data version associated with this orig call.
   
               // since these are all crud methods the Fqn is at arg subscript 1.
  -            Fqn fqn = (Fqn) origArgs[1];
  +            Fqn fqn = (Fqn) origArgs[origCall.getMethodId() == MethodDeclarations.moveMethodLocal_id ? 0 : 1];
               // now get a hold of the data version for this specific modification
               DataVersion versionToBroadcast = getVersionToBroadcast(w, fqn);
   
  @@ -301,6 +301,8 @@
            DefaultDataVersion v = (DefaultDataVersion) n.getVersion();
            if (log.isTraceEnabled())
               log.trace("Fqn " + f + " has implicit versioning.  Broadcasting an incremented version.");
  +
  +         // potential bug here - need to check if we *need* to increment at all, because of Configuration.isLockParentForChildInsertRemove() 
            return v.increment();
         }
         else
  
  
  
  1.60      +202 -198  JBossCache/src/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: OptimisticNodeInterceptor.java
  ===================================================================
  RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java,v
  retrieving revision 1.59
  retrieving revision 1.60
  diff -u -b -r1.59 -r1.60
  --- OptimisticNodeInterceptor.java	29 Mar 2007 16:02:58 -0000	1.59
  +++ OptimisticNodeInterceptor.java	30 Mar 2007 14:02:09 -0000	1.60
  @@ -17,6 +17,7 @@
   import org.jboss.cache.config.Option;
   import org.jboss.cache.marshall.MethodCall;
   import org.jboss.cache.marshall.MethodDeclarations;
  +import org.jboss.cache.notifications.Notifier;
   import org.jboss.cache.optimistic.DataVersion;
   import org.jboss.cache.optimistic.DefaultDataVersion;
   import org.jboss.cache.optimistic.TransactionWorkspace;
  @@ -24,87 +25,49 @@
   import org.jboss.cache.transaction.GlobalTransaction;
   
   import java.util.HashMap;
  -import java.util.Iterator;
   import java.util.Map;
   import java.util.SortedMap;
   
   /**
  - * Operations on nodes are done on the copies that exist in the workspace rather than passed down to the {@link org.jboss.cache.interceptors.CallInterceptor}
  + * Operations on nodes are done on the copies that exist in the workspace rather than passed down
  + * to the {@link org.jboss.cache.interceptors.CallInterceptor}.  These operations happen in this interceptor.
    *
    * @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
    * @author <a href="mailto:stevew at jofti.com">Steve Woodcock (stevew at jofti.com)</a>
    */
   public class OptimisticNodeInterceptor extends OptimisticInterceptor
   {
  +   /**
  +    * Needed for the creation of workspace nodes based on underlying nodes in the cache.
  +    */
      private NodeFactory nodeFactory;
  +   private Notifier notifier;
   
      public void setCache(CacheSPI c)
      {
         super.setCache(c);
         nodeFactory = c.getConfiguration().getRuntimeConfig().getNodeFactory();
  +      notifier = cache.getNotifier();
      }
   
      public Object invoke(MethodCall m) throws Throwable
      {
  -      // bypass for buddy group org method calls.
  -      if (MethodDeclarations.isBuddyGroupOrganisationMethod(m.getMethodId())) return super.invoke(m);
  -
  -      if (trace) log.trace("Processing method call " + m);
  -
         InvocationContext ctx = cache.getInvocationContext();
         Object[] args = m.getArgs();
   
         Object result = null;
   
  -      GlobalTransaction gtx = ctx.getGlobalTransaction();
  -
  -      TransactionWorkspace workspace = getTransactionWorkspace(gtx);
  -
  -      if (MethodDeclarations.moveMethodLocal_id == m.getMethodId())
  -      {
  -         if (ctx.getOptionOverrides().getDataVersion() != null && ctx.isOriginLocal())
  -         {
  -            throw new CacheException("Setting a data version while performing a move() is not supported!!");
  -         }
  -
  -         Fqn parentFqn = (Fqn) args[1], nodeFqn = (Fqn) args[0];
  -
  -         if (trace)
  -         {
  -            log.trace("Adding nodes " + parentFqn + " and " + nodeFqn + " to the workspace.");
  -         }
  -
  -         WorkspaceNode parent = getOrCreateWorkspaceNode(parentFqn, workspace, false);
  -         if (parent == null) throw new NodeNotExistsException("Node " + parentFqn + " does not exist!");
  -         WorkspaceNode node = getOrCreateWorkspaceNode(nodeFqn, workspace, true);
  -
  -         if (trace)
  -         {
  -            log.trace("Parent: " + parent);
  -            log.trace("Node: " + node);
  -            log.trace("Workspace snapshot: " + workspace);
  -         }
  -
  -         // be greedy about it - get children as well.
  -         greedyGetNodes(node, workspace);
  -
  -         // now that we have all we need in the workspace, perform the move.
  -
  -         doMove(parent, node, workspace);
  -
  -         addToModificationList(gtx, m);
  -      }
  -      else if (MethodDeclarations.isCrudMethod(m.getMethodId()))
  +      if (MethodDeclarations.isCrudMethod(m.getMethodId()))
         {
  -         // assign a global transaction here if we need to - should do all
  -         // this in the transaction interceptor
  -         Fqn fqn = getFqn(args);
  -         WorkspaceNode workspaceNode = getOrCreateWorkspaceNode(fqn, workspace, true);
  +         GlobalTransaction gtx = getGlobalTransaction();
  +         TransactionWorkspace workspace = getTransactionWorkspace(gtx);
  +         Fqn fqn = getFqn(args, m.getMethodId());
  +         WorkspaceNode workspaceNode = fetchWorkspaceNode(fqn, workspace, true);
   
            // in the case of a data gravitation cleanup, if the primary Fqn does not exist the backup one may.
            if (workspaceNode == null && m.getMethodId() == MethodDeclarations.dataGravitationCleanupMethod_id)
            {
  -            workspaceNode = getOrCreateWorkspaceNode(getBackupFqn(args), workspace, true);
  +            workspaceNode = fetchWorkspaceNode(getBackupFqn(args), workspace, true);
            }
   
            if (workspaceNode != null)
  @@ -112,6 +75,10 @@
               // use explicit versioning
               if (ctx.getOptionOverrides() != null && ctx.getOptionOverrides().getDataVersion() != null)
               {
  +               // if the method call is a move() then barf.  Note that remove calls will set data versions explicitly, regardless.
  +               if (ctx.isOriginLocal() && m.getMethodId() == MethodDeclarations.moveMethodLocal_id)
  +                  throw new CacheException("Setting a data version while performing a move() is not supported!!");
  +
                  workspace.setVersioningImplicit(false);
                  DataVersion version = ctx.getOptionOverrides().getDataVersion();
   
  @@ -131,57 +98,43 @@
               // "fail-more-silently" patch thanks to Owen Taylor - JBCACHE-767
               if ((ctx.getOptionOverrides() == null || !ctx.getOptionOverrides().isFailSilently()) && MethodDeclarations.isPutMethod(m.getMethodId()))
               {
  -               throw new CacheException("Unable to set node version for " + getFqn(args) + ", node is null.");
  +               throw new CacheException("Unable to set node version for " + fqn + ", node is null.");
               }
            }
   
            switch (m.getMethodId())
            {
  +            case MethodDeclarations.moveMethodLocal_id:
  +               Fqn parentFqn = (Fqn) args[1];
  +               moveNodeAndNotify(parentFqn, workspaceNode, workspace);
  +               break;
               case MethodDeclarations.putDataMethodLocal_id:
                  Boolean erase = (Boolean) args[3];
  -               cache.getNotifier().notifyNodeModified(fqn, true, CacheListener.ModificationType.PUT_MAP, workspaceNode.getData(), false);
  -               putDataMap((Map<Object, Object>) args[2], erase, workspace, workspaceNode);
  -               cache.getNotifier().notifyNodeModified(fqn, false, CacheListener.ModificationType.PUT_MAP, workspaceNode.getData(), false);
  +               putDataMapAndNotify((Map<Object, Object>) args[2], erase, workspace, workspaceNode);
                  break;
               case MethodDeclarations.putDataEraseMethodLocal_id:
  -               cache.getNotifier().notifyNodeModified(fqn, true, CacheListener.ModificationType.PUT_MAP, workspaceNode.getData(), false);
  -               putDataMap((Map<Object, Object>) args[2], true, workspace, workspaceNode);
  -               cache.getNotifier().notifyNodeModified(fqn, false, CacheListener.ModificationType.PUT_MAP, workspaceNode.getData(), false);
  +               putDataMapAndNotify((Map<Object, Object>) args[2], true, workspace, workspaceNode);
                  break;
               case MethodDeclarations.putKeyValMethodLocal_id:
               case MethodDeclarations.putForExternalReadMethodLocal_id:
                  Object key = args[2];
                  Object value = args[3];
  -               Map addedData = new HashMap();
  -               addedData.put(key, value);
  -
  -               cache.getNotifier().notifyNodeModified(fqn, true, CacheListener.ModificationType.PUT_DATA, workspaceNode.getData(), false);
  -               result = putDataKeyValue(key, value, workspace, workspaceNode);
  -               cache.getNotifier().notifyNodeModified(fqn, false, CacheListener.ModificationType.PUT_DATA, addedData, false);
  +               result = putDataKeyValueAndNotify(key, value, workspace, workspaceNode);
                  break;
               case MethodDeclarations.removeNodeMethodLocal_id:
  -               cache.getNotifier().notifyNodeRemoved(fqn, true, workspaceNode == null ? null : workspaceNode.getData(), false);
  -               result = removeNode(workspace, workspaceNode);
  -               cache.getNotifier().notifyNodeRemoved(fqn, false, null, false);
  +               result = removeNodeAndNotify(workspace, workspaceNode);
                  break;
               case MethodDeclarations.removeKeyMethodLocal_id:
  -               cache.getNotifier().notifyNodeModified(fqn, true, CacheListener.ModificationType.REMOVE_DATA, workspaceNode == null ? null : workspaceNode.getData(), false);
                  Object removeKey = args[2];
  -               result = removeKey(removeKey, workspace, workspaceNode);
  -               Map removedData = new HashMap();
  -               removedData.put(removeKey, result);
  -               cache.getNotifier().notifyNodeModified(fqn, false, CacheListener.ModificationType.REMOVE_DATA, removedData, false);
  +               result = removeKeyAndNotify(removeKey, workspace, workspaceNode);
                  break;
               case MethodDeclarations.removeDataMethodLocal_id:
  -               Map data = workspaceNode == null ? null : new HashMap(workspaceNode.getData());
  -               cache.getNotifier().notifyNodeModified(fqn, true, CacheListener.ModificationType.REMOVE_DATA, data, false);
  -               removeData(workspace, workspaceNode);
  -               cache.getNotifier().notifyNodeModified(fqn, false, CacheListener.ModificationType.REMOVE_DATA, data, false);
  +               removeDataAndNotify(workspace, workspaceNode);
                  break;
               case MethodDeclarations.dataGravitationCleanupMethod_id:
                  result = super.invoke(m);
               default:
  -               if (log.isInfoEnabled()) log.info("Cannot Handle Method " + m);
  +               if (log.isWarnEnabled()) log.warn("Cannot handle CRUD method " + m);
                  break;
            }
   
  @@ -192,22 +145,19 @@
            switch (m.getMethodId())
            {
               case MethodDeclarations.getKeyValueMethodLocal_id:
  -               result = getValueForKey(args, workspace);
  +               result = getValueForKeyAndNotify(args, getTransactionWorkspace(getGlobalTransaction()));
                  break;
               case MethodDeclarations.getKeysMethodLocal_id:
  -               result = getKeys(args, workspace);
  +               result = getKeysAndNotify(args, getTransactionWorkspace(getGlobalTransaction()));
                  break;
               case MethodDeclarations.getChildrenNamesMethodLocal_id:
  -               result = getChildNames(args, workspace);
  +               result = getChildNamesAndNotify(args, getTransactionWorkspace(getGlobalTransaction()));
                  break;
               case MethodDeclarations.getNodeMethodLocal_id:
  -               result = getNode(args, workspace);
  +               result = getNodeAndNotify(args, getTransactionWorkspace(getGlobalTransaction()));
                  break;
               default:
  -               if (log.isInfoEnabled())
  -               {
  -                  log.info("read Method " + m + " called - don't know how to handle, passing on!");
  -               }
  +               if (trace) log.trace("read Method " + m + " called - Not handling, passing on.");
                  result = super.invoke(m);
                  break;
            }
  @@ -215,11 +165,34 @@
         return result;
      }
   
  +   /**
  +    * Extracts the Fqn from the array of arguments passed in
  +    *
  +    * @param args array of args
  +    * @return fqn
  +    */
  +   private Fqn getFqn(Object[] args, int methodId)
  +   {
  +      return (Fqn) args[methodId == MethodDeclarations.moveMethodLocal_id ? 0 : 1];
  +   }
  +
  +   /**
  +    * Retrieves a backup fqn in an array of arguments.  This is typically used to parse arguments from a data gravitation cleanup method.
  +    *
  +    * @param args array of arguments to parse
  +    * @return an Fqn
  +    */
      private Fqn getBackupFqn(Object[] args)
      {
         return (Fqn) args[2];
      }
   
  +   /**
  +    * Adds a method call to the modification list of a given transaction's transaction entry
  +    *
  +    * @param gtx transaction
  +    * @param m   methodcall to add
  +    */
      private void addToModificationList(GlobalTransaction gtx, MethodCall m)
      {
         Option opt = cache.getInvocationContext().getOptionOverrides();
  @@ -232,7 +205,21 @@
   
      }
   
  -   public void doMove(WorkspaceNode parent, WorkspaceNode node, TransactionWorkspace ws)
  +   // -----------------------------------------------------------------
  +
  +   // Methods that mimic core functionality in the cache, except that they work on WorkspaceNodes in the TransactionWorkspace.
  +
  +   // -----------------------------------------------------------------
  +
  +
  +   /**
  +    * Performs a move within the workspace.
  +    *
  +    * @param parentFqn parent under which the node is to be moved
  +    * @param node      node to move
  +    * @param ws        transaction workspace
  +    */
  +   private void moveNodeAndNotify(Fqn parentFqn, WorkspaceNode node, TransactionWorkspace ws)
      {
         Fqn nodeFqn = node.getFqn();
         if (nodeFqn.isRoot())
  @@ -240,134 +227,110 @@
            log.warn("Attempting to move the root node.  Not taking any action, treating this as a no-op.");
            return;
         }
  -      WorkspaceNode oldParent = getOrCreateWorkspaceNode(nodeFqn.getParent(), ws, false);
  +      // retrieve parent
  +      WorkspaceNode parent = fetchWorkspaceNode(parentFqn, ws, false);
  +      if (parent == null) throw new NodeNotExistsException("Node " + parentFqn + " does not exist!");
  +
  +      WorkspaceNode oldParent = fetchWorkspaceNode(nodeFqn.getParent(), ws, false);
         if (oldParent == null) throw new NodeNotExistsException("Node " + nodeFqn.getParent() + " does not exist!");
  +
         Object nodeName = nodeFqn.getLastElement();
   
         // now that we have the parent and target nodes:
         // first correct the pointers at the pruning point
         oldParent.removeChild(new Fqn(nodeName));
  -      //      parent.addChild(nodeName, node);
  -      //      parent.createChild(nodeName, nodeFqn, parent.getNode(), ((TreeCacheProxyImpl)cache).cache, null);
   
         // parent pointer is calculated on the fly using Fqns.
  -
         // now adjust Fqns of node and all children.
  -      // notify
         Fqn nodeNewFqn = new Fqn(parent.getFqn(), nodeFqn.getLastElement());
  -      cache.getNotifier().notifyNodeMoved(nodeFqn, nodeNewFqn, true, false);
  -      moveFqns(node, parent.getFqn(), ws);
  +
  +      // pre-notify
  +      notifier.notifyNodeMoved(nodeFqn, nodeNewFqn, true, false);
  +      recursiveMoveNode(node, parent.getFqn(), ws);
   
         // remove old nodes. this may mark some nodes which have already been moved as deleted
  -      removeNode(ws, node);
  +      removeNodeAndNotify(ws, node);
   
  -      // notify
  -      cache.getNotifier().notifyNodeMoved(nodeFqn, nodeNewFqn, false, false);
  +      // post-notify
  +      notifier.notifyNodeMoved(nodeFqn, nodeNewFqn, false, false);
      }
   
      /**
       * Moves a node to a new base.
  +    *
  +    * @param node    node to move
  +    * @param newBase new base Fqn under which the given node will now exist
  +    * @param ws      transaction workspace
       */
  -   private void moveFqns(WorkspaceNode node, Fqn newBase, TransactionWorkspace ws)
  +   private void recursiveMoveNode(WorkspaceNode node, Fqn newBase, TransactionWorkspace ws)
      {
         Fqn newFqn = new Fqn(newBase, node.getFqn().getLastElement());
  -      WorkspaceNode movedNode = getOrCreateWorkspaceNode(newFqn, ws, true);
  +      WorkspaceNode movedNode = fetchWorkspaceNode(newFqn, ws, true);
         movedNode.putAll(node.getData());
   
         // process children
         for (Object n : node.getChildrenNames())
         {
  -         WorkspaceNode child = getOrCreateWorkspaceNode(new Fqn(node.getFqn(), n), ws, false);
  -         if (child != null) moveFqns(child, newFqn, ws);
  +         WorkspaceNode child = fetchWorkspaceNode(new Fqn(node.getFqn(), n), ws, false);
  +         if (child != null) recursiveMoveNode(child, newFqn, ws);
         }
      }
   
  -   /**
  -    * performs a getOrCreateNode on all n's children, recursively.
  -    *
  -    * @param n
  -    */
  -   protected void greedyGetNodes(WorkspaceNode n, TransactionWorkspace ws)
  -   {
  -      Fqn myFqn = n.getFqn();
  -
  -      for (Object child : n.getChildrenNames())
  -      {
  -         Fqn childFqn = new Fqn(myFqn, child);
  -         WorkspaceNode cn = getOrCreateWorkspaceNode(childFqn, ws, false);
  -         if (!ws.hasNode(childFqn)) ws.addNode(cn);
  -         greedyGetNodes(cn, ws);
  -      }
  -   }
  -
  -   private Fqn getFqn(Object[] args)
  -   {
  -      return (Fqn) args[1];
  -   }
  -
  -   private void putDataMap(Map<Object, Object> data, boolean eraseExisitng,
  -                           TransactionWorkspace workspace, WorkspaceNode workspaceNode)
  +   private void putDataMapAndNotify(Map<Object, Object> data, boolean eraseExisitng, TransactionWorkspace workspace, WorkspaceNode workspaceNode)
      {
         if (workspaceNode == null)
  -      {
  -         return;
  -      }
  +         throw new NodeNotExistsException("optimisticCreateIfNotExistsInterceptor should have created this node!");
  +      // pre-notify
  +      notifier.notifyNodeModified(workspaceNode.getFqn(), true, CacheListener.ModificationType.PUT_MAP, workspaceNode.getData(), false);
         if (eraseExisitng) workspaceNode.clearData();
         workspaceNode.putAll(data);
         workspace.addNode(workspaceNode);
  +      // post-notify
  +      notifier.notifyNodeModified(workspaceNode.getFqn(), false, CacheListener.ModificationType.PUT_MAP, workspaceNode.getData(), false);
      }
   
  -   private Object putDataKeyValue(Object key, Object value, TransactionWorkspace workspace, WorkspaceNode workspaceNode)
  +   private Object putDataKeyValueAndNotify(Object key, Object value, TransactionWorkspace workspace, WorkspaceNode workspaceNode)
      {
         if (workspaceNode == null)
  -      {
  -         return null;// this should be an exception
  -      }
  +         throw new NodeNotExistsException("optimisticCreateIfNotExistsInterceptor should have created this node!");
  +
  +      Map addedData = new HashMap();
  +      addedData.put(key, value);
  +      // pre-notify
  +      notifier.notifyNodeModified(workspaceNode.getFqn(), true, CacheListener.ModificationType.PUT_DATA, workspaceNode.getData(), false);
   
         Object old = workspaceNode.put(key, value);
         workspace.addNode(workspaceNode);
  +
  +      // post-notify
  +      notifier.notifyNodeModified(workspaceNode.getFqn(), false, CacheListener.ModificationType.PUT_DATA, addedData, false);
  +
         return old;
      }
   
  -   private boolean removeNode(TransactionWorkspace workspace, WorkspaceNode workspaceNode) throws CacheException
  +   private boolean removeNodeAndNotify(TransactionWorkspace workspace, WorkspaceNode workspaceNode) throws CacheException
      {
  -      if (trace) log.trace("removeNode " + workspace + " node=" + workspaceNode);
  -
         // it is already removed - we can ignore it
  -      if (workspaceNode == null)
  -      {
  -         return false;
  -      }
  -
  -      boolean debug = log.isDebugEnabled();
  +      if (workspaceNode == null) return false;
   
         Fqn parentFqn = workspaceNode.getFqn().getParent();
  -      WorkspaceNode parentNode = getOrCreateWorkspaceNode(parentFqn, workspace, false);
  -      if (parentNode == null)
  -      {
  -         // chk if this has been removed in the same tx
  -         parentNode = workspace.getNode(parentFqn);
  -         if (parentNode == null || !parentNode.isDeleted())
  -         {
  -            throw new NodeNotExistsException("Unable to find parent node with Fqn " + parentFqn);
  -         }
  -      }
  +      WorkspaceNode parentNode = fetchWorkspaceNode(parentFqn, workspace, true);
  +      if (parentNode == null) throw new NodeNotExistsException("Unable to find parent node with fqn " + parentFqn);
  +
  +      // pre-notify
  +      notifier.notifyNodeRemoved(workspaceNode.getFqn(), true, workspaceNode.getData(), false);
  +
  +      parentNode.removeChild(workspaceNode.getFqn().getLastElement());
   
  -      parentNode.removeChild(new Fqn(workspaceNode.getFqn().getLastElement()));
  -      workspace.addNode(parentNode);
  -      if (debug) log.debug("added parent node " + parentNode.getFqn() + " to workspace");
         Fqn nodeFqn = workspaceNode.getFqn();
   
  -      // Mark this node and all children as deleted
  -      workspace.addNode(workspaceNode);// deleted below
  -      SortedMap tailMap = workspace.getNodesAfter(workspaceNode.getFqn());
  +      SortedMap<Fqn, WorkspaceNode> tailMap = workspace.getNodesAfter(workspaceNode.getFqn());
   
  -      for (Iterator it = tailMap.entrySet().iterator(); it.hasNext();)
  +      for (WorkspaceNode toDelete : tailMap.values())
         {
  -         WorkspaceNode toDelete = (WorkspaceNode) ((Map.Entry) it.next()).getValue();
            if (toDelete.getFqn().isChildOrEquals(nodeFqn))
            {
  -            if (debug) log.debug("marking node " + toDelete.getFqn() + " as deleted");
  +            if (trace) log.trace("marking node " + toDelete.getFqn() + " as deleted");
               toDelete.markAsDeleted(true);
            }
            else
  @@ -375,148 +338,189 @@
               break;// no more children, we came to the end
            }
         }
  +
  +      // post-notify
  +      notifier.notifyNodeRemoved(workspaceNode.getFqn(), false, null, false);
         return true;
      }
   
  -   private Object removeKey(Object removeKey, TransactionWorkspace workspace, WorkspaceNode workspaceNode)
  -   {
  -      if (workspaceNode == null)
  +   private Object removeKeyAndNotify(Object removeKey, TransactionWorkspace workspace, WorkspaceNode workspaceNode)
         {
  -         return null;
  -      }
  +      if (workspaceNode == null) return null;
  +
  +      // pre-notify
  +      notifier.notifyNodeModified(workspaceNode.getFqn(), true, CacheListener.ModificationType.REMOVE_DATA, workspaceNode.getData(), false);
   
         Object old = workspaceNode.remove(removeKey);
         workspace.addNode(workspaceNode);
  +
  +      Map removedData = new HashMap();
  +      removedData.put(removeKey, old);
  +      // post-notify
  +      notifier.notifyNodeModified(workspaceNode.getFqn(), false, CacheListener.ModificationType.REMOVE_DATA, removedData, false);
  +
         return old;
      }
   
  -   private void removeData(TransactionWorkspace workspace, WorkspaceNode workspaceNode)
  -   {
  -      if (workspaceNode == null)
  +   private void removeDataAndNotify(TransactionWorkspace workspace, WorkspaceNode workspaceNode)
         {
  -         return;
  -      }
  +      if (workspaceNode == null) return;
  +
  +      Map data = new HashMap(workspaceNode.getData());
  +
  +      // pre-notify
  +      notifier.notifyNodeModified(workspaceNode.getFqn(), true, CacheListener.ModificationType.REMOVE_DATA, data, false);
  +
         workspaceNode.clearData();
         workspace.addNode(workspaceNode);
  +
  +      // post-notify
  +      notifier.notifyNodeModified(workspaceNode.getFqn(), false, CacheListener.ModificationType.REMOVE_DATA, data, false);
      }
   
  -   private Object getValueForKey(Object[] args, TransactionWorkspace workspace)
  +   private Object getValueForKeyAndNotify(Object[] args, TransactionWorkspace workspace)
      {
         Fqn fqn = (Fqn) args[0];
         Object key = args[1];
  -      WorkspaceNode workspaceNode = getOrCreateWorkspaceNode(fqn, workspace, false);
  +      WorkspaceNode workspaceNode = fetchWorkspaceNode(fqn, workspace, false);
   
         if (workspaceNode == null)
         {
  -         if (log.isDebugEnabled()) log.debug("unable to find node " + fqn + " in workspace.");
  +         if (trace) log.debug("Unable to find node " + fqn + " in workspace.");
            return null;
         }
         else
         {
            //add this node into the wrokspace
  -         cache.getNotifier().notifyNodeVisited(fqn, true, false);
  +         notifier.notifyNodeVisited(fqn, true, false);
            Object val = workspaceNode.get(key);
            workspace.addNode(workspaceNode);
  -         cache.getNotifier().notifyNodeVisited(fqn, false, false);
  +         notifier.notifyNodeVisited(fqn, false, false);
            return val;
         }
      }
   
  -   private Object getNode(Object[] args, TransactionWorkspace workspace)
  +   private Object getNodeAndNotify(Object[] args, TransactionWorkspace workspace)
      {
         Fqn fqn = (Fqn) args[0];
   
  -      WorkspaceNode workspaceNode = getOrCreateWorkspaceNode(fqn, workspace, false);
  +      WorkspaceNode workspaceNode = fetchWorkspaceNode(fqn, workspace, false);
   
         if (workspaceNode == null)
         {
  -         if (log.isDebugEnabled()) log.debug("unable to find node " + fqn + " in workspace.");
  +         if (trace) log.trace("Unable to find node " + fqn + " in workspace.");
            return null;
         }
         else
         {
  -         cache.getNotifier().notifyNodeVisited(fqn, true, false);
  +         notifier.notifyNodeVisited(fqn, true, false);
            workspace.addNode(workspaceNode);
  -         cache.getNotifier().notifyNodeVisited(fqn, false, false);
  +         notifier.notifyNodeVisited(fqn, false, false);
            return workspaceNode.getNode();
         }
      }
   
  -   private Object getKeys(Object[] args, TransactionWorkspace workspace)
  +   private Object getKeysAndNotify(Object[] args, TransactionWorkspace workspace)
      {
         Fqn fqn = (Fqn) args[0];
   
  -      WorkspaceNode workspaceNode = getOrCreateWorkspaceNode(fqn, workspace, false);
  +      WorkspaceNode workspaceNode = fetchWorkspaceNode(fqn, workspace, false);
   
         if (workspaceNode == null)
         {
  -         if (log.isDebugEnabled()) log.debug("unable to find node " + fqn + " in workspace.");
  +         if (trace) log.trace("unable to find node " + fqn + " in workspace.");
            return null;
         }
         else
         {
  -         cache.getNotifier().notifyNodeVisited(fqn, true, false);
  +         notifier.notifyNodeVisited(fqn, true, false);
            Object keySet = workspaceNode.getKeys();
            workspace.addNode(workspaceNode);
  -         cache.getNotifier().notifyNodeVisited(fqn, false, false);
  +         notifier.notifyNodeVisited(fqn, false, false);
            return keySet;
         }
      }
   
  -   private Object getChildNames(Object[] args, TransactionWorkspace workspace)
  +   private Object getChildNamesAndNotify(Object[] args, TransactionWorkspace workspace)
      {
         Fqn fqn = (Fqn) args[0];
   
  -      WorkspaceNode workspaceNode = getOrCreateWorkspaceNode(fqn, workspace, false);
  +      WorkspaceNode workspaceNode = fetchWorkspaceNode(fqn, workspace, false);
   
         if (workspaceNode == null)
         {
  -         if (log.isDebugEnabled()) log.debug("unable to find node " + fqn + " in workspace.");
  +         if (trace) log.trace("Unable to find node " + fqn + " in workspace.");
            return null;
         }
         else
         {
  -         cache.getNotifier().notifyNodeVisited(fqn, true, false);
  +         notifier.notifyNodeVisited(fqn, true, false);
            Object nameSet = workspaceNode.getChildrenNames();
            workspace.addNode(workspaceNode);
  -         cache.getNotifier().notifyNodeVisited(fqn, false, false);
  +         notifier.notifyNodeVisited(fqn, false, false);
            return nameSet;
         }
      }
   
  -   private WorkspaceNode getOrCreateWorkspaceNode(Fqn fqn, TransactionWorkspace workspace, boolean undeleteIfNecessary)
  +   // -----------------------------------------------------------------
  +
  +   // Methods to help retrieval of nodes from the transaction workspace.
  +
  +   // -----------------------------------------------------------------
  +
  +   /**
  +    * Retrieves a node for a given Fqn from the workspace.  If the node does not exist in the workspace it is retrieved
  +    * from the cache's data structure.  Note that at no point is a NEW node created in the underlying data structure.
  +    * That is up to the {@link org.jboss.cache.interceptors.OptimisticCreateIfNotExistsInterceptor}.
  +    * <p/>
  +    * If the node requested is in the workspace but marked as deleted, this method will NOT retrieve it, unless undeleteIfNecessary
  +    * is true, in which case the node's <tt>deleted</tt> property is set to false first before being retrieved.
  +    *
  +    * @param fqn                 Fqn of the node to retrieve
  +    * @param workspace           transaction workspace to look in
  +    * @param undeleteIfNecessary if the node is in the workspace but marked as deleted, this meth
  +    * @return a node, if found, or null if not.
  +    */
  +   private WorkspaceNode fetchWorkspaceNode(Fqn fqn, TransactionWorkspace workspace, boolean undeleteIfNecessary)
      {
         WorkspaceNode workspaceNode = workspace.getNode(fqn);
         // if we do not have the node then we need to add it to the workspace
         if (workspaceNode == null)
         {
            NodeSPI node = cache.peek(fqn, true);
  -         if (node == null)
  -         {
  -            return null;// seems to happen quite a bit
  -         }
  +         if (node == null) return null;
  +
  +         // create new workspace node based on the node from the underlying data structure
            workspaceNode = nodeFactory.createWorkspaceNode(node, workspace);
  +
  +         // and add the node to the workspace.
            workspace.addNode(workspaceNode);
         }
  -      // the node has been deleted dude!
  +
  +      // Check that the workspace node has been marked as deleted.
         if (workspaceNode.isDeleted())
         {
  -         if (log.isDebugEnabled()) log.debug("Node " + fqn + " has been deleted in the workspace.");
  +         if (trace) log.trace("Node " + fqn + " has been deleted in the workspace.");
            if (undeleteIfNecessary)
            {
               workspaceNode.markAsDeleted(false);
               // re-add to parent
  -            WorkspaceNode parent = getOrCreateWorkspaceNode(fqn.getParent(), workspace, true);
  +            WorkspaceNode parent = fetchWorkspaceNode(fqn.getParent(), workspace, true);
               parent.addChild(workspaceNode);
            }
            else
            {
  +            // don't return deleted nodes if undeleteIfNecessary is false!
               workspaceNode = null;
            }
         }
   
  +      // set implicit node versioning flag.
         if (workspaceNode != null && !(workspaceNode.getVersion() instanceof DefaultDataVersion))
  +      {
            workspaceNode.setVersioningImplicit(false);
  +      }
  +
         return workspaceNode;
      }
   }
  
  
  



More information about the jboss-cvs-commits mailing list