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:28:26 UTC
[sling-org-apache-sling-discovery-oak] 05/32: SLING-5458 : support
cluster id of discovery lite descriptor to be null - in which case
discovery.oak stores and reads a clusterId property to/from
/var/discovery/oak
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.2.10
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-discovery-oak.git
commit 7a5c7eef972c247dd114a69cb129ae1d6070220a
Author: Stefan Egli <st...@apache.org>
AuthorDate: Wed Jan 27 13:20:04 2016 +0000
SLING-5458 : support cluster id of discovery lite descriptor to be null - in which case discovery.oak stores and reads a clusterId property to/from /var/discovery/oak
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/discovery/oak@1727035 13f79535-47bb-0310-9956-ffa450edef68
---
.../oak/cluster/OakClusterViewService.java | 82 ++++++++++++++++++++++
1 file changed, 82 insertions(+)
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 4f770cf..ee082f9 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
@@ -18,6 +18,7 @@
*/
package org.apache.sling.discovery.oak.cluster;
+import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -25,11 +26,14 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ModifiableValueMap;
+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.ResourceResolverFactory;
@@ -42,6 +46,7 @@ import org.apache.sling.discovery.commons.providers.DefaultInstanceDescription;
import org.apache.sling.discovery.commons.providers.spi.LocalClusterView;
import org.apache.sling.discovery.commons.providers.spi.base.DiscoveryLiteDescriptor;
import org.apache.sling.discovery.commons.providers.spi.base.IdMapService;
+import org.apache.sling.discovery.commons.providers.util.ResourceHelper;
import org.apache.sling.discovery.oak.Config;
import org.apache.sling.settings.SlingSettingsService;
import org.slf4j.Logger;
@@ -54,6 +59,10 @@ import org.slf4j.LoggerFactory;
@Service(value = ClusterViewService.class)
public class OakClusterViewService implements ClusterViewService {
+ private static final String PROPERTY_CLUSTER_ID = "clusterId";
+ private static final String PROPERTY_CLUSTER_ID_DEFINED_AT = "clusterIdDefinedAt";
+ private static final String PROPERTY_CLUSTER_ID_DEFINED_BY = "clusterIdDefinedBy";
+
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Reference
@@ -130,6 +139,10 @@ public class OakClusterViewService implements ClusterViewService {
}
logger.trace("asClusterView: start");
String clusterViewId = descriptor.getViewId();
+ if (clusterViewId == null || clusterViewId.length() == 0) {
+ logger.trace("asClusterView: no clusterId provided by discovery-lite descriptor - reading from repo.");
+ clusterViewId = readOrDefineClusterId(resourceResolver);
+ }
String localClusterSyncTokenId = /*descriptor.getViewId()+"_"+*/String.valueOf(descriptor.getSeqNum());
if (!descriptor.isFinal()) {
throw new UndefinedClusterViewException(Reason.NO_ESTABLISHED_VIEW, "descriptor is not yet final: "+descriptor);
@@ -200,6 +213,75 @@ public class OakClusterViewService implements ClusterViewService {
}
}
+ /**
+ * oak's discovery-lite can opt to not provide a clusterViewId eg in the
+ * single-VM case. (for clusters discovery-lite normally defines the
+ * clusterViewId, as it is the one responsible for defining the membership
+ * too) Thus if we're not getting an id here we have to define one here. (we
+ * can typically assume that this corresponds to a singleVM case, but that's
+ * not a 100% requirement). This id must be stored to ensure the contract
+ * that the clusterId is stable across restarts. For that, the id is stored
+ * under /var/discovery/oak (and to account for odd/edgy cases we'll do a
+ * retry when storing the id, in case we'd run into conflicts, even though
+ * they should not occur in singleVM cases)
+ *
+ * @param resourceResolver the ResourceResolver with which to read or write
+ * the clusterId properties under /var/discovery/oak
+ * @return the clusterId to be used - either the one read or defined
+ * at /var/discovery/oak - or the slingId in case of non-fixable exceptions
+ * @throws PersistenceException when /var/discovery/oak could not be
+ * accessed or auto-created
+ */
+ private String readOrDefineClusterId(ResourceResolver resourceResolver) throws PersistenceException {
+ //TODO: if Config gets a specific, public getDiscoveryResourcePath, this can be simplified:
+ final String clusterInstancesPath = config.getClusterInstancesPath();
+ final String discoveryResourcePath = clusterInstancesPath.substring(0,
+ clusterInstancesPath.lastIndexOf("/", clusterInstancesPath.length()-2));
+ final int MAX_RETRIES = 5;
+ for(int retryCnt=0; retryCnt<MAX_RETRIES; retryCnt++) {
+ Resource varDiscoveryOak = resourceResolver.getResource(discoveryResourcePath);
+ if (varDiscoveryOak == null) {
+ varDiscoveryOak = ResourceHelper.getOrCreateResource(resourceResolver, discoveryResourcePath);
+ }
+ if (varDiscoveryOak == null) {
+ logger.error("readOrDefinedClusterId: Could not create: "+discoveryResourcePath);
+ throw new RuntimeException("could not create " + discoveryResourcePath);
+ }
+ ModifiableValueMap props = varDiscoveryOak.adaptTo(ModifiableValueMap.class);
+ if (props == null) {
+ logger.error("readOrDefineClusterId: Could not adaptTo ModifiableValueMap: "+varDiscoveryOak);
+ throw new RuntimeException("could not adaptTo ModifiableValueMap: " + varDiscoveryOak);
+ }
+ Object clusterIdObj = props.get(PROPERTY_CLUSTER_ID);
+ String clusterId = (clusterIdObj == null) ? null : String.valueOf(clusterIdObj);
+ if (clusterId != null && clusterId.length() > 0) {
+ logger.trace("readOrDefineClusterId: read clusterId from repo as {}", clusterId);
+ return clusterId;
+ }
+
+ // must now define a new clusterId and store it under /var/discovery/oak
+ final String newClusterId = UUID.randomUUID().toString();
+ props.put(PROPERTY_CLUSTER_ID, newClusterId);
+ props.put(PROPERTY_CLUSTER_ID_DEFINED_BY, getSlingId());
+ props.put(PROPERTY_CLUSTER_ID_DEFINED_AT, Calendar.getInstance());
+ try {
+ logger.info("readOrDefineClusterId: storing new clusterId as " + newClusterId);
+ resourceResolver.commit();
+ return newClusterId;
+ } catch (PersistenceException e) {
+ logger.warn("readOrDefineClusterId: could not persist clusterId "
+ + "(retrying in 1 sec max " + (MAX_RETRIES - retryCnt - 1) + " more times: " + e, e);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e1) {
+ logger.warn("readOrDefineClusterId: got interrupted: "+e1, e1);
+ }
+ logger.info("readOrDefineClusterId: retrying now.");
+ }
+ }
+ throw new RuntimeException("failed to write new clusterId (see log file earlier for more details)");
+ }
+
private String getLeaderElectionId(ResourceResolver resourceResolver, String slingId) {
if (slingId==null) {
throw new IllegalStateException("slingId must not be null");
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.