stefan-egli closed pull request #1: SLING-7830 : introduce
invertLeaderElectionPrefixOrder and leaderElec…
URL: https://github.com/apache/sling-org-apache-sling-discovery-oak/pull/1
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/src/main/java/org/apache/sling/discovery/oak/Config.java
b/src/main/java/org/apache/sling/discovery/oak/Config.java
index 4bb4095..e47cd9d 100644
--- a/src/main/java/org/apache/sling/discovery/oak/Config.java
+++ b/src/main/java/org/apache/sling/discovery/oak/Config.java
@@ -179,6 +179,16 @@
private static final String BACKOFF_STABLE_FACTOR = "backoffStableFactor";
private static final int DEFAULT_BACKOFF_STABLE_FACTOR = 5;
+ private static final long DEFAULT_LEADER_ELECTION_PREFIX = 1;
+ @Property(longValue=DEFAULT_LEADER_ELECTION_PREFIX)
+ private static final String LEADER_ELECTION_PREFIX =
"leaderElectionPrefix";
+ protected long leaderElectionPrefix = DEFAULT_LEADER_ELECTION_PREFIX;
+
+ private static final boolean DEFAULT_INVERT_LEADER_ELECTION_PREFIX_ORDER =
false;
+ @Property(boolValue=DEFAULT_INVERT_LEADER_ELECTION_PREFIX_ORDER)
+ private static final String INVERT_LEADER_ELECTION_PREFIX_ORDER =
"invertLeaderElectionPrefixOrder";
+ protected boolean invertLeaderElectionPrefixOrder =
DEFAULT_INVERT_LEADER_ELECTION_PREFIX_ORDER;
+
/** True when auto-stop of a local-loop is enabled. Default is false. **/
private boolean autoStopLocalLoopEnabled;
@@ -339,6 +349,17 @@ protected void configure(final Map<String, Object>
properties) {
DEFAULT_BACKOFF_STANDBY_FACTOR);
backoffStableFactor =
PropertiesUtil.toInteger(properties.get(BACKOFF_STABLE_FACTOR),
DEFAULT_BACKOFF_STABLE_FACTOR);
+
+ this.invertLeaderElectionPrefixOrder = PropertiesUtil.toBoolean(
+ properties.get(INVERT_LEADER_ELECTION_PREFIX_ORDER),
+ DEFAULT_INVERT_LEADER_ELECTION_PREFIX_ORDER);
+ logger.debug("configure: invertLeaderElectionPrefixOrder='{}'",
+ this.invertLeaderElectionPrefixOrder);
+ this.leaderElectionPrefix = PropertiesUtil.toLong(
+ properties.get(LEADER_ELECTION_PREFIX),
+ DEFAULT_LEADER_ELECTION_PREFIX);
+ logger.debug("configure: leaderElectionPrefix='{}'",
+ this.leaderElectionPrefix);
}
/**
@@ -506,4 +527,12 @@ public long getClusterSyncServiceIntervalMillis() {
public boolean getSyncTokenEnabled() {
return syncTokenEnabled;
}
+
+ public boolean isInvertLeaderElectionPrefixOrder() {
+ return invertLeaderElectionPrefixOrder;
+ }
+
+ public long getLeaderElectionPrefix() {
+ return leaderElectionPrefix;
+ }
}
diff --git
a/src/main/java/org/apache/sling/discovery/oak/cluster/OakClusterViewService.java
b/src/main/java/org/apache/sling/discovery/oak/cluster/OakClusterViewService.java
index af30f20..2632806 100644
---
a/src/main/java/org/apache/sling/discovery/oak/cluster/OakClusterViewService.java
+++
b/src/main/java/org/apache/sling/discovery/oak/cluster/OakClusterViewService.java
@@ -196,14 +196,7 @@ private LocalClusterView
asClusterView(DiscoveryLiteDescriptor descriptor, Resou
leaderElectionIds.put(id, leaderElectionId);
}
- Collections.sort(activeIdsList, new Comparator<Integer>() {
-
- @Override
- public int compare(Integer arg0, Integer arg1) {
- return leaderElectionIds.get(arg0)
- .compareTo(leaderElectionIds.get(arg1));
- }
- });
+ leaderElectionSort(activeIdsList, leaderElectionIds);
for(int i=0; i<activeIdsList.size(); i++) {
int id = activeIdsList.get(i);
@@ -233,6 +226,66 @@ public int compare(Integer arg0, Integer arg1) {
}
}
+ private void leaderElectionSort(List<Integer> activeIdsList, final
Map<Integer, String> leaderElectionIds) {
+ final Comparator<Integer> comparator;
+ if (config.isInvertLeaderElectionPrefixOrder()) {
+ // SLING-7830 : inverted leaderElectionPrefix sorting
+ comparator = new Comparator<Integer>() {
+
+ private long prefixOf(String leaderElectionId) {
+ final int underScore = leaderElectionId.indexOf("_");
+ if (underScore == -1) {
+ return -1;
+ }
+ final String prefixStr = leaderElectionId.substring(0,
underScore);
+ try{
+ return Long.parseLong(prefixStr);
+ } catch(Exception e) {
+ return -1;
+ }
+ }
+
+ @Override
+ public int compare(Integer arg0, Integer arg1) {
+ // 'inverted sorting' means that the prefix is ordered
descending
+ // while the remainder is ordered ascending
+ final String leaderElectionId0 =
leaderElectionIds.get(arg0);
+ final String leaderElectionId1 =
leaderElectionIds.get(arg1);
+ // so first step is to order the part before '_', eg the
'1' in
+ //
1_0000001534409616936_374019fc-68bd-4c8d-a4cf-8ee8b07c63bc
+ final long prefix0 = prefixOf(leaderElectionId0);
+ final long prefix1 = prefixOf(leaderElectionId1);
+ // if a prefix is -1 (due to eg wrong formatting) it
automatically
+ // ends up at the end
+ if (prefix0 == prefix1) {
+ // if they are the same, order the classic way
+ // note that when they are both '-1' that can be one
of the following
+ //
-1_0000001534409616936_374019fc-68bd-4c8d-a4cf-8ee8b07c63bc
+ //
_0000001534409616936_374019fc-68bd-4c8d-a4cf-8ee8b07c63bc
+ //
notALong_0000001534409616936_374019fc-68bd-4c8d-a4cf-8ee8b07c63bc
+ // so all of the above three get compared the classic
way
+ return leaderElectionId0
+ .compareTo(leaderElectionId1);
+ } else {
+ // inverted order comparison:
+ return new Long(prefix1).compareTo(prefix0);
+ }
+ }
+
+ };
+ } else {
+ comparator = new Comparator<Integer>() {
+
+ @Override
+ public int compare(Integer arg0, Integer arg1) {
+ return leaderElectionIds.get(arg0)
+ .compareTo(leaderElectionIds.get(arg1));
+ }
+ };
+ }
+ Collections.sort(activeIdsList, comparator);
+ }
+
/**
* oak's discovery-lite can opt to not provide a clusterViewId eg in the
* single-VM case. (for clusters discovery-lite normally defines the
diff --git
a/src/main/java/org/apache/sling/discovery/oak/pinger/OakViewChecker.java
b/src/main/java/org/apache/sling/discovery/oak/pinger/OakViewChecker.java
index 6938d13..3773166 100644
--- a/src/main/java/org/apache/sling/discovery/oak/pinger/OakViewChecker.java
+++ b/src/main/java/org/apache/sling/discovery/oak/pinger/OakViewChecker.java
@@ -292,7 +292,7 @@ private String newLeaderElectionId() {
String currentTimeMillisStr = String.format("%0"
+ maxLongLength + "d", System.currentTimeMillis());
- String prefix = "1";
+ String prefix = String.valueOf(config.getLeaderElectionPrefix());
final String newLeaderElectionId = prefix + "_"
+ currentTimeMillisStr + "_" + slingId;
diff --git
a/src/test/java/org/apache/sling/discovery/oak/OakDiscoveryServiceTest.java
b/src/test/java/org/apache/sling/discovery/oak/OakDiscoveryServiceTest.java
index 4a41e7f..cfff2cc 100644
--- a/src/test/java/org/apache/sling/discovery/oak/OakDiscoveryServiceTest.java
+++ b/src/test/java/org/apache/sling/discovery/oak/OakDiscoveryServiceTest.java
@@ -19,6 +19,7 @@
package org.apache.sling.discovery.oak;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -37,6 +38,7 @@
import org.apache.sling.discovery.base.its.setup.VirtualInstance;
import
org.apache.sling.discovery.base.its.setup.mock.DummyResourceResolverFactory;
import org.apache.sling.discovery.base.its.setup.mock.MockFactory;
+import org.apache.sling.discovery.commons.providers.BaseTopologyView;
import org.apache.sling.discovery.commons.providers.base.DummyListener;
import org.apache.sling.discovery.commons.providers.spi.base.DescriptorHelper;
import
org.apache.sling.discovery.commons.providers.spi.base.DiscoveryLiteConfig;
@@ -333,4 +335,53 @@ private DiscoveryLiteDescriptorBuilder
prefill(DiscoveryLiteDescriptor d) throws
private ResourceResolver getResourceResolver(ResourceResolverFactory
resourceResolverFactory) throws LoginException {
return resourceResolverFactory.getServiceResourceResolver(null);
}
+
+ @Test
+ public void testInvertedLeaderElectionOrder() throws Exception {
+ logger.info("testInvertedLeaderElectionOrder: start");
+ // instance1 should be leader
+ BaseTopologyView lastView = doTestInvertedLeaderElectionOrder(20, 10);
+ assertTrue(lastView.getLocalInstance().isLeader());
+ // instance2 should be leader
+ lastView = doTestInvertedLeaderElectionOrder(10, 20);
+ assertFalse(lastView.getLocalInstance().isLeader());
+ // instance1 should be leader
+ lastView = doTestInvertedLeaderElectionOrder(10, 10);
+ assertTrue(lastView.getLocalInstance().isLeader());
+ }
+
+ private BaseTopologyView doTestInvertedLeaderElectionOrder(final int
instance1Prefix, final int instance2Prefix)
+ throws Exception {
+ OakVirtualInstanceBuilder builder1 =
+ (OakVirtualInstanceBuilder) new OakVirtualInstanceBuilder()
+ .setDebugName("instance1")
+ .newRepository("/foo/barrio/foo/", true)
+ .setConnectorPingInterval(999)
+ .setConnectorPingTimeout(999);
+ builder1.getConfig().leaderElectionPrefix = instance1Prefix;
+ builder1.getConfig().invertLeaderElectionPrefixOrder = true;
+ VirtualInstance instance1 = builder1.build();
+ OakVirtualInstanceBuilder builder2 =
+ (OakVirtualInstanceBuilder) new OakVirtualInstanceBuilder()
+ .setDebugName("instance2")
+ .useRepositoryOf(instance1)
+ .setConnectorPingInterval(999)
+ .setConnectorPingTimeout(999);
+ builder2.getConfig().leaderElectionPrefix = instance2Prefix;
+ builder2.getConfig().invertLeaderElectionPrefixOrder = true;
+ VirtualInstance instance2 = builder2.build();
+
+ DummyListener listener = new DummyListener();
+ OakDiscoveryService discoveryService = (OakDiscoveryService)
instance1.getDiscoveryService();
+ discoveryService.bindTopologyEventListener(listener);
+
+ instance1.heartbeatsAndCheckView();
+ instance2.heartbeatsAndCheckView();
+ instance1.heartbeatsAndCheckView();
+ instance2.heartbeatsAndCheckView();
+
+ assertEquals(0,
discoveryService.getViewStateManager().waitForAsyncEvents(2000));
+ assertEquals(1, listener.countEvents());
+ return listener.getLastView();
+ }
}
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 ccbfb68..5674606 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
@@ -112,7 +112,7 @@ protected ClusterViewService createClusterViewService() {
return
OakClusterViewService.testConstructor(getSlingSettingsService(),
getResourceResolverFactory(), getIdMapService(), getConfig());
}
- OakTestConfig getConfig() {
+ public OakTestConfig getConfig() {
if (config==null) {
config = createConfig();
}
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services