You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by st...@apache.org on 2013/10/31 11:04:37 UTC
svn commit: r1537422 - in /sling/trunk/bundles/extensions/discovery/impl/src:
main/java/org/apache/sling/discovery/impl/cluster/voting/
main/java/org/apache/sling/discovery/impl/common/
test/java/org/apache/sling/discovery/impl/cluster/
Author: stefanegli
Date: Thu Oct 31 10:04:37 2013
New Revision: 1537422
URL: http://svn.apache.org/r1537422
Log:
SLING-3195 : Provide a property to uniquely identify a Cluster : achieved by making the existing ClusterView.getId stable: the id is stored as part of the votingView and propagates as part of view changes. The initial id is identical to the one chosen for the isolated-mode - hence for one-node cases the clusterView.getId is also stable in that case.
Modified:
sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/cluster/voting/VotingHandler.java
sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/cluster/voting/VotingView.java
sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/common/View.java
sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/ClusterTest.java
Modified: sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/cluster/voting/VotingHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/cluster/voting/VotingHandler.java?rev=1537422&r1=1537421&r2=1537422&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/cluster/voting/VotingHandler.java (original)
+++ sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/cluster/voting/VotingHandler.java Thu Oct 31 10:04:37 2013
@@ -366,6 +366,7 @@ public class VotingHandler implements Ev
winningVoteMap.put("leaderId", leaderid);
winningVoteMap.put("leaderElectionId", leaderElectionId);
winningVoteMap.put("promotedAt", Calendar.getInstance());
+ winningVoteMap.put("promotedBy", slingId);
// 3b: move the result under /established
final String newEstablishedViewPath = establishedViewsResource.getPath()
Modified: sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/cluster/voting/VotingView.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/cluster/voting/VotingView.java?rev=1537422&r1=1537421&r2=1537422&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/cluster/voting/VotingView.java (original)
+++ sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/cluster/voting/VotingView.java Thu Oct 31 10:04:37 2013
@@ -32,6 +32,7 @@ import org.apache.sling.api.resource.Res
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.discovery.impl.Config;
import org.apache.sling.discovery.impl.common.View;
+import org.apache.sling.discovery.impl.common.ViewHelper;
import org.apache.sling.discovery.impl.common.resource.ResourceHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -64,6 +65,37 @@ public class VotingView extends View {
+ newViewId);
final ModifiableValueMap votingMap = votingResource.adaptTo(ModifiableValueMap.class);
votingMap.put("votingStart", Calendar.getInstance());
+
+ String clusterId = null;
+ Calendar clusterIdDefinedAt = null;
+ String clusterIdDefinedBy = null;
+ final View currentlyEstablishedView = ViewHelper.getEstablishedView(resourceResolver, config);
+ if (currentlyEstablishedView != null) {
+ final ValueMap establishedViewValueMap = currentlyEstablishedView.getResource().adaptTo(ValueMap.class);
+ clusterId = establishedViewValueMap.get(VIEW_PROPERTY_CLUSTER_ID, String.class);
+ if (clusterId == null || clusterId.length() == 0) {
+ clusterId = currentlyEstablishedView.getResource().getName();
+ }
+ Date date = establishedViewValueMap.get(VIEW_PROPERTY_CLUSTER_ID_DEFINED_AT, Date.class);
+ if (date!=null) {
+ clusterIdDefinedAt = Calendar.getInstance();
+ clusterIdDefinedAt.setTime(date);
+ }
+ clusterIdDefinedBy = establishedViewValueMap.get(VIEW_PROPERTY_CLUSTER_ID_DEFINED_BY, String.class);
+ }
+ if (clusterId == null || clusterId.length() == 0) {
+ clusterId = newViewId;
+ clusterIdDefinedAt = Calendar.getInstance();
+ }
+ votingMap.put(VIEW_PROPERTY_CLUSTER_ID, clusterId);
+ if (clusterIdDefinedAt != null) {
+ votingMap.put(VIEW_PROPERTY_CLUSTER_ID_DEFINED_AT, clusterIdDefinedAt);
+ }
+ if (clusterIdDefinedBy == null || clusterIdDefinedBy.length() == 0) {
+ clusterIdDefinedBy = initiatorId;
+ }
+ votingMap.put(VIEW_PROPERTY_CLUSTER_ID_DEFINED_BY, clusterIdDefinedBy);
+
final Resource membersResource = resourceResolver.create(votingResource, "members", null);
final Iterator<String> it = liveInstances.iterator();
while (it.hasNext()) {
Modified: sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/common/View.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/common/View.java?rev=1537422&r1=1537421&r2=1537422&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/common/View.java (original)
+++ sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/common/View.java Thu Oct 31 10:04:37 2013
@@ -25,6 +25,7 @@ import java.util.Set;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.discovery.impl.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,6 +35,10 @@ import org.slf4j.LoggerFactory;
*/
public class View {
+ protected static final String VIEW_PROPERTY_CLUSTER_ID = "clusterId";
+ protected static final String VIEW_PROPERTY_CLUSTER_ID_DEFINED_AT = "clusterIdDefinedAt";
+ protected static final String VIEW_PROPERTY_CLUSTER_ID_DEFINED_BY = "clusterIdDefinedBy";
+
/**
* use static logger to avoid frequent initialization as is potentially the
* case with ClusterViewResource.
@@ -76,7 +81,13 @@ public class View {
* @return the id of this view
*/
public String getViewId() {
- return getResource().getName();
+ final ValueMap props = getResource().adaptTo(ValueMap.class);
+ final String clusterId = props.get(VIEW_PROPERTY_CLUSTER_ID, String.class);
+ if (clusterId != null && clusterId.length() > 0) {
+ return clusterId;
+ } else {
+ return getResource().getName();
+ }
}
/**
Modified: sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/ClusterTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/ClusterTest.java?rev=1537422&r1=1537421&r2=1537422&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/ClusterTest.java (original)
+++ sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/ClusterTest.java Thu Oct 31 10:04:37 2013
@@ -19,6 +19,7 @@
package org.apache.sling.discovery.impl.cluster;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -74,6 +75,81 @@ public class ClusterTest {
}
@Test
+ public void testStableClusterId() throws Throwable {
+ // stop 1 and 2 and create them with a lower heartbeat timeout
+ instance2.stopHeartbeats();
+ instance1.stopHeartbeats();
+ instance2.stop();
+ instance1.stop();
+ instance1 = Instance.newStandaloneInstance("/var/discovery/impl/", "firstInstance", true, 1, 1);
+ instance2 = Instance.newClusterInstance("/var/discovery/impl/", "secondInstance", instance1,
+ false, 1, 1);
+ assertNotNull(instance1);
+ assertNotNull(instance2);
+
+ String clusterId1 = instance1.getClusterViewService()
+ .getClusterView().getId();
+ String clusterId2 = instance2.getClusterViewService()
+ .getClusterView().getId();
+ // the cluster ids must differ
+ assertNotEquals(clusterId1, clusterId2);
+ assertEquals(1, instance1.getClusterViewService().getClusterView().getInstances().size());
+ assertEquals(1, instance2.getClusterViewService().getClusterView().getInstances().size());
+
+ // let the sync/voting happen
+ instance1.runHeartbeatOnce();
+ instance2.runHeartbeatOnce();
+ Thread.sleep(500);
+ instance1.runHeartbeatOnce();
+ instance2.runHeartbeatOnce();
+ Thread.sleep(500);
+ instance1.runHeartbeatOnce();
+ instance2.runHeartbeatOnce();
+
+ String newClusterId1 = instance1.getClusterViewService()
+ .getClusterView().getId();
+ String newClusterId2 = instance2.getClusterViewService()
+ .getClusterView().getId();
+ // both cluster ids must be the same
+ assertEquals(newClusterId1, newClusterId1);
+
+ // either instance1 or instance2 must have kept the cluster id
+ if (!newClusterId1.equals(clusterId1)) {
+ assertEquals(newClusterId2, clusterId2);
+ }
+ instance1.dumpRepo();
+ assertEquals(2, instance1.getClusterViewService().getClusterView().getInstances().size());
+ assertEquals(2, instance2.getClusterViewService().getClusterView().getInstances().size());
+
+ // let instance2 'die' by now longer doing heartbeats
+ instance2.stopHeartbeats(); // would actually not be necessary as it was never started.. this test only runs heartbeats manually
+ instance1.runHeartbeatOnce();
+ Thread.sleep(500);
+ instance1.runHeartbeatOnce();
+ Thread.sleep(500);
+ instance1.runHeartbeatOnce();
+ Thread.sleep(500);
+ instance1.runHeartbeatOnce();
+ Thread.sleep(500);
+ instance1.runHeartbeatOnce();
+ Thread.sleep(500);
+ instance1.runHeartbeatOnce();
+ // the cluster should now have size 1
+ assertEquals(1, instance1.getClusterViewService().getClusterView().getInstances().size());
+ // the instance 2 should be in isolated mode as it is no longer in the established view
+ // hence also size 1
+ assertEquals(1, instance2.getClusterViewService().getClusterView().getInstances().size());
+
+ // but the cluster id must have remained stable
+ instance1.dumpRepo();
+ String actualClusterId = instance1.getClusterViewService()
+ .getClusterView().getId();
+ System.err.println("expected cluster id: "+newClusterId1);
+ System.err.println("actual cluster id: "+actualClusterId);
+ assertEquals(newClusterId1, actualClusterId);
+ }
+
+ @Test
public void testClusterView() throws Exception {
assertNotNull(instance1);
assertNotNull(instance2);