You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2016/06/13 08:38:31 UTC

[2/3] brooklyn-library git commit: AbstractGeoDnsServiceImpl uses own lock to guard tracker

AbstractGeoDnsServiceImpl uses own lock to guard tracker

Otherwise a deadlock is possible by -

Thread A:
 Geoscaling.startTracker is synchronized on the entity
 Calls config.get(CONFIG_KEY)
 Dependent value set for config key
 Brooklyn starts Thread B to resolve value.

Thread B:
 Tries to get AbstractEntity.getExecutionContext,
 which is also a method synchronized on the entity.
 Blocks forever


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-library/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-library/commit/2e1246a8
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-library/tree/2e1246a8
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-library/diff/2e1246a8

Branch: refs/heads/master
Commit: 2e1246a8714422b21ab0262192837f6d31fd086b
Parents: afbf8f1
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Wed May 18 17:46:43 2016 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed May 18 17:46:43 2016 +0100

----------------------------------------------------------------------
 .../entity/dns/AbstractGeoDnsServiceImpl.java   | 62 ++++++++++++--------
 1 file changed, 39 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/2e1246a8/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
index 65e4291..843673f 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
@@ -46,14 +46,14 @@ import org.apache.brooklyn.core.location.geo.HostGeoInfo;
 import org.apache.brooklyn.entity.group.AbstractMembershipTrackingPolicy;
 import org.apache.brooklyn.entity.group.DynamicGroup;
 import org.apache.brooklyn.entity.webapp.WebAppService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.net.Networking;
 import org.apache.brooklyn.util.time.Duration;
 import org.apache.brooklyn.util.time.Time;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -65,6 +65,8 @@ public abstract class AbstractGeoDnsServiceImpl extends AbstractEntity implement
     @SetFromFlag
     protected Group targetEntityProvider;
     protected AbstractMembershipTrackingPolicy tracker;
+    /** Guards access to {@link #tracker}. */
+    protected final Object trackerLock = new Object[0];
 
     protected Map<Entity, HostGeoInfo> targetHosts = Collections.synchronizedMap(new LinkedHashMap<Entity, HostGeoInfo>());
 
@@ -134,31 +136,45 @@ public abstract class AbstractGeoDnsServiceImpl extends AbstractEntity implement
     /** should set up so these hosts are targeted, and setServiceState appropriately */
     protected abstract void reconfigureService(Collection<HostGeoInfo> targetHosts);
 
-    protected synchronized void startTracker() {
-        if (targetEntityProvider==null || !getManagementSupport().isDeployed()) {
-            log.debug("Tracker for "+this+" not yet active: "+targetEntityProvider+" / "+getManagementContext());
-            return;
-        }
-        endTracker();
+    /**
+     * Start the tracker.
+     * <p>
+     * Subclasses should take care to synchronize on {@link #trackerLock}.
+     */
+    protected void startTracker() {
+        synchronized (trackerLock) {
+            if (targetEntityProvider == null || !getManagementSupport().isDeployed()) {
+                log.debug("Tracker for " + this + " not yet active: " + targetEntityProvider + " / " + getManagementContext());
+                return;
+            }
+            endTracker();
 
-        ImmutableSet.Builder<Sensor<?>> sensorsToTrack = ImmutableSet.<Sensor<?>>builder().add(
-                HOSTNAME, ADDRESS, Attributes.MAIN_URI, WebAppService.ROOT_URL);
-        // Don't subscribe to lifecycle events if entities will be included regardless of their status.
-        if (Boolean.TRUE.equals(config().get(FILTER_FOR_RUNNING))) {
-            sensorsToTrack.add(Attributes.SERVICE_STATE_ACTUAL);
+            ImmutableSet.Builder<Sensor<?>> sensorsToTrack = ImmutableSet.<Sensor<?>>builder().add(
+                    HOSTNAME, ADDRESS, Attributes.MAIN_URI, WebAppService.ROOT_URL);
+            // Don't subscribe to lifecycle events if entities will be included regardless of their status.
+            if (Boolean.TRUE.equals(config().get(FILTER_FOR_RUNNING))) {
+                sensorsToTrack.add(Attributes.SERVICE_STATE_ACTUAL);
+            }
+            log.debug("Initializing tracker for " + this + ", following " + targetEntityProvider);
+            tracker = policies().add(PolicySpec.create(MemberTrackingPolicy.class)
+                    .displayName("GeoDNS targets tracker")
+                    .configure(AbstractMembershipTrackingPolicy.SENSORS_TO_TRACK, sensorsToTrack.build())
+                    .configure(AbstractMembershipTrackingPolicy.GROUP, targetEntityProvider));
+            refreshGroupMembership();
         }
-        log.debug("Initializing tracker for "+this+", following "+targetEntityProvider);
-        tracker = policies().add(PolicySpec.create(MemberTrackingPolicy.class)
-                .displayName("GeoDNS targets tracker")
-                .configure(AbstractMembershipTrackingPolicy.SENSORS_TO_TRACK, sensorsToTrack.build())
-                .configure(AbstractMembershipTrackingPolicy.GROUP, targetEntityProvider));
-        refreshGroupMembership();
     }
 
-    protected synchronized void endTracker() {
-        if (tracker == null || targetEntityProvider==null) return;
-        policies().remove(tracker);
-        tracker = null;
+    /**
+     * End the tracker.
+     * <p>
+     * Subclasses should take care to synchronize on {@link #trackerLock}.
+     */
+    protected void endTracker() {
+        synchronized (trackerLock) {
+            if (tracker == null || targetEntityProvider == null) return;
+            policies().remove(tracker);
+            tracker = null;
+        }
     }
 
     public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {