You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2016/02/01 18:48:57 UTC

[27/50] brooklyn-server git commit: return quickly on attempts to look up external ip address, so we don't block excessively when network is dodgy; and misc tidies elsewhere for better http test routings and logging on duplicated sensor definitions

return quickly on attempts to look up external ip address, so we don't block excessively when network is dodgy;
and misc tidies elsewhere for better http test routings and logging on duplicated sensor definitions


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

Branch: refs/heads/0.4.0
Commit: 2da0cf6bf0a2e99b54b7564365e159b90abef664
Parents: a0e7c13
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Oct 10 00:50:46 2012 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Oct 10 00:50:46 2012 +0100

----------------------------------------------------------------------
 .../entity/basic/EntityDynamicType.java         | 16 ++++--
 .../location/geo/UtraceHostGeoLookup.java       | 51 ++++++++++++++++++--
 core/src/main/java/brooklyn/util/Time.java      |  2 +
 .../brooklyn/util/internal/TimeExtras.groovy    | 19 ++++++--
 .../main/java/brooklyn/test/HttpTestUtils.java  | 34 +++++++++++++
 .../main/java/brooklyn/test/TestUtils.groovy    | 15 ++++--
 6 files changed, 121 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2da0cf6b/core/src/main/java/brooklyn/entity/basic/EntityDynamicType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/EntityDynamicType.java b/core/src/main/java/brooklyn/entity/basic/EntityDynamicType.java
index c1f5701..0024e3b 100644
--- a/core/src/main/java/brooklyn/entity/basic/EntityDynamicType.java
+++ b/core/src/main/java/brooklyn/entity/basic/EntityDynamicType.java
@@ -176,12 +176,14 @@ public class EntityDynamicType {
         try {
             Class<? extends Entity> clazz = entity.getClass();
             Map<String,Effector<?>> result = Maps.newLinkedHashMap();
+            Map<String,Field> sources = Maps.newLinkedHashMap();
             for (Field f : clazz.getFields()) {
                 if (Effector.class.isAssignableFrom(f.getType())) {
                     Effector<?> eff = (Effector<?>) f.get(entity);
                     Effector<?> overwritten = result.put(eff.getName(), eff);
+                    Field source = sources.put(eff.getName(), f);
                     if (overwritten!=null && overwritten != eff) 
-                        LOG.warn("multiple definitions for effector {} on {}; preferring {} to {}", new Object[] {eff.getName(), entity, eff, overwritten});
+                        LOG.warn("multiple definitions for effector {} on {}; preferring {} from {} to {} from {}", new Object[] {eff.getName(), entity, eff, f, overwritten, source});
                 }
             }
             
@@ -198,12 +200,20 @@ public class EntityDynamicType {
         try {
             Class<? extends Entity> clazz = entity.getClass();
             Map<String,Sensor<?>> result = Maps.newLinkedHashMap();
+            Map<String,Field> sources = Maps.newLinkedHashMap();
             for (Field f : clazz.getFields()) {
                 if (Sensor.class.isAssignableFrom(f.getType())) {
                     Sensor<?> sens = (Sensor<?>) f.get(entity);
                     Sensor<?> overwritten = result.put(sens.getName(), sens);
-                    if (overwritten!=null && overwritten != sens) 
-                        LOG.warn("multiple definitions for sensor {} on {}; preferring {} to {}", new Object[] {sens.getName(), entity, sens, overwritten});
+                    Field source = sources.put(sens.getName(), f);
+                    if (overwritten!=null && overwritten != sens) {
+                        if (sens instanceof HasConfigKey) {
+                            // probably overriding defaults, just log as debug (there will be add'l logging in config key section)
+                            LOG.debug("multiple definitions for config sensor {} on {}; preferring {} from {} to {} from {}", new Object[] {sens.getName(), entity, sens, f, overwritten, source});
+                        } else {
+                            LOG.warn("multiple definitions for sensor {} on {}; preferring {} from {} to {} from {}", new Object[] {sens.getName(), entity, sens, f, overwritten, source});
+                        }
+                    }
                 }
             }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2da0cf6b/core/src/main/java/brooklyn/location/geo/UtraceHostGeoLookup.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/location/geo/UtraceHostGeoLookup.java b/core/src/main/java/brooklyn/location/geo/UtraceHostGeoLookup.java
index 9a41344..221534c 100644
--- a/core/src/main/java/brooklyn/location/geo/UtraceHostGeoLookup.java
+++ b/core/src/main/java/brooklyn/location/geo/UtraceHostGeoLookup.java
@@ -7,15 +7,18 @@ import groovy.util.XmlParser;
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Throwables;
-
 import brooklyn.util.NetworkUtils;
 import brooklyn.util.ResourceUtils;
 
+import com.google.common.base.Throwables;
+
 public class UtraceHostGeoLookup implements HostGeoLookup {
 
     /*
@@ -51,11 +54,49 @@ Beyond this you get blacklisted and requests may time out, or return none.
         return "http://xml.utrace.de/?query="+ip.trim();
     }
 
-    static String localExternalIp;
+    static AtomicBoolean retrievingLocalExternalIp = new AtomicBoolean(false); 
+    volatile static String localExternalIp;
     /** returns public IP of localhost */
-    public synchronized static String getLocalhostExternalIp() {
+    public static synchronized String getLocalhostExternalIp() {
         if (localExternalIp!=null) return localExternalIp;
-        localExternalIp = new ResourceUtils(HostGeoLookup.class).getResourceAsString("http://api.externalip.net/ip/").trim();
+
+        // do in private thread, otherwise blocks for 30s+ on dodgy network!
+        // (we can skip it if someone else is doing it, we have synch lock so we'll get notified)
+        if (!retrievingLocalExternalIp.get())
+            new Thread(new Runnable() {
+                public void run() {
+                    if (retrievingLocalExternalIp.getAndSet(true))
+                        // someone else already trying to retrieve; caller can safely just wait,
+                        // as they will get notified by the someone else
+                        return;
+                    try {
+                        if (localExternalIp!=null)
+                            // someone else succeeded
+                            return;
+                        log.debug("Looking up external IP of this host in private thread "+Thread.currentThread());
+                        localExternalIp = new ResourceUtils(HostGeoLookup.class).getResourceAsString("http://api.externalip.net/ip/").trim();
+                        log.debug("Finished looking up external IP of this host in private thread, result "+localExternalIp);
+                    } catch (Throwable t) {
+                        log.debug("Not able to look up external IP of this host in private thread, probably offline ("+t+")");
+                    } finally {
+                        synchronized (UtraceHostGeoLookup.class) {
+                            UtraceHostGeoLookup.class.notifyAll();        
+                            retrievingLocalExternalIp.set(false);
+                        }
+                    }
+                }
+            }).start();
+        
+        try {
+            // only wait 2s, so startup is fast
+            UtraceHostGeoLookup.class.wait(2000);
+        } catch (InterruptedException e) {
+            throw Throwables.propagate(e);
+        }
+        if (localExternalIp==null) throw 
+            Throwables.propagate(new IOException("Unable to discover external IP of local machine; response to server timed out (thread may be ongoing)"));
+        
+        log.debug("Looked up external IP of this host, result is: "+localExternalIp);
         return localExternalIp;
     }
     public String getLookupUrlForLocalhost() {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2da0cf6b/core/src/main/java/brooklyn/util/Time.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/Time.java b/core/src/main/java/brooklyn/util/Time.java
index d59240a..0aa32b3 100644
--- a/core/src/main/java/brooklyn/util/Time.java
+++ b/core/src/main/java/brooklyn/util/Time.java
@@ -147,6 +147,7 @@ public class Time {
 		return result;
 	}
 
+	/** sleep which propagates Interrupted as unchecked */
 	public static void sleep(long millis) {
 		try {
 			Thread.sleep(millis);
@@ -275,4 +276,5 @@ public class Time {
 			return d*multiplier + dd;
 		}
 	}
+	
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2da0cf6b/core/src/main/java/brooklyn/util/internal/TimeExtras.groovy
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/TimeExtras.groovy b/core/src/main/java/brooklyn/util/internal/TimeExtras.groovy
index 7a694a9..61c5169 100644
--- a/core/src/main/java/brooklyn/util/internal/TimeExtras.groovy
+++ b/core/src/main/java/brooklyn/util/internal/TimeExtras.groovy
@@ -3,12 +3,12 @@ package brooklyn.util.internal
 import groovy.time.TimeDuration
 
 import java.util.concurrent.TimeUnit
-import java.util.concurrent.atomic.AtomicBoolean
 
-import org.codehaus.groovy.reflection.ClassInfo;
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 
+import brooklyn.util.Time
+
 
 /**
  * Classloading this class will cause multiply/add to be made available on TimeDuration.
@@ -44,6 +44,19 @@ class TimeExtras {
      * where an int may get constructed too early and not have the multiply syntax available
      * (because grail is invoked?; if e.g. 5*SECONDS throws an error, try duration(5, SECONDS)  */ 
     public static TimeDuration duration(int value, TimeUnit unit) {
-        return new TimeDuration(unit.toMillis(value));
+        return new TimeDuration(0, 0, 0, (int)unit.toMillis(value));
     }
+    
+    public static final TimeDuration ONE_SECOND = duration(1, TimeUnit.SECONDS);
+    public static final TimeDuration FIVE_SECONDS = duration(5, TimeUnit.SECONDS);
+    public static final TimeDuration TEN_SECONDS = duration(10, TimeUnit.SECONDS);
+    public static final TimeDuration THIRTY_SECONDS = duration(30, TimeUnit.SECONDS);
+    public static final TimeDuration ONE_MINUTE = duration(1, TimeUnit.MINUTES);
+    public static final TimeDuration TWO_MINUTES = duration(2, TimeUnit.MINUTES);
+    public static final TimeDuration FIVE_MINUTES = duration(5, TimeUnit.MINUTES);
+
+    public static void sleep(TimeDuration duration) {
+        Time.sleep(duration.toMilliseconds());
+    }    
+    
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2da0cf6b/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java b/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java
index a64adfa..a9167fe 100644
--- a/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java
+++ b/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java
@@ -10,6 +10,7 @@ import java.io.IOException;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLConnection;
+import java.util.Collections;
 import java.util.Map;
 import java.util.NoSuchElementException;
 
@@ -17,10 +18,13 @@ import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLSession;
 
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.testng.Assert;
 
 import com.google.common.base.Throwables;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
@@ -108,6 +112,36 @@ public class HttpTestUtils {
          });
     }
 
+    public static void assertContentContainsText(final String url, final String phrase, final String ...additionalPhrases) {
+        try {
+            String contents = DefaultGroovyMethods.getText(new URL(url).openStream());
+            Assert.assertTrue(contents!=null && contents.length()>0);
+            for (String text: Lists.asList(phrase, additionalPhrases)) {
+                if (!contents.contains(text)) {
+                    LOG.warn("CONTENTS OF URL "+url+" MISSING TEXT: "+text+"\n"+contents);
+                    Assert.fail("URL "+url+" does not contain text: "+text);
+                }
+            }
+        } catch (Exception e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+    public static void assertContentEventuallyContainsText(Map flags, final String url, final String phrase, final String ...additionalPhrases) {
+        TestUtils.executeUntilSucceeds(new Runnable() {
+            public void run() {
+                assertContentContainsText(url, phrase, additionalPhrases);
+            }
+         });
+    }
+    public static void assertContentEventuallyContainsText(final String url, final String phrase, final String ...additionalPhrases) {
+        assertContentEventuallyContainsText(Collections.emptyMap(), url, phrase, additionalPhrases);
+    }
+
+    /** @deprecated since 0.4.0 use assertContentEventuallyContainsText */
+    // it's not necessarily http (and http is implied by the class name anyway)
+    // more importantly, we want to use new routines above which don't wrap execute-until-succeeds twice!
+    @Deprecated
     public static void assertHttpContentEventuallyContainsText(final String url, final String containedText) {
         TestUtils.executeUntilSucceeds(new Runnable() {
             public void run() {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2da0cf6b/usage/test-support/src/main/java/brooklyn/test/TestUtils.groovy
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/brooklyn/test/TestUtils.groovy b/usage/test-support/src/main/java/brooklyn/test/TestUtils.groovy
index d2d340f..1c7a828 100644
--- a/usage/test-support/src/main/java/brooklyn/test/TestUtils.groovy
+++ b/usage/test-support/src/main/java/brooklyn/test/TestUtils.groovy
@@ -188,14 +188,14 @@ public class TestUtils {
         TimeDuration fixedPeriod = toTimeDuration(flags.period) ?: null
         TimeDuration minPeriod = fixedPeriod ?: toTimeDuration(flags.minPeriod) ?: new TimeDuration(0,0,0,1)
         TimeDuration maxPeriod = fixedPeriod ?: toTimeDuration(flags.maxPeriod) ?: new TimeDuration(0,0,0,500)
-        int maxAttempts = flags.maxAttempts ?: Integer.MAX_VALUE
+        int maxAttempts = flags.maxAttempts ?: Integer.MAX_VALUE;
+        int attempt = 0;
+        long startTime = System.currentTimeMillis();
         try {
             Throwable lastException = null;
             Object result;
             long lastAttemptTime = 0;
-            long startTime = System.currentTimeMillis()
-            long expireTime = startTime+duration.toMilliseconds()
-            int attempt = 0;
+            long expireTime = startTime+duration.toMilliseconds();
             long sleepTimeBetweenAttempts = minPeriod.toMilliseconds();
             
             while (attempt<maxAttempts && lastAttemptTime<expireTime) {
@@ -229,7 +229,9 @@ public class TestUtils {
                 throw lastException
             fail "invalid result: $result"
         } catch (Throwable t) {
-			if (logException) log.info("failed execute-until-succeeds (rethrowing): "+t)
+			if (logException) log.info("failed execute-until-succeeds, "+attempt+" attempts, "+
+                (System.currentTimeMillis()-startTime)+"ms elapsed "+
+                "(rethrowing): "+t);
 			throw t
         } finally {
             finallyBlock.call()
@@ -319,6 +321,9 @@ public class TestUtils {
         }
     }
     
+    /** @deprecated since 0.4.0 use HttpTestUtils.assertUrlEventuallyHasText or HttpTestUtils.assertUrlHasText 
+     * (NB: this method has "eventually" logic, with default timeout of 30s, despite the absence of that in the name) */
+    @Deprecated
     public static void assertUrlHasText(Map flags=[:], String url, String ...phrases) {
         String contents;
         TimeDuration timeout = flags.timeout in Number ? flags.timeout*TimeUnit.MILLISECONDS : flags.timeout ?: 30*TimeUnit.SECONDS