Author: stefanegli
Date: Wed May 29 18:54:56 2013
New Revision: 1487591
URL: http://svn.apache.org/r1487591
Log:
SLING-2892 : add a simple paranoia check to detect situation with
duplicate/identical sling.ids in a cluster
Modified:
sling/trunk/bundles/extensions/discovery/impl/pom.xml
sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/common/heartbeat/HeartbeatHandler.java
sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/setup/MockedResource.java
Modified: sling/trunk/bundles/extensions/discovery/impl/pom.xml
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/impl/pom.xml?rev=1487591&r1=1487590&r2=1487591&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/discovery/impl/pom.xml (original)
+++ sling/trunk/bundles/extensions/discovery/impl/pom.xml Wed May 29 18:54:56
2013
@@ -29,7 +29,7 @@
<artifactId>org.apache.sling.discovery.impl</artifactId>
<packaging>bundle</packaging>
- <version>0.1.0-SNAPSHOT</version>
+ <version>0.1.0-R1486590_FUTURE3</version>
<name>Apache Sling Resource-Based Discovery Service</name>
<description>Implementation of Apache Sling Discovery based on Sling
Resource providing a ClusterView through resource-clustering (eg jackrabbit
clustering) and a TopologyView through HTTP POST heartbeats announcing
sub-topologies to each other.</description>
@@ -114,7 +114,7 @@
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.discovery.api</artifactId>
- <version>1.0.1-SNAPSHOT</version>
+ <version>0.1.0-R1484784</version>
<scope>provided</scope>
</dependency>
<dependency>
Modified:
sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/common/heartbeat/HeartbeatHandler.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/common/heartbeat/HeartbeatHandler.java?rev=1487591&r1=1487590&r2=1487591&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/common/heartbeat/HeartbeatHandler.java
(original)
+++
sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/common/heartbeat/HeartbeatHandler.java
Wed May 29 18:54:56 2013
@@ -103,6 +103,12 @@ public class HeartbeatHandler implements
/** lock object for synchronizing the run method **/
private final Object lock = new Object();
+ /** SLING-2892: remember first heartbeat written to repository by this
instance **/
+ private long firstHeartbeatWritten = -1;
+
+ /** SLING-2892: remember the value of the heartbeat this instance has
written the last time **/
+ private Calendar lastHeartbeatWritten = null;
+
@Activate
protected void activate(ComponentContext context) {
slingId = slingSettingsService.getSlingId();
@@ -209,6 +215,7 @@ public class HeartbeatHandler implements
private void issueClusterLocalHeartbeat() {
ResourceResolver resourceResolver = null;
final String myClusterNodePath = getLocalClusterNodePath();
+ final Calendar currentTime = Calendar.getInstance();
try {
resourceResolver = getResourceResolver();
if (resourceResolver == null) {
@@ -219,7 +226,36 @@ public class HeartbeatHandler implements
final Resource resource = ResourceHelper.getOrCreateResource(
resourceResolver, myClusterNodePath);
final ModifiableValueMap resourceMap =
resource.adaptTo(ModifiableValueMap.class);
- resourceMap.put("lastHeartbeat", Calendar.getInstance());
+
+ if (firstHeartbeatWritten!=-1 && lastHeartbeatWritten!=null) {
+ // SLING-2892: additional paranoia check
+ // after the first heartbeat, check if there's someone else
using
+ // the same sling.id in this cluster
+ final long timeSinceFirstHeartbeat =
+ System.currentTimeMillis() -
firstHeartbeatWritten;
+ if (timeSinceFirstHeartbeat > 2*config.getHeartbeatInterval()) {
+ // but wait at least 2 heartbeat intervals to handle
the situation
+ // where a bundle is refreshed, and startup cases.
+ final Calendar lastHeartbeat =
resourceMap.get("lastHeartbeat", Calendar.class);
+ if (lastHeartbeat!=null) {
+ // if there is a heartbeat value, check if it
is what I've written
+ // the last time
+ if
(!lastHeartbeatWritten.getTime().equals(lastHeartbeat.getTime())) {
+ // then we've likely hit the situation
where there is another
+ // sling instance accessing the same
repository (ie in the same cluster)
+ // using the same sling.id - hence
writing to the same
+ // resource
+
logger.error("issueClusterLocalHeartbeat: SLING-2892: Detected unexpected,
concurrent update of: "+
+ myClusterNodePath+"
'lastHeartbeat'. If not done manually, " +
+ "this likely indicates
that there is more than 1 instance running in this cluster" +
+ " with the same
sling.id. My sling.id is "+slingId+"." +
+ " Check for
sling.id.file in your installation of all instances in this cluster " +
+ "to verify this!
Duplicate sling.ids are not allowed within a cluster!");
+ }
+ }
+ }
+ }
+ resourceMap.put("lastHeartbeat", currentTime);
if (resetLeaderElectionId ||
!resourceMap.containsKey("leaderElectionId")) {
int maxLongLength = String.valueOf(Long.MAX_VALUE).length();
String currentTimeMillisStr = String.format("%0"
@@ -247,6 +283,13 @@ public class HeartbeatHandler implements
}
resourceResolver.commit();
+ // SLING-2892: only in success case: remember the last heartbeat
value written
+ lastHeartbeatWritten = currentTime;
+ // and set the first heartbeat written value - if it is not
already set
+ if (firstHeartbeatWritten==-1) {
+ firstHeartbeatWritten = System.currentTimeMillis();
+ }
+
} catch (LoginException e) {
logger.error("issueHeartbeat: could not log in administratively: "
+ e, e);
Modified:
sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/setup/MockedResource.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/setup/MockedResource.java?rev=1487591&r1=1487590&r2=1487591&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/setup/MockedResource.java
(original)
+++
sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/setup/MockedResource.java
Wed May 29 18:54:56 2013
@@ -191,7 +191,7 @@ public class MockedResource extends Synt
}
public Object get(Object arg0) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException();
}
public Set<Entry<String, Object>> entrySet() {
@@ -221,7 +221,24 @@ public class MockedResource extends Synt
}
public <T> T get(String name, Class<T> type) {
- throw new UnsupportedOperationException();
+ Session session = getSession();
+ try{
+ final Node node = session.getNode(getPath());
+ if (node==null) {
+ return null;
+ }
+ Property p = node.getProperty(name);
+ if (p==null) {
+ return null;
+ }
+ if (type.equals(Calendar.class)) {
+ return (T) p.getDate();
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ } catch(RepositoryException e) {
+ throw new RuntimeException(e);
+ }
}
};
} else {