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 2015/10/22 14:33:16 UTC
svn commit: r1710003 - in /sling/trunk/bundles/extensions/discovery:
commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/
oak/src/main/java/org/apache/sling/discovery/oak/
oak/src/main/java/org/apache/sling/discovery/oak/cluster/
Author: stefanegli
Date: Thu Oct 22 12:33:15 2015
New Revision: 1710003
URL: http://svn.apache.org/viewvc?rev=1710003&view=rev
Log:
SLING-4603 : more aggressively clearing the idMap-cache to avoid stale entries on slingId change - plus added getSyncHistory to BaseSyncTokenConsistencyService to allow adding it to the webconsole for debug - plus some cleanup in webconsole wrt discoveryLite info
Modified:
sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/BaseSyncTokenConsistencyService.java
sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/IdMapService.java
sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/OakSyncTokenConsistencyService.java
sling/trunk/bundles/extensions/discovery/oak/src/main/java/org/apache/sling/discovery/oak/TopologyWebConsolePlugin.java
sling/trunk/bundles/extensions/discovery/oak/src/main/java/org/apache/sling/discovery/oak/cluster/OakClusterViewService.java
Modified: sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/BaseSyncTokenConsistencyService.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/BaseSyncTokenConsistencyService.java?rev=1710003&r1=1710002&r2=1710003&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/BaseSyncTokenConsistencyService.java (original)
+++ sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/BaseSyncTokenConsistencyService.java Thu Oct 22 12:33:15 2015
@@ -18,6 +18,13 @@
*/
package org.apache.sling.discovery.commons.providers.spi.base;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.PersistenceException;
@@ -38,8 +45,19 @@ import org.apache.sling.settings.SlingSe
*/
public abstract class BaseSyncTokenConsistencyService extends AbstractServiceWithBackgroundCheck implements ConsistencyService {
+ class HistoryEntry {
+ BaseTopologyView view;
+ String msg;
+ String fullLine;
+ }
+
+ /** the date format used in the truncated log of topology events **/
+ private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
+
protected String slingId;
+ protected List<HistoryEntry> history = new LinkedList<HistoryEntry>();
+
protected abstract DiscoveryLiteConfig getCommonsConfig();
protected abstract ResourceResolverFactory getResourceResolverFactory();
@@ -73,11 +91,13 @@ public abstract class BaseSyncTokenConsi
@Override
public boolean check() {
// 1) first storing my syncToken
- if (!storeMySyncToken(view.getLocalClusterSyncTokenId())) {
+ final String localClusterSyncTokenId = view.getLocalClusterSyncTokenId();
+ if (!storeMySyncToken(localClusterSyncTokenId)) {
// if anything goes wrong above, then this will mean for the others
// that they will have to wait until the timeout hits
// so to try to avoid this, retry storing my sync token later:
+ addHistoryEntry(view, "storing my syncToken ("+localClusterSyncTokenId+")");
return false;
}
@@ -144,20 +164,35 @@ public abstract class BaseSyncTokenConsi
String syncToken = view.getLocalClusterSyncTokenId();
boolean success = true;
+ StringBuffer historyEntry = new StringBuffer();
for (InstanceDescription instance : view.getLocalInstance().getClusterView().getInstances()) {
Object currentValue = syncTokens.get(instance.getSlingId());
if (currentValue == null) {
- logger.info("seenAllSyncTokens: no syncToken of "+instance.getSlingId());
+ String msg = "no syncToken yet of "+instance.getSlingId();
+ logger.info("seenAllSyncTokens: " + msg);
+ if (historyEntry.length() != 0) {
+ historyEntry.append(",");
+ }
+ historyEntry.append(msg);
success = false;
} else if (!syncToken.equals(currentValue)) {
- logger.info("seenAllSyncTokens: old syncToken of " + instance.getSlingId()
- + " : expected=" + syncToken + " got="+currentValue);
+ String msg = "syncToken of " + instance.getSlingId()
+ + " is " + currentValue
+ + " waiting for " + syncToken;
+ logger.info("seenAllSyncTokens: " + msg);
+ if (historyEntry.length() != 0) {
+ historyEntry.append(",");
+ }
+ historyEntry.append(msg);
success = false;
}
}
if (!success) {
logger.info("seenAllSyncTokens: not yet seen all expected syncTokens (see above for details)");
+ addHistoryEntry(view, historyEntry.toString());
return false;
+ } else {
+ addHistoryEntry(view, "seen all syncTokens");
}
resourceResolver.commit();
@@ -176,4 +211,45 @@ public abstract class BaseSyncTokenConsi
}
}
}
+
+ public List<String> getSyncHistory() {
+ List<HistoryEntry> snapshot;
+ synchronized(history) {
+ snapshot = Collections.unmodifiableList(history);
+ }
+ List<String> result = new ArrayList<String>(snapshot.size());
+ for (HistoryEntry historyEntry : snapshot) {
+ result.add(historyEntry.fullLine);
+ }
+ return result;
+ }
+
+ protected void addHistoryEntry(BaseTopologyView view, String msg) {
+ synchronized(history) {
+ for(int i = history.size() - 1; i>=0; i--) {
+ HistoryEntry entry = history.get(i);
+ if (!entry.view.equals(view)) {
+ // don't filter if the view starts differing,
+ // only filter for the last few entries where
+ // the view is equal
+ break;
+ }
+ if (entry.msg.equals(msg)) {
+ // if the view is equal and the msg matches
+ // then this is a duplicate entry, so ignore
+ return;
+ }
+ }
+ String fullLine = sdf.format(Calendar.getInstance().getTime()) + ": " + msg;
+ HistoryEntry newEntry = new HistoryEntry();
+ newEntry.view = view;
+ newEntry.fullLine = fullLine;
+ newEntry.msg = msg;
+ history.add(newEntry);
+ while (history.size() > 12) {
+ history.remove(0);
+ }
+ }
+ }
+
}
Modified: sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/IdMapService.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/IdMapService.java?rev=1710003&r1=1710002&r2=1710003&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/IdMapService.java (original)
+++ sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/IdMapService.java Thu Oct 22 12:33:15 2015
@@ -19,6 +19,7 @@
package org.apache.sling.discovery.commons.providers.spi.base;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
import org.apache.felix.scr.annotations.Activate;
@@ -141,9 +142,42 @@ public class IdMapService extends Abstra
long me = descriptor.getMyId();
final Resource resource = ResourceHelper.getOrCreateResource(resourceResolver, getIdMapPath());
ModifiableValueMap idmap = resource.adaptTo(ModifiableValueMap.class);
- idmap.put(slingId, me);
+ // check to see if either my slingId is already mapped to another clusterNodeId
+ // or when my clusterNodeId is already mapped to another slingId
+ // in both cases: clean that up
+ boolean foundMe = false;
+ for (String aKey : new HashSet<String>(idmap.keySet())) {
+ Object value = idmap.get(aKey);
+ if (value instanceof Number) {
+ Number n = (Number)value;
+ if (n.longValue()==me) {
+ // my clusterNodeId is already mapped to
+ // let's check if the key is my slingId
+ if (aKey.equals(slingId)) {
+ // perfect
+ foundMe = true;
+ } else {
+ // cleanup necessary
+ logger.info("init: my clusterNodeId is already mapped to by another slingId, deleting entry: key="+aKey+" mapped to "+value);
+ idmap.remove(aKey);
+ }
+ } else if (aKey.equals(slingId)) {
+ // cleanup necessary
+ logger.info("init: my slingId is already mapped to by another clusterNodeId, deleting entry: key="+aKey+" mapped to "+value);
+ idmap.remove(aKey);
+ } else {
+ // that's just some other slingId-clusterNodeId mapping
+ // leave it unchanged
+ }
+ }
+ }
+ if (!foundMe) {
+ logger.info("init: added the following mapping: slingId="+slingId+" to discovery-lite id="+me);
+ idmap.put(slingId, me);
+ } else {
+ logger.info("init: mapping already existed, left unchanged: slingId="+slingId+" to discovery-lite id="+me);
+ }
resourceResolver.commit();
- logger.info("init: mapped slingId="+slingId+" to discovery-lite id="+me);
this.me = me;
initialized = true;
notifyAll();
@@ -160,6 +194,7 @@ public class IdMapService extends Abstra
}
public synchronized void clearCache() {
+ logger.info("clearCache: clearing idmap cache");
idMapCache.clear();
}
@@ -171,6 +206,7 @@ public class IdMapService extends Abstra
}
// cache-miss
Map<Integer, String> readMap = readIdMap(resourceResolver);
+ logger.info("toSlingId: cache miss, refreshing idmap cache");
idMapCache.putAll(readMap);
return idMapCache.get(clusterNodeId);
}
Modified: sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/OakSyncTokenConsistencyService.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/OakSyncTokenConsistencyService.java?rev=1710003&r1=1710002&r2=1710003&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/OakSyncTokenConsistencyService.java (original)
+++ sling/trunk/bundles/extensions/discovery/commons/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/OakSyncTokenConsistencyService.java Thu Oct 22 12:33:15 2015
@@ -61,7 +61,7 @@ public class OakSyncTokenConsistencyServ
@Reference
protected SlingSettingsService settingsService;
-
+
public static OakSyncTokenConsistencyService testConstructorAndActivate(
final DiscoveryLiteConfig commonsConfig,
final IdMapService idMapService,
@@ -141,18 +141,24 @@ public class OakSyncTokenConsistencyServ
try {
if (!idMapService.isInitialized()) {
logger.info("waitWhileBacklog: could not initialize...");
+ addHistoryEntry(view, "could not initialize idMapService");
return false;
}
} catch (Exception e) {
logger.error("waitWhileBacklog: could not initialized due to "+e, e);
+ addHistoryEntry(view, "got Exception while initializing idMapService ("+e+")");
return false;
}
BacklogStatus backlogStatus = getBacklogStatus(view);
if (backlogStatus == BacklogStatus.NO_BACKLOG) {
logger.info("waitWhileBacklog: no backlog (anymore), done.");
+ addHistoryEntry(view, "no backlog (anymore)");
return true;
} else {
logger.info("waitWhileBacklog: backlogStatus still "+backlogStatus);
+ // clear the cache to make sure to get the latest version in case something changed
+ idMapService.clearCache();
+ addHistoryEntry(view, "backlog status "+backlogStatus);
return false;
}
}
@@ -243,5 +249,4 @@ public class OakSyncTokenConsistencyServ
return settingsService;
}
-
}
Modified: sling/trunk/bundles/extensions/discovery/oak/src/main/java/org/apache/sling/discovery/oak/TopologyWebConsolePlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/oak/src/main/java/org/apache/sling/discovery/oak/TopologyWebConsolePlugin.java?rev=1710003&r1=1710002&r2=1710003&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/discovery/oak/src/main/java/org/apache/sling/discovery/oak/TopologyWebConsolePlugin.java (original)
+++ sling/trunk/bundles/extensions/discovery/oak/src/main/java/org/apache/sling/discovery/oak/TopologyWebConsolePlugin.java Thu Oct 22 12:33:15 2015
@@ -55,6 +55,8 @@ import org.apache.sling.discovery.Instan
import org.apache.sling.discovery.InstanceFilter;
import org.apache.sling.discovery.TopologyEvent;
import org.apache.sling.discovery.TopologyEvent.Type;
+import org.apache.sling.discovery.TopologyEventListener;
+import org.apache.sling.discovery.TopologyView;
import org.apache.sling.discovery.base.commons.ClusterViewService;
import org.apache.sling.discovery.base.connectors.announcement.Announcement;
import org.apache.sling.discovery.base.connectors.announcement.AnnouncementRegistry;
@@ -62,8 +64,7 @@ import org.apache.sling.discovery.base.c
import org.apache.sling.discovery.base.connectors.ping.ConnectorRegistry;
import org.apache.sling.discovery.base.connectors.ping.TopologyConnectorClientInformation;
import org.apache.sling.discovery.commons.providers.spi.base.DiscoveryLiteDescriptor;
-import org.apache.sling.discovery.TopologyEventListener;
-import org.apache.sling.discovery.TopologyView;
+import org.apache.sling.discovery.commons.providers.spi.base.OakSyncTokenConsistencyService;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -110,10 +111,19 @@ public class TopologyWebConsolePlugin ex
@Reference
protected ResourceResolverFactory resourceResolverFactory;
+ @Reference
+ private OakSyncTokenConsistencyService consistencyService;
+
private TopologyView currentView;
private List<String> discoveryLiteHistory = new LinkedList<String>();
+ /**
+ * keeps hold of the last DiscoveryLiteDescriptor that was added
+ * to the discoveryLiteHistory - in order to de-duplicate as we go
+ */
+ private DiscoveryLiteDescriptor lastDiscoveryLiteDescriptor = null;
+
@Override
public String getLabel() {
return LABEL;
@@ -277,32 +287,6 @@ public class TopologyWebConsolePlugin ex
listIncomingTopologyConnectors(pw);
listOutgoingTopologyConnectors(pw);
pw.println("<br/>");
-
- ResourceResolver resourceResolver = null;
- pw.println("<p class=\"statline ui-state-highlight\">Oak Discovery-Lite Descriptor History</p>");
- pw.println("<pre>");
- for (String discoLiteHistoryEntry : discoveryLiteHistory) {
- pw.println(discoLiteHistoryEntry);
- }
- pw.println("</pre>");
- pw.println("<br/>");
- pw.println("<p class=\"statline ui-state-highlight\">Current Oak Discovery-Lite Descriptor</p>");
- pw.println("<pre>");
- try{
- resourceResolver = getResourceResolver();
- DiscoveryLiteDescriptor descriptor = DiscoveryLiteDescriptor.getDescriptorFrom(resourceResolver);
- final String logEntry = getCurrentDateFormatted() + ": " + descriptor.getDescriptorStr();
- pw.println(logEntry);
- } catch(Exception e) {
- logger.error("renderOverview: Exception: "+e, e);
- pw.println("Got exception trying to get repository descriptor: "+e);
- } finally {
- if (resourceResolver != null) {
- resourceResolver.close();
- }
- }
- pw.println("</pre>");
- pw.println("<br/>");
pw.println("<p class=\"statline ui-state-highlight\">Topology Change History</p>");
pw.println("<pre>");
@@ -322,6 +306,23 @@ public class TopologyWebConsolePlugin ex
}
pw.println("</pre>");
pw.println("</br>");
+
+ pw.println("<p class=\"statline ui-state-highlight\">Oak Discovery-Lite Descriptor History</p>");
+ updateDiscoveryLiteHistory();
+ pw.println("<pre>");
+ for (String discoLiteHistoryEntry : discoveryLiteHistory) {
+ pw.println(discoLiteHistoryEntry);
+ }
+ pw.println("</pre>");
+ pw.println("<br/>");
+
+ pw.println("<p class=\"statline ui-state-highlight\">ConsistencyService History</p>");
+ pw.println("<pre>");
+ for (String syncHistoryEntry : consistencyService.getSyncHistory()) {
+ pw.println(syncHistoryEntry);
+ }
+ pw.println("</pre>");
+ pw.println("<br/>");
}
/**
@@ -600,7 +601,7 @@ public class TopologyWebConsolePlugin ex
+ newInstanceDescription
+ " in oldview.. event="
+ event);
- addEventLog(event.getType(), event.getType().toString());
+ addEventLog(event.getType(), event.getType().toString()+" (new instance "+newInstanceDescription.getSlingId()+" not found in old view)");
return;
}
@@ -619,7 +620,7 @@ public class TopologyWebConsolePlugin ex
}
}
- addEventLog(event.getType(), sb.toString());
+ addEventLog(event.getType(), "details: "+sb.toString());
} else if (event.getType() == Type.TOPOLOGY_INIT) {
this.currentView = event.getNewView();
StringBuilder details = new StringBuilder();
@@ -692,7 +693,7 @@ public class TopologyWebConsolePlugin ex
+ details);
}
}
- addDiscoveryLiteHistoryEntry();
+ updateDiscoveryLiteHistory();
}
/**
@@ -735,17 +736,22 @@ public class TopologyWebConsolePlugin ex
}
/**
- * add a discoveryLite descriptor entry to the history, truncating if necessary
+ * if there's any change add a discoveryLite descriptor entry to the history, truncating if necessary
*/
- private synchronized void addDiscoveryLiteHistoryEntry() {
+ private synchronized void updateDiscoveryLiteHistory() {
ResourceResolver resourceResolver = null;
try{
resourceResolver = getResourceResolver();
DiscoveryLiteDescriptor descriptor =
DiscoveryLiteDescriptor.getDescriptorFrom(resourceResolver);
+ if (lastDiscoveryLiteDescriptor!=null &&
+ descriptor.getDescriptorStr().equals(lastDiscoveryLiteDescriptor.getDescriptorStr())) {
+ // de-duplication - then there's nothing to update
+ return;
+ }
final String logEntry = getCurrentDateFormatted() + ": " + descriptor.getDescriptorStr();
-
+ lastDiscoveryLiteDescriptor = descriptor;
discoveryLiteHistory.add(logEntry);
while (discoveryLiteHistory.size() > 12) {
discoveryLiteHistory.remove(0);
@@ -923,34 +929,6 @@ public class TopologyWebConsolePlugin ex
pw.println();
}
- ResourceResolver resourceResolver = null;
- pw.println("Oak Discovery-Lite Descriptor History");
- pw.println("---------------------------------------");
- for (String discoLiteHistoryEntry : discoveryLiteHistory) {
- pw.println(discoLiteHistoryEntry);
- }
- pw.println();
- pw.println();
- pw.println("Current Oak Discovery-Lite Descriptor");
- pw.println("---------------------------------------");
- try{
- resourceResolver = getResourceResolver();
- DiscoveryLiteDescriptor descriptor = DiscoveryLiteDescriptor.getDescriptorFrom(resourceResolver);
- final String logEntry = getCurrentDateFormatted() + ": " + descriptor.getDescriptorStr();
- pw.println(logEntry);
- pw.println();
- pw.println();
- } catch(Exception e) {
- logger.error("renderOverview: Exception: "+e, e);
- pw.println("Got exception trying to get repository descriptor: "+e);
- pw.println();
- pw.println();
- } finally {
- if (resourceResolver != null) {
- resourceResolver.close();
- }
- }
-
if ( topologyLog.size() > 0 ) {
pw.println("Topology Change History");
pw.println("---------------------------------------");
@@ -969,6 +947,23 @@ public class TopologyWebConsolePlugin ex
}
pw.println();
}
+
+ pw.println("Oak Discovery-Lite Descriptor History");
+ pw.println("---------------------------------------");
+ updateDiscoveryLiteHistory();
+ for (String discoLiteHistoryEntry : discoveryLiteHistory) {
+ pw.println(discoLiteHistoryEntry);
+ }
+ pw.println();
+ pw.println();
+
+ pw.println("ConsistencyService History");
+ pw.println("---------------------------------------");
+ for (String syncHistoryEntry : consistencyService.getSyncHistory()) {
+ pw.println(syncHistoryEntry);
+ }
+ pw.println();
+ pw.println();
}
private String getCurrentDateFormatted() {
Modified: sling/trunk/bundles/extensions/discovery/oak/src/main/java/org/apache/sling/discovery/oak/cluster/OakClusterViewService.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/oak/src/main/java/org/apache/sling/discovery/oak/cluster/OakClusterViewService.java?rev=1710003&r1=1710002&r2=1710003&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/discovery/oak/src/main/java/org/apache/sling/discovery/oak/cluster/OakClusterViewService.java (original)
+++ sling/trunk/bundles/extensions/discovery/oak/src/main/java/org/apache/sling/discovery/oak/cluster/OakClusterViewService.java Thu Oct 22 12:33:15 2015
@@ -68,6 +68,9 @@ public class OakClusterViewService imple
@Reference
private IdMapService idMapService;
+ /** the last sequence number read from the oak discovery-lite descriptor **/
+ private long lastSeqNum = -1;
+
public static OakClusterViewService testConstructor(SlingSettingsService settingsService,
ResourceResolverFactory resourceResolverFactory,
IdMapService idMapService,
@@ -98,6 +101,11 @@ public class OakClusterViewService imple
resourceResolver = getResourceResolver();
DiscoveryLiteDescriptor descriptor =
DiscoveryLiteDescriptor.getDescriptorFrom(resourceResolver);
+ if (lastSeqNum!=descriptor.getSeqNum()) {
+ logger.info("getLocalClusterView: sequence number change detected - clearing idmap cache");
+ idMapService.clearCache();
+ lastSeqNum = descriptor.getSeqNum();
+ }
return asClusterView(descriptor, resourceResolver);
} catch (UndefinedClusterViewException e) {
logger.info("getLocalClusterView: undefined clusterView: "+e.getReason()+" - "+e.getMessage());
@@ -122,7 +130,7 @@ public class OakClusterViewService imple
}
logger.trace("asClusterView: start");
String clusterViewId = descriptor.getViewId();
- String localClusterSyncTokenId = descriptor.getViewId()+"_"+descriptor.getSeqNum();
+ String localClusterSyncTokenId = /*descriptor.getViewId()+"_"+*/String.valueOf(descriptor.getSeqNum());
if (!descriptor.isFinal()) {
throw new UndefinedClusterViewException(Reason.NO_ESTABLISHED_VIEW, "descriptor is not yet final: "+descriptor);
}
@@ -146,6 +154,7 @@ public class OakClusterViewService imple
for (Integer id : activeIdsList) {
String slingId = idMapService.toSlingId(id, resourceResolver);
if (slingId == null) {
+ idMapService.clearCache();
throw new UndefinedClusterViewException(Reason.NO_ESTABLISHED_VIEW,
"no slingId mapped for clusterNodeId="+id);
}
@@ -169,6 +178,7 @@ public class OakClusterViewService imple
boolean isOwn = id==me;
String slingId = idMapService.toSlingId(id, resourceResolver);
if (slingId==null) {
+ idMapService.clearCache();
logger.info("asClusterView: cannot resolve oak-clusterNodeId {} to a slingId", id);
throw new Exception("Cannot resolve oak-clusterNodeId "+id+" to a slingId");
}