Author: mircea.markus
Date: 2008-05-15 08:44:49 -0400 (Thu, 15 May 2008)
New Revision: 5850
Added:
core/trunk/src/main/java/org/jboss/cache/DataContainer.java
core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java
core/trunk/src/main/java/org/jboss/cache/notifications/Notifier.java
core/trunk/src/main/java/org/jboss/cache/notifications/NotifierImpl.java
core/trunk/src/test/java/org/jboss/cache/commands/
core/trunk/src/test/java/org/jboss/cache/commands/read/
core/trunk/src/test/java/org/jboss/cache/commands/read/AbstractDataCommandTest.java
core/trunk/src/test/java/org/jboss/cache/commands/read/ExistsCommandTest.java
core/trunk/src/test/java/org/jboss/cache/commands/read/GetChildrenNamesCommandTest.java
core/trunk/src/test/java/org/jboss/cache/commands/read/GetDataMapCommandTest.java
core/trunk/src/test/java/org/jboss/cache/commands/read/GetKeyValueCommandTest.java
core/trunk/src/test/java/org/jboss/cache/commands/read/GetKeysCommandTest.java
core/trunk/src/test/java/org/jboss/cache/commands/read/GravitateDataCommandTest.java
core/trunk/src/test/java/org/jboss/cache/mock/MockNodesFixture.java
Removed:
core/trunk/src/main/java/org/jboss/cache/DataContainer.java
core/trunk/src/main/java/org/jboss/cache/notifications/Notifier.java
Modified:
core/trunk/src/main/java/org/jboss/cache/CacheSPI.java
core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java
core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java
core/trunk/src/main/java/org/jboss/cache/buddyreplication/GravitateResult.java
core/trunk/src/main/java/org/jboss/cache/commands/read/ExistsCommand.java
core/trunk/src/main/java/org/jboss/cache/commands/read/GetChildrenNamesCommand.java
core/trunk/src/main/java/org/jboss/cache/commands/read/GetDataMapCommand.java
core/trunk/src/main/java/org/jboss/cache/commands/read/GetKeyValueCommand.java
core/trunk/src/main/java/org/jboss/cache/commands/read/GetKeysCommand.java
core/trunk/src/main/java/org/jboss/cache/commands/read/GravitateDataCommand.java
core/trunk/src/main/java/org/jboss/cache/commands/remote/ClusteredGetCommand.java
core/trunk/src/main/java/org/jboss/cache/commands/remote/DataGravitationCleanupCommand.java
core/trunk/src/main/java/org/jboss/cache/commands/write/AbstractVersionedDataCommand.java
core/trunk/src/main/java/org/jboss/cache/commands/write/MoveCommand.java
core/trunk/src/main/java/org/jboss/cache/factories/CommandsFactory.java
core/trunk/src/main/java/org/jboss/cache/factories/EmptyConstructorFactory.java
core/trunk/src/main/java/org/jboss/cache/interceptors/CacheLoaderInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/CacheMgmtInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/CacheStoreInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/DataGravitatorInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/EvictionInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/NotificationInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticCreateIfNotExistsInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticValidatorInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/PassivationInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java
core/trunk/src/main/java/org/jboss/cache/invocation/CacheInvocationDelegate.java
core/trunk/src/main/java/org/jboss/cache/lock/LockManager.java
core/trunk/src/main/java/org/jboss/cache/util/CachePrinter.java
core/trunk/src/test/java/org/jboss/cache/DataContainerTest.java
core/trunk/src/test/java/org/jboss/cache/marshall/ReturnValueMarshallingTest.java
core/trunk/src/test/java/org/jboss/cache/notifications/AnnotationsTest.java
core/trunk/src/test/java/org/jboss/cache/notifications/RemoteCacheListenerTest.java
Log:
JBCACHE-1338 - added unit tests for read commands
Modified: core/trunk/src/main/java/org/jboss/cache/CacheSPI.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/CacheSPI.java 2008-05-14 17:05:33 UTC (rev
5849)
+++ core/trunk/src/main/java/org/jboss/cache/CacheSPI.java 2008-05-15 12:44:49 UTC (rev
5850)
@@ -13,7 +13,7 @@
import org.jboss.cache.loader.CacheLoader;
import org.jboss.cache.loader.CacheLoaderManager;
import org.jboss.cache.marshall.Marshaller;
-import org.jboss.cache.notifications.Notifier;
+import org.jboss.cache.notifications.NotifierImpl;
import org.jboss.cache.statetransfer.StateTransferManager;
import org.jboss.cache.transaction.GlobalTransaction;
import org.jboss.cache.transaction.TransactionTable;
@@ -204,10 +204,10 @@
* From 2.1.0, Interceptor authors should obtain this by injection rather than this
method. See the
* {@link org.jboss.cache.factories.annotations.Inject} annotation.
*
- * @return the notifier attached with this instance of the cache. See {@link
Notifier}, a class
+ * @return the notifier attached with this instance of the cache. See {@link
org.jboss.cache.notifications.NotifierImpl}, a class
* that is responsible for emitting notifications to registered
CacheListeners.
*/
- Notifier getNotifier();
+ NotifierImpl getNotifier();
/**
* @return the name of the cluster. Null if running in local mode.
Deleted: core/trunk/src/main/java/org/jboss/cache/DataContainer.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/DataContainer.java 2008-05-14 17:05:33 UTC
(rev 5849)
+++ core/trunk/src/main/java/org/jboss/cache/DataContainer.java 2008-05-15 12:44:49 UTC
(rev 5850)
@@ -1,659 +0,0 @@
-package org.jboss.cache;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.buddyreplication.BuddyFqnTransformer;
-import org.jboss.cache.buddyreplication.BuddyManager;
-import org.jboss.cache.config.Configuration;
-import org.jboss.cache.factories.annotations.Inject;
-import org.jboss.cache.factories.annotations.NonVolatile;
-import org.jboss.cache.factories.annotations.Start;
-import org.jboss.cache.factories.annotations.Stop;
-import org.jboss.cache.invocation.NodeInvocationDelegate;
-import org.jboss.cache.marshall.NodeData;
-import org.jboss.cache.optimistic.DataVersion;
-import org.jboss.cache.transaction.GlobalTransaction;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A container for the root node in the cache, which also provides helpers for
efficiently accessing nodes, walking trees, etc.
- *
- * @author Mircea.Markus(a)jboss.com
- * @since 2.2
- */
-@NonVolatile
-public class DataContainer
-{
- private static final Log log = LogFactory.getLog(DataContainer.class);
- private static boolean trace = log.isTraceEnabled();
-
- private Configuration configuration;
-
- /**
- * Root node.
- */
- private NodeSPI root;
-
- /**
- * Set<Fqn> of Fqns of the topmost node of internal regions that should
- * not included in standard state transfers.
- */
- private final Set<Fqn> internalFqns = new HashSet<Fqn>();
- private NodeFactory nodeFactory;
-
- @Inject
- public void injectDependencies(Configuration configuration, NodeFactory nodeFactory)
- {
- setDependencies(configuration, nodeFactory);
-
- // We need to create a root node even at this stage since certain components rely
on this being available before
- // start() is called.
- // TODO: Investigate which components rely on this being available before start(),
and why!
- //TODO - remove setDependencies method at this point
- createRootNode();
- }
-
- public void setDependencies(Configuration configuration, NodeFactory nodeFactory)
- {
- this.configuration = configuration;
- this.nodeFactory = nodeFactory;
- }
-
- @Start(priority = 12)
- public void createRootNode()
- {
- if (trace) log.trace("Starting data container");
- // create a new root temporarily.
- NodeSPI tempRoot = nodeFactory.createRootDataNode();
- // if we don't already have a root or the new (temp) root is of a different
class (optimistic vs pessimistic) to
- // the current root, then we use the new one.
-
- Class currentRootType = root == null ? null : ((NodeInvocationDelegate)
root).getDelegationTarget().getClass();
- Class tempRootType = ((NodeInvocationDelegate)
tempRoot).getDelegationTarget().getClass();
-
- if (!tempRootType.equals(currentRootType))
- {
- if (trace) log.trace("Setting root node to an instance of " +
tempRootType);
- setRoot(tempRoot);
- }
- }
-
- @Stop(priority = 100)
- public void stop()
- {
- // empty in-memory state
- root.clearDataDirect();
- root.removeChildrenDirect();
- }
-
- /**
- * Retrieves the root node.
- *
- * @return the root node
- */
- public NodeSPI getRoot()
- {
- return root;
- }
-
- /**
- * Sets the root node reference to the node passed in.
- *
- * @param root node
- */
- public void setRoot(NodeSPI root)
- {
- if (root == null || !root.getFqn().isRoot())
- throw new CacheException("Attempting to set an invalid node [" + root
+ "] as a root node!");
- this.root = root;
- }
-
- /**
- * Adds the specified Fqn to the list of Fqns to be considered "internal".
- *
- * @param fqn fqn to add to list
- */
- public void registerInternalFqn(Fqn fqn)
- {
- internalFqns.add(fqn);
- }
-
- /**
- * Finds a node given a fully qualified name, directly off the interceptor chain. In
the event of an exception,
- * returns null. Does not include invalid or deleted nodes.
- *
- * @param fqn Fully qualified name for the corresponding node.
- * @return Node referenced by the given Fqn, or null if the node cannot be found or if
there is an exception.
- */
- public NodeSPI peek(Fqn fqn)
- {
- try
- {
- return peekVersioned(fqn, null);
- }
- catch (CacheException e)
- {
- log.warn("Unexpected error", e);
- return null;
- }
- }
-
- /**
- * Finds a node given a fully qualified name and DataVersion. Does not include
invalid or deleted nodes. If the data
- * version passed in is null, then data version checking is skipped. Data version
checking is also skipped if optimistic
- * locking is not used.
- *
- * @param fqn fqn to find
- * @param version version of the node to find
- * @return a node, if found, or null if not.
- */
- public NodeSPI peekVersioned(Fqn fqn, DataVersion version)
- {
- return peekVersioned(fqn, version, false);
- }
-
- /**
- * Similar to {@link #peekVersioned(Fqn, org.jboss.cache.optimistic.DataVersion)}
except that it throws a {@link org.jboss.cache.NodeNotExistsException}
- * if the node cannot be found.
- *
- * @param gtx global transaction
- * @param fqn fqn to find
- * @param includeInvalid if true, invalid nodes are considered as well.
- * @return the node
- */
- public NodeSPI peekStrict(GlobalTransaction gtx, Fqn fqn, boolean includeInvalid)
- {
- NodeSPI n = peekVersioned(fqn, null, includeInvalid);
- if (n == null)
- {
- StringBuilder builder = new StringBuilder();
- builder.append("Node ").append(fqn).append(" not found
(gtx=").append(gtx).append(")");
- String errStr = builder.toString();
- if (trace) log.trace(errStr);
- throw new NodeNotExistsException(errStr);
- }
- return n;
- }
-
- /**
- * Searches for a specific node, with a specific data version and, optionally, invalid
nodes as well, but not
- * deleted nodes. If the data version passed in is null, then data version checking
is skipped. Data version
- * checking is also skipped if optimistic locking is not used.
- *
- * @param fqn Fqn to find
- * @param version version of the node to find
- * @param includeInvalidNodes if true, invalid nodes are considered
- * @return the node, if found, or null otherwise.
- */
- public NodeSPI peekVersioned(Fqn fqn, DataVersion version, boolean
includeInvalidNodes)
- {
- if (fqn == null) return null;
-
- NodeSPI toReturn = peek(fqn, false, includeInvalidNodes);
-
- if (toReturn != null && version != null &&
configuration.isNodeLockingOptimistic())
- {
- // we need to check the version of the data node...
- DataVersion nodeVersion = toReturn.getVersion();
- if (trace)
- {
- log.trace("looking for optimistic node [" + fqn + "] with
version [" + version + "]. My version is [" + nodeVersion +
"]");
- }
- if (nodeVersion.newerThan(version))
- {
- // we have a versioning problem; throw an exception!
- throw new CacheException("Unable to validate versions.");
- }
- }
- return toReturn;
- }
-
- /**
- * Same as calling <tt>peek(fqn, includeDeletedNodes, false)</tt>.
- *
- * @param fqn Fqn to find
- * @param includeDeletedNodes if true, deleted nodes are considered
- * @return the node, if found, or null otherwise.
- */
- public NodeSPI peek(Fqn<?> fqn, boolean includeDeletedNodes)
- {
- return peek(fqn, includeDeletedNodes, false);
- }
-
- /**
- * Peeks for a specified node. This involves a direct walk of the tree, starting at
the root, until the required node
- * is found. If the node is not found, a null is returned.
- *
- * @param fqn Fqn of the node to find
- * @param includeDeletedNodes if true, deleted nodes are also considered
- * @param includeInvalidNodes if true, invalid nodes are also considered
- * @return the node, if found, or null otherwise.
- */
- public NodeSPI peek(Fqn<?> fqn, boolean includeDeletedNodes, boolean
includeInvalidNodes)
- {
- if (fqn == null || fqn.size() == 0) return getRoot();
- NodeSPI n = getRoot();
- int fqnSize = fqn.size();
- for (int i = 0; i < fqnSize; i++)
- {
- Object obj = fqn.get(i);
- n = n.getChildDirect(obj);
- if (n == null)
- {
- return null;
- }
- else if (!includeDeletedNodes && n.isDeleted())
- {
- return null;
- }
- else if (!includeInvalidNodes && !n.isValid())
- {
- return null;
- }
- }
- return n;
- }
-
- /**
- * Tests if an Fqn exists and is valid and not deleted.
- *
- * @param fqn the fqn representing the node to test
- * @return true if the node exists, false otherwise.
- */
- public boolean exists(Fqn fqn)
- {
- return peek(fqn, false, false) != null;
- }
-
- /**
- * Returns true if the Fqn exists, is valid and is not deleted, and the node has
children.
- *
- * @param fqn the fqn to test
- * @return true if the Fqn exists, is valid and is not deleted, and the node has
children.
- */
- public boolean hasChildren(Fqn fqn)
- {
- if (fqn == null) return false;
-
- NodeSPI n = peek(fqn);
- return n != null && n.hasChildrenDirect();
- }
-
- /**
- * Prepares a list of {@link NodeData} objects for a specified node and all its
children.
- *
- * @param list List of NodeData objects, which will be added to.
- * @param node node to recursively add to the list
- * @return the same list passed in
- */
- public List<NodeData> buildNodeData(List<NodeData> list, NodeSPI node)
- {
- NodeData data = new NodeData(BuddyFqnTransformer.getActualFqn(node.getFqn()),
node.getDataDirect());
- list.add(data);
- for (Object childNode : node.getChildrenDirect())
- {
- buildNodeData(list, (NodeSPI) childNode);
- }
- return list;
- }
-
- /**
- * Generates a list of nodes for eviction. This filters out nodes that cannot be
evicted, such as those which are
- * marked as resident. See {@link NodeSPI#setResident(boolean)}.
- *
- * @param fqn the node to consider for eviction
- * @param recursive if recursive, child nodes are also considered
- * @return a list of Fqns that can be considered for eviction
- */
- public List<Fqn> getNodesForEviction(Fqn fqn, boolean recursive)
- {
- List<Fqn> result = new ArrayList<Fqn>();
- NodeSPI node = peek(fqn, false);
- if (recursive)
- {
- recursiveAddEvictionNodes(node, result);
- }
- else
- {
- if (node == null)
- {
- result.add(fqn);
- return result;
- }
- if (fqn.isRoot())
- {
- for (Object childName : node.getChildrenNamesDirect())
- {
- if (!node.isResident()) result.add(Fqn.fromRelativeElements(fqn,
childName));
- }
- }
- else if (!node.isResident())
- {
- result.add(fqn);
- }
- }
- return result;
- }
-
- private void recursiveAddEvictionNodes(NodeSPI node, List<Fqn> result)
- {
- for (NodeSPI child : (Set<NodeSPI>) node.getChildrenDirect())
- {
- recursiveAddEvictionNodes(child, result);
- }
- Fqn fqn = node.getFqn();
- if (node != null && !fqn.isRoot() && !node.isResident())
- {
- result.add(fqn);
- }
- }
-
- @Override
- public String toString()
- {
- return toString(false);
- }
-
- /**
- * Returns a Set<Fqn> of Fqns of the topmost node of internal regions that
- * should not included in standard state transfers. Will include
- * {@link BuddyManager#BUDDY_BACKUP_SUBTREE} if buddy replication is
- * enabled.
- *
- * @return an unmodifiable Set<Fqn>. Will not return
<code>null</code>.
- */
- public Set<Fqn> getInternalFqns()
- {
- return Collections.unmodifiableSet(internalFqns);
- }
-
- /**
- * Returns a debug string with optional details of contents.
- */
- @SuppressWarnings("deprecation")
- public String toString(boolean details)
- {
- StringBuffer sb = new StringBuffer();
- int indent = 0;
-
- if (!details)
- {
- sb.append(getClass().getName()).append("
[").append(getNumberOfNodes()).append(" nodes, ");
- sb.append(getNumberOfLocksHeld()).append(" locks]");
- }
- else
- {
- if (root == null)
- return sb.toString();
- for (Object n : root.getChildrenDirect())
- {
- ((NodeSPI) n).print(sb, indent);
- sb.append("\n");
- }
- }
- return sb.toString();
- }
-
- /**
- * Returns the number of read or write locks held across the entire cache.
- */
- public int getNumberOfLocksHeld()
- {
- return numLocks(root);
- }
-
- private int numLocks(NodeSPI n)
- {
- int num = 0;
- if (n != null)
- {
- if (n.getLock().isLocked())
- {
- num++;
- }
- for (Object cn : n.getChildrenDirect(true))
- {
- num += numLocks((NodeSPI) cn);
- }
- }
- return num;
- }
-
- /**
- * Returns an <em>approximation</em> of the total number of nodes in the
- * cache. Since this method doesn't acquire any locks, the number might be
- * incorrect, or the method might even throw a
- * ConcurrentModificationException
- */
- public int getNumberOfNodes()
- {
- return numNodes(root) - 1;
- }
-
- private int numNodes(NodeSPI n)
- {
- int count = 1;// for n
- if (n != null)
- {
- for (Object child : n.getChildrenDirect())
- {
- count += numNodes((NodeSPI) child);
- }
- }
- return count;
- }
-
- /**
- * Prints information about the contents of the nodes in the cache's current
- * in-memory state. Does not load any previously evicted nodes from a
- * cache loader, so evicted nodes will not be included.
- */
- public String printDetails()
- {
- StringBuffer sb = new StringBuffer();
- root.printDetails(sb, 0);
- sb.append("\n");
- return sb.toString();
- }
-
-
- /**
- * Returns lock information.
- */
- public String printLockInfo()
- {
- StringBuffer sb = new StringBuffer("\n");
- int indent = 0;
-
- for (Object n : root.getChildrenDirect())
- {
- ((NodeSPI) n).getLock().printLockInfo(sb, indent);
- sb.append("\n");
- }
- return sb.toString();
- }
-
- /**
- * Returns an <em>approximation</em> of the total number of attributes in
- * this sub cache.
- *
- * @see #getNumberOfAttributes
- */
- public int getNumberOfAttributes(Fqn fqn)
- {
- return numAttributes(peek(fqn));
- }
-
- private int numAttributes(NodeSPI n)
- {
- int count = 0;
- for (Object child : n.getChildrenDirect())
- {
- count += numAttributes((NodeSPI) child);
- }
- count += n.getDataDirect().size();
- return count;
- }
-
- /**
- * Returns an <em>approximation</em> of the total number of attributes in
- * the cache. Since this method doesn't acquire any locks, the number might
- * be incorrect, or the method might even throw a
- * ConcurrentModificationException
- */
- public int getNumberOfAttributes()
- {
- return numAttributes(root);
- }
-
- /**
- * Removes the actual node from the tree data structure.
- *
- * @param f the Fqn of the node to remove
- * @param skipMarkerCheck if true, skips checking the boolean {@link
org.jboss.cache.NodeSPI#isDeleted()} flag and deletes the node anyway.
- * @return Returns true if the node was found and removed, false if not.
- */
- public boolean removeFromDataStructure(Fqn f, boolean skipMarkerCheck)
- {
- NodeSPI n = peek(f, true);
- if (n == null)
- {
- return false;
- }
-
- if (trace) log.trace("Performing a real remove for node " + f + ",
marked for removal.");
- if (skipMarkerCheck || n.isDeleted())
- {
- if (n.getFqn().isRoot())
- {
- // do not actually delete; just remove deletion marker
- n.markAsDeleted(true);
-
- // mark the node to be removed (and all children) as invalid so anyone
holding a direct reference to it will
- // be aware that it is no longer valid.
- n.setValid(false, true);
- n.setValid(true, false);
-
- // but now remove all children, since the call has been to
remove("/")
- n.removeChildrenDirect();
- return true;
- }
- else
- {
- // mark the node to be removed (and all children) as invalid so anyone
holding a direct reference to it will
- // be aware that it is no longer valid.
- n.setValid(false, true);
- return n.getParent().removeChildDirect(n.getFqn().getLastElement());
- }
- }
- else
- {
- if (log.isDebugEnabled()) log.debug("Node " + f + " NOT marked
for removal as expected, not removing!");
- return false;
- }
- }
-
- public void evict(Fqn fqn, boolean recursive)
- {
- List<Fqn> toEvict = getNodesForEviction(fqn, recursive);
- for (Fqn aFqn : toEvict)
- {
- evict(aFqn);
- }
- }
-
- /**
- * @return true if the FQN is leaf and was removed; false if is an intermediate FQN
and only contained data
- * is droped.
- */
- public boolean evict(Fqn fqn)
- {
- if (peek(fqn, false, true) == null) return true;
- if (hasChildren(fqn))
- {
- if (trace)
- log.trace("removing DATA as node has children: evict(" + fqn +
")");
- removeData(fqn);
- return false;
- }
- else
- {
- if (trace) log.trace("removing NODE as it is a leaf: evict(" + fqn +
")");
- removeNode(fqn);
- return true;
- }
- }
-
- private void removeNode(Fqn fqn)
- {
- NodeSPI targetNode = peekVersioned(fqn, null, true);
- if (targetNode == null) return;
- NodeSPI parentNode = targetNode.getParent();
- targetNode.setValid(false, false);
- if (parentNode != null)
- {
- parentNode.removeChildDirect(fqn.getLastElement());
- parentNode.setChildrenLoaded(false);
- }
- }
-
- protected void removeData(Fqn fqn)
- {
- NodeSPI n = peekVersioned(fqn, null);
- if (n == null)
- {
- log.warn("node " + fqn + " not found");
- return;
- }
- n.clearDataDirect();
- n.setDataLoaded(false);
- }
-
- /**
- * Traverses the tree to the given Fqn, creating nodes if needed. Returns a list of
nodes created, as well as a reference to the last node.
- * <p/>
- * E.g.,
- * <code>
- * Object[] results = createNode(myFqn);
- * results[0] // this is a List<NodeSPI> of nodes
<i>created</i> in getting to the target node.
- * results[1] // is a NodeSPI reference to the target node, regardless of whether it
was <i>created</i> or just <i>found</i>.
- * </code>
- *
- * @param fqn fqn to find
- * @return see above.
- */
- public Object[] createNodes(Fqn fqn)
- {
- List<NodeSPI> result = new ArrayList<NodeSPI>(fqn.size());
- Fqn tmpFqn = Fqn.ROOT;
-
- int size = fqn.size();
-
- // root node
- NodeSPI n = root;
- for (int i = 0; i < size; i++)
- {
- Object childName = fqn.get(i);
- tmpFqn = Fqn.fromRelativeElements(tmpFqn, childName);
-
- NodeSPI childNode;
- Map children = n.getChildrenMapDirect();
- childNode = children == null ? null : (NodeSPI) children.get(childName);
-
- if (childNode == null)
- {
- childNode = n.addChildDirect(Fqn.fromElements(childName));
- result.add(childNode);
- }
-
- n = childNode;
- }
- return new Object[]{result, n};
- }
-}
Added: core/trunk/src/main/java/org/jboss/cache/DataContainer.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/DataContainer.java
(rev 0)
+++ core/trunk/src/main/java/org/jboss/cache/DataContainer.java 2008-05-15 12:44:49 UTC
(rev 5850)
@@ -0,0 +1,201 @@
+package org.jboss.cache;
+
+import org.jboss.cache.optimistic.DataVersion;
+import org.jboss.cache.transaction.GlobalTransaction;
+import org.jboss.cache.marshall.NodeData;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class defines the functionality needed for node manipulation.
+ *
+ * @author Mircea.Markus(a)jboss.com
+ * @see org.jboss.cache.DataConatainerImpl
+ * @since 2.2
+ */
+public interface DataContainer
+{
+ /**
+ * Retrieves the root node.
+ *
+ * @return the root node
+ */
+ NodeSPI getRoot();
+
+ /**
+ * Adds the specified Fqn to the list of Fqns to be considered "internal".
+ *
+ * @param fqn fqn to add to list
+ */
+ void registerInternalFqn(Fqn fqn);
+
+ /**
+ * Finds a node given a fully qualified name, directly off the interceptor chain. In
the event of an exception,
+ * returns null. Does not include invalid or deleted nodes.
+ *
+ * @param fqn Fully qualified name for the corresponding node.
+ * @return Node referenced by the given Fqn, or null if the node cannot be found or if
there is an exception.
+ */
+ NodeSPI peek(Fqn fqn);
+
+ /**
+ * Finds a node given a fully qualified name and DataVersion. Does not include
invalid or deleted nodes. If the data
+ * version passed in is null, then data version checking is skipped. Data version
checking is also skipped if optimistic
+ * locking is not used.
+ *
+ * @param fqn fqn to find
+ * @param version version of the node to find
+ * @return a node, if found, or null if not.
+ */
+ NodeSPI peekVersioned(Fqn fqn, DataVersion version);
+
+ /**
+ * Similar to {@link #peekVersioned(Fqn, org.jboss.cache.optimistic.DataVersion)}
except that it throws a {@link org.jboss.cache.NodeNotExistsException}
+ * if the node cannot be found.
+ *
+ * @param gtx global transaction
+ * @param fqn fqn to find
+ * @param includeInvalid if true, invalid nodes are considered as well.
+ * @return the node
+ */
+ NodeSPI peekStrict(GlobalTransaction gtx, Fqn fqn, boolean includeInvalid);
+
+ /**
+ * Searches for a specific node, with a specific data version and, optionally, invalid
nodes as well, but not
+ * deleted nodes. If the data version passed in is null, then data version checking
is skipped. Data version
+ * checking is also skipped if optimistic locking is not used.
+ *
+ * @param fqn Fqn to find
+ * @param version version of the node to find
+ * @param includeInvalidNodes if true, invalid nodes are considered
+ * @return the node, if found, or null otherwise.
+ */
+ NodeSPI peekVersioned(Fqn fqn, DataVersion version, boolean includeInvalidNodes);
+
+ /**
+ * Same as calling <tt>peek(fqn, includeDeletedNodes, false)</tt>.
+ *
+ * @param fqn Fqn to find
+ * @param includeDeletedNodes if true, deleted nodes are considered
+ * @return the node, if found, or null otherwise.
+ */
+ NodeSPI peek(Fqn<?> fqn, boolean includeDeletedNodes);
+
+ /**
+ * Peeks for a specified node. This involves a direct walk of the tree, starting at
the root, until the required node
+ * is found. If the node is not found, a null is returned.
+ *
+ * @param fqn Fqn of the node to find
+ * @param includeDeletedNodes if true, deleted nodes are also considered
+ * @param includeInvalidNodes if true, invalid nodes are also considered
+ * @return the node, if found, or null otherwise.
+ */
+ NodeSPI peek(Fqn<?> fqn, boolean includeDeletedNodes, boolean
includeInvalidNodes);
+
+ /**
+ * Tests if an Fqn exists and is valid and not deleted.
+ *
+ * @param fqn the fqn representing the node to test
+ * @return true if the node exists, false otherwise.
+ */
+ boolean exists(Fqn fqn);
+
+ /**
+ * Returns true if the Fqn exists, is valid and is not deleted, and the node has
children.
+ *
+ * @param fqn the fqn to test
+ * @return true if the Fqn exists, is valid and is not deleted, and the node has
children.
+ */
+ boolean hasChildren(Fqn fqn);
+
+ /**
+ * Prepares a list of {@link NodeData} objects for a specified node and all its
children.
+ *
+ * @param list List of NodeData objects, which will be added to.
+ * @param node node to recursively add to the list
+ * @return the same list passed in
+ */
+ List<NodeData> buildNodeData(List<NodeData> list, NodeSPI node);
+
+ /**
+ * Generates a list of nodes for eviction. This filters out nodes that cannot be
evicted, such as those which are
+ * marked as resident. See {@link NodeSPI#setResident(boolean)}.
+ *
+ * @param fqn the node to consider for eviction
+ * @param recursive if recursive, child nodes are also considered
+ * @return a list of Fqns that can be considered for eviction
+ */
+ List<Fqn> getNodesForEviction(Fqn fqn, boolean recursive);
+
+ /**
+ * Returns a Set<Fqn> of Fqns of the topmost node of internal regions that
+ * should not included in standard state transfers. Will include
+ * {@link org.jboss.cache.buddyreplication.BuddyManager#BUDDY_BACKUP_SUBTREE} if buddy
replication is
+ * enabled.
+ *
+ * @return an unmodifiable Set<Fqn>. Will not return
<code>null</code>.
+ */
+ Set<Fqn> getInternalFqns();
+
+ /**
+ * Returns the number of read or write locks held across the entire cache.
+ */
+ int getNumberOfLocksHeld();
+
+ /**
+ * Returns an <em>approximation</em> of the total number of nodes in the
+ * cache. Since this method doesn't acquire any locks, the number might be
+ * incorrect, or the method might even throw a
+ * ConcurrentModificationException
+ */
+ int getNumberOfNodes();
+
+ /**
+ * Returns an <em>approximation</em> of the total number of attributes in
+ * this sub cache.
+ */
+ int getNumberOfAttributes(Fqn fqn);
+
+ /**
+ * Removes the actual node from the tree data structure.
+ *
+ * @param f the Fqn of the node to remove
+ * @param skipMarkerCheck if true, skips checking the boolean {@link
org.jboss.cache.NodeSPI#isDeleted()} flag and deletes the node anyway.
+ * @return Returns true if the node was found and removed, false if not.
+ */
+ boolean removeFromDataStructure(Fqn f, boolean skipMarkerCheck);
+
+ /**
+ * Evicts the given node. If recursive is set to true then all child nodes are
recusively evicted.
+ */
+ void evict(Fqn fqn, boolean recursive);
+
+ /**
+ * <pre>
+ * Following scenarios define how eviction works.
+ * 1. If the given node is a leaf then it is entirely removed from the data structure.
The node is marked as invalid.</li>
+ * 2. If the given node is a leaf then only the data map is cleared.
+ * 3. If the given node is the root node then the cildren nodes are evicted. For each
child node 1. or 2. applies
+ * </pre>
+ *
+ * @return true if the FQN is leaf and was removed; false if is an intermediate FQN
and only contained data
+ * is droped.
+ */
+ boolean evict(Fqn fqn);
+
+ /**
+ * Traverses the tree to the given Fqn, creating nodes if needed. Returns a list of
nodes created, as well as a reference to the last node.
+ * <p/>
+ * E.g.,
+ * <code>
+ * Object[] results = createNode(myFqn);
+ * results[0] // this is a List<NodeSPI> of nodes
<i>created</i> in getting to the target node.
+ * results[1] // is a NodeSPI reference to the target node, regardless of whether it
was <i>created</i> or just <i>found</i>.
+ * </code>
+ *
+ * @param fqn fqn to find
+ * @return see above.
+ */
+ Object[] createNodes(Fqn fqn);
+}
Copied: core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java (from rev 5848,
core/trunk/src/main/java/org/jboss/cache/DataContainer.java)
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java
(rev 0)
+++ core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java 2008-05-15 12:44:49
UTC (rev 5850)
@@ -0,0 +1,530 @@
+package org.jboss.cache;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.buddyreplication.BuddyFqnTransformer;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.factories.annotations.Inject;
+import org.jboss.cache.factories.annotations.NonVolatile;
+import org.jboss.cache.factories.annotations.Start;
+import org.jboss.cache.factories.annotations.Stop;
+import org.jboss.cache.invocation.NodeInvocationDelegate;
+import org.jboss.cache.marshall.NodeData;
+import org.jboss.cache.optimistic.DataVersion;
+import org.jboss.cache.transaction.GlobalTransaction;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A container for the root node in the cache, which also provides helpers for
efficiently accessing nodes, walking trees, etc.
+ *
+ * @author Mircea.Markus(a)jboss.com
+ * @since 2.2
+ */
+@NonVolatile
+public class DataContainerImpl implements DataContainer
+{
+ private static final Log log = LogFactory.getLog(DataContainerImpl.class);
+ private static boolean trace = log.isTraceEnabled();
+
+ private Configuration configuration;
+
+ /**
+ * Root node.
+ */
+ private NodeSPI root;
+
+ /**
+ * Set<Fqn> of Fqns of the topmost node of internal regions that should
+ * not included in standard state transfers.
+ */
+ private final Set<Fqn> internalFqns = new HashSet<Fqn>();
+ private NodeFactory nodeFactory;
+
+ @Inject
+ public void injectDependencies(Configuration configuration, NodeFactory nodeFactory)
+ {
+ setDependencies(configuration, nodeFactory);
+
+ // We need to create a root node even at this stage since certain components rely
on this being available before
+ // start() is called.
+ // TODO: Investigate which components rely on this being available before start(),
and why!
+ //TODO - remove setDependencies method at this point
+ createRootNode();
+ }
+
+ public void setDependencies(Configuration configuration, NodeFactory nodeFactory)
+ {
+ this.configuration = configuration;
+ this.nodeFactory = nodeFactory;
+ }
+
+ @Start(priority = 12)
+ public void createRootNode()
+ {
+ if (trace) log.trace("Starting data container");
+ // create a new root temporarily.
+ NodeSPI tempRoot = nodeFactory.createRootDataNode();
+ // if we don't already have a root or the new (temp) root is of a different
class (optimistic vs pessimistic) to
+ // the current root, then we use the new one.
+
+ Class currentRootType = root == null ? null : ((NodeInvocationDelegate)
root).getDelegationTarget().getClass();
+ Class tempRootType = ((NodeInvocationDelegate)
tempRoot).getDelegationTarget().getClass();
+
+ if (!tempRootType.equals(currentRootType))
+ {
+ if (trace) log.trace("Setting root node to an instance of " +
tempRootType);
+ setRoot(tempRoot);
+ }
+ }
+
+ @Stop(priority = 100)
+ public void stop()
+ {
+ // empty in-memory state
+ root.clearDataDirect();
+ root.removeChildrenDirect();
+ }
+
+ public NodeSPI getRoot()
+ {
+ return root;
+ }
+
+ /**
+ * Sets the root node reference to the node passed in.
+ *
+ * @param root node
+ */
+ public void setRoot(NodeSPI root)
+ {
+ if (root == null || !root.getFqn().isRoot())
+ throw new CacheException("Attempting to set an invalid node [" + root
+ "] as a root node!");
+ this.root = root;
+ }
+
+ public void registerInternalFqn(Fqn fqn)
+ {
+ internalFqns.add(fqn);
+ }
+
+ /**
+ * Finds a node given a fully qualified name, directly off the interceptor chain. In
the event of an exception,
+ * returns null. Does not include invalid or deleted nodes.
+ *
+ * @param fqn Fully qualified name for the corresponding node.
+ * @return Node referenced by the given Fqn, or null if the node cannot be found or if
there is an exception.
+ */
+ public NodeSPI peek(Fqn fqn)
+ {
+ try
+ {
+ return peekVersioned(fqn, null);
+ }
+ catch (CacheException e)
+ {
+ log.warn("Unexpected error", e);
+ return null;
+ }
+ }
+
+ public NodeSPI peekVersioned(Fqn fqn, DataVersion version)
+ {
+ return peekVersioned(fqn, version, false);
+ }
+
+ public NodeSPI peekStrict(GlobalTransaction gtx, Fqn fqn, boolean includeInvalid)
+ {
+ NodeSPI n = peekVersioned(fqn, null, includeInvalid);
+ if (n == null)
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Node ").append(fqn).append(" not found
(gtx=").append(gtx).append(")");
+ String errStr = builder.toString();
+ if (trace) log.trace(errStr);
+ throw new NodeNotExistsException(errStr);
+ }
+ return n;
+ }
+
+ public NodeSPI peekVersioned(Fqn fqn, DataVersion version, boolean
includeInvalidNodes)
+ {
+ if (fqn == null) return null;
+
+ NodeSPI toReturn = peek(fqn, false, includeInvalidNodes);
+
+ if (toReturn != null && version != null &&
configuration.isNodeLockingOptimistic())
+ {
+ // we need to check the version of the data node...
+ DataVersion nodeVersion = toReturn.getVersion();
+ if (trace)
+ {
+ log.trace("looking for optimistic node [" + fqn + "] with
version [" + version + "]. My version is [" + nodeVersion +
"]");
+ }
+ if (nodeVersion.newerThan(version))
+ {
+ // we have a versioning problem; throw an exception!
+ throw new CacheException("Unable to validate versions.");
+ }
+ }
+ return toReturn;
+ }
+
+ public NodeSPI peek(Fqn<?> fqn, boolean includeDeletedNodes)
+ {
+ return peek(fqn, includeDeletedNodes, false);
+ }
+
+ public NodeSPI peek(Fqn<?> fqn, boolean includeDeletedNodes, boolean
includeInvalidNodes)
+ {
+ if (fqn == null || fqn.size() == 0) return getRoot();
+ NodeSPI n = getRoot();
+ int fqnSize = fqn.size();
+ for (int i = 0; i < fqnSize; i++)
+ {
+ Object obj = fqn.get(i);
+ n = n.getChildDirect(obj);
+ if (n == null)
+ {
+ return null;
+ }
+ else if (!includeDeletedNodes && n.isDeleted())
+ {
+ return null;
+ }
+ else if (!includeInvalidNodes && !n.isValid())
+ {
+ return null;
+ }
+ }
+ return n;
+ }
+
+ public boolean exists(Fqn fqn)
+ {
+ return peek(fqn, false, false) != null;
+ }
+
+ public boolean hasChildren(Fqn fqn)
+ {
+ if (fqn == null) return false;
+
+ NodeSPI n = peek(fqn);
+ return n != null && n.hasChildrenDirect();
+ }
+
+ public List<NodeData> buildNodeData(List<NodeData> list, NodeSPI node)
+ {
+ NodeData data = new NodeData(BuddyFqnTransformer.getActualFqn(node.getFqn()),
node.getDataDirect());
+ list.add(data);
+ for (Object childNode : node.getChildrenDirect())
+ {
+ buildNodeData(list, (NodeSPI) childNode);
+ }
+ return list;
+ }
+
+ public List<Fqn> getNodesForEviction(Fqn fqn, boolean recursive)
+ {
+ List<Fqn> result = new ArrayList<Fqn>();
+ NodeSPI node = peek(fqn, false);
+ if (recursive)
+ {
+ recursiveAddEvictionNodes(node, result);
+ }
+ else
+ {
+ if (node == null)
+ {
+ result.add(fqn);
+ return result;
+ }
+ if (fqn.isRoot())
+ {
+ for (Object childName : node.getChildrenNamesDirect())
+ {
+ if (!node.isResident()) result.add(Fqn.fromRelativeElements(fqn,
childName));
+ }
+ }
+ else if (!node.isResident())
+ {
+ result.add(fqn);
+ }
+ }
+ return result;
+ }
+
+ private void recursiveAddEvictionNodes(NodeSPI node, List<Fqn> result)
+ {
+ for (NodeSPI child : (Set<NodeSPI>) node.getChildrenDirect())
+ {
+ recursiveAddEvictionNodes(child, result);
+ }
+ Fqn fqn = node.getFqn();
+ if (node != null && !fqn.isRoot() && !node.isResident())
+ {
+ result.add(fqn);
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return toString(false);
+ }
+
+ public Set<Fqn> getInternalFqns()
+ {
+ return Collections.unmodifiableSet(internalFqns);
+ }
+
+ /**
+ * Returns a debug string with optional details of contents.
+ */
+ @SuppressWarnings("deprecation")
+ public String toString(boolean details)
+ {
+ StringBuffer sb = new StringBuffer();
+ int indent = 0;
+
+ if (!details)
+ {
+ sb.append(getClass().getName()).append("
[").append(getNumberOfNodes()).append(" nodes, ");
+ sb.append(getNumberOfLocksHeld()).append(" locks]");
+ }
+ else
+ {
+ if (root == null)
+ return sb.toString();
+ for (Object n : root.getChildrenDirect())
+ {
+ ((NodeSPI) n).print(sb, indent);
+ sb.append("\n");
+ }
+ }
+ return sb.toString();
+ }
+
+ public int getNumberOfLocksHeld()
+ {
+ return numLocks(root);
+ }
+
+ private int numLocks(NodeSPI n)
+ {
+ int num = 0;
+ if (n != null)
+ {
+ if (n.getLock().isLocked())
+ {
+ num++;
+ }
+ for (Object cn : n.getChildrenDirect(true))
+ {
+ num += numLocks((NodeSPI) cn);
+ }
+ }
+ return num;
+ }
+
+ public int getNumberOfNodes()
+ {
+ return numNodes(root) - 1;
+ }
+
+ private int numNodes(NodeSPI n)
+ {
+ int count = 1;// for n
+ if (n != null)
+ {
+ for (Object child : n.getChildrenDirect())
+ {
+ count += numNodes((NodeSPI) child);
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Prints information about the contents of the nodes in the cache's current
+ * in-memory state. Does not load any previously evicted nodes from a
+ * cache loader, so evicted nodes will not be included.
+ */
+ public String printDetails()
+ {
+ StringBuffer sb = new StringBuffer();
+ root.printDetails(sb, 0);
+ sb.append("\n");
+ return sb.toString();
+ }
+
+
+ /**
+ * Returns lock information.
+ */
+ public String printLockInfo()
+ {
+ StringBuffer sb = new StringBuffer("\n");
+ int indent = 0;
+
+ for (Object n : root.getChildrenDirect())
+ {
+ ((NodeSPI) n).getLock().printLockInfo(sb, indent);
+ sb.append("\n");
+ }
+ return sb.toString();
+ }
+
+ public int getNumberOfAttributes(Fqn fqn)
+ {
+ return numAttributes(peek(fqn));
+ }
+
+ private int numAttributes(NodeSPI n)
+ {
+ int count = 0;
+ for (Object child : n.getChildrenDirect())
+ {
+ count += numAttributes((NodeSPI) child);
+ }
+ count += n.getDataDirect().size();
+ return count;
+ }
+
+ /**
+ * Returns an <em>approximation</em> of the total number of attributes in
+ * the cache. Since this method doesn't acquire any locks, the number might
+ * be incorrect, or the method might even throw a
+ * ConcurrentModificationException
+ */
+ public int getNumberOfAttributes()
+ {
+ return numAttributes(root);
+ }
+
+ public boolean removeFromDataStructure(Fqn f, boolean skipMarkerCheck)
+ {
+ NodeSPI n = peek(f, true);
+ if (n == null)
+ {
+ return false;
+ }
+
+ if (trace) log.trace("Performing a real remove for node " + f + ",
marked for removal.");
+ if (skipMarkerCheck || n.isDeleted())
+ {
+ if (n.getFqn().isRoot())
+ {
+ // do not actually delete; just remove deletion marker
+ n.markAsDeleted(true);
+
+ // mark the node to be removed (and all children) as invalid so anyone
holding a direct reference to it will
+ // be aware that it is no longer valid.
+ n.setValid(false, true);
+ n.setValid(true, false);
+
+ // but now remove all children, since the call has been to
remove("/")
+ n.removeChildrenDirect();
+ return true;
+ }
+ else
+ {
+ // mark the node to be removed (and all children) as invalid so anyone
holding a direct reference to it will
+ // be aware that it is no longer valid.
+ n.setValid(false, true);
+ return n.getParent().removeChildDirect(n.getFqn().getLastElement());
+ }
+ }
+ else
+ {
+ if (log.isDebugEnabled()) log.debug("Node " + f + " NOT marked
for removal as expected, not removing!");
+ return false;
+ }
+ }
+
+ public void evict(Fqn fqn, boolean recursive)
+ {
+ List<Fqn> toEvict = getNodesForEviction(fqn, recursive);
+ for (Fqn aFqn : toEvict)
+ {
+ evict(aFqn);
+ }
+ }
+
+ public boolean evict(Fqn fqn)
+ {
+ if (peek(fqn, false, true) == null) return true;
+ if (hasChildren(fqn))
+ {
+ if (trace)
+ log.trace("removing DATA as node has children: evict(" + fqn +
")");
+ removeData(fqn);
+ return false;
+ }
+ else
+ {
+ if (trace) log.trace("removing NODE as it is a leaf: evict(" + fqn +
")");
+ removeNode(fqn);
+ return true;
+ }
+ }
+
+ private void removeNode(Fqn fqn)
+ {
+ NodeSPI targetNode = peekVersioned(fqn, null, true);
+ if (targetNode == null) return;
+ NodeSPI parentNode = targetNode.getParent();
+ targetNode.setValid(false, false);
+ if (parentNode != null)
+ {
+ parentNode.removeChildDirect(fqn.getLastElement());
+ parentNode.setChildrenLoaded(false);
+ }
+ }
+
+ protected void removeData(Fqn fqn)
+ {
+ NodeSPI n = peekVersioned(fqn, null);
+ if (n == null)
+ {
+ log.warn("node " + fqn + " not found");
+ return;
+ }
+ n.clearDataDirect();
+ n.setDataLoaded(false);
+ }
+
+ public Object[] createNodes(Fqn fqn)
+ {
+ List<NodeSPI> result = new ArrayList<NodeSPI>(fqn.size());
+ Fqn tmpFqn = Fqn.ROOT;
+
+ int size = fqn.size();
+
+ // root node
+ NodeSPI n = root;
+ for (int i = 0; i < size; i++)
+ {
+ Object childName = fqn.get(i);
+ tmpFqn = Fqn.fromRelativeElements(tmpFqn, childName);
+
+ NodeSPI childNode;
+ Map children = n.getChildrenMapDirect();
+ childNode = children == null ? null : (NodeSPI) children.get(childName);
+
+ if (childNode == null)
+ {
+ childNode = n.addChildDirect(Fqn.fromElements(childName));
+ result.add(childNode);
+ }
+
+ n = childNode;
+ }
+ return new Object[]{result, n};
+ }
+}
Modified: core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java 2008-05-14 17:05:33 UTC
(rev 5849)
+++ core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java 2008-05-15 12:44:49 UTC
(rev 5850)
@@ -23,7 +23,7 @@
import org.jboss.cache.marshall.CommandAwareRpcDispatcher;
import org.jboss.cache.marshall.InactiveRegionAwareRpcDispatcher;
import org.jboss.cache.marshall.Marshaller;
-import org.jboss.cache.notifications.Notifier;
+import org.jboss.cache.notifications.NotifierImpl;
import org.jboss.cache.remoting.jgroups.ChannelMessageListener;
import org.jboss.cache.statetransfer.StateTransferManager;
import org.jboss.cache.transaction.GlobalTransaction;
@@ -82,7 +82,7 @@
*/
private ChannelMessageListener messageListener;
private Configuration configuration;
- private Notifier notifier;
+ private NotifierImpl notifier;
private CacheSPI spi;
private InvocationContextContainer invocationContextContainer;
private final boolean trace = log.isTraceEnabled();
@@ -96,7 +96,7 @@
private ComponentRegistry componentRegistry;
@Inject
- private void setupDependencies(ChannelMessageListener messageListener, Configuration
configuration, Notifier notifier,
+ private void setupDependencies(ChannelMessageListener messageListener, Configuration
configuration, NotifierImpl notifier,
CacheSPI spi, Marshaller marshaller, TransactionTable
txTable,
TransactionManager txManager,
InvocationContextContainer container, InterceptorChain interceptorChain,
ComponentRegistry componentRegistry)
Modified: core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java 2008-05-14
17:05:33 UTC (rev 5849)
+++ core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -8,14 +8,8 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.CacheSPI;
-import org.jboss.cache.DataContainer;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.Node;
-import org.jboss.cache.RPCManager;
-import org.jboss.cache.Region;
-import org.jboss.cache.RegionManager;
+import org.jboss.cache.DataContainerImpl;
+import org.jboss.cache.*;
import org.jboss.cache.commands.ReplicableCommand;
import org.jboss.cache.commands.VisitableCommand;
import org.jboss.cache.commands.remote.AnnounceBuddyPoolNameCommand;
@@ -31,7 +25,7 @@
import org.jboss.cache.factories.annotations.Start;
import org.jboss.cache.factories.annotations.Stop;
import org.jboss.cache.lock.TimeoutException;
-import org.jboss.cache.notifications.Notifier;
+import org.jboss.cache.notifications.NotifierImpl;
import org.jboss.cache.notifications.annotation.CacheListener;
import org.jboss.cache.notifications.annotation.ViewChanged;
import org.jboss.cache.notifications.event.ViewChangedEvent;
@@ -78,7 +72,7 @@
private CacheSPI<?, ?> cache;
private Configuration configuration;
private RegionManager regionManager;
- private Notifier notifier;
+ private NotifierImpl notifier;
private StateTransferManager stateTransferManager;
private RPCManager rpcManager;
/**
@@ -141,7 +135,7 @@
private ViewChangeListener viewChangeListener; // the view-change viewChangeListener
private boolean receivedBuddyInfo;
- private DataContainer dataContainer;
+ private DataContainerImpl dataContainer;
public BuddyManager()
{
@@ -179,8 +173,8 @@
@Inject
public void injectDependencies(CacheSPI cache, Configuration configuration,
RegionManager regionManager,
- StateTransferManager stateTransferManager, RPCManager
rpcManager, Notifier notifier,
- CommandsFactory factory, DataContainer dataContainer)
+ StateTransferManager stateTransferManager, RPCManager
rpcManager, NotifierImpl notifier,
+ CommandsFactory factory, DataContainerImpl
dataContainer)
{
this.cache = cache;
this.configuration = configuration;
Modified: core/trunk/src/main/java/org/jboss/cache/buddyreplication/GravitateResult.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/buddyreplication/GravitateResult.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/buddyreplication/GravitateResult.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -80,4 +80,28 @@
" nodeData=" + nodeData +
" fqn=" + buddyBackupFqn;
}
+
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ GravitateResult that = (GravitateResult) o;
+
+ if (dataFound != that.dataFound) return false;
+ if (buddyBackupFqn != null ? !buddyBackupFqn.equals(that.buddyBackupFqn) :
that.buddyBackupFqn != null)
+ return false;
+ if (nodeData != null ? !nodeData.equals(that.nodeData) : that.nodeData != null)
return false;
+
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int result;
+ result = (dataFound ? 1 : 0);
+ result = 31 * result + (nodeData != null ? nodeData.hashCode() : 0);
+ result = 31 * result + (buddyBackupFqn != null ? buddyBackupFqn.hashCode() : 0);
+ return result;
+ }
}
Modified: core/trunk/src/main/java/org/jboss/cache/commands/read/ExistsCommand.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/commands/read/ExistsCommand.java 2008-05-14
17:05:33 UTC (rev 5849)
+++ core/trunk/src/main/java/org/jboss/cache/commands/read/ExistsCommand.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -35,14 +35,13 @@
/**
* Checks whether a node represented by a given Fqn exists.
+ * Deleted and invalid nodes are not considered.
*
- * @param ctx invocation context
* @return true if the node exists, false otherwise.
*/
public Object perform(InvocationContext ctx)
{
- Node n = dataContainer.peek(fqn, false);
- return n != null;
+ return dataContainer.exists(fqn);
}
public Object acceptVisitor(InvocationContext ctx, Visitor visitor) throws Throwable
Modified:
core/trunk/src/main/java/org/jboss/cache/commands/read/GetChildrenNamesCommand.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/commands/read/GetChildrenNamesCommand.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/commands/read/GetChildrenNamesCommand.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -43,9 +43,9 @@
{
NodeSPI n = dataContainer.peek(fqn);
if (n == null) return null;
- Set childNames = new HashSet();
Map childrenMap = n.getChildrenMapDirect();
if (childrenMap == null || childrenMap.isEmpty()) return Collections.emptySet();
+ Set childNames = new HashSet();
Collection s = childrenMap.values();
// prune deleted children - JBCACHE-1136
for (Object c : s)
Modified: core/trunk/src/main/java/org/jboss/cache/commands/read/GetDataMapCommand.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/commands/read/GetDataMapCommand.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/commands/read/GetDataMapCommand.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -31,7 +31,6 @@
/**
* Retrieves an unmodifiable map of data contained in a node referenced by the
specified Fqn.
*
- * @param ctx invocation context
* @return an unmodifiable Map<K, V> of data contained in a node for a given
Fqn, or null if the Fqn refers to a node that does not exist.
*/
public Object perform(InvocationContext ctx)
Modified: core/trunk/src/main/java/org/jboss/cache/commands/read/GetKeyValueCommand.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/commands/read/GetKeyValueCommand.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/commands/read/GetKeyValueCommand.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -2,10 +2,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.DataContainer;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.InvocationContext;
-import org.jboss.cache.NodeSPI;
+import org.jboss.cache.*;
import org.jboss.cache.commands.Visitor;
import org.jboss.cache.notifications.Notifier;
@@ -48,25 +45,25 @@
/**
* Retrieves the value stored under a specified key in a node referenced by the
specified Fqn.
*
- * @param ctx invocation context
* @return an Object of type V, stored under a specific key in a node for a given Fqn,
or null if the Fqn refers to a node that does not exist.
*/
public Object perform(InvocationContext ctx)
{
if (trace)
{
- log.trace(new
StringBuffer("_get(").append("\"").append(fqn).append("\",
\"").append(key).append("\", \"").
+ log.trace(new
StringBuffer("get(").append("\"").append(fqn).append("\",
\"").append(key).append("\", \"").
append(sendNodeEvent).append("\")"));
}
- if (sendNodeEvent) notifier.notifyNodeVisited(fqn, true, ctx);
NodeSPI n = dataContainer.peek(fqn);
if (n == null)
{
log.trace("node not found");
return null;
}
+ if (sendNodeEvent) notifier.notifyNodeVisited(fqn, true, ctx);
+ Object result = n.getDirect(key);
if (sendNodeEvent) notifier.notifyNodeVisited(fqn, false, ctx);
- return n.getDirect(key);
+ return result;
}
Modified: core/trunk/src/main/java/org/jboss/cache/commands/read/GetKeysCommand.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/commands/read/GetKeysCommand.java 2008-05-14
17:05:33 UTC (rev 5849)
+++ core/trunk/src/main/java/org/jboss/cache/commands/read/GetKeysCommand.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -41,8 +41,7 @@
{
NodeSPI n = dataContainer.peek(fqn);
if (n == null) return null;
- Set keys = n.getKeysDirect();
- return new HashSet(keys);
+ return n.getKeysDirect();
}
public Object acceptVisitor(InvocationContext ctx, Visitor visitor) throws Throwable
Modified:
core/trunk/src/main/java/org/jboss/cache/commands/read/GravitateDataCommand.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/commands/read/GravitateDataCommand.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/commands/read/GravitateDataCommand.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -2,18 +2,13 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.CacheSPI;
-import org.jboss.cache.DataContainer;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.InvocationContext;
-import org.jboss.cache.Node;
-import org.jboss.cache.NodeSPI;
-import org.jboss.cache.RPCManager;
+import org.jboss.cache.*;
import org.jboss.cache.buddyreplication.BuddyFqnTransformer;
import org.jboss.cache.buddyreplication.BuddyManager;
import org.jboss.cache.buddyreplication.GravitateResult;
import org.jboss.cache.commands.Visitor;
import org.jboss.cache.marshall.NodeData;
+import org.jgroups.Address;
import java.util.LinkedList;
import java.util.List;
@@ -34,29 +29,30 @@
public static final int METHOD_ID = 35;
/* dependencies */
- private RPCManager rpcManager;
private CacheSPI spi;
/* parametres */
private boolean searchSubtrees;
+ private Address localAddress;
private static final Log log = LogFactory.getLog(GravitateDataCommand.class);
private static boolean trace = log.isTraceEnabled();
- public GravitateDataCommand(Fqn fqn, boolean searchSubtrees)
+ public GravitateDataCommand(Fqn fqn, boolean searchSubtrees, Address localAddress)
{
this.fqn = fqn;
this.searchSubtrees = searchSubtrees;
+ this.localAddress = localAddress;
}
- public GravitateDataCommand()
+ public GravitateDataCommand(Address localAddress)
{
+ this.localAddress = localAddress;
}
- public void initialize(DataContainer dataContainer, RPCManager manager, CacheSPI spi)
+ public void initialize(DataContainer dataContainer, CacheSPI spi)
{
this.dataContainer = dataContainer;
- this.rpcManager = manager;
this.spi = spi;
}
@@ -77,6 +73,7 @@
ctx.setOriginLocal(false);
// use a get() call into the cache to make sure cache loading takes place.
// no need to cache the original skipDataGravitation setting here - it will
always be false of we got here!!
+ //todo 2.2 use dataContainer for peek and load the data in the CLInterceptor
rather than using the SPI for than!!!
ctx.getOptionOverrides().setSkipDataGravitation(true);
Node actualNode = spi.getNode(fqn);
ctx.getOptionOverrides().setSkipDataGravitation(false);
@@ -91,14 +88,14 @@
if (backupSubtree != null)
{
// need to loop through backupSubtree's children
- Set childNames = backupSubtree.getChildrenNamesDirect();
- if (childNames != null)
+ Set allGroupNames = backupSubtree.getChildrenNamesDirect();
+ if (allGroupNames != null)
{
- for (Object childName : childNames)
+ for (Object groupName : allGroupNames)
{
- // childName is the name of a buddy group since all child names in
this
+ // groupName is the name of a buddy group since all child names in
this
// collection are direct children of BUDDY_BACKUP_SUBTREE_FQN
- Fqn backupRoot =
Fqn.fromRelativeElements(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN, childName);
+ Fqn backupRoot =
Fqn.fromRelativeElements(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN, groupName);
if (BuddyFqnTransformer.isDeadBackupRoot(backupRoot))
{
Set<Integer> deadChildNames = new
TreeSet<Integer>(spi.getChildrenNames(backupRoot));
@@ -150,7 +147,7 @@
if (backupNodeFqn == null && searchSubtrees)
{
- backupNodeFqn =
BuddyFqnTransformer.getBackupFqn(BuddyFqnTransformer.getGroupNameFromAddress(rpcManager.getLocalAddress()),
fqn);
+ backupNodeFqn =
BuddyFqnTransformer.getBackupFqn(BuddyFqnTransformer.getGroupNameFromAddress(localAddress),
fqn);
}
List<NodeData> list = dataContainer.buildNodeData(new
LinkedList<NodeData>(), (NodeSPI) actualNode);
@@ -226,4 +223,9 @@
", searchSubtrees=" + searchSubtrees +
'}';
}
+
+ void setSearchSubtrees(boolean searchSubtrees)
+ {
+ this.searchSubtrees = searchSubtrees;
+ }
}
Modified:
core/trunk/src/main/java/org/jboss/cache/commands/remote/ClusteredGetCommand.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/commands/remote/ClusteredGetCommand.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/commands/remote/ClusteredGetCommand.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -2,7 +2,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.DataContainer;
+import org.jboss.cache.DataContainerImpl;
import org.jboss.cache.InvocationContext;
import org.jboss.cache.commands.DataCommand;
import org.jboss.cache.commands.ReplicableCommand;
@@ -30,7 +30,7 @@
private DataCommand dataCommand;
private boolean searchBackupSubtrees;
- private DataContainer dataContainer;
+ private DataContainerImpl dataContainer;
private InterceptorChain interceptorChain;
private static final Log log = LogFactory.getLog(ClusteredGetCommand.class);
@@ -46,7 +46,7 @@
{
}
- public void initialize(DataContainer dataContainer, InterceptorChain
interceptorChain)
+ public void initialize(DataContainerImpl dataContainer, InterceptorChain
interceptorChain)
{
this.dataContainer = dataContainer;
this.interceptorChain = interceptorChain;
Modified:
core/trunk/src/main/java/org/jboss/cache/commands/remote/DataGravitationCleanupCommand.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/commands/remote/DataGravitationCleanupCommand.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/commands/remote/DataGravitationCleanupCommand.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -2,7 +2,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.DataContainer;
+import org.jboss.cache.DataContainerImpl;
import org.jboss.cache.Fqn;
import org.jboss.cache.InvocationContext;
import org.jboss.cache.NodeSPI;
@@ -38,7 +38,7 @@
private TransactionTable transactionTable;
private InterceptorChain invoker;
private CommandsFactory commandsFactory;
- private DataContainer dataContainer;
+ private DataContainerImpl dataContainer;
/* parameters */
private GlobalTransaction globalTransaction;
@@ -57,7 +57,7 @@
}
public void initialize(BuddyManager buddyManager, InterceptorChain invoker,
TransactionTable transactionTable,
- CommandsFactory commandsFactory, DataContainer dataContainer)
+ CommandsFactory commandsFactory, DataContainerImpl
dataContainer)
{
this.buddyManager = buddyManager;
this.invoker = invoker;
Modified:
core/trunk/src/main/java/org/jboss/cache/commands/write/AbstractVersionedDataCommand.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/commands/write/AbstractVersionedDataCommand.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/commands/write/AbstractVersionedDataCommand.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -1,7 +1,7 @@
package org.jboss.cache.commands.write;
import org.jboss.cache.Fqn;
-import org.jboss.cache.DataContainer;
+import org.jboss.cache.DataContainerImpl;
import org.jboss.cache.commands.VersionedDataCommand;
import org.jboss.cache.commands.read.AbstractDataCommand;
import org.jboss.cache.notifications.Notifier;
@@ -21,7 +21,7 @@
protected DataVersion dataVersion;
protected GlobalTransaction globalTransaction;
- public void initialize(Notifier notifier, DataContainer dataContainer)
+ public void initialize(Notifier notifier, DataContainerImpl dataContainer)
{
this.notifier = notifier;
this.dataContainer = dataContainer;
Modified: core/trunk/src/main/java/org/jboss/cache/commands/write/MoveCommand.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/commands/write/MoveCommand.java 2008-05-14
17:05:33 UTC (rev 5849)
+++ core/trunk/src/main/java/org/jboss/cache/commands/write/MoveCommand.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -2,7 +2,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.DataContainer;
+import org.jboss.cache.DataContainerImpl;
import org.jboss.cache.Fqn;
import org.jboss.cache.InvocationContext;
import org.jboss.cache.NodeNotExistsException;
@@ -37,7 +37,7 @@
{
}
- public void initialize(Notifier notifier, DataContainer dataContainer)
+ public void initialize(Notifier notifier, DataContainerImpl dataContainer)
{
this.notifier = notifier;
this.dataContainer = dataContainer;
Modified: core/trunk/src/main/java/org/jboss/cache/factories/CommandsFactory.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/factories/CommandsFactory.java 2008-05-14
17:05:33 UTC (rev 5849)
+++ core/trunk/src/main/java/org/jboss/cache/factories/CommandsFactory.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -2,7 +2,7 @@
import org.jboss.cache.CacheException;
import org.jboss.cache.CacheSPI;
-import org.jboss.cache.DataContainer;
+import org.jboss.cache.DataContainerImpl;
import org.jboss.cache.Fqn;
import org.jboss.cache.RPCManager;
import org.jboss.cache.buddyreplication.BuddyGroup;
@@ -40,7 +40,7 @@
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.factories.annotations.NonVolatile;
import org.jboss.cache.interceptors.InterceptorChain;
-import org.jboss.cache.notifications.Notifier;
+import org.jboss.cache.notifications.NotifierImpl;
import org.jboss.cache.transaction.GlobalTransaction;
import org.jboss.cache.transaction.TransactionTable;
import org.jgroups.Address;
@@ -66,8 +66,8 @@
public class CommandsFactory
{
private RPCManager rpcManager;
- private DataContainer dataContainer;
- private Notifier notifier;
+ private DataContainerImpl dataContainer;
+ private NotifierImpl notifier;
private InterceptorChain invoker;
private BuddyManager buddyManager;
private TransactionTable transactionTable;
@@ -80,7 +80,7 @@
}
@Inject
- public void initialize(RPCManager rpc, DataContainer dataContainer, Notifier notifier,
BuddyManager buddyManager,
+ public void initialize(RPCManager rpc, DataContainerImpl dataContainer, NotifierImpl
notifier, BuddyManager buddyManager,
InterceptorChain invoker, TransactionTable transactionTable,
CacheSPI cacheSpi,
Configuration configuration, TransactionManager txManager)
{
@@ -147,8 +147,8 @@
public GravitateDataCommand buildGravitateDataCommand(Fqn fqn, Boolean
searchSubtrees)
{
- GravitateDataCommand command = new GravitateDataCommand(fqn, searchSubtrees);
- command.initialize(dataContainer, rpcManager, cacheSpi);
+ GravitateDataCommand command = new GravitateDataCommand(fqn, searchSubtrees,
rpcManager.getLocalAddress());
+ command.initialize(dataContainer, cacheSpi);
return command;
}
@@ -239,8 +239,8 @@
public GravitateDataCommand buildGravitateDataCacheCommand(Fqn fqn, boolean
searchSubtrees)
{
- GravitateDataCommand command = new GravitateDataCommand(fqn, searchSubtrees);
- command.initialize(dataContainer, rpcManager, cacheSpi);
+ GravitateDataCommand command = new GravitateDataCommand(fqn, searchSubtrees,
rpcManager.getLocalAddress());
+ command.initialize(dataContainer, cacheSpi);
return command;
}
@@ -485,8 +485,8 @@
}
case GravitateDataCommand.METHOD_ID:
{
- GravitateDataCommand returnValue = new GravitateDataCommand();
- returnValue.initialize(dataContainer, rpcManager, cacheSpi);
+ GravitateDataCommand returnValue = new
GravitateDataCommand(rpcManager.getLocalAddress());
+ returnValue.initialize(dataContainer, cacheSpi);
command = returnValue;
break;
}
Modified: core/trunk/src/main/java/org/jboss/cache/factories/EmptyConstructorFactory.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/factories/EmptyConstructorFactory.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/factories/EmptyConstructorFactory.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -1,6 +1,6 @@
package org.jboss.cache.factories;
-import org.jboss.cache.DataContainer;
+import org.jboss.cache.DataContainerImpl;
import org.jboss.cache.RegionManager;
import org.jboss.cache.config.ConfigurationException;
import org.jboss.cache.factories.annotations.DefaultFactoryFor;
@@ -11,7 +11,7 @@
import org.jboss.cache.lock.LockStrategyFactory;
import org.jboss.cache.marshall.Marshaller;
import org.jboss.cache.marshall.VersionAwareMarshaller;
-import org.jboss.cache.notifications.Notifier;
+import org.jboss.cache.notifications.NotifierImpl;
import org.jboss.cache.remoting.jgroups.ChannelMessageListener;
import org.jboss.cache.statetransfer.StateTransferManager;
import org.jboss.cache.transaction.TransactionTable;
@@ -22,10 +22,10 @@
* @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
* @since 2.1.0
*/
-@DefaultFactoryFor(classes = {StateTransferManager.class, RegionManager.class,
Notifier.class,
+@DefaultFactoryFor(classes = {StateTransferManager.class, RegionManager.class,
NotifierImpl.class,
ChannelMessageListener.class, CacheLoaderManager.class, Marshaller.class,
InvocationContextContainer.class, CacheInvocationDelegate.class,
- TransactionTable.class, DataContainer.class, CommandsFactory.class,
LockManager.class,
+ TransactionTable.class, DataContainerImpl.class, CommandsFactory.class,
LockManager.class,
LockStrategyFactory.class})
public class EmptyConstructorFactory extends ComponentFactory
{
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/CacheLoaderInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/CacheLoaderInterceptor.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/CacheLoaderInterceptor.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -1,7 +1,7 @@
package org.jboss.cache.interceptors;
import org.jboss.cache.CacheException;
-import org.jboss.cache.DataContainer;
+import org.jboss.cache.DataContainerImpl;
import org.jboss.cache.Fqn;
import org.jboss.cache.InvocationContext;
import org.jboss.cache.NodeSPI;
@@ -27,7 +27,7 @@
import org.jboss.cache.loader.CacheLoaderManager;
import org.jboss.cache.lock.LockManager;
import org.jboss.cache.lock.NodeLock;
-import org.jboss.cache.notifications.Notifier;
+import org.jboss.cache.notifications.NotifierImpl;
import org.jboss.cache.transaction.TransactionEntry;
import org.jboss.cache.transaction.TransactionTable;
@@ -53,8 +53,8 @@
protected TransactionTable txTable = null;
protected CacheLoader loader;
- protected DataContainer dataContainer;
- protected Notifier notifier;
+ protected DataContainerImpl dataContainer;
+ protected NotifierImpl notifier;
protected boolean isActivation = false;
protected boolean usingOptimisticInvalidation = false;
@@ -69,7 +69,7 @@
@Inject
protected void injectDependencies(TransactionTable txTable, CacheLoaderManager clm,
Configuration configuration,
- DataContainer dataContainer, LockManager
lockManager, Notifier notifier)
+ DataContainerImpl dataContainer, LockManager
lockManager, NotifierImpl notifier)
{
this.txTable = txTable;
this.clm = clm;
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/CacheMgmtInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/CacheMgmtInterceptor.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/CacheMgmtInterceptor.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -21,7 +21,7 @@
*/
package org.jboss.cache.interceptors;
-import org.jboss.cache.DataContainer;
+import org.jboss.cache.DataContainerImpl;
import org.jboss.cache.InvocationContext;
import org.jboss.cache.commands.read.GetKeyValueCommand;
import org.jboss.cache.commands.write.EvictCommand;
@@ -51,10 +51,10 @@
private long m_start = System.currentTimeMillis();
private long m_reset = m_start;
- private DataContainer dataContainer;
+ private DataContainerImpl dataContainer;
@Inject
- public void setDependencies(DataContainer dataContainer)
+ public void setDependencies(DataContainerImpl dataContainer)
{
this.dataContainer = dataContainer;
}
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/CacheStoreInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/CacheStoreInterceptor.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/CacheStoreInterceptor.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -1,11 +1,7 @@
package org.jboss.cache.interceptors;
import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.DataContainer;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.InvocationContext;
-import org.jboss.cache.Modification;
-import org.jboss.cache.NodeSPI;
+import org.jboss.cache.*;
import org.jboss.cache.commands.AbstractVisitor;
import org.jboss.cache.commands.ReversibleCommand;
import org.jboss.cache.commands.VisitableCommand;
@@ -13,12 +9,7 @@
import org.jboss.cache.commands.tx.OptimisticPrepareCommand;
import org.jboss.cache.commands.tx.PrepareCommand;
import org.jboss.cache.commands.tx.RollbackCommand;
-import org.jboss.cache.commands.write.MoveCommand;
-import org.jboss.cache.commands.write.PutDataMapCommand;
-import org.jboss.cache.commands.write.PutKeyValueCommand;
-import org.jboss.cache.commands.write.RemoveDataCommand;
-import org.jboss.cache.commands.write.RemoveKeyCommand;
-import org.jboss.cache.commands.write.RemoveNodeCommand;
+import org.jboss.cache.commands.write.*;
import org.jboss.cache.config.CacheLoaderConfig;
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.factories.annotations.Start;
@@ -30,12 +21,7 @@
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -53,7 +39,7 @@
private Map<GlobalTransaction, Set<Fqn>> preparingTxs = new
ConcurrentHashMap<GlobalTransaction, Set<Fqn>>();
private long cacheStores = 0;
private CacheLoader loader;
- private DataContainer dataContainer;
+ private DataContainerImpl dataContainer;
private CacheLoaderManager loaderManager;
public CacheStoreInterceptor()
@@ -63,7 +49,7 @@
}
@Inject
- protected void init(DataContainer dataContainer, CacheLoaderManager loaderManager,
TransactionManager txManager, CacheLoaderConfig clConfig)
+ protected void init(DataContainerImpl dataContainer, CacheLoaderManager loaderManager,
TransactionManager txManager, CacheLoaderConfig clConfig)
{
// never inject a CacheLoader at this stage - only a CacheLoaderManager, since the
CacheLoaderManager only creates a CacheLoader instance when it @Starts.
this.loaderManager = loaderManager;
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/DataGravitatorInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/DataGravitatorInterceptor.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/DataGravitatorInterceptor.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -6,11 +6,8 @@
*/
package org.jboss.cache.interceptors;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.CacheSPI;
-import org.jboss.cache.DataContainer;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.InvocationContext;
+import org.jboss.cache.DataContainerImpl;
+import org.jboss.cache.*;
import org.jboss.cache.buddyreplication.BuddyFqnTransformer;
import org.jboss.cache.buddyreplication.BuddyManager;
import org.jboss.cache.buddyreplication.GravitateResult;
@@ -69,12 +66,12 @@
* cleanup commands corresponding to all gravitate calls made during the course of the
transaction in question.
*/
private Map<GlobalTransaction, List<ReplicableCommand>> cleanupCommands =
new ConcurrentHashMap<GlobalTransaction, List<ReplicableCommand>>();
- private DataContainer dataContainer;
+ private DataContainerImpl dataContainer;
private CommandsFactory commandsFactory;
private CacheSPI cacheSPI;
@Inject
- public void injectComponents(BuddyManager buddyManager, DataContainer dataContainer,
CommandsFactory commandsFactory, CacheSPI cacheSPI)
+ public void injectComponents(BuddyManager buddyManager, DataContainerImpl
dataContainer, CommandsFactory commandsFactory, CacheSPI cacheSPI)
{
this.buddyManager = buddyManager;
this.dataContainer = dataContainer;
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/EvictionInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/EvictionInterceptor.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/EvictionInterceptor.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -7,12 +7,8 @@
*/
package org.jboss.cache.interceptors;
-import org.jboss.cache.DataContainer;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.InvocationContext;
-import org.jboss.cache.NodeSPI;
-import org.jboss.cache.Region;
-import org.jboss.cache.RegionManager;
+import org.jboss.cache.DataContainerImpl;
+import org.jboss.cache.*;
import org.jboss.cache.commands.read.GetDataMapCommand;
import org.jboss.cache.commands.read.GetKeyValueCommand;
import org.jboss.cache.commands.read.GetNodeCommand;
@@ -40,10 +36,10 @@
{
protected RegionManager regionManager;
- private DataContainer dataContainer;
+ private DataContainerImpl dataContainer;
@Inject
- public void initialize(DataContainer dataContainer)
+ public void initialize(DataContainerImpl dataContainer)
{
this.dataContainer = dataContainer;
}
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/NotificationInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/NotificationInterceptor.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/NotificationInterceptor.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -5,7 +5,7 @@
import org.jboss.cache.commands.tx.CommitCommand;
import org.jboss.cache.commands.tx.RollbackCommand;
import org.jboss.cache.factories.annotations.Inject;
-import org.jboss.cache.notifications.Notifier;
+import org.jboss.cache.notifications.NotifierImpl;
/**
* The interceptor in charge of firing off notifications to cache listeners
@@ -15,11 +15,11 @@
*/
public class NotificationInterceptor extends BaseTransactionalContextInterceptor
{
- private Notifier notifier;
+ private NotifierImpl notifier;
private CacheSPI cacheSPI;
@Inject
- public void injectDependencies(Notifier notifier, CacheSPI cacheSPI)
+ public void injectDependencies(NotifierImpl notifier, CacheSPI cacheSPI)
{
this.notifier = notifier;
this.cacheSPI = cacheSPI;
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticCreateIfNotExistsInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticCreateIfNotExistsInterceptor.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticCreateIfNotExistsInterceptor.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -6,13 +6,8 @@
*/
package org.jboss.cache.interceptors;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.CacheSPI;
-import org.jboss.cache.DataContainer;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.InvocationContext;
-import org.jboss.cache.NodeFactory;
-import org.jboss.cache.NodeSPI;
+import org.jboss.cache.DataContainerImpl;
+import org.jboss.cache.*;
import org.jboss.cache.commands.write.MoveCommand;
import org.jboss.cache.commands.write.PutDataMapCommand;
import org.jboss.cache.commands.write.PutKeyValueCommand;
@@ -45,14 +40,14 @@
*/
private NodeFactory nodeFactory;
- private DataContainer dataContainer;
+ private DataContainerImpl dataContainer;
private CacheSPI cache;
private long lockAcquisitionTimeout;
@Inject
- private void injectDependencies(NodeFactory nodeFactory, DataContainer dataContainer,
CacheSPI cacheSPI)
+ private void injectDependencies(NodeFactory nodeFactory, DataContainerImpl
dataContainer, CacheSPI cacheSPI)
{
this.nodeFactory = nodeFactory;
this.dataContainer = dataContainer;
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -7,13 +7,8 @@
package org.jboss.cache.interceptors;
import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.DataContainer;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.InvocationContext;
-import org.jboss.cache.NodeFactory;
-import org.jboss.cache.NodeNotExistsException;
-import org.jboss.cache.NodeSPI;
+import org.jboss.cache.DataContainerImpl;
+import org.jboss.cache.*;
import org.jboss.cache.commands.ReversibleCommand;
import org.jboss.cache.commands.read.GetChildrenNamesCommand;
import org.jboss.cache.commands.read.GetDataMapCommand;
@@ -29,7 +24,7 @@
import org.jboss.cache.config.Option;
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.factories.annotations.Start;
-import org.jboss.cache.notifications.Notifier;
+import org.jboss.cache.notifications.NotifierImpl;
import static org.jboss.cache.notifications.event.NodeModifiedEvent.ModificationType.*;
import org.jboss.cache.optimistic.DataVersion;
import org.jboss.cache.optimistic.DefaultDataVersion;
@@ -55,12 +50,12 @@
* Needed for the creation of workspace nodes based on underlying nodes in the cache.
*/
private NodeFactory nodeFactory;
- private Notifier notifier;
- private DataContainer dataContainer;
+ private NotifierImpl notifier;
+ private DataContainerImpl dataContainer;
private long lockAcquisitionTimeout;
@Inject
- protected void injectDependencies(Notifier notifier, NodeFactory nodeFactory,
DataContainer dataContainer)
+ protected void injectDependencies(NotifierImpl notifier, NodeFactory nodeFactory,
DataContainerImpl dataContainer)
{
this.notifier = notifier;
this.nodeFactory = nodeFactory;
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticValidatorInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticValidatorInterceptor.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticValidatorInterceptor.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -6,11 +6,8 @@
*/
package org.jboss.cache.interceptors;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.DataContainer;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.InvocationContext;
-import org.jboss.cache.NodeSPI;
+import org.jboss.cache.DataContainerImpl;
+import org.jboss.cache.*;
import org.jboss.cache.commands.tx.CommitCommand;
import org.jboss.cache.commands.tx.OptimisticPrepareCommand;
import org.jboss.cache.commands.tx.RollbackCommand;
@@ -50,10 +47,10 @@
{
private boolean useTombstones;
- private DataContainer dataContainer;
+ private DataContainerImpl dataContainer;
@Inject
- public void initialize(DataContainer dataContainer)
+ public void initialize(DataContainerImpl dataContainer)
{
this.dataContainer = dataContainer;
}
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/PassivationInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/PassivationInterceptor.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/PassivationInterceptor.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -1,6 +1,6 @@
package org.jboss.cache.interceptors;
-import org.jboss.cache.DataContainer;
+import org.jboss.cache.DataContainerImpl;
import org.jboss.cache.Fqn;
import org.jboss.cache.InvocationContext;
import org.jboss.cache.NodeSPI;
@@ -9,7 +9,7 @@
import org.jboss.cache.interceptors.base.CommandInterceptor;
import org.jboss.cache.loader.CacheLoader;
import org.jboss.cache.loader.CacheLoaderManager;
-import org.jboss.cache.notifications.Notifier;
+import org.jboss.cache.notifications.NotifierImpl;
import java.util.Collections;
import java.util.HashMap;
@@ -30,11 +30,11 @@
private final AtomicLong passivations = new AtomicLong(0);
protected CacheLoader loader;
- private Notifier notifier;
- private DataContainer dataContainer;
+ private NotifierImpl notifier;
+ private DataContainerImpl dataContainer;
@Inject
- public void setDependencies(Notifier notifier, DataContainer dataContainer,
CacheLoaderManager loaderManager)
+ public void setDependencies(NotifierImpl notifier, DataContainerImpl dataContainer,
CacheLoaderManager loaderManager)
{
this.notifier = notifier;
this.dataContainer = dataContainer;
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -6,7 +6,7 @@
*/
package org.jboss.cache.interceptors;
-import org.jboss.cache.DataContainer;
+import org.jboss.cache.DataContainerImpl;
import org.jboss.cache.Fqn;
import org.jboss.cache.InvocationContext;
import org.jboss.cache.NodeSPI;
@@ -59,12 +59,12 @@
public class PessimisticLockInterceptor extends PostProcessingCommandInterceptor
{
private TransactionTable txTable;
- private DataContainer dataContainer;
+ private DataContainerImpl dataContainer;
private LockManager lockManager;
private long lockAcquisitionTimeout;
@Inject
- public void injectDependencies(DataContainer dataContainer, TransactionTable txTable,
LockManager lockManager)
+ public void injectDependencies(DataContainerImpl dataContainer, TransactionTable
txTable, LockManager lockManager)
{
this.dataContainer = dataContainer;
this.txTable = txTable;
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java 2008-05-14
17:05:33 UTC (rev 5849)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -30,7 +30,7 @@
import org.jboss.cache.factories.ComponentRegistry;
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.invocation.InvocationContextContainer;
-import org.jboss.cache.notifications.Notifier;
+import org.jboss.cache.notifications.NotifierImpl;
import org.jboss.cache.transaction.GlobalTransaction;
import org.jboss.cache.transaction.TransactionEntry;
import org.jboss.cache.transaction.TransactionTable;
@@ -62,7 +62,7 @@
{
protected CommandsFactory commandsFactory;
protected RPCManager rpcManager;
- private Notifier notifier;
+ private NotifierImpl notifier;
private InvocationContextContainer invocationContextContainer;
private ComponentRegistry componentRegistry;
@@ -78,7 +78,7 @@
@Inject
public void intialize(RPCManager rpcManager,
- Notifier notifier, InvocationContextContainer icc,
+ NotifierImpl notifier, InvocationContextContainer icc,
CommandsFactory factory, ComponentRegistry componentRegistry)
{
this.commandsFactory = factory;
Modified:
core/trunk/src/main/java/org/jboss/cache/invocation/CacheInvocationDelegate.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/invocation/CacheInvocationDelegate.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/main/java/org/jboss/cache/invocation/CacheInvocationDelegate.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -23,7 +23,7 @@
import org.jboss.cache.interceptors.base.CommandInterceptor;
import org.jboss.cache.loader.CacheLoaderManager;
import org.jboss.cache.marshall.Marshaller;
-import org.jboss.cache.notifications.Notifier;
+import org.jboss.cache.notifications.NotifierImpl;
import org.jboss.cache.statetransfer.StateTransferManager;
import org.jboss.cache.transaction.GlobalTransaction;
import org.jboss.cache.transaction.TransactionTable;
@@ -51,21 +51,21 @@
// this stuff is needed since the SPI has methods to retrieve these.
private StateTransferManager stateTransferManager;
private CacheLoaderManager cacheLoaderManager;
- private Notifier notifier;
+ private NotifierImpl notifier;
private TransactionManager transactionManager;
private BuddyManager buddyManager;
private TransactionTable transactionTable;
private RPCManager rpcManager;
private RegionManager regionManager;
private Marshaller marshaller;
- private DataContainer dataContainer;
+ private DataContainerImpl dataContainer;
private CommandsFactory commandsFactory;
@Inject
- public void initialize(StateTransferManager stateTransferManager, CacheLoaderManager
cacheLoaderManager, Notifier notifier,
+ public void initialize(StateTransferManager stateTransferManager, CacheLoaderManager
cacheLoaderManager, NotifierImpl notifier,
TransactionManager transactionManager, BuddyManager
buddyManager, TransactionTable transactionTable,
RPCManager rpcManager, RegionManager regionManager, Marshaller
marshaller,
- CommandsFactory commandsFactory, DataContainer dataContainer)
+ CommandsFactory commandsFactory, DataContainerImpl
dataContainer)
{
this.stateTransferManager = stateTransferManager;
this.cacheLoaderManager = cacheLoaderManager;
@@ -214,7 +214,7 @@
return peek(fqn, false, false) != null;
}
- public Notifier getNotifier()
+ public NotifierImpl getNotifier()
{
return notifier;
}
@@ -574,7 +574,7 @@
return getChildrenNames(Fqn.fromString(fqn));
}
- public DataContainer getDataContainer()
+ public DataContainerImpl getDataContainer()
{
return dataContainer;
}
Modified: core/trunk/src/main/java/org/jboss/cache/lock/LockManager.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/lock/LockManager.java 2008-05-14 17:05:33 UTC
(rev 5849)
+++ core/trunk/src/main/java/org/jboss/cache/lock/LockManager.java 2008-05-15 12:44:49 UTC
(rev 5850)
@@ -2,7 +2,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.DataContainer;
+import org.jboss.cache.DataContainerImpl;
import org.jboss.cache.Fqn;
import org.jboss.cache.InvocationContext;
import org.jboss.cache.NodeSPI;
@@ -31,13 +31,13 @@
private Configuration configuration;
private long lockAcquisitionTimeout;
- private DataContainer dataContainer;
+ private DataContainerImpl dataContainer;
private NodeSPI rootNode;
private TransactionTable txTable;
private CommandsFactory commandsFactory;
@Inject
- public void inject(Configuration configuration, DataContainer dataContainer,
TransactionTable txTable,
+ public void inject(Configuration configuration, DataContainerImpl dataContainer,
TransactionTable txTable,
CommandsFactory commandsFactory)
{
this.configuration = configuration;
Deleted: core/trunk/src/main/java/org/jboss/cache/notifications/Notifier.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/notifications/Notifier.java 2008-05-14
17:05:33 UTC (rev 5849)
+++ core/trunk/src/main/java/org/jboss/cache/notifications/Notifier.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -1,733 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at
gnu.org.
- */
-package org.jboss.cache.notifications;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.Cache;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.CacheSPI;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.InvocationContext;
-import org.jboss.cache.buddyreplication.BuddyGroup;
-import org.jboss.cache.config.Configuration;
-import org.jboss.cache.factories.annotations.Destroy;
-import org.jboss.cache.factories.annotations.Inject;
-import org.jboss.cache.factories.annotations.NonVolatile;
-import org.jboss.cache.factories.annotations.Start;
-import org.jboss.cache.factories.annotations.Stop;
-import org.jboss.cache.marshall.MarshalledValueMap;
-import org.jboss.cache.notifications.annotation.*;
-import org.jboss.cache.notifications.event.*;
-import static org.jboss.cache.notifications.event.Event.Type.*;
-import org.jboss.cache.util.MapCopy;
-import org.jgroups.View;
-
-import javax.transaction.Transaction;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * Helper class that handles all notifications to registered listeners.
- *
- * @author <a href="mailto:manik@jboss.org">Manik Surtani
(manik(a)jboss.org)</a>
- */
-@NonVolatile
-public class Notifier
-{
- private static final Log log = LogFactory.getLog(Notifier.class);
-
- private static final Class emptyMap = Collections.emptyMap().getClass();
-
- private static final Class singletonMap = Collections.singletonMap(null,
null).getClass();
- private static final Class[] allowedMethodAnnotations =
- {
- CacheStarted.class, CacheStopped.class, CacheBlocked.class,
CacheUnblocked.class, NodeCreated.class, NodeRemoved.class, NodeVisited.class,
NodeModified.class, NodeMoved.class,
- NodeActivated.class, NodePassivated.class, NodeLoaded.class,
NodeEvicted.class, TransactionRegistered.class, TransactionCompleted.class,
ViewChanged.class, BuddyGroupChanged.class
- };
- private static final Class[] parameterTypes =
- {
- CacheStartedEvent.class, CacheStoppedEvent.class, CacheBlockedEvent.class,
CacheUnblockedEvent.class, NodeCreatedEvent.class, NodeRemovedEvent.class,
NodeVisitedEvent.class, NodeModifiedEvent.class, NodeMovedEvent.class,
- NodeActivatedEvent.class, NodePassivatedEvent.class,
NodeLoadedEvent.class, NodeEvictedEvent.class, TransactionRegisteredEvent.class,
TransactionCompletedEvent.class, ViewChangedEvent.class, BuddyGroupChangedEvent.class
- };
-
-
- final Map<Class, List<ListenerInvocation>> listenerInvocations = new
ConcurrentHashMap<Class, List<ListenerInvocation>>();
- private Cache cache;
- private boolean useMarshalledValueMaps;
- private Configuration config;
-
- public Notifier()
- {
- }
-
- public Notifier(Cache cache)
- {
- this.cache = cache;
- }
-
- @Inject
- private void injectDependencies(CacheSPI cache, Configuration config)
- {
- this.cache = cache;
- this.config = config;
- }
-
- @Destroy
- protected void destroy()
- {
- listenerInvocations.clear();
- }
-
- @Start
- protected void start()
- {
- useMarshalledValueMaps = config.isUseLazyDeserialization();
- }
-
- /**
- * Loops through all valid methods on the object passed in, and caches the relevant
methods as {@link org.jboss.cache.notifications.Notifier.ListenerInvocation}
- * for invocation by reflection.
- *
- * @param listener object to be considered as a listener.
- */
- private void validateAndAddListenerInvocation(Object listener)
- {
- testListenerClassValidity(listener.getClass());
-
- boolean foundMethods = false;
- // now try all methods on the listener for anything that we like. Note that only
PUBLIC methods are scanned.
- for (Method m : listener.getClass().getMethods())
- {
- // loop through all valid method annotations
- for (int i = 0; i < allowedMethodAnnotations.length; i++)
- {
- if (m.isAnnotationPresent(allowedMethodAnnotations[i]))
- {
- testListenerMethodValidity(m, parameterTypes[i],
allowedMethodAnnotations[i].getName());
- addListenerInvocation(allowedMethodAnnotations[i], new
ListenerInvocation(listener, m));
- foundMethods = true;
- }
- }
- }
-
- if (!foundMethods && log.isWarnEnabled())
- log.warn("Attempted to register listener of class " +
listener.getClass() + ", but no valid, public methods annotated with method-level
event annotations found! Ignoring listener.");
- }
-
- private static void testListenerClassValidity(Class<?> listenerClass)
- {
- if (!listenerClass.isAnnotationPresent(CacheListener.class))
- throw new IncorrectCacheListenerException("Cache listener class MUST be
annotated with org.jboss.cache.notifications.annotation.CacheListener");
- if (!Modifier.isPublic(listenerClass.getModifiers()))
- throw new IncorrectCacheListenerException("Cache listener class MUST be
public!");
- }
-
- private static void testListenerMethodValidity(Method m, Class allowedParameter,
String annotationName)
- {
- if (m.getParameterTypes().length != 1 ||
!m.getParameterTypes()[0].isAssignableFrom(allowedParameter))
- throw new IncorrectCacheListenerException("Methods annotated with " +
annotationName + " must accept exactly one parameter, of assignable from type "
+ allowedParameter.getName());
- if (!m.getReturnType().equals(void.class))
- throw new IncorrectCacheListenerException("Methods annotated with " +
annotationName + " should have a return type of void.");
- }
-
- private void addListenerInvocation(Class annotation, ListenerInvocation li)
- {
- synchronized (listenerInvocations)
- {
- List<ListenerInvocation> l = listenerInvocations.get(annotation);
- if (l == null)
- {
- l = new CopyOnWriteArrayList<ListenerInvocation>();
- listenerInvocations.put(annotation, l);
- }
- l.add(li);
- }
- }
-
- /**
- * Adds a cache listener to the list of cache listeners registered.
- *
- * @param listener
- */
- public void addCacheListener(Object listener)
- {
- validateAndAddListenerInvocation(listener);
- }
-
- /**
- * Removes a cache listener from the list of cache listeners registered.
- *
- * @param listener
- */
- public void removeCacheListener(Object listener)
- {
- synchronized (listenerInvocations)
- {
- for (Class annotation : allowedMethodAnnotations)
removeListenerInvocation(annotation, listener);
- }
- }
-
- private void removeListenerInvocation(Class annotation, Object listener)
- {
- if (listener == null) return;
-
- List<ListenerInvocation> l = listenerInvocations.get(annotation);
- Set<Object> markedForRemoval = new HashSet<Object>();
- if (l != null)
- {
- for (ListenerInvocation li : l)
- {
- if (listener.equals(li.target)) markedForRemoval.add(li);
- }
-
- l.removeAll(markedForRemoval);
-
- if (l.isEmpty()) listenerInvocations.remove(annotation);
- }
- }
-
- /**
- * Removes all listeners from the notifier, including the evictionPolicyListener.
- */
- @Stop(priority = 99)
- public void removeAllCacheListeners()
- {
- synchronized (listenerInvocations)
- {
- listenerInvocations.clear();
- }
- }
-
- /**
- * @return Retrieves an (unmodifiable) set of cache listeners registered.
- */
- public Set<Object> getCacheListeners()
- {
- Set<Object> s = new HashSet<Object>();
- synchronized (listenerInvocations)
- {
- for (Class annotation : allowedMethodAnnotations)
- {
- List<ListenerInvocation> l = listenerInvocations.get(annotation);
- if (l != null)
- {
- for (ListenerInvocation li : l) s.add(li.target);
- }
- }
- }
- return Collections.unmodifiableSet(s);
- }
-
- /**
- * Notifies all registered listeners of a nodeCreated event.
- *
- * @param fqn
- * @param pre
- * @param ctx context of invocation
- */
- public void notifyNodeCreated(Fqn fqn, boolean pre, InvocationContext ctx)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(NodeCreated.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- boolean originLocal = ctx.isOriginLocal();
- Transaction tx = ctx.getTransaction();
- InvocationContext backup = resetInvocationContext(ctx);
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setOriginLocal(originLocal);
- e.setPre(pre);
- e.setFqn(fqn);
- e.setTransaction(tx);
- e.setType(NODE_CREATED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- restoreInvocationContext(backup);
- }
- }
-
- /**
- * Notifies all registered listeners of a nodeModified event.
- *
- * @param fqn
- * @param pre
- * @param modificationType
- * @param data
- * @param ctx context of invocation
- */
- public void notifyNodeModified(Fqn fqn, boolean pre,
NodeModifiedEvent.ModificationType modificationType, Map data, InvocationContext ctx)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(NodeModified.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- boolean originLocal = ctx.isOriginLocal();
- Map dataCopy = copy(data, useMarshalledValueMaps);
- Transaction tx = ctx.getTransaction();
- InvocationContext backup = resetInvocationContext(ctx);
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setOriginLocal(originLocal);
- e.setPre(pre);
- e.setFqn(fqn);
- e.setTransaction(tx);
- e.setModificationType(modificationType);
- e.setData(dataCopy);
- e.setType(NODE_MODIFIED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- restoreInvocationContext(backup);
- }
- }
-
- /**
- * Notifies all registered listeners of a nodeRemoved event.
- *
- * @param fqn
- * @param pre
- * @param data
- * @param ctx context of invocation
- */
- public void notifyNodeRemoved(Fqn fqn, boolean pre, Map data, InvocationContext ctx)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(NodeRemoved.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- boolean originLocal = ctx.isOriginLocal();
- Map dataCopy = copy(data, useMarshalledValueMaps);
- Transaction tx = ctx.getTransaction();
- InvocationContext backup = resetInvocationContext(ctx);
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setOriginLocal(originLocal);
- e.setPre(pre);
- e.setFqn(fqn);
- e.setTransaction(tx);
- e.setData(dataCopy);
- e.setType(NODE_REMOVED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- restoreInvocationContext(backup);
- }
- }
-
- /**
- * Notifies all registered listeners of a nodeVisited event.
- *
- * @param fqn
- * @param pre
- * @param ctx context of invocation
- */
- public void notifyNodeVisited(Fqn fqn, boolean pre, InvocationContext ctx)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(NodeVisited.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- Transaction tx = ctx.getTransaction();
- InvocationContext backup = resetInvocationContext(ctx);
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setPre(pre);
- e.setFqn(fqn);
- e.setTransaction(tx);
- e.setType(NODE_VISITED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- restoreInvocationContext(backup);
- }
- }
-
- public void notifyNodeMoved(Fqn originalFqn, Fqn newFqn, boolean pre,
InvocationContext ctx)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(NodeMoved.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- boolean originLocal = ctx.isOriginLocal();
- Transaction tx = ctx.getTransaction();
- InvocationContext backup = resetInvocationContext(ctx);
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setOriginLocal(originLocal);
- e.setPre(pre);
- e.setFqn(originalFqn);
- e.setTargetFqn(newFqn);
- e.setTransaction(tx);
- e.setType(NODE_MOVED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- restoreInvocationContext(backup);
- }
- }
-
-
- /**
- * Notifies all registered listeners of a nodeEvicted event.
- *
- * @param fqn
- * @param pre
- * @param ctx context of invocation
- */
- public void notifyNodeEvicted(final Fqn fqn, final boolean pre, InvocationContext
ctx)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(NodeEvicted.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- final boolean originLocal = ctx.isOriginLocal();
- Transaction tx = ctx.getTransaction();
- InvocationContext backup = resetInvocationContext(ctx);
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setOriginLocal(originLocal);
- e.setPre(pre);
- e.setFqn(fqn);
- e.setTransaction(tx);
- e.setType(NODE_EVICTED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- restoreInvocationContext(backup);
- }
- }
-
- /**
- * Notifies all registered listeners of a nodeLoaded event.
- *
- * @param fqn
- * @param pre
- * @param data
- * @param ctx context of invocation
- */
- public void notifyNodeLoaded(Fqn fqn, boolean pre, Map data, InvocationContext ctx)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(NodeLoaded.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- boolean originLocal = ctx.isOriginLocal();
- Map dataCopy = copy(data, useMarshalledValueMaps);
- Transaction tx = ctx.getTransaction();
- InvocationContext backup = resetInvocationContext(ctx);
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setOriginLocal(originLocal);
- e.setPre(pre);
- e.setFqn(fqn);
- e.setTransaction(tx);
- e.setData(dataCopy);
- e.setType(NODE_LOADED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- restoreInvocationContext(backup);
- }
- }
-
- /**
- * Notifies all registered listeners of a nodeActivated event.
- *
- * @param fqn
- * @param pre
- * @param data
- * @param ctx context of invocation
- */
- public void notifyNodeActivated(Fqn fqn, boolean pre, Map data, InvocationContext
ctx)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(NodeActivated.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- boolean originLocal = ctx.isOriginLocal();
- Map dataCopy = copy(data, useMarshalledValueMaps);
- Transaction tx = ctx.getTransaction();
- InvocationContext backup = resetInvocationContext(ctx);
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setOriginLocal(originLocal);
- e.setPre(pre);
- e.setFqn(fqn);
- e.setTransaction(tx);
- e.setData(dataCopy);
- e.setType(NODE_ACTIVATED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- restoreInvocationContext(backup);
- }
- }
-
- /**
- * Notifies all registered listeners of a nodePassivated event.
- *
- * @param fqn
- * @param pre
- * @param data
- * @param ctx context of invocation
- */
- public void notifyNodePassivated(Fqn fqn, boolean pre, Map data, InvocationContext
ctx)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(NodePassivated.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- Map dataCopy = copy(data, useMarshalledValueMaps);
- Transaction tx = ctx.getTransaction();
- InvocationContext backup = resetInvocationContext(ctx);
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setPre(pre);
- e.setFqn(fqn);
- e.setTransaction(tx);
- e.setData(dataCopy);
- e.setType(NODE_PASSIVATED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- restoreInvocationContext(backup);
- }
- }
-
- /**
- * Notifies all registered listeners of a cacheStarted event.
- */
- @Start(priority = 99)
- public void notifyCacheStarted()
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(CacheStarted.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setType(CACHE_STARTED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- }
- }
-
- /**
- * Notifies all registered listeners of a cacheStopped event.
- */
- @Stop(priority = 98)
- public void notifyCacheStopped()
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(CacheStopped.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setType(CACHE_STOPPED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- }
- }
-
- /**
- * Notifies all registered listeners of a viewChange event. Note that viewChange
notifications are ALWAYS sent
- * immediately.
- *
- * @param new_view
- * @param ctx context of invocation
- */
- public void notifyViewChange(final View new_view, InvocationContext ctx)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(ViewChanged.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- InvocationContext backup = resetInvocationContext(ctx);
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setNewView(new_view);
- e.setType(VIEW_CHANGED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- restoreInvocationContext(backup);
- }
- }
-
- /**
- * Notifies all registered listeners of a buddy group change event. Note that buddy
group change notifications are ALWAYS sent
- * immediately.
- *
- * @param buddyGroup buddy group to set
- * @param pre if true, this has occured before the buddy group message is
broadcast to the cluster
- */
- public void notifyBuddyGroupChange(final BuddyGroup buddyGroup, boolean pre)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(BuddyGroupChanged.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setBuddyGroup(buddyGroup);
- e.setPre(pre);
- e.setType(BUDDY_GROUP_CHANGED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- }
- }
-
- /**
- * Notifies all registered listeners of a transaction completion event.
- *
- * @param transaction the transaction that has just completed
- * @param successful if true, the transaction committed. If false, this is a
rollback event
- */
- public void notifyTransactionCompleted(Transaction transaction, boolean successful,
InvocationContext ctx)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(TransactionCompleted.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- Transaction tx = ctx.getTransaction();
- boolean isOriginLocal = ctx.isOriginLocal();
- InvocationContext backup = resetInvocationContext(ctx);
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setOriginLocal(isOriginLocal);
- e.setTransaction(tx);
- e.setSuccessful(successful);
- e.setType(TRANSACTION_COMPLETED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- restoreInvocationContext(backup);
- }
- }
-
- /**
- * Notifies all registered listeners of a transaction registration event.
- *
- * @param transaction the transaction that has just completed
- */
- public void notifyTransactionRegistered(Transaction transaction, InvocationContext
ctx)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(TransactionRegistered.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- Transaction tx = ctx.getTransaction();
- boolean isOriginLocal = ctx.isOriginLocal();
- InvocationContext backup = resetInvocationContext(ctx);
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setOriginLocal(isOriginLocal);
- e.setTransaction(tx);
- e.setType(TRANSACTION_REGISTERED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- restoreInvocationContext(backup);
- }
- }
-
- public void notifyCacheBlocked(CacheSPI cache, boolean pre)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(CacheBlocked.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setPre(pre);
- e.setType(CACHE_BLOCKED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- }
- }
-
- public void notifyCacheUnblocked(CacheSPI cache, boolean pre)
- {
- List<ListenerInvocation> listeners =
listenerInvocations.get(CacheUnblocked.class);
-
- if (listeners != null && !listeners.isEmpty())
- {
- EventImpl e = new EventImpl();
- e.setCache(cache);
- e.setPre(pre);
- e.setType(CACHE_UNBLOCKED);
- for (ListenerInvocation listener : listeners) listener.invoke(e);
- }
- }
-
- private static Map copy(Map data, boolean useMarshalledValueMaps)
- {
- if (data == null) return null;
- if (data.isEmpty()) return Collections.emptyMap();
- if (safe(data)) return useMarshalledValueMaps ? new MarshalledValueMap(data) :
data;
- Map defensivelyCopiedData = new MapCopy(data);
- return useMarshalledValueMaps ? new MarshalledValueMap(defensivelyCopiedData) :
defensivelyCopiedData;
- }
-
- private void restoreInvocationContext(InvocationContext backup)
- {
- cache.setInvocationContext(backup);
- }
-
- /**
- * Resets the current (passed-in) invocation, and returns a temp InvocationContext
containing its state so it can
- * be restored later using {@link
#restoreInvocationContext(org.jboss.cache.InvocationContext)}
- *
- * @param ctx the current context to be reset
- * @return a clone of ctx, before it was reset
- */
- private InvocationContext resetInvocationContext(InvocationContext ctx)
- {
- // wipe current context.
- cache.setInvocationContext(null);
- return ctx;
- }
-
- /**
- * A map is deemed 'safe' to be passed as-is to a listener, if either of the
following are true:
- * <ul>
- * <li>It is null</li>
- * <li>It is an instance of {@link org.jboss.cache.util.MapCopy}, which is
immutable</li>
- * <li>It is an instance of {@link java.util.Collections#emptyMap()}, which is
also immutable</li>
- * <li>It is an instance of {@link
java.util.Collections#singletonMap(Object,Object)}, which is also immutable</li>
- * </ul>
- *
- * @param map
- * @return
- */
- private static boolean safe(Map map)
- {
- return map == null || map instanceof MapCopy || map.getClass().equals(emptyMap) ||
map.getClass().equals(singletonMap);
- }
-
- /**
- * Class that encapsulates a valid invocation for a given registered listener -
containing a reference to the
- * method to be invoked as well as the target object.
- */
- class ListenerInvocation
- {
- private final Object target;
- private final Method method;
-
- public ListenerInvocation(Object target, Method method)
- {
- this.target = target;
- this.method = method;
- }
-
- public void invoke(Event e)
- {
- try
- {
- method.invoke(target, e);
- }
- catch (InvocationTargetException e1)
- {
- Throwable cause = e1.getCause();
- if (cause != null)
- throw new CacheException("Caught exception invoking method " +
method + " on listener instance " + target, cause);
- else
- throw new CacheException("Caught exception invoking method " +
method + " on listener instance " + target, e1);
- }
- catch (IllegalAccessException e1)
- {
- log.warn("Unable to invoke method " + method + " on Object
instance " + target + " - removing this target object from list of
listeners!", e1);
- removeCacheListener(this.target);
- }
- }
- }
-
-}
Added: core/trunk/src/main/java/org/jboss/cache/notifications/Notifier.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/notifications/Notifier.java
(rev 0)
+++ core/trunk/src/main/java/org/jboss/cache/notifications/Notifier.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -0,0 +1,99 @@
+package org.jboss.cache.notifications;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.InvocationContext;
+import org.jboss.cache.CacheSPI;
+import org.jboss.cache.buddyreplication.BuddyGroup;
+import org.jboss.cache.factories.annotations.Start;
+import org.jboss.cache.factories.annotations.Stop;
+import org.jboss.cache.notifications.event.NodeModifiedEvent;
+import org.jgroups.View;
+
+import javax.transaction.Transaction;
+import java.util.Map;
+
+/**
+ * @author Mircea.Markus(a)jboss.com
+ * @since 2.2
+ */
+public interface Notifier
+{
+ /**
+ * Notifies all registered listeners of a nodeCreated event.
+ */
+ void notifyNodeCreated(Fqn fqn, boolean pre, InvocationContext ctx);
+
+ /**
+ * Notifies all registered listeners of a nodeModified event.
+ */
+ void notifyNodeModified(Fqn fqn, boolean pre, NodeModifiedEvent.ModificationType
modificationType, Map data, InvocationContext ctx);
+
+ /**
+ * Notifies all registered listeners of a nodeRemoved event.
+ */
+ void notifyNodeRemoved(Fqn fqn, boolean pre, Map data, InvocationContext ctx);
+
+ /**
+ * Notifies all registered listeners of a nodeVisited event.
+ */
+ void notifyNodeVisited(Fqn fqn, boolean pre, InvocationContext ctx);
+
+ /**
+ * Notifies all registered listeners of a nodeMoved event.
+ */
+ void notifyNodeMoved(Fqn originalFqn, Fqn newFqn, boolean pre, InvocationContext
ctx);
+
+ /**
+ * Notifies all registered listeners of a nodeEvicted event.
+ */
+ void notifyNodeEvicted(Fqn fqn, boolean pre, InvocationContext ctx);
+
+ /**
+ * Notifies all registered listeners of a nodeLoaded event.
+ */
+ void notifyNodeLoaded(Fqn fqn, boolean pre, Map data, InvocationContext ctx);
+
+ /**
+ * Notifies all registered listeners of a nodeActivated event.
+ */
+ void notifyNodeActivated(Fqn fqn, boolean pre, Map data, InvocationContext ctx);
+
+ /**
+ * Notifies all registered listeners of a nodePassivated event.
+ */
+ void notifyNodePassivated(Fqn fqn, boolean pre, Map data, InvocationContext ctx);
+
+ /**
+ * Notifies all registered listeners of a viewChange event. Note that viewChange
notifications are ALWAYS sent
+ * immediately.
+ */
+ void notifyViewChange(View new_view, InvocationContext ctx);
+
+ /**
+ * Notifies all registered listeners of a buddy group change event. Note that buddy
group change notifications are ALWAYS sent
+ * immediately.
+ *
+ * @param buddyGroup buddy group to set
+ * @param pre if true, this has occured before the buddy group message is
broadcast to the cluster
+ */
+ void notifyBuddyGroupChange(BuddyGroup buddyGroup, boolean pre);
+
+ /**
+ * Notifies all registered listeners of a transaction completion event.
+ *
+ * @param transaction the transaction that has just completed
+ * @param successful if true, the transaction committed. If false, this is a
rollback event
+ */
+ void notifyTransactionCompleted(Transaction transaction, boolean successful,
InvocationContext ctx);
+
+ /**
+ * Notifies all registered listeners of a transaction registration event.
+ *
+ * @param transaction the transaction that has just completed
+ */
+ void notifyTransactionRegistered(Transaction transaction, InvocationContext ctx);
+
+ void notifyCacheBlocked(CacheSPI cache, boolean pre);
+
+ void notifyCacheUnblocked(CacheSPI cache, boolean pre);
+}
Copied: core/trunk/src/main/java/org/jboss/cache/notifications/NotifierImpl.java (from rev
5840, core/trunk/src/main/java/org/jboss/cache/notifications/Notifier.java)
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/notifications/NotifierImpl.java
(rev 0)
+++ core/trunk/src/main/java/org/jboss/cache/notifications/NotifierImpl.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -0,0 +1,633 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at
gnu.org.
+ */
+package org.jboss.cache.notifications;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.*;
+import org.jboss.cache.buddyreplication.BuddyGroup;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.factories.annotations.*;
+import org.jboss.cache.marshall.MarshalledValueMap;
+import org.jboss.cache.notifications.annotation.*;
+import org.jboss.cache.notifications.event.*;
+import static org.jboss.cache.notifications.event.Event.Type.*;
+import org.jboss.cache.util.MapCopy;
+import org.jgroups.View;
+
+import javax.transaction.Transaction;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Helper class that handles all notifications to registered listeners.
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani
(manik(a)jboss.org)</a>
+ */
+@NonVolatile
+public class NotifierImpl implements Notifier
+{
+ private static final Log log = LogFactory.getLog(NotifierImpl.class);
+
+ private static final Class emptyMap = Collections.emptyMap().getClass();
+
+ private static final Class singletonMap = Collections.singletonMap(null,
null).getClass();
+ private static final Class[] allowedMethodAnnotations =
+ {
+ CacheStarted.class, CacheStopped.class, CacheBlocked.class,
CacheUnblocked.class, NodeCreated.class, NodeRemoved.class, NodeVisited.class,
NodeModified.class, NodeMoved.class,
+ NodeActivated.class, NodePassivated.class, NodeLoaded.class,
NodeEvicted.class, TransactionRegistered.class, TransactionCompleted.class,
ViewChanged.class, BuddyGroupChanged.class
+ };
+ private static final Class[] parameterTypes =
+ {
+ CacheStartedEvent.class, CacheStoppedEvent.class, CacheBlockedEvent.class,
CacheUnblockedEvent.class, NodeCreatedEvent.class, NodeRemovedEvent.class,
NodeVisitedEvent.class, NodeModifiedEvent.class, NodeMovedEvent.class,
+ NodeActivatedEvent.class, NodePassivatedEvent.class,
NodeLoadedEvent.class, NodeEvictedEvent.class, TransactionRegisteredEvent.class,
TransactionCompletedEvent.class, ViewChangedEvent.class, BuddyGroupChangedEvent.class
+ };
+
+
+ final Map<Class, List<ListenerInvocation>> listenerInvocations = new
ConcurrentHashMap<Class, List<ListenerInvocation>>();
+ private Cache cache;
+ private boolean useMarshalledValueMaps;
+ private Configuration config;
+
+ public NotifierImpl()
+ {
+ }
+
+ public NotifierImpl(Cache cache)
+ {
+ this.cache = cache;
+ }
+
+ @Inject
+ private void injectDependencies(CacheSPI cache, Configuration config)
+ {
+ this.cache = cache;
+ this.config = config;
+ }
+
+ @Destroy
+ protected void destroy()
+ {
+ listenerInvocations.clear();
+ }
+
+ @Start
+ protected void start()
+ {
+ useMarshalledValueMaps = config.isUseLazyDeserialization();
+ }
+
+ /**
+ * Loops through all valid methods on the object passed in, and caches the relevant
methods as {@link NotifierImpl.ListenerInvocation}
+ * for invocation by reflection.
+ *
+ * @param listener object to be considered as a listener.
+ */
+ private void validateAndAddListenerInvocation(Object listener)
+ {
+ testListenerClassValidity(listener.getClass());
+
+ boolean foundMethods = false;
+ // now try all methods on the listener for anything that we like. Note that only
PUBLIC methods are scanned.
+ for (Method m : listener.getClass().getMethods())
+ {
+ // loop through all valid method annotations
+ for (int i = 0; i < allowedMethodAnnotations.length; i++)
+ {
+ if (m.isAnnotationPresent(allowedMethodAnnotations[i]))
+ {
+ testListenerMethodValidity(m, parameterTypes[i],
allowedMethodAnnotations[i].getName());
+ addListenerInvocation(allowedMethodAnnotations[i], new
ListenerInvocation(listener, m));
+ foundMethods = true;
+ }
+ }
+ }
+
+ if (!foundMethods && log.isWarnEnabled())
+ log.warn("Attempted to register listener of class " +
listener.getClass() + ", but no valid, public methods annotated with method-level
event annotations found! Ignoring listener.");
+ }
+
+ private static void testListenerClassValidity(Class<?> listenerClass)
+ {
+ if (!listenerClass.isAnnotationPresent(CacheListener.class))
+ throw new IncorrectCacheListenerException("Cache listener class MUST be
annotated with org.jboss.cache.notifications.annotation.CacheListener");
+ if (!Modifier.isPublic(listenerClass.getModifiers()))
+ throw new IncorrectCacheListenerException("Cache listener class MUST be
public!");
+ }
+
+ private static void testListenerMethodValidity(Method m, Class allowedParameter,
String annotationName)
+ {
+ if (m.getParameterTypes().length != 1 ||
!m.getParameterTypes()[0].isAssignableFrom(allowedParameter))
+ throw new IncorrectCacheListenerException("Methods annotated with " +
annotationName + " must accept exactly one parameter, of assignable from type "
+ allowedParameter.getName());
+ if (!m.getReturnType().equals(void.class))
+ throw new IncorrectCacheListenerException("Methods annotated with " +
annotationName + " should have a return type of void.");
+ }
+
+ private void addListenerInvocation(Class annotation, ListenerInvocation li)
+ {
+ synchronized (listenerInvocations)
+ {
+ List<ListenerInvocation> l = listenerInvocations.get(annotation);
+ if (l == null)
+ {
+ l = new CopyOnWriteArrayList<ListenerInvocation>();
+ listenerInvocations.put(annotation, l);
+ }
+ l.add(li);
+ }
+ }
+
+ /**
+ * Adds a cache listener to the list of cache listeners registered.
+ *
+ * @param listener
+ */
+ public void addCacheListener(Object listener)
+ {
+ validateAndAddListenerInvocation(listener);
+ }
+
+ /**
+ * Removes a cache listener from the list of cache listeners registered.
+ *
+ * @param listener
+ */
+ public void removeCacheListener(Object listener)
+ {
+ synchronized (listenerInvocations)
+ {
+ for (Class annotation : allowedMethodAnnotations)
removeListenerInvocation(annotation, listener);
+ }
+ }
+
+ private void removeListenerInvocation(Class annotation, Object listener)
+ {
+ if (listener == null) return;
+
+ List<ListenerInvocation> l = listenerInvocations.get(annotation);
+ Set<Object> markedForRemoval = new HashSet<Object>();
+ if (l != null)
+ {
+ for (ListenerInvocation li : l)
+ {
+ if (listener.equals(li.target)) markedForRemoval.add(li);
+ }
+
+ l.removeAll(markedForRemoval);
+
+ if (l.isEmpty()) listenerInvocations.remove(annotation);
+ }
+ }
+
+ /**
+ * Removes all listeners from the notifier, including the evictionPolicyListener.
+ */
+ @Stop(priority = 99)
+ public void removeAllCacheListeners()
+ {
+ synchronized (listenerInvocations)
+ {
+ listenerInvocations.clear();
+ }
+ }
+
+ /**
+ * @return Retrieves an (unmodifiable) set of cache listeners registered.
+ */
+ public Set<Object> getCacheListeners()
+ {
+ Set<Object> s = new HashSet<Object>();
+ synchronized (listenerInvocations)
+ {
+ for (Class annotation : allowedMethodAnnotations)
+ {
+ List<ListenerInvocation> l = listenerInvocations.get(annotation);
+ if (l != null)
+ {
+ for (ListenerInvocation li : l) s.add(li.target);
+ }
+ }
+ }
+ return Collections.unmodifiableSet(s);
+ }
+
+ public void notifyNodeCreated(Fqn fqn, boolean pre, InvocationContext ctx)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(NodeCreated.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ boolean originLocal = ctx.isOriginLocal();
+ Transaction tx = ctx.getTransaction();
+ InvocationContext backup = resetInvocationContext(ctx);
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setOriginLocal(originLocal);
+ e.setPre(pre);
+ e.setFqn(fqn);
+ e.setTransaction(tx);
+ e.setType(NODE_CREATED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ restoreInvocationContext(backup);
+ }
+ }
+
+ public void notifyNodeModified(Fqn fqn, boolean pre,
NodeModifiedEvent.ModificationType modificationType, Map data, InvocationContext ctx)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(NodeModified.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ boolean originLocal = ctx.isOriginLocal();
+ Map dataCopy = copy(data, useMarshalledValueMaps);
+ Transaction tx = ctx.getTransaction();
+ InvocationContext backup = resetInvocationContext(ctx);
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setOriginLocal(originLocal);
+ e.setPre(pre);
+ e.setFqn(fqn);
+ e.setTransaction(tx);
+ e.setModificationType(modificationType);
+ e.setData(dataCopy);
+ e.setType(NODE_MODIFIED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ restoreInvocationContext(backup);
+ }
+ }
+
+ public void notifyNodeRemoved(Fqn fqn, boolean pre, Map data, InvocationContext ctx)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(NodeRemoved.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ boolean originLocal = ctx.isOriginLocal();
+ Map dataCopy = copy(data, useMarshalledValueMaps);
+ Transaction tx = ctx.getTransaction();
+ InvocationContext backup = resetInvocationContext(ctx);
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setOriginLocal(originLocal);
+ e.setPre(pre);
+ e.setFqn(fqn);
+ e.setTransaction(tx);
+ e.setData(dataCopy);
+ e.setType(NODE_REMOVED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ restoreInvocationContext(backup);
+ }
+ }
+
+ public void notifyNodeVisited(Fqn fqn, boolean pre, InvocationContext ctx)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(NodeVisited.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ Transaction tx = ctx.getTransaction();
+ InvocationContext backup = resetInvocationContext(ctx);
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setPre(pre);
+ e.setFqn(fqn);
+ e.setTransaction(tx);
+ e.setType(NODE_VISITED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ restoreInvocationContext(backup);
+ }
+ }
+
+ public void notifyNodeMoved(Fqn originalFqn, Fqn newFqn, boolean pre,
InvocationContext ctx)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(NodeMoved.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ boolean originLocal = ctx.isOriginLocal();
+ Transaction tx = ctx.getTransaction();
+ InvocationContext backup = resetInvocationContext(ctx);
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setOriginLocal(originLocal);
+ e.setPre(pre);
+ e.setFqn(originalFqn);
+ e.setTargetFqn(newFqn);
+ e.setTransaction(tx);
+ e.setType(NODE_MOVED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ restoreInvocationContext(backup);
+ }
+ }
+
+ public void notifyNodeEvicted(final Fqn fqn, final boolean pre, InvocationContext
ctx)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(NodeEvicted.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ final boolean originLocal = ctx.isOriginLocal();
+ Transaction tx = ctx.getTransaction();
+ InvocationContext backup = resetInvocationContext(ctx);
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setOriginLocal(originLocal);
+ e.setPre(pre);
+ e.setFqn(fqn);
+ e.setTransaction(tx);
+ e.setType(NODE_EVICTED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ restoreInvocationContext(backup);
+ }
+ }
+
+ public void notifyNodeLoaded(Fqn fqn, boolean pre, Map data, InvocationContext ctx)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(NodeLoaded.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ boolean originLocal = ctx.isOriginLocal();
+ Map dataCopy = copy(data, useMarshalledValueMaps);
+ Transaction tx = ctx.getTransaction();
+ InvocationContext backup = resetInvocationContext(ctx);
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setOriginLocal(originLocal);
+ e.setPre(pre);
+ e.setFqn(fqn);
+ e.setTransaction(tx);
+ e.setData(dataCopy);
+ e.setType(NODE_LOADED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ restoreInvocationContext(backup);
+ }
+ }
+
+ public void notifyNodeActivated(Fqn fqn, boolean pre, Map data, InvocationContext
ctx)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(NodeActivated.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ boolean originLocal = ctx.isOriginLocal();
+ Map dataCopy = copy(data, useMarshalledValueMaps);
+ Transaction tx = ctx.getTransaction();
+ InvocationContext backup = resetInvocationContext(ctx);
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setOriginLocal(originLocal);
+ e.setPre(pre);
+ e.setFqn(fqn);
+ e.setTransaction(tx);
+ e.setData(dataCopy);
+ e.setType(NODE_ACTIVATED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ restoreInvocationContext(backup);
+ }
+ }
+
+ public void notifyNodePassivated(Fqn fqn, boolean pre, Map data, InvocationContext
ctx)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(NodePassivated.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ Map dataCopy = copy(data, useMarshalledValueMaps);
+ Transaction tx = ctx.getTransaction();
+ InvocationContext backup = resetInvocationContext(ctx);
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setPre(pre);
+ e.setFqn(fqn);
+ e.setTransaction(tx);
+ e.setData(dataCopy);
+ e.setType(NODE_PASSIVATED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ restoreInvocationContext(backup);
+ }
+ }
+
+ /**
+ * Notifies all registered listeners of a cacheStarted event.
+ */
+ @Start(priority = 99)
+ public void notifyCacheStarted()
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(CacheStarted.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setType(CACHE_STARTED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ }
+ }
+
+ /**
+ * Notifies all registered listeners of a cacheStopped event.
+ */
+ @Stop(priority = 98)
+ public void notifyCacheStopped()
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(CacheStopped.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setType(CACHE_STOPPED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ }
+ }
+
+ public void notifyViewChange(final View new_view, InvocationContext ctx)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(ViewChanged.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ InvocationContext backup = resetInvocationContext(ctx);
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setNewView(new_view);
+ e.setType(VIEW_CHANGED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ restoreInvocationContext(backup);
+ }
+ }
+
+ public void notifyBuddyGroupChange(final BuddyGroup buddyGroup, boolean pre)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(BuddyGroupChanged.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setBuddyGroup(buddyGroup);
+ e.setPre(pre);
+ e.setType(BUDDY_GROUP_CHANGED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ }
+ }
+
+ public void notifyTransactionCompleted(Transaction transaction, boolean successful,
InvocationContext ctx)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(TransactionCompleted.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ Transaction tx = ctx.getTransaction();
+ boolean isOriginLocal = ctx.isOriginLocal();
+ InvocationContext backup = resetInvocationContext(ctx);
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setOriginLocal(isOriginLocal);
+ e.setTransaction(tx);
+ e.setSuccessful(successful);
+ e.setType(TRANSACTION_COMPLETED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ restoreInvocationContext(backup);
+ }
+ }
+
+ public void notifyTransactionRegistered(Transaction transaction, InvocationContext
ctx)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(TransactionRegistered.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ Transaction tx = ctx.getTransaction();
+ boolean isOriginLocal = ctx.isOriginLocal();
+ InvocationContext backup = resetInvocationContext(ctx);
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setOriginLocal(isOriginLocal);
+ e.setTransaction(tx);
+ e.setType(TRANSACTION_REGISTERED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ restoreInvocationContext(backup);
+ }
+ }
+
+ public void notifyCacheBlocked(CacheSPI cache, boolean pre)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(CacheBlocked.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setPre(pre);
+ e.setType(CACHE_BLOCKED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ }
+ }
+
+ public void notifyCacheUnblocked(CacheSPI cache, boolean pre)
+ {
+ List<ListenerInvocation> listeners =
listenerInvocations.get(CacheUnblocked.class);
+
+ if (listeners != null && !listeners.isEmpty())
+ {
+ EventImpl e = new EventImpl();
+ e.setCache(cache);
+ e.setPre(pre);
+ e.setType(CACHE_UNBLOCKED);
+ for (ListenerInvocation listener : listeners) listener.invoke(e);
+ }
+ }
+
+ private static Map copy(Map data, boolean useMarshalledValueMaps)
+ {
+ if (data == null) return null;
+ if (data.isEmpty()) return Collections.emptyMap();
+ if (safe(data)) return useMarshalledValueMaps ? new MarshalledValueMap(data) :
data;
+ Map defensivelyCopiedData = new MapCopy(data);
+ return useMarshalledValueMaps ? new MarshalledValueMap(defensivelyCopiedData) :
defensivelyCopiedData;
+ }
+
+ private void restoreInvocationContext(InvocationContext backup)
+ {
+ cache.setInvocationContext(backup);
+ }
+
+ /**
+ * Resets the current (passed-in) invocation, and returns a temp InvocationContext
containing its state so it can
+ * be restored later using {@link
#restoreInvocationContext(org.jboss.cache.InvocationContext)}
+ *
+ * @param ctx the current context to be reset
+ * @return a clone of ctx, before it was reset
+ */
+ private InvocationContext resetInvocationContext(InvocationContext ctx)
+ {
+ // wipe current context.
+ cache.setInvocationContext(null);
+ return ctx;
+ }
+
+ /**
+ * A map is deemed 'safe' to be passed as-is to a listener, if either of the
following are true:
+ * <ul>
+ * <li>It is null</li>
+ * <li>It is an instance of {@link org.jboss.cache.util.MapCopy}, which is
immutable</li>
+ * <li>It is an instance of {@link java.util.Collections#emptyMap()}, which is
also immutable</li>
+ * <li>It is an instance of {@link
java.util.Collections#singletonMap(Object,Object)}, which is also immutable</li>
+ * </ul>
+ *
+ * @param map
+ * @return
+ */
+ private static boolean safe(Map map)
+ {
+ return map == null || map instanceof MapCopy || map.getClass().equals(emptyMap) ||
map.getClass().equals(singletonMap);
+ }
+
+ /**
+ * Class that encapsulates a valid invocation for a given registered listener -
containing a reference to the
+ * method to be invoked as well as the target object.
+ */
+ class ListenerInvocation
+ {
+ private final Object target;
+ private final Method method;
+
+ public ListenerInvocation(Object target, Method method)
+ {
+ this.target = target;
+ this.method = method;
+ }
+
+ public void invoke(Event e)
+ {
+ try
+ {
+ method.invoke(target, e);
+ }
+ catch (InvocationTargetException e1)
+ {
+ Throwable cause = e1.getCause();
+ if (cause != null)
+ throw new CacheException("Caught exception invoking method " +
method + " on listener instance " + target, cause);
+ else
+ throw new CacheException("Caught exception invoking method " +
method + " on listener instance " + target, e1);
+ }
+ catch (IllegalAccessException e1)
+ {
+ log.warn("Unable to invoke method " + method + " on Object
instance " + target + " - removing this target object from list of
listeners!", e1);
+ removeCacheListener(this.target);
+ }
+ }
+ }
+
+}
Property changes on:
core/trunk/src/main/java/org/jboss/cache/notifications/NotifierImpl.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:eol-style
+ native
Modified: core/trunk/src/main/java/org/jboss/cache/util/CachePrinter.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/CachePrinter.java 2008-05-14 17:05:33
UTC (rev 5849)
+++ core/trunk/src/main/java/org/jboss/cache/util/CachePrinter.java 2008-05-15 12:44:49
UTC (rev 5850)
@@ -2,7 +2,7 @@
import org.jboss.cache.Cache;
import org.jboss.cache.CacheSPI;
-import org.jboss.cache.DataContainer;
+import org.jboss.cache.DataContainerImpl;
import org.jboss.cache.interceptors.base.CommandInterceptor;
import org.jboss.cache.invocation.CacheInvocationDelegate;
@@ -23,7 +23,7 @@
public static String printCacheDetails(Cache c)
{
// internal cast
- DataContainer ci = ((CacheInvocationDelegate) c).getDataContainer();
+ DataContainerImpl ci = ((CacheInvocationDelegate) c).getDataContainer();
return ci.printDetails();
}
@@ -36,7 +36,7 @@
public static String printCacheLockingInfo(Cache c)
{
// internal cast
- DataContainer cd = ((CacheInvocationDelegate) c).getDataContainer();
+ DataContainerImpl cd = ((CacheInvocationDelegate) c).getDataContainer();
return cd.printLockInfo();
}
Modified: core/trunk/src/test/java/org/jboss/cache/DataContainerTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/DataContainerTest.java 2008-05-14 17:05:33
UTC (rev 5849)
+++ core/trunk/src/test/java/org/jboss/cache/DataContainerTest.java 2008-05-15 12:44:49
UTC (rev 5850)
@@ -2,7 +2,7 @@
import org.jboss.cache.config.Configuration;
import org.jboss.cache.marshall.NodeData;
-import org.jboss.cache.mock.NodeSpiMock;
+import org.jboss.cache.mock.MockNodesFixture;
import org.jboss.cache.optimistic.DataVersion;
import org.jboss.cache.optimistic.DefaultDataVersion;
import org.testng.annotations.BeforeMethod;
@@ -20,100 +20,74 @@
@Test(groups = "unit")
public class DataContainerTest
{
- private DataContainer container;
+ private DataContainerImpl container;
+ private MockNodesFixture nodes;
- //node structure on which all tests are being run.
- private NodeSpiMock root;
- private Fqn a = Fqn.fromString("/a");
- private NodeSpiMock aNode;
- private Fqn ab = Fqn.fromString("/a/b");
- private NodeSpiMock abNode;
- private Fqn abc = Fqn.fromString("/a/b/c");
- private NodeSpiMock abcNode;
- private Fqn ad = Fqn.fromString("/a/d");
- private NodeSpiMock adNode;
- private Fqn ade = Fqn.fromString("/a/d/e");
- private NodeSpiMock adeNode;
- private Fqn adf = Fqn.fromString("/a/d/f");
- private NodeSpiMock adfNode;
- private Fqn adfh = Fqn.fromString("/a/d/f/h");
- private NodeSpiMock adfhNode;
- private Fqn adfg = Fqn.fromString("/a/d/f/g");
- private NodeSpiMock adfgNode;
- private Fqn notExistent = Fqn.fromString("aaa" +
System.currentTimeMillis());
//end of node structure.
@BeforeMethod
public void setUp()
{
- root = new NodeSpiMock(Fqn.ROOT);
- container = new DataContainer();
- container.setRoot(root);
- aNode = (NodeSpiMock) root.addChild(a);
- abNode = (NodeSpiMock) root.addChild(ab);
- abcNode = (NodeSpiMock) root.addChild(abc);
- adNode = (NodeSpiMock) root.addChild(ad);
- adeNode = (NodeSpiMock) root.addChild(ade);
- adfNode = (NodeSpiMock) root.addChild(adf);
- adfhNode = (NodeSpiMock) root.addChild(adfh);
- adfgNode = (NodeSpiMock) root.addChild(adfg);
+ nodes = new MockNodesFixture();
+ container = new DataContainerImpl();
+ container.setRoot(nodes.root);
}
/**
- * tests {@link org.jboss.cache.DataContainer#peek(Fqn, boolean, boolean)} method
+ * tests {@link DataContainerImpl#peek(Fqn, boolean, boolean)} method
*/
public void testPeekNodesSimple()
{
- assert root == container.peek(Fqn.ROOT, true, true);
- assert adfgNode == container.peek(adfg, false, false);
- assert adfgNode == container.peek(adfg, false, true);
- assert adfgNode == container.peek(adfg, true, true);
+ assert nodes.root == container.peek(Fqn.ROOT, true, true);
+ assert nodes.adfgNode == container.peek(nodes.adfg, false, false);
+ assert nodes.adfgNode == container.peek(nodes.adfg, false, true);
+ assert nodes.adfgNode == container.peek(nodes.adfg, true, true);
}
/**
- * tests {@link org.jboss.cache.DataContainer#peek(Fqn, boolean, boolean)} for invalid
nodes.
+ * tests {@link DataContainerImpl#peek(Fqn, boolean, boolean)} for invalid nodes.
*/
public void testPeekInvalidNodes()
{
- adfgNode.setValid(false, false);
- assert null == container.peek(adfg, true, false);
- assert adfgNode == container.peek(adfg, true, true);
+ nodes.adfgNode.setValid(false, false);
+ assert null == container.peek(nodes.adfg, true, false);
+ assert nodes.adfgNode == container.peek(nodes.adfg, true, true);
}
/**
- * tests {@link org.jboss.cache.DataContainer#peek(Fqn, boolean, boolean)} method for
deleted nodes.
+ * tests {@link DataContainerImpl#peek(Fqn, boolean, boolean)} method for deleted
nodes.
*/
public void testPeekDeletedNodes()
{
- adfgNode.markAsDeleted(true);
- assert null == container.peek(adfg, false, false);
- assert adfgNode == container.peek(adfg, true, false);
+ nodes.adfgNode.markAsDeleted(true);
+ assert null == container.peek(nodes.adfg, false, false);
+ assert nodes.adfgNode == container.peek(nodes.adfg, true, false);
}
/**
- * tests {@link org.jboss.cache.DataContainer#peekVersioned(Fqn,
org.jboss.cache.optimistic.DataVersion, boolean)} method.
+ * tests {@link DataContainerImpl#peekVersioned(Fqn,
org.jboss.cache.optimistic.DataVersion, boolean)} method.
*/
public void testPeekVersioned()
{
- assert adfgNode == container.peekVersioned(adfg, null, true) : "if data
version is null this returns same value as peek(boolean, boolean)";
+ assert nodes.adfgNode == container.peekVersioned(nodes.adfg, null, true) : "if
data version is null this returns same value as peek(boolean, boolean)";
//test pessimistic loking
Configuration config = new Configuration();
config.setNodeLockingOptimistic(false);
DataVersion dataVersion = new DefaultDataVersion(2);
container.setDependencies(config, null);
- assert adfgNode == container.peekVersioned(adfg, dataVersion, true) : "if NOT
opt locking same value as peek(boolean, boolean) expected";
+ assert nodes.adfgNode == container.peekVersioned(nodes.adfg, dataVersion, true) :
"if NOT opt locking same value as peek(boolean, boolean) expected";
//test optimistic locking with same version
config.setNodeLockingOptimistic(true);
DataVersion adfgDataVersion = new DefaultDataVersion(2);
- adfgNode.setVersion(adfgDataVersion);
- assert adfgNode == container.peekVersioned(adfg, adfgDataVersion, true) :
"same version, expcting node to be returned";
+ nodes.adfgNode.setVersion(adfgDataVersion);
+ assert nodes.adfgNode == container.peekVersioned(nodes.adfg, adfgDataVersion, true)
: "same version, expcting node to be returned";
//test optimistic locking with a an older
try
{
- container.peekVersioned(adfg, new DefaultDataVersion(1), true);
+ container.peekVersioned(nodes.adfg, new DefaultDataVersion(1), true);
assert false : "exception expected as version changed.";
} catch (CacheException e)
{
@@ -122,15 +96,15 @@
}
/**
- * tests {@link
DataContainer#peekStrict(org.jboss.cache.transaction.GlobalTransaction, Fqn, boolean)}.
+ * tests {@link
DataContainerImpl#peekStrict(org.jboss.cache.transaction.GlobalTransaction, Fqn,
boolean)}.
*/
public void testPeekStrict()
{
- assert adfgNode == container.peekStrict(null, adfg, true) : "if data version
is null this returns same value as peek(boolean, boolean)";
+ assert nodes.adfgNode == container.peekStrict(null, nodes.adfg, true) : "if
data version is null this returns same value as peek(boolean, boolean)";
try
{
- container.peekStrict(null, notExistent, true);
+ container.peekStrict(null, nodes.notExistent, true);
assert false : "excpetion expected as node does not exist";
} catch (Exception e)
{
@@ -139,67 +113,67 @@
}
/**
- * tests {@link org.jboss.cache.DataContainer#exists(Fqn)}
+ * tests {@link DataContainerImpl#exists(Fqn)}
*/
public void testsExists()
{
- assert container.exists(ab) : "ab exists";
- abNode.markAsDeleted(true);
- assert !container.exists(ab) : "ab marked as deleted";
- assert container.exists(ad);
- adNode.setValid(false, false);
- assert !container.exists(ade) : "its parent was marked as invalid";
+ assert container.exists(nodes.ab) : "ab exists";
+ nodes.abNode.markAsDeleted(true);
+ assert !container.exists(nodes.ab) : "ab marked as deleted";
+ assert container.exists(nodes.ad);
+ nodes.adNode.setValid(false, false);
+ assert !container.exists(nodes.ade) : "its parent was marked as
invalid";
}
/**
- * tests {@link org.jboss.cache.DataContainer#hasChildren(Fqn)}
+ * tests {@link DataContainerImpl#hasChildren(Fqn)}
*/
public void testHasChildren()
{
- assert container.hasChildren(ad) : " ade is a child of ad";
- assert !container.hasChildren(notExistent) : " this one does not exist";
- assert !container.hasChildren(adfg) : "this one exists but does not have
children";
- adNode.setValid(false, false);
- assert !container.hasChildren(ad) : "ad exists and has children but is
invalid";
+ assert container.hasChildren(nodes.ad) : " ade is a child of ad";
+ assert !container.hasChildren(nodes.notExistent) : " this one does not
exist";
+ assert !container.hasChildren(nodes.adfg) : "this one exists but does not have
children";
+ nodes.adNode.setValid(false, false);
+ assert !container.hasChildren(nodes.ad) : "ad exists and has children but is
invalid";
}
/**
- * test {@link DataContainer#buildNodeData(java.util.List, NodeSPI)}
+ * test {@link DataContainerImpl#buildNodeData(java.util.List, NodeSPI)}
*/
public void testBuildNodeData()
{
- abNode.put("ab", "ab");
- abcNode.put("abc", "abc");
+ nodes.abNode.put("ab", "ab");
+ nodes.abcNode.put("abc", "abc");
List<NodeData> result = new ArrayList<NodeData>();
- container.buildNodeData(result, abNode);
+ container.buildNodeData(result, nodes.abNode);
assert result.size() == 2;
- assert result.contains(new NodeData(ab, abNode.getData()));
- assert result.contains(new NodeData(abc, abcNode.getData()));
+ assert result.contains(new NodeData(nodes.ab, nodes.abNode.getData()));
+ assert result.contains(new NodeData(nodes.abc, nodes.abcNode.getData()));
}
/**
- * tests {@link org.jboss.cache.DataContainer#getNodesForEviction(Fqn, boolean)} in a
nonrecursive scenario.
+ * tests {@link DataContainerImpl#getNodesForEviction(Fqn, boolean)} in a nonrecursive
scenario.
*/
public void testGetNodesForEvictionNonrecursive()
{
//check for root first
List<Fqn> result = container.getNodesForEviction(Fqn.ROOT, false);
assert result.size() == 1 : "for root the direct children are considered for
eviction";
- assert result.contains(a);
+ assert result.contains(nodes.a);
//check normal
- result = container.getNodesForEviction(ad, false);
+ result = container.getNodesForEviction(nodes.ad, false);
assert result.size() == 1 : "one child expected";
- assert result.contains(ad);
+ assert result.contains(nodes.ad);
//check resident scenario
- adNode.setResident(true);
- result = container.getNodesForEviction(ad, false);
+ nodes.adNode.setResident(true);
+ result = container.getNodesForEviction(nodes.ad, false);
assert result.size() == 0 : "no children expected";
}
/**
- * tests {@link org.jboss.cache.DataContainer#getNodesForEviction(Fqn, boolean)} in a
recursive scenario.
+ * tests {@link DataContainerImpl#getNodesForEviction(Fqn, boolean)} in a recursive
scenario.
*/
public void testGetNodesForEvictionRecursive()
{
@@ -208,26 +182,26 @@
assert result.size() == 8 : "all children are considered for eviction";
//check normal
- result = container.getNodesForEviction(ad, true);
+ result = container.getNodesForEviction(nodes.ad, true);
assert result.size() == 5 : "five childrens expected";
- assert result.contains(ad);
- assert result.contains(ade);
- assert result.contains(adf);
- assert result.contains(adfh);
- assert result.contains(adfg);
+ assert result.contains(nodes.ad);
+ assert result.contains(nodes.ade);
+ assert result.contains(nodes.adf);
+ assert result.contains(nodes.adfh);
+ assert result.contains(nodes.adfg);
//check resident scenario
- adNode.setResident(true);
- result = container.getNodesForEviction(ad, true);
+ nodes.adNode.setResident(true);
+ result = container.getNodesForEviction(nodes.ad, true);
assert result.size() == 4 : "only children expected";
- assert result.contains(ade);
- assert result.contains(adf);
- assert result.contains(adfh);
- assert result.contains(adfg);
+ assert result.contains(nodes.ade);
+ assert result.contains(nodes.adf);
+ assert result.contains(nodes.adfh);
+ assert result.contains(nodes.adfg);
}
/**
- * tests {@link DataContainer#getNumberOfNodes()}
+ * tests {@link DataContainerImpl#getNumberOfNodes()}
*/
public void testGetNumberOfNodes()
{
@@ -235,87 +209,87 @@
}
/**
- * tests {@link DataContainer#removeFromDataStructure(Fqn, boolean)} having
skipMarkerCheck set to false.
+ * tests {@link DataContainerImpl#removeFromDataStructure(Fqn, boolean)} having
skipMarkerCheck set to false.
*/
public void removeFromDataStructureNoSkip1()
{
//check inexisten node
- assert !container.removeFromDataStructure(notExistent, false);
+ assert !container.removeFromDataStructure(nodes.notExistent, false);
//check root - all the subnodes should be deleted and marked as invalid, but the
root itself
- root.markAsDeleted(true);
+ nodes.root.markAsDeleted(true);
assert container.removeFromDataStructure(Fqn.ROOT, false);
- assert !aNode.isValid();
- assert !abNode.isValid();
- assert !abcNode.isValid();
- assert !adNode.isValid();
- assert !adeNode.isValid();
- assert !adfNode.isValid();
- assert !adfgNode.isValid();
- assert !adfhNode.isValid();
- assert root.isValid();
+ assert !nodes.aNode.isValid();
+ assert !nodes.abNode.isValid();
+ assert !nodes.abcNode.isValid();
+ assert !nodes.adNode.isValid();
+ assert !nodes.adeNode.isValid();
+ assert !nodes.adfNode.isValid();
+ assert !nodes.adfgNode.isValid();
+ assert !nodes.adfhNode.isValid();
+ assert nodes.root.isValid();
}
/**
- * tests {@link DataContainer#removeFromDataStructure(Fqn, boolean)} having
skipMarkerCheck set to false.
+ * tests {@link DataContainerImpl#removeFromDataStructure(Fqn, boolean)} having
skipMarkerCheck set to false.
*/
public void removeFromDataStructureNoSkip2()
{
//check root - all the subnodes should be deleted and marked as invalid, but the
root itself
- root.markAsDeleted(false);
+ nodes.root.markAsDeleted(false);
assert !container.removeFromDataStructure(Fqn.ROOT, false);
//check a normal node
- adNode.markAsDeleted(true);
- assert container.removeFromDataStructure(ad, false);
- assert !adeNode.isValid();
- assert !adfNode.isValid();
- assert !adfhNode.isValid();
- assert !adfhNode.isValid();
+ nodes.adNode.markAsDeleted(true);
+ assert container.removeFromDataStructure(nodes.ad, false);
+ assert !nodes.adeNode.isValid();
+ assert !nodes.adfNode.isValid();
+ assert !nodes.adfhNode.isValid();
+ assert !nodes.adfhNode.isValid();
}
/**
- * tests {@link DataContainer#removeFromDataStructure(Fqn, boolean)} having
skipMarkerCheck set to true.
+ * tests {@link DataContainerImpl#removeFromDataStructure(Fqn, boolean)} having
skipMarkerCheck set to true.
*/
public void removeFromDataStructureWithSkip()
{
//check inexisten node
- assert !container.removeFromDataStructure(notExistent, false);
+ assert !container.removeFromDataStructure(nodes.notExistent, false);
//check root - all the subnodes should be deleted and marked as invalid, but the
root itself
assert container.removeFromDataStructure(Fqn.ROOT, true);
- assert !aNode.isValid();
- assert !abNode.isValid();
- assert !abcNode.isValid();
- assert !adNode.isValid();
- assert !adeNode.isValid();
- assert !adfNode.isValid();
- assert !adfgNode.isValid();
- assert !adfhNode.isValid();
- assert root.isValid();
+ assert !nodes.aNode.isValid();
+ assert !nodes.abNode.isValid();
+ assert !nodes.abcNode.isValid();
+ assert !nodes.adNode.isValid();
+ assert !nodes.adeNode.isValid();
+ assert !nodes.adfNode.isValid();
+ assert !nodes.adfgNode.isValid();
+ assert !nodes.adfhNode.isValid();
+ assert nodes.root.isValid();
}
/**
- * tests {@link org.jboss.cache.DataContainer#evict(Fqn)}
+ * tests {@link DataContainerImpl#evict(Fqn)}
*/
public void testEvict()
{
//tests eviction of leaf nodes
- assert container.evict(abc);
- assert !abcNode.isValid();
- assert !abNode.hasChild("c");
+ assert container.evict(nodes.abc);
+ assert !nodes.abcNode.isValid();
+ assert !nodes.abNode.hasChild("c");
//test eviction of intermediate nodes
- adNode.put("key", "value");
- assert !container.evict(ad);
- assert adNode.isValid();
- assert adNode.getData().isEmpty();
- assert aNode.hasChild("d");
- assert adNode.hasChild("e");
+ nodes.adNode.put("key", "value");
+ assert !container.evict(nodes.ad);
+ assert nodes.adNode.isValid();
+ assert nodes.adNode.getData().isEmpty();
+ assert nodes.aNode.hasChild("d");
+ assert nodes.adNode.hasChild("e");
}
/**
- * test {@link org.jboss.cache.DataContainer#createNodes(Fqn)}
+ * test {@link DataContainerImpl#createNodes(Fqn)}
*/
public void testCreateNodes()
{
Added:
core/trunk/src/test/java/org/jboss/cache/commands/read/AbstractDataCommandTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/commands/read/AbstractDataCommandTest.java
(rev 0)
+++
core/trunk/src/test/java/org/jboss/cache/commands/read/AbstractDataCommandTest.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -0,0 +1,32 @@
+package org.jboss.cache.commands.read;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.DataContainer;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import static org.easymock.EasyMock.createMock;
+
+/**
+ * Class that has convinience fixture for all tests that operated on {@link
AbstractDataCommand}
+ *
+ * @author Mircea.Markus(a)jboss.com
+ * @since 2.2
+ */
+public abstract class AbstractDataCommandTest
+{
+ protected Fqn testFqn = Fqn.fromString("/testfqn");
+ protected DataContainer containerMock;
+
+ @BeforeMethod
+ final public void setUp()
+ {
+ containerMock = createMock(DataContainer.class);
+ moreSetup();
+ }
+
+ /**
+ * called by setUp after initializing the testFqn and containeMock.
+ */
+ protected abstract void moreSetup();
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/commands/read/ExistsCommandTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/commands/read/ExistsCommandTest.java
(rev 0)
+++
core/trunk/src/test/java/org/jboss/cache/commands/read/ExistsCommandTest.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -0,0 +1,33 @@
+package org.jboss.cache.commands.read;
+
+import static org.easymock.EasyMock.*;
+import org.testng.annotations.Test;
+
+/**
+ * Tester class for {@link org.jboss.cache.commands.read.ExistsCommand}
+ * @author Mircea.Markus(a)jboss.com
+ * @since 2.2
+ */
+@Test(groups="unit")
+public class ExistsCommandTest extends AbstractDataCommandTest
+{
+ private ExistsCommand command;
+
+ protected void moreSetup()
+ {
+ command = new ExistsCommand(testFqn);
+ command.initialize(containerMock);
+ }
+
+ public void testPerform()
+ {
+ expect(containerMock.exists(testFqn)).andReturn(Boolean.FALSE);
+ replay(containerMock);
+ assert Boolean.FALSE == command.perform(null);
+ reset(containerMock);
+
+ expect(containerMock.exists(testFqn)).andReturn(Boolean.TRUE);
+ replay(containerMock);
+ assert Boolean.TRUE == command.perform(null);
+ }
+}
Added:
core/trunk/src/test/java/org/jboss/cache/commands/read/GetChildrenNamesCommandTest.java
===================================================================
---
core/trunk/src/test/java/org/jboss/cache/commands/read/GetChildrenNamesCommandTest.java
(rev 0)
+++
core/trunk/src/test/java/org/jboss/cache/commands/read/GetChildrenNamesCommandTest.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -0,0 +1,66 @@
+package org.jboss.cache.commands.read;
+
+import static org.easymock.EasyMock.*;
+
+import org.testng.annotations.Test;
+import org.jboss.cache.mock.NodeSpiMock;
+import org.jboss.cache.mock.MockNodesFixture;
+
+import java.util.Set;
+
+/**
+ * Tester class for {@link org.jboss.cache.commands.read.GetChildrenNamesCommand}.
+ *
+ * @author Mircea.Markus(a)jboss.com
+ * @since 2.2
+ */
+@Test (groups="unit")
+public class GetChildrenNamesCommandTest extends AbstractDataCommandTest
+{
+ private GetChildrenNamesCommand command;
+ private MockNodesFixture nodes;
+
+ protected void moreSetup()
+ {
+ nodes = new MockNodesFixture();
+ command = new GetChildrenNamesCommand(testFqn);
+ command.initialize(containerMock);
+ }
+
+ public void testPerformNoChildren()
+ {
+ NodeSpiMock node = new NodeSpiMock(testFqn);
+ expect(containerMock.peek(testFqn)).andReturn(node);
+ replay(containerMock);
+ Set result = (Set) command.perform(null);
+ assert result.isEmpty() : "empty result expected";
+ }
+
+ public void testPerformInexistingNode()
+ {
+ expect(containerMock.peek(testFqn)).andReturn(null);
+ replay(containerMock);
+ Set result = (Set) command.perform(null);
+ assert result == null : "empty result expected";
+ }
+
+ public void testNodeWithChildren()
+ {
+ expect(containerMock.peek(testFqn)).andReturn(nodes.adfNode);
+ replay(containerMock);
+ Set result = (Set) command.perform(null);
+ assert result.size() == 2;
+ assert result.contains("h");
+ assert result.contains("g");
+ }
+
+ public void testNodeInvalidChildren()
+ {
+ nodes.adfgNode.markAsDeleted(true);
+ expect(containerMock.peek(testFqn)).andReturn(nodes.adfNode);
+ replay(containerMock);
+ Set result = (Set) command.perform(null);
+ assert result.size() == 1;
+ assert result.contains("h");
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/commands/read/GetDataMapCommandTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/commands/read/GetDataMapCommandTest.java
(rev 0)
+++
core/trunk/src/test/java/org/jboss/cache/commands/read/GetDataMapCommandTest.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -0,0 +1,54 @@
+package org.jboss.cache.commands.read;
+
+import org.testng.annotations.Test;
+import static org.easymock.EasyMock.*;
+import org.jboss.cache.mock.NodeSpiMock;
+
+import java.util.Map;
+
+/**
+ * Tester class for {@link GetDataMapCommand}.
+ *
+ * @author Mircea.Markus(a)jboss.com
+ * @since 2.2
+ */
+@Test(groups = "unit")
+public class GetDataMapCommandTest extends AbstractDataCommandTest
+{
+ GetDataMapCommand command;
+
+ protected void moreSetup()
+ {
+ command = new GetDataMapCommand(testFqn);
+ command.initialize(containerMock);
+ }
+
+ public void testForNonexistentNode()
+ {
+ expect(containerMock.peek(testFqn)).andReturn(null);
+ replay(containerMock);
+ assert null == command.perform(null);
+ }
+
+ public void testForExistingNode()
+ {
+ NodeSpiMock node = new NodeSpiMock(testFqn);
+ node.putDirect("k1","v1");
+ node.putDirect("k2","v2");
+ expect(containerMock.peek(testFqn)).andReturn(node);
+ replay(containerMock);
+ Map result = (Map) command.perform(null);
+ assert 2 == result.entrySet().size();
+ assert result.get("k1").equals("v1");
+ assert result.get("k2").equals("v2");
+
+ try
+ {
+ result.put("k3", "v3");
+ assert false : "map should be immutable";
+ } catch (RuntimeException ex)
+ {
+ //expected
+ }
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/commands/read/GetKeyValueCommandTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/commands/read/GetKeyValueCommandTest.java
(rev 0)
+++
core/trunk/src/test/java/org/jboss/cache/commands/read/GetKeyValueCommandTest.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -0,0 +1,82 @@
+package org.jboss.cache.commands.read;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeMethod;
+import static org.easymock.EasyMock.*;
+import org.easymock.*;
+import org.jboss.cache.notifications.Notifier;
+import org.jboss.cache.DataContainer;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.mock.NodeSpiMock;
+
+/**
+ * Tester class for {@link GetKeyValueCommand}.
+ *
+ * @author Mircea.Markus(a)jboss.com
+ * @since 2.2
+ */
+@Test(groups = "unit")
+public class GetKeyValueCommandTest
+{
+ private IMocksControl control;
+ Notifier notifierMock;
+ DataContainer containerMock;
+ GetKeyValueCommand command;
+ Fqn fqn = Fqn.fromString("/dummy");
+ String key = "key";
+
+ @BeforeMethod
+ protected void setUup()
+ {
+ control = createStrictControl();
+ containerMock = control.createMock(DataContainer.class);
+ notifierMock = control.createMock(Notifier.class);
+ command = new GetKeyValueCommand(fqn, key, false);
+ command.initialize(containerMock, notifierMock);
+ }
+
+ public void testNonexistentNodeNoNotifications()
+ {
+ expect(containerMock.peek(fqn)).andReturn(null);
+ control.replay();
+ assert null == command.perform(null);
+ }
+
+ public void testExistentNodeNoNotifications()
+ {
+ NodeSpiMock node = new NodeSpiMock(fqn);
+ String value = "vvv";
+ node.put(key, value);
+ expect(containerMock.peek(fqn)).andReturn(node);
+ control.replay();
+ assert value.equals(command.perform(null));
+ }
+
+ /**
+ * Notification should only be triggered if the node exists.
+ */
+ public void testNonexistentNodeWithNotifications()
+ {
+ command.sendNodeEvent = true;
+ expect(containerMock.peek(fqn)).andReturn(null);
+ control.replay();
+ assert null == command.perform(null);
+ }
+
+ public void testExistentNodeWithNotifications()
+ {
+ command.sendNodeEvent = true;
+ NodeSpiMock node = new NodeSpiMock(fqn);
+ String value = "vvv";
+ node.put(key, value);
+ //not ordred because the peek hapens before notification - that is to make sure
that no notification
+ // is sent for an nonexistent node.
+ control.checkOrder(false);
+ notifierMock.notifyNodeVisited(fqn, true, null);
+ expect(containerMock.peek(fqn)).andReturn(node);
+ notifierMock.notifyNodeVisited(fqn, false, null);
+ control.replay();
+ assert value.equals(command.perform(null));
+ control.verify();
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/commands/read/GetKeysCommandTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/commands/read/GetKeysCommandTest.java
(rev 0)
+++
core/trunk/src/test/java/org/jboss/cache/commands/read/GetKeysCommandTest.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -0,0 +1,48 @@
+package org.jboss.cache.commands.read;
+
+import org.testng.annotations.Test;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import org.jboss.cache.mock.NodeSpiMock;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Tester class for {@link GetKeysCommand}.
+ *
+ * @author Mircea.Markus(a)jboss.com
+ * @since 2.2
+ */
+@Test(groups = "unit")
+public class GetKeysCommandTest extends AbstractDataCommandTest
+{
+
+ GetKeysCommand command;
+
+ protected void moreSetup()
+ {
+ command = new GetKeysCommand(testFqn);
+ command.initialize(containerMock);
+ }
+
+ public void testForNonexistentNode()
+ {
+ expect(containerMock.peek(testFqn)).andReturn(null);
+ replay(containerMock);
+ assert null == command.perform(null);
+ }
+
+ public void testForExistingNode()
+ {
+ NodeSpiMock node = new NodeSpiMock(testFqn);
+ node.putDirect("k1", "v1");
+ node.putDirect("k2", "v2");
+ expect(containerMock.peek(testFqn)).andReturn(node);
+ replay(containerMock);
+ Set result = (Set) command.perform(null);
+ assert 2 == result.size();
+ assert result.contains("k1");
+ assert result.contains("k2");
+ }
+}
Added:
core/trunk/src/test/java/org/jboss/cache/commands/read/GravitateDataCommandTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/commands/read/GravitateDataCommandTest.java
(rev 0)
+++
core/trunk/src/test/java/org/jboss/cache/commands/read/GravitateDataCommandTest.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -0,0 +1,141 @@
+package org.jboss.cache.commands.read;
+
+import static org.easymock.EasyMock.*;
+import org.easymock.IMocksControl;
+import org.jboss.cache.*;
+import org.jboss.cache.buddyreplication.BuddyManager;
+import org.jboss.cache.buddyreplication.GravitateResult;
+import org.jboss.cache.buddyreplication.BuddyFqnTransformer;
+import org.jboss.cache.mock.MockNodesFixture;
+import org.jboss.cache.mock.NodeSpiMock;
+import org.jgroups.stack.IpAddress;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * Tester class for {@link org.jboss.cache.commands.read.GravitateDataCommand}
+ *
+ * @author Mircea.Markus(a)jboss.com
+ * @since 2.2
+ */
+@Test(groups="unit")
+public class GravitateDataCommandTest
+{
+ GravitateDataCommand command;
+ DataContainer containerMock;
+ CacheSPI spiMock;
+ IMocksControl control;
+ Fqn fqn = Fqn.fromString("/dummy");
+ InvocationContext ctx;
+
+ @BeforeMethod
+ public void setUp()
+ {
+ control = createStrictControl();
+ containerMock = control.createMock(DataContainer.class);
+ spiMock = control.createMock(CacheSPI.class);
+ command = new GravitateDataCommand(fqn, true, new IpAddress());
+ command.initialize(containerMock, spiMock);
+ ctx = new InvocationContext();
+ }
+
+ public void testNonexistentNode()
+ {
+ command.setSearchSubtrees(false);
+ expect(spiMock.getNode(fqn)).andReturn(null);
+ control.replay();
+ assert GravitateResult.noDataFound().equals(command.perform(ctx));
+ }
+
+ public void testExistentNodeInTheCache()
+ {
+ MockNodesFixture nodes = new MockNodesFixture();
+ command.setSearchSubtrees(false);
+
+ expect(spiMock.getNode(fqn)).andReturn(nodes.adfNode);
+ ArrayList arrayList = new ArrayList();
+ expect(containerMock.buildNodeData(Collections.EMPTY_LIST,
nodes.adfNode)).andReturn(arrayList);
+ control.replay();
+ GravitateResult result = (GravitateResult) command.perform(ctx);
+ control.verify();
+
+ assert result != null;
+ assert result.getNodeData() == arrayList;
+ }
+
+ public void testNodeDoesExistsInBackupAndNoDead()
+ {
+ MockNodesFixture nodes = new MockNodesFixture();
+ expect(spiMock.getNode(fqn)).andReturn(null);
+
expect(containerMock.peek(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN)).andReturn(nodes.abNode);
+
+ Fqn firstSearch = Fqn.fromString(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN +
"/c/dummy");
+ expect(spiMock.getNode(firstSearch)).andReturn(nodes.abcNode);
+
+ ArrayList listReference = new ArrayList();
+ expect(containerMock.buildNodeData(Collections.EMPTY_LIST,
nodes.abcNode)).andReturn(listReference);
+
+ control.replay();
+ GravitateResult result = (GravitateResult) command.perform(ctx);
+ assert result.getNodeData()== listReference;
+ control.verify();
+ }
+
+ public void testNodeDoesNotExistsInBackupAndNoDead()
+ {
+ MockNodesFixture nodes = new MockNodesFixture();
+ expect(spiMock.getNode(fqn)).andReturn(null);
+
expect(containerMock.peek(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN)).andReturn(nodes.adfNode);
+
+ control.checkOrder(false);
+ Fqn firstSearch = Fqn.fromString(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN +
"/g/dummy");
+ expect(spiMock.getNode(firstSearch)).andReturn(null);
+ Fqn secondSearch = Fqn.fromString(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN +
"/h/dummy");
+ expect(spiMock.getNode(secondSearch)).andReturn(null);
+ control.checkOrder(true);
+
+ control.replay();
+ assert GravitateResult.noDataFound().equals(command.perform(ctx));
+ control.verify();
+ }
+
+ public void testDeadBeackup() throws Exception
+ {
+ NodeSpiMock root = new NodeSpiMock(Fqn.ROOT);
+
+ //add first dead child
+ IpAddress firstAddress = new IpAddress("127.0.0.1", 1234);
+ NodeSpiMock firstDeadNode = (NodeSpiMock)
root.addChildDirect(BuddyFqnTransformer.getDeadBackupRoot(firstAddress));
+ firstDeadNode.addChildDirect(Fqn.fromElements(0));
+ firstDeadNode.addChildDirect(Fqn.fromElements(1));
+ firstDeadNode.addChildDirect(Fqn.fromElements(2));
+
+ //add second dead child
+ IpAddress secondAddress = new IpAddress("127.0.0.1", 4321);
+ NodeSpiMock secondDeadNode = (NodeSpiMock)
root.addChildDirect(BuddyFqnTransformer.getDeadBackupRoot(secondAddress));
+ secondDeadNode.addChildDirect(Fqn.fromElements(0));
+
+
+ expect(spiMock.getNode(fqn)).andReturn(null);
+ NodeSPI buddyBackupRoot = (NodeSPI)
root.getChild(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN);
+
expect(containerMock.peek(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN)).andReturn(buddyBackupRoot);
+
+ control.checkOrder(false);
+
expect(spiMock.getChildrenNames(firstDeadNode.getFqn())).andReturn(firstDeadNode.getChildrenNames());
+ Object fqnElement = fqn.getLastElement();//this is only composed from one element
+ expect(spiMock.peek(Fqn.fromRelativeElements(firstDeadNode.getFqn(), 0,
fqnElement), false)).andReturn(null);
+ expect(spiMock.peek(Fqn.fromRelativeElements(firstDeadNode.getFqn(), 1,
fqnElement), false)).andReturn(null);
+ expect(spiMock.peek(Fqn.fromRelativeElements(firstDeadNode.getFqn(), 2,
fqnElement), false)).andReturn(null);
+
+
expect(spiMock.getChildrenNames(secondDeadNode.getFqn())).andReturn(secondDeadNode.getChildrenNames());
+ expect(spiMock.peek(Fqn.fromRelativeElements(secondDeadNode.getFqn(), 0,
fqnElement), false)).andReturn(null);
+ control.checkOrder(true);
+
+ control.replay();
+ assert GravitateResult.noDataFound().equals(command.perform(ctx));
+ control.verify();
+ }
+}
Modified:
core/trunk/src/test/java/org/jboss/cache/marshall/ReturnValueMarshallingTest.java
===================================================================
---
core/trunk/src/test/java/org/jboss/cache/marshall/ReturnValueMarshallingTest.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/test/java/org/jboss/cache/marshall/ReturnValueMarshallingTest.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -128,7 +128,7 @@
assertNotSame(MyList.class, cache2.get(fqn, key).getClass());
assertSame(listClass, cache2.get(fqn, key).getClass());
- GravitateDataCommand gravitateDataCommand = new GravitateDataCommand(fqn, false);
+ GravitateDataCommand gravitateDataCommand = new GravitateDataCommand(fqn, false,
cache1.getRPCManager().getLocalAddress());
List responses = cache1.getRPCManager().callRemoteMethods(null,
gravitateDataCommand, true, 15000, false);
GravitateResult data = (GravitateResult) responses.get(0);// response from the
first (and only) node
Added: core/trunk/src/test/java/org/jboss/cache/mock/MockNodesFixture.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/mock/MockNodesFixture.java
(rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/mock/MockNodesFixture.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -0,0 +1,67 @@
+package org.jboss.cache.mock;
+
+import org.jboss.cache.Fqn;
+
+/**
+ * This class builds a tree of <code>NodeSpiMock</code>s that can be used
through tests.
+ * <pre>
+ * It serves following purposes:
+ * - having a common known structure through all the tests is useful for test redability
+ * - not having to write again and again a new fixture for each test.
+ * </pre>
+ * Note: changing the fixture might cause tests depending on this class to fail, as the
expect certain number of nodes,
+ * number of child etc.
+ *
+ * @author Mircea.Markus(a)jboss.com
+ * @since 2.2
+ */
+public class MockNodesFixture
+{
+ public NodeSpiMock root;
+ public NodeSpiMock aNode;
+ public Fqn a;
+ public Fqn ab;
+ public Fqn abc;
+ public Fqn ad;
+ public Fqn ade;
+ public Fqn adf;
+ public Fqn adfh;
+ public Fqn adfg;
+ public NodeSpiMock abNode;
+ public NodeSpiMock abcNode;
+ public NodeSpiMock adNode;
+ public NodeSpiMock adeNode;
+ public NodeSpiMock adfNode;
+ public NodeSpiMock adfhNode;
+ public NodeSpiMock adfgNode;
+ public Fqn notExistent = Fqn.fromString("aaa" +
System.currentTimeMillis());
+
+ public MockNodesFixture()
+ {
+ this(Fqn.ROOT);
+ }
+
+ /**
+ * Will place the fqn prefix before all created nodes.
+ */
+ public MockNodesFixture(Fqn prefix)
+ {
+ a = Fqn.fromRelativeElements(prefix, "a");
+ ab = Fqn.fromRelativeElements(prefix, "a", "b");
+ abc = Fqn.fromRelativeElements(prefix, "a", "b",
"c");
+ ad = Fqn.fromRelativeElements(prefix, "a", "d");
+ ade = Fqn.fromRelativeElements(prefix, "a", "d",
"e");
+ adf = Fqn.fromRelativeElements(prefix, "a", "d",
"f");
+ adfh = Fqn.fromRelativeElements(prefix, "a", "d",
"f", "h");
+ adfg = Fqn.fromRelativeElements(prefix, "a", "d",
"f", "g");
+ root = new NodeSpiMock(Fqn.ROOT);
+ aNode = (NodeSpiMock) root.addChild(a);
+ abNode = (NodeSpiMock) root.addChild(ab);
+ abcNode = (NodeSpiMock) root.addChild(abc);
+ adNode = (NodeSpiMock) root.addChild(ad);
+ adeNode = (NodeSpiMock) root.addChild(ade);
+ adfNode = (NodeSpiMock) root.addChild(adf);
+ adfhNode = (NodeSpiMock) root.addChild(adfh);
+ adfgNode = (NodeSpiMock) root.addChild(adfg);
+ }
+}
Modified: core/trunk/src/test/java/org/jboss/cache/notifications/AnnotationsTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/notifications/AnnotationsTest.java 2008-05-14
17:05:33 UTC (rev 5849)
+++ core/trunk/src/test/java/org/jboss/cache/notifications/AnnotationsTest.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -23,13 +23,13 @@
@Test(groups = {"functional"})
public class AnnotationsTest
{
- private Notifier n;
+ private NotifierImpl n;
@BeforeMethod(alwaysRun = true)
public void setUp()
{
Cache c = new DefaultCacheFactory().createCache(false);
- n = new Notifier(c);
+ n = new NotifierImpl(c);
}
public void testControl()
Modified:
core/trunk/src/test/java/org/jboss/cache/notifications/RemoteCacheListenerTest.java
===================================================================
---
core/trunk/src/test/java/org/jboss/cache/notifications/RemoteCacheListenerTest.java 2008-05-14
17:05:33 UTC (rev 5849)
+++
core/trunk/src/test/java/org/jboss/cache/notifications/RemoteCacheListenerTest.java 2008-05-15
12:44:49 UTC (rev 5850)
@@ -114,7 +114,7 @@
cr1 = TestingUtil.extractComponentRegistry(cache1);
cr2 = TestingUtil.extractComponentRegistry(cache2);
assert cr1 != cr2;
- assert cr1.getComponent(Notifier.class) != cr2.getComponent(Notifier.class);
+ assert cr1.getComponent(NotifierImpl.class) !=
cr2.getComponent(NotifierImpl.class);
assert eventLog1 != eventLog2;
assert cache1.getLocalAddress() != cache2.getLocalAddress();
CacheSPI spi1, spi2;