Author: manik.surtani(a)jboss.com
Date: 2007-11-14 14:48:10 -0500 (Wed, 14 Nov 2007)
New Revision: 4755
Modified:
core/trunk/src/main/java/org/jboss/cache/statetransfer/DefaultStateTransferIntegrator.java
core/trunk/src/test/java/org/jboss/cache/notifications/RemoteCacheListenerTest.java
Log:
JBCACHE-1216 - node modified notifications not emitted during state transfer
Modified:
core/trunk/src/main/java/org/jboss/cache/statetransfer/DefaultStateTransferIntegrator.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/statetransfer/DefaultStateTransferIntegrator.java 2007-11-14
17:00:17 UTC (rev 4754)
+++
core/trunk/src/main/java/org/jboss/cache/statetransfer/DefaultStateTransferIntegrator.java 2007-11-14
19:48:10 UTC (rev 4755)
@@ -23,10 +23,11 @@
import org.jboss.cache.marshall.NodeData;
import org.jboss.cache.marshall.NodeDataExceptionMarker;
import org.jboss.cache.marshall.NodeDataMarker;
-import org.jboss.cache.optimistic.DataVersion;
+import org.jboss.cache.notifications.event.NodeModifiedEvent;
import java.io.IOException;
import java.io.ObjectInputStream;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -198,8 +199,16 @@
private void notifyAllNodesCreated(InvocationContext ctx, NodeSPI curr)
{
if (curr == null) return;
+ ctx.setOriginLocal(false);
getCache().getNotifier().notifyNodeCreated(curr.getFqn(), true, ctx);
getCache().getNotifier().notifyNodeCreated(curr.getFqn(), false, ctx);
+ if (!curr.getKeysDirect().isEmpty())
+ {
+ getCache().getNotifier().notifyNodeModified(curr.getFqn(), true,
NodeModifiedEvent.ModificationType.PUT_MAP, Collections.emptyMap(), ctx);
+ getCache().getNotifier().notifyNodeModified(curr.getFqn(), false,
NodeModifiedEvent.ModificationType.PUT_MAP, curr.getDataDirect(), ctx);
+ }
+ ctx.setOriginLocal(true);
+ // AND notify that they have been modified!!
Set<NodeSPI> children = curr.getChildrenDirect();
for (NodeSPI n : children)
{
Modified:
core/trunk/src/test/java/org/jboss/cache/notifications/RemoteCacheListenerTest.java
===================================================================
---
core/trunk/src/test/java/org/jboss/cache/notifications/RemoteCacheListenerTest.java 2007-11-14
17:00:17 UTC (rev 4754)
+++
core/trunk/src/test/java/org/jboss/cache/notifications/RemoteCacheListenerTest.java 2007-11-14
19:48:10 UTC (rev 4755)
@@ -22,29 +22,6 @@
package org.jboss.cache.notifications;
-import static org.jboss.cache.notifications.event.Event.Type.NODE_CREATED;
-import static org.jboss.cache.notifications.event.Event.Type.NODE_MODIFIED;
-import static org.jboss.cache.notifications.event.Event.Type.NODE_MOVED;
-import static org.jboss.cache.notifications.event.Event.Type.NODE_REMOVED;
-import static org.jboss.cache.notifications.event.Event.Type.TRANSACTION_COMPLETED;
-import static org.jboss.cache.notifications.event.Event.Type.TRANSACTION_REGISTERED;
-import static
org.jboss.cache.notifications.event.NodeModifiedEvent.ModificationType.PUT_DATA;
-import static
org.jboss.cache.notifications.event.NodeModifiedEvent.ModificationType.PUT_MAP;
-import static
org.jboss.cache.notifications.event.NodeModifiedEvent.ModificationType.REMOVE_DATA;
-import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertNull;
-import static org.testng.AssertJUnit.assertTrue;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-
import org.jboss.cache.Cache;
import org.jboss.cache.CacheFactory;
import org.jboss.cache.DefaultCacheFactory;
@@ -52,11 +29,25 @@
import org.jboss.cache.Node;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.lock.IsolationLevel;
+import org.jboss.cache.misc.TestingUtil;
import org.jboss.cache.notifications.event.Event;
+import static org.jboss.cache.notifications.event.Event.Type.*;
import org.jboss.cache.notifications.event.EventImpl;
+import org.jboss.cache.notifications.event.NodeModifiedEvent;
+import static org.jboss.cache.notifications.event.NodeModifiedEvent.ModificationType.*;
+import static org.testng.AssertJUnit.*;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
/**
* Remote conterpart of CacheListenerTest. Main difference is event is originating as
local.
*
@@ -82,7 +73,6 @@
if (optLocking)
c.setNodeLockingScheme(Configuration.NodeLockingScheme.OPTIMISTIC);
c.setTransactionManagerLookupClass("org.jboss.cache.transaction.DummyTransactionManagerLookup");
- c.setFetchInMemoryState(false);
// we need this because notifications emitted by the notification interceptor are
done during the commit call.
// If we want to check notifications on remote nodes we need to make sure the
commit completes before we test anything.
@@ -613,6 +603,51 @@
assertEquals(expected, eventLog2.events);
}
+ public void testStateTransfer() throws Exception
+ {
+ // first stop cache2
+ TestingUtil.killCaches(cache2);
+ // wait till cache2 has disappeared.
+ TestingUtil.blockUntilViewsReceived(5000, false, cache1);
+
+ // get some state in cache1
+ Fqn fqnA = Fqn.fromString("/a");
+ Fqn fqnB = Fqn.fromString("/a/b");
+ Map<String, String> data = Collections.singletonMap("k",
"v");
+ cache1.put(fqnA, data);
+ cache1.put(fqnB, data);
+
+ // create cache2
+ CacheFactory<String, String> instance = DefaultCacheFactory.getInstance();
+ cache2 = instance.createCache(cache1.getConfiguration().clone(), false);
+ cache2.create();
+ eventLog2.events.clear();
+ cache2.addCacheListener(eventLog2);
+ cache2.start(); // should initiate a state transfer
+
+ // wait until cache2 has joined the cluster
+ TestingUtil.blockUntilViewsReceived(5000, cache1, cache2);
+
+ List<Event> expected = new ArrayList<Event>();
+ // public EventImpl(boolean pre, Cache cache, ModificationType modificationType,
Map data, Fqn fqn,
+ // Transaction transaction, boolean originLocal, Fqn targetFqn, boolean successful,
View newView, Type type)
+
+ expected.add(new EventImpl(true, cache2, null, null, Fqn.ROOT, null, false, null,
false, null, NODE_CREATED));
+ expected.add(new EventImpl(false, cache2, null, null, Fqn.ROOT, null, false, null,
false, null, NODE_CREATED));
+
+ expected.add(new EventImpl(true, cache2, null, null, fqnA, null, false, null,
false, null, NODE_CREATED));
+ expected.add(new EventImpl(false, cache2, null, null, fqnA, null, false, null,
false, null, NODE_CREATED));
+ expected.add(new EventImpl(true, cache2,
NodeModifiedEvent.ModificationType.PUT_MAP, Collections.emptyMap(), fqnA, null, false,
null, false, null, NODE_MODIFIED));
+ expected.add(new EventImpl(false, cache2,
NodeModifiedEvent.ModificationType.PUT_MAP, data, fqnA, null, false, null, false, null,
NODE_MODIFIED));
+
+ expected.add(new EventImpl(true, cache2, null, null, fqnB, null, false, null,
false, null, NODE_CREATED));
+ expected.add(new EventImpl(false, cache2, null, null, fqnB, null, false, null,
false, null, NODE_CREATED));
+ expected.add(new EventImpl(true, cache2,
NodeModifiedEvent.ModificationType.PUT_MAP, Collections.emptyMap(), fqnB, null, false,
null, false, null, NODE_MODIFIED));
+ expected.add(new EventImpl(false, cache2,
NodeModifiedEvent.ModificationType.PUT_MAP, data, fqnB, null, false, null, false, null,
NODE_MODIFIED));
+
+ assertEquals(expected, eventLog2.events);
+ }
+
private void setCache(Cache<String, String> c, List<Event> l)
{
for (Event e : l)