brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject [1/4] brooklyn-server git commit: Fix config().getNonBlocking for MapConfigKey
Date Tue, 24 May 2016 09:18:22 GMT
Repository: brooklyn-server
Updated Branches:
  refs/heads/master dee107447 -> 97e3e407b


Fix config().getNonBlocking for MapConfigKey

Previously for MapConfigKey, the getNonBlocking would always return
null. This could badly impacted VanillaSoftwareProcess, where 
`VanillaSoftwareProcessSshDriver.getInstallLabelExtraSalt` would call
this for SHELL_ENVIRONMENT. The shell env was therefore not included
in the hash.

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

Branch: refs/heads/master
Commit: 8bfff1635c77affa19b9a33522ac1ab2ae6d2c8d
Parents: dee1074
Author: Aled Sage <aled.sage@gmail.com>
Authored: Fri May 20 18:05:47 2016 +0100
Committer: Aled Sage <aled.sage@gmail.com>
Committed: Fri May 20 18:05:47 2016 +0100

----------------------------------------------------------------------
 .../AbstractConfigurationSupportInternal.java   | 72 +++++++++++++++++++-
 .../brooklyn/core/entity/EntityConfigTest.java  | 65 +++++++++++++++++-
 2 files changed, 132 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8bfff163/core/src/main/java/org/apache/brooklyn/core/objs/AbstractConfigurationSupportInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractConfigurationSupportInternal.java
b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractConfigurationSupportInternal.java
index 1d4cfea..9cb7a9e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractConfigurationSupportInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractConfigurationSupportInternal.java
@@ -19,19 +19,33 @@
 
 package org.apache.brooklyn.core.objs;
 
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
 import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.mgmt.ExecutionContext;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
+import org.apache.brooklyn.core.config.MapConfigKey;
+import org.apache.brooklyn.core.config.StructuredConfigKey;
+import org.apache.brooklyn.core.config.SubElementConfigKey;
+import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
 import org.apache.brooklyn.util.core.flags.TypeCoercions;
 import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.core.task.ValueResolver;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.exceptions.RuntimeInterruptedException;
 import org.apache.brooklyn.util.guava.Maybe;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public abstract class AbstractConfigurationSupportInternal implements BrooklynObjectInternal.ConfigurationSupportInternal
{
 
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractConfigurationSupportInternal.class);
+
     @Override
     public <T> T get(HasConfigKey<T> key) {
         return get(key.getConfigKey());
@@ -53,7 +67,61 @@ public abstract class AbstractConfigurationSupportInternal implements BrooklynOb
     }
 
     @Override
-    public <T> Maybe<T> getNonBlocking(ConfigKey<T> key) {
+    public <T> Maybe<T> getNonBlocking(final ConfigKey<T> key) {
+        if (key instanceof StructuredConfigKey || key instanceof SubElementConfigKey) {
+            return getNonBlockingResolvingStructuredKey(key);
+        } else {
+            return getNonBlockingResolvingSimple(key);
+        }
+    }
+
+    /**
+     * For resolving a {@link StructuredConfigKey}, such as a {@link MapConfigKey}. Here
we need to 
+     * execute the custom logic, as is done by {@link #get(ConfigKey)}, but non-blocking!
+     */
+    protected <T> Maybe<T> getNonBlockingResolvingStructuredKey(final ConfigKey<T>
key) {
+        // TODO This is a poor implementation. We risk timing out when it's just doing its
+        // normal work (e.g. because job's thread was starved), rather than when it's truly

+        // blocked. Really we'd need to dig into the implementation of get(key), so that
the 
+        // underlying work can be configured with a timeout, for when it finally calls 
+        // ValueResolver.
+        
+        Callable<T> job = new Callable<T>() {
+            public T call() {
+                try {
+                    return get(key);
+                } catch (RuntimeInterruptedException e) {
+                    throw Exceptions.propagate(e); // expected; return gracefully
+                }
+            }
+        };
+        
+        Task<T> t = getContext().submit(Tasks.<T>builder().body(job)
+                .displayName("Resolving dependent value")
+                .description("Resolving "+key.getName())
+                .tag(BrooklynTaskTags.TRANSIENT_TASK_TAG)
+                .build());
+        try {
+            T result = t.get(ValueResolver.PRETTY_QUICK_WAIT);
+            return Maybe.of(result);
+        } catch (TimeoutException e) {
+            t.cancel(true);
+            return Maybe.<T>absent();
+        } catch (ExecutionException e) {
+            LOG.debug("Problem resolving "+key.getName()+", returning <absent>", e);
+            return Maybe.<T>absent();
+        } catch (InterruptedException e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+    /**
+     * For resolving a "simple" config key - i.e. where there's not custom logic inside a

+     * {@link StructuredConfigKey} such as a {@link MapConfigKey}. For those, we'd need to
do the
+     * same as is in {@link #get(ConfigKey)}, but non-blocking! 
+     * See {@link #getNonBlockingResolvingStructuredKey(ConfigKey)}.
+     */
+    protected <T> Maybe<T> getNonBlockingResolvingSimple(ConfigKey<T> key)
{
         // getRaw returns Maybe(val) if the key was explicitly set (where val can be null)
         // or Absent if the config key was unset.
         Object unresolved = getRaw(key).or(key.getDefaultValue());
@@ -70,7 +138,7 @@ public abstract class AbstractConfigurationSupportInternal implements BrooklynOb
                ? TypeCoercions.tryCoerce(resolved, key.getTypeToken())
                : Maybe.<T>absent();
     }
-
+    
     @Override
     public <T> T set(HasConfigKey<T> key, Task<T> val) {
         return set(key.getConfigKey(), val);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8bfff163/core/src/test/java/org/apache/brooklyn/core/entity/EntityConfigTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/EntityConfigTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/EntityConfigTest.java
index 2c58f66..41284fb 100644
--- a/core/src/test/java/org/apache/brooklyn/core/entity/EntityConfigTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/EntityConfigTest.java
@@ -19,16 +19,22 @@
 package org.apache.brooklyn.core.entity;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.api.mgmt.TaskAdaptable;
+import org.apache.brooklyn.api.mgmt.TaskFactory;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.entity.AbstractEntity;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.core.test.entity.TestEntity;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import org.apache.brooklyn.util.core.task.Tasks;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -152,6 +158,59 @@ public class EntityConfigTest {
         assertEquals(child.getAllConfigBag().getAllConfig(), ImmutableMap.of("mychildentity.myconfigwithflagname",
"overrideMyval"));
         assertEquals(child.getLocalConfigBag().getAllConfig(), ImmutableMap.of("mychildentity.myconfigwithflagname",
"overrideMyval"));
     }
+
+    @Test
+    public void testGetConfigMapWithSubKeys() throws Exception {
+        TestEntity entity = managementContext.getEntityManager().createEntity(EntitySpec.create(TestEntity.class)
+                .configure(TestEntity.CONF_MAP_THING.subKey("mysub"), "myval"));
+        
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_THING), ImmutableMap.of("mysub",
"myval"));
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_MAP_THING).get(), ImmutableMap.of("mysub",
"myval"));
+        
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_THING.subKey("mysub")), "myval");
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_MAP_THING.subKey("mysub")).get(),
"myval");
+    }
+    
+    @Test
+    public void testGetConfigMapWithExplicitMap() throws Exception {
+        TestEntity entity = managementContext.getEntityManager().createEntity(EntitySpec.create(TestEntity.class)
+                .configure(TestEntity.CONF_MAP_THING, ImmutableMap.of("mysub", "myval")));
+        
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_THING), ImmutableMap.of("mysub",
"myval"));
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_MAP_THING).get(), ImmutableMap.of("mysub",
"myval"));
+        
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_THING.subKey("mysub")), "myval");
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_MAP_THING.subKey("mysub")).get(),
"myval");
+    }
+    
+    @Test
+    public void testGetConfigNonBlocking() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        Task<String> task = Tasks.<String>builder().body(
+                new Callable<String>() {
+                    @Override
+                    public String call() throws Exception {
+                        latch.await();
+                        return "myval";
+                    }})
+                .build();
+        TestEntity entity = managementContext.getEntityManager().createEntity(EntitySpec.create(TestEntity.class)
+                .configure(TestEntity.CONF_MAP_THING_OBJECT, ImmutableMap.<String, Object>of("mysub",
task))
+                .configure(TestEntity.CONF_NAME, task));
+        
+        // Will initially return absent, because task is not done
+        assertTrue(entity.config().getNonBlocking(TestEntity.CONF_MAP_THING_OBJECT).isAbsent());
+        assertTrue(entity.config().getNonBlocking(TestEntity.CONF_MAP_THING_OBJECT.subKey("mysub")).isAbsent());
+        
+        latch.countDown();
+        
+        // Can now finish task, so will return "myval"
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_THING_OBJECT), ImmutableMap.of("mysub",
"myval"));
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_THING_OBJECT.subKey("mysub")),
"myval");
+        
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_MAP_THING_OBJECT).get(),
ImmutableMap.of("mysub", "myval"));
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_MAP_THING_OBJECT.subKey("mysub")).get(),
"myval");
+    }
     
     public static class MyEntity extends AbstractEntity {
         public static final ConfigKey<String> MY_CONFIG = ConfigKeys.newStringConfigKey("myentity.myconfig");


Mime
View raw message