You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:27:52 UTC

[sling-org-apache-sling-discovery-oak] 04/08: SLING-5215 : fixed getTopology to return the correct, previous oldView when the view is undefined, ie not current. This is achieved by making sure OakDiscoveryService sets the oldView whenever the view changes

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.discovery.oak-1.0.2
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-discovery-oak.git

commit ed30aaa4113cbf5edda89e3ea9004c6906ed4f31
Author: Stefan Egli <st...@apache.org>
AuthorDate: Thu Oct 29 12:45:55 2015 +0000

    SLING-5215 : fixed getTopology to return the correct, previous oldView when the view is undefined, ie not current. This is achieved by making sure OakDiscoveryService sets the oldView whenever the view changes
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/discovery/oak@1711239 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/discovery/oak/OakDiscoveryService.java   |   3 +-
 .../discovery/oak/its/OakDiscoveryServiceTest.java | 186 +++++++++++++++++++++
 .../oak/its/setup/OakVirtualInstanceBuilder.java   |   4 +
 .../oak/its/setup/SimulatedLeaseCollection.java    |   8 +-
 4 files changed, 199 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/apache/sling/discovery/oak/OakDiscoveryService.java b/src/main/java/org/apache/sling/discovery/oak/OakDiscoveryService.java
index 49c307b..49677c9 100644
--- a/src/main/java/org/apache/sling/discovery/oak/OakDiscoveryService.java
+++ b/src/main/java/org/apache/sling/discovery/oak/OakDiscoveryService.java
@@ -619,11 +619,12 @@ public class OakDiscoveryService extends BaseDiscoveryService {
                 logger.debug("checkForTopologyChange: not yet activated, ignoring");
                 return;
             }
-            BaseTopologyView t = (BaseTopologyView) getTopology();
+            DefaultTopologyView t = (DefaultTopologyView) getTopology();
             if (t.isCurrent()) {
                 // if we have a valid view, let the viewStateManager do the
                 // comparison and sending of an event, if necessary
                 viewStateManager.handleNewView(t);
+                setOldView(t);
             } else {
                 // if we don't have a view, then we might have to send
                 // a CHANGING event, let that be decided by the viewStateManager as well
diff --git a/src/test/java/org/apache/sling/discovery/oak/its/OakDiscoveryServiceTest.java b/src/test/java/org/apache/sling/discovery/oak/its/OakDiscoveryServiceTest.java
new file mode 100644
index 0000000..65f63a3
--- /dev/null
+++ b/src/test/java/org/apache/sling/discovery/oak/its/OakDiscoveryServiceTest.java
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.oak.its;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
+import org.apache.sling.discovery.TopologyEvent.Type;
+import org.apache.sling.discovery.TopologyView;
+import org.apache.sling.discovery.base.its.setup.VirtualInstance;
+import org.apache.sling.discovery.base.its.setup.VirtualInstanceBuilder;
+import org.apache.sling.discovery.base.its.setup.mock.AssertingTopologyEventListener;
+import org.apache.sling.discovery.oak.OakDiscoveryService;
+import org.apache.sling.discovery.oak.its.setup.OakVirtualInstanceBuilder;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OakDiscoveryServiceTest {
+
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    private Level logLevel;
+
+    private VirtualInstance instance1;
+
+    private VirtualInstance instance2;
+
+    protected OakVirtualInstanceBuilder newBuilder() {
+        return new OakVirtualInstanceBuilder();
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        final org.apache.log4j.Logger discoveryLogger = LogManager.getRootLogger().getLogger("org.apache.sling.discovery");
+        logLevel = discoveryLogger.getLevel();
+        discoveryLogger.setLevel(Level.TRACE);        
+    }
+    
+    @After
+    public void teartDown() throws Throwable {
+        final org.apache.log4j.Logger discoveryLogger = LogManager.getRootLogger().getLogger("org.apache.sling.discovery");
+        discoveryLogger.setLevel(logLevel);
+        if (instance1!=null) {
+            instance1.stopViewChecker();
+            instance1.stop();
+            instance1 = null;
+        }
+        if (instance2!=null) {
+            instance2.stopViewChecker();
+            instance2.stop();
+            instance2 = null;
+        }
+    }
+    
+    /**
+     * Tests whether the not-current view returned by getTopology()
+     * matches what listeners get in TOPOLOGY_CHANGING - it should
+     * basically be the same.
+     */
+    @Test
+    public void testOldView() throws Throwable {
+        final org.apache.log4j.Logger discoveryLogger = LogManager.getRootLogger().getLogger("org.apache.sling.discovery");
+        discoveryLogger.setLevel(Level.INFO); // info should do
+        OakVirtualInstanceBuilder builder = newBuilder();
+        builder.setDebugName("firstInstanceA")
+                .newRepository("/var/discovery/oak/", true)
+                .setConnectorPingTimeout(3 /* heartbeat-timeout */)
+                .setMinEventDelay(3 /*min event delay*/);
+        instance1 = builder.build();
+        instance1.stopViewChecker();
+//        instance1.stopVoting();
+        TopologyView t1 = instance1.getDiscoveryService().getTopology();
+        assertFalse(t1.isCurrent()); // current it should not be
+        assertEquals(1, t1.getInstances().size()); // but it can as well contain the local instance
+        AssertingTopologyEventListener l1 = new AssertingTopologyEventListener("instance1.l1");
+        l1.addExpected(Type.TOPOLOGY_INIT);
+        instance1.bindTopologyEventListener(l1);
+        logger.info("testOldView: instance1 created, no events expected yet. slingId="+instance1.slingId);
+        instance1.heartbeatsAndCheckView();
+        Thread.sleep(200);
+        instance1.heartbeatsAndCheckView();
+        Thread.sleep(200);
+        instance1.heartbeatsAndCheckView();
+        Thread.sleep(200);
+        logger.info("testOldView: 2nd/3rd heartbeat sent - now expecting a TOPOLOGY_INIT");
+        instance1.dumpRepo();
+        assertEquals(1, l1.getEvents().size()); // one event
+        assertEquals(0, l1.getRemainingExpectedCount()); // the expected one
+        assertEquals(0, l1.getUnexpectedCount());
+        t1 = instance1.getDiscoveryService().getTopology();
+        assertTrue(t1.isCurrent()); // current it should now be
+        assertEquals(1, t1.getInstances().size()); // and it must contain the local instance
+        
+        logger.info("testOldView: creating instance2");
+        builder.getSimulatedLeaseCollection().setFinal(false);
+        l1.addExpected(Type.TOPOLOGY_CHANGING);
+        VirtualInstanceBuilder builder2 = newBuilder();
+        builder2.setDebugName("secondInstanceB")
+                .useRepositoryOf(instance1)
+                .setConnectorPingTimeout(3)
+                .setMinEventDelay(3);
+        instance2 = builder2.build();
+        instance2.stopViewChecker();
+//        instance2.stopVoting();
+        
+        logger.info("testOldView: instance2 created, now issuing one heartbeat with instance2 first, so that instance1 can take note of it");
+        instance2.getViewChecker().checkView();
+        OakDiscoveryService oakDisco1 = (OakDiscoveryService) instance2.getDiscoveryService();
+        oakDisco1.checkForTopologyChange();
+        logger.info("testOldView: now instance1 is also doing a heartbeat and should see that a new instance is there");
+        instance1.getViewChecker().checkView();
+        OakDiscoveryService oakDisco2 = (OakDiscoveryService) instance1.getDiscoveryService();
+        oakDisco2.checkForTopologyChange();
+        logger.info("testOldView: 500ms sleep...");
+        Thread.sleep(500); // allow some time for CHANGING to be sent
+        logger.info("testOldView: 500ms sleep done.");
+
+        assertEquals(2, l1.getEvents().size()); // INIT and CHANGING
+        assertEquals(0, l1.getRemainingExpectedCount()); // no remaining expected
+        assertEquals(0, l1.getUnexpectedCount()); // and no unexpected
+        t1 = instance1.getDiscoveryService().getTopology();
+        assertFalse(t1.isCurrent()); // current it should not be
+        assertEquals(1, t1.getInstances().size()); // but it should still contain the local instance from before
+        
+        builder.getSimulatedLeaseCollection().setFinal(true);
+        l1.addExpected(Type.TOPOLOGY_CHANGED);
+        logger.info("testOldView: now issuing 3 rounds of heartbeats/checks and expecting a TOPOLOGY_CHANGED then");
+
+        instance2.heartbeatsAndCheckView();
+//        instance2.analyzeVotings();
+        instance1.heartbeatsAndCheckView();
+//        instance1.analyzeVotings();
+        Thread.sleep(1200);
+        instance2.heartbeatsAndCheckView();
+        instance1.heartbeatsAndCheckView();
+        Thread.sleep(1200);
+        instance2.heartbeatsAndCheckView();
+        instance1.heartbeatsAndCheckView();
+        Thread.sleep(1200);
+        
+        assertEquals(3, l1.getEvents().size()); // INIT, CHANGING and CHANGED
+        assertEquals(0, l1.getRemainingExpectedCount()); // no remaining expected
+        assertEquals(0, l1.getUnexpectedCount()); // and no unexpected
+        t1 = instance1.getDiscoveryService().getTopology();
+        assertTrue(t1.isCurrent()); // and we should be current again
+        assertEquals(2, t1.getInstances().size()); // and contain both instances now
+        
+        // timeout is set to 3sec, so we now do heartbeats for 4sec with only instance1
+        // to let instance2 crash
+        builder.getSimulatedLeaseCollection().setFinal(false);
+        l1.addExpected(Type.TOPOLOGY_CHANGING);
+        for(int i=0; i<8; i++) {
+            instance1.heartbeatsAndCheckView();
+            Thread.sleep(500);
+        }
+        assertEquals(4, l1.getEvents().size()); // INIT, CHANGING, CHANGED and CHANGING
+        assertEquals(0, l1.getRemainingExpectedCount()); // no remaining expected
+        assertEquals(0, l1.getUnexpectedCount()); // and no unexpected
+        t1 = instance1.getDiscoveryService().getTopology();
+        assertFalse(t1.isCurrent()); // and we should be current again
+        assertEquals(2, t1.getInstances().size()); // and contain both instances now
+    }
+    
+}
diff --git a/src/test/java/org/apache/sling/discovery/oak/its/setup/OakVirtualInstanceBuilder.java b/src/test/java/org/apache/sling/discovery/oak/its/setup/OakVirtualInstanceBuilder.java
index acf20e3..bfb7296 100644
--- a/src/test/java/org/apache/sling/discovery/oak/its/setup/OakVirtualInstanceBuilder.java
+++ b/src/test/java/org/apache/sling/discovery/oak/its/setup/OakVirtualInstanceBuilder.java
@@ -57,6 +57,10 @@ public class OakVirtualInstanceBuilder extends VirtualInstanceBuilder {
     private OakBacklogClusterSyncService consistencyService;
     private SyncTokenService syncTokenService;
     
+    public SimulatedLeaseCollection getSimulatedLeaseCollection() {
+        return leaseCollection;
+    }
+    
     @Override
     public VirtualInstanceBuilder createNewRepository() throws Exception {
         nodeStore = new MemoryNodeStore();
diff --git a/src/test/java/org/apache/sling/discovery/oak/its/setup/SimulatedLeaseCollection.java b/src/test/java/org/apache/sling/discovery/oak/its/setup/SimulatedLeaseCollection.java
index eed9568..02abf26 100644
--- a/src/test/java/org/apache/sling/discovery/oak/its/setup/SimulatedLeaseCollection.java
+++ b/src/test/java/org/apache/sling/discovery/oak/its/setup/SimulatedLeaseCollection.java
@@ -40,6 +40,8 @@ public class SimulatedLeaseCollection {
     private final String viewId = UUID.randomUUID().toString();
     
     List<SimulatedLease> leases = new LinkedList<SimulatedLease>();
+
+    private volatile boolean isFinal = true;
     
     public SimulatedLeaseCollection() {
         // empty
@@ -66,7 +68,7 @@ public class SimulatedLeaseCollection {
                 new DiscoveryLiteDescriptorBuilder();
         discoBuilder.me(clusterNodeId);
         discoBuilder.id(viewId);
-        discoBuilder.setFinal(true);       
+        discoBuilder.setFinal(isFinal);       
         List<Integer> actives = new LinkedList<Integer>();
         List<Integer> inactives = new LinkedList<Integer>();
         for (Map.Entry<String, Long> entry : leaseUpdates.entrySet()) {
@@ -99,4 +101,8 @@ public class SimulatedLeaseCollection {
         clusterNodeIds.clear();
     }
 
+    public void setFinal(boolean isFinal) {
+        this.isFinal = isFinal;
+    }
+
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.