This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.discovery.commons-1.0.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-discovery-commons.git
commit e88458a352bf66b2fa682cb2011fa38e25b10288 Author: Stefan Egli <[email protected]> AuthorDate: Thu Oct 22 12:33:15 2015 +0000 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 git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/discovery/commons@1710003 13f79535-47bb-0310-9956-ffa450edef68 --- .../spi/base/BaseSyncTokenConsistencyService.java | 84 ++++++++++++++++++++-- .../commons/providers/spi/base/IdMapService.java | 40 ++++++++++- .../spi/base/OakSyncTokenConsistencyService.java | 9 ++- 3 files changed, 125 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/BaseSyncTokenConsistencyService.java b/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/BaseSyncTokenConsistencyService.java index fd53e82..ba6d6ec 100644 --- a/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/BaseSyncTokenConsistencyService.java +++ b/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/BaseSyncTokenConsistencyService.java @@ -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.SlingSettingsService; */ 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 BaseSyncTokenConsistencyService extends AbstractServiceWit @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 BaseSyncTokenConsistencyService extends AbstractServiceWit 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 BaseSyncTokenConsistencyService extends AbstractServiceWit } } } + + 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); + } + } + } + } diff --git a/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/IdMapService.java b/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/IdMapService.java index 20ad3bc..12e8db7 100644 --- a/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/IdMapService.java +++ b/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/IdMapService.java @@ -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 AbstractServiceWithBackgroundCheck { 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 AbstractServiceWithBackgroundCheck { } public synchronized void clearCache() { + logger.info("clearCache: clearing idmap cache"); idMapCache.clear(); } @@ -171,6 +206,7 @@ public class IdMapService extends AbstractServiceWithBackgroundCheck { } // cache-miss Map<Integer, String> readMap = readIdMap(resourceResolver); + logger.info("toSlingId: cache miss, refreshing idmap cache"); idMapCache.putAll(readMap); return idMapCache.get(clusterNodeId); } diff --git a/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/OakSyncTokenConsistencyService.java b/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/OakSyncTokenConsistencyService.java index 24c12dc..55c3411 100644 --- a/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/OakSyncTokenConsistencyService.java +++ b/src/main/java/org/apache/sling/discovery/commons/providers/spi/base/OakSyncTokenConsistencyService.java @@ -61,7 +61,7 @@ public class OakSyncTokenConsistencyService extends BaseSyncTokenConsistencyServ @Reference protected SlingSettingsService settingsService; - + public static OakSyncTokenConsistencyService testConstructorAndActivate( final DiscoveryLiteConfig commonsConfig, final IdMapService idMapService, @@ -141,18 +141,24 @@ public class OakSyncTokenConsistencyService extends BaseSyncTokenConsistencyServ 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 OakSyncTokenConsistencyService extends BaseSyncTokenConsistencyServ return settingsService; } - } -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
