Merge branch 'master' into config-immediate-more a couple conflicts in cleanup to exec immediately
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/ce094d75 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/ce094d75 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/ce094d75 Branch: refs/heads/master Commit: ce094d7595b502493cebc565008d3855d5ebdee7 Parents: b61b46e 94c6a30 Author: Alex Heneveld <[email protected]> Authored: Fri Mar 3 16:17:54 2017 +0000 Committer: Alex Heneveld <[email protected]> Committed: Fri Mar 3 16:17:54 2017 +0000 ---------------------------------------------------------------------- .../brooklyn/spi/dsl/methods/DslComponent.java | 6 +- .../methods/FormatStringIntegrationTest.java | 76 ------ .../methods/FormatStringIntegrationTest.java | 76 ++++++ .../catalog/internal/BasicBrooklynCatalog.java | 2 +- .../impl/DeleteOrphanedStateTransformer.java | 8 +- .../core/sensor/ssh/SshCommandSensor.java | 6 +- .../brooklyn/feed/AbstractCommandFeed.java | 259 ++++++++++++++++++ .../apache/brooklyn/feed/CommandPollConfig.java | 179 +++++++++++++ .../org/apache/brooklyn/feed/ssh/SshFeed.java | 217 +++------------ .../apache/brooklyn/feed/ssh/SshPollConfig.java | 177 +------------ .../brooklyn/util/core/file/ArchiveUtils.java | 29 +- .../brooklyn/util/core/osgi/BundleMaker.java | 35 ++- .../util/core/task/BasicExecutionContext.java | 8 +- .../brooklyn/util/core/task/CompoundTask.java | 15 ++ .../task/InterruptingImmediateSupplier.java | 4 +- .../brooklyn/util/core/task/ValueResolver.java | 22 +- .../deserializingClassRenames.properties | 3 + .../feed/ssh/SshFeedIntegrationTest.java | 20 +- .../util/core/task/ValueResolverTest.java | 46 ++++ .../brooklyn/launcher/common/BasicLauncher.java | 6 +- .../brooklyn/launcher/BrooklynLauncher.java | 2 +- .../brooklyn/launcher/BrooklynWebServer.java | 12 +- .../brooklyn/launcher/BrooklynLauncherTest.java | 2 +- .../CleanOrphanedLocationsIntegrationTest.java | 27 +- .../brooklyn/launcher/WebAppRunnerTest.java | 34 +-- .../location/jclouds/JcloudsLocation.java | 10 +- .../apache/brooklyn/rest/domain/ApiError.java | 14 +- .../rest/resources/ApplicationResource.java | 12 +- .../rest/resources/EffectorResource.java | 3 +- .../rest/resources/ErrorResponseTest.java | 21 +- .../core/sensor/windows/WinRmCommandSensor.java | 167 ++++++++++++ .../apache/brooklyn/feed/windows/CmdFeed.java | 83 ++++++ .../util/core/internal/winrm/WinRmTool.java | 6 + .../internal/winrm/winrm4j/Winrm4jTool.java | 7 +- .../feed/windows/WinRmFeedIntegrationTest.java | 262 +++++++++++++++++++ .../util/javalang/LoadedClassLoader.java | 10 +- .../apache/brooklyn/util/net/Networking.java | 8 +- .../java/org/apache/brooklyn/util/os/Os.java | 2 +- 38 files changed, 1347 insertions(+), 529 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ce094d75/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ce094d75/core/src/main/java/org/apache/brooklyn/util/core/task/InterruptingImmediateSupplier.java ---------------------------------------------------------------------- diff --cc core/src/main/java/org/apache/brooklyn/util/core/task/InterruptingImmediateSupplier.java index 0a34a18,afbc285..9c7979b --- a/core/src/main/java/org/apache/brooklyn/util/core/task/InterruptingImmediateSupplier.java +++ b/core/src/main/java/org/apache/brooklyn/util/core/task/InterruptingImmediateSupplier.java @@@ -58,12 -59,10 +59,13 @@@ public class InterruptingImmediateSuppl if (!interrupted) Thread.currentThread().interrupt(); return Maybe.ofAllowingNull(get()); } catch (Throwable t) { + if (Exceptions.getFirstThrowableOfType(t, ImmediateValueNotAvailableException.class)!=null) { + return Maybe.absent(Exceptions.getFirstThrowableOfType(t, ImmediateValueNotAvailableException.class)); + } if (Exceptions.getFirstThrowableOfType(t, InterruptedException.class)!=null || - Exceptions.getFirstThrowableOfType(t, RuntimeInterruptedException.class)!=null) { + Exceptions.getFirstThrowableOfType(t, RuntimeInterruptedException.class)!=null || + Exceptions.getFirstThrowableOfType(t, CancellationException.class)!=null) { - return Maybe.absent(new UnsupportedOperationException("Immediate value not available", t)); + return Maybe.absent(new ImmediateValueNotAvailableException("Immediate value not available, required non-blocking execution", t)); } throw Exceptions.propagate(t); } finally { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ce094d75/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java ---------------------------------------------------------------------- diff --cc core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java index 4446d92,3c6d96b..c5316fc --- a/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java +++ b/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java @@@ -384,32 -384,36 +384,35 @@@ public class ValueResolver<T> implement v = ((TaskAdaptable<?>) v).asTask(); } } - + if (allowImmediateExecution && isEvaluatingImmediately()) { - // TODO could allow for everything, when evaluating immediately -- but if the target isn't safe to run again - // then we have to fail if immediate didn't work; to avoid breaking semantics we only do that for a few cases; - // might be nice to get to the point where we can break those semantics however, - // ie weakening what getImmediate supports and making it be non-blocking, so that bailOut=true is the default. - // if: v instanceof TaskFactory -- it is safe, it's a new API (but it is currently the only one supported); - // more than safe, we have to do it -- or add code here to cancel tasks -- because it spawns new tasks - // (other objects passed through here don't get cancelled, because other things might try again later; - // ie a task or future passed in here might naturally be long-running so cancelling is wrong, - // but with a task factory generated task it would leak if we submitted and didn't cancel!) - // if: v instanceof ImmediateSupplier -- it probably is safe to change to bailOut = true ? - // if: v instanceof Task or other things -- it currently isn't safe, there are places where - // we expect to getImmediate on things which don't support it nicely, - // and we rely on the blocking-short-wait behaviour, e.g. QuorumChecks in ConfigYamlTest + // Feb 2017 - many things now we try to run immediate; notable exceptions are: + // * where the target isn't safe to run again (such as a Task which someone else might need), + // * or where he can't be run in an "interrupting" mode even if non-blocking (eg Future.get(), some other tasks) + // (the latter could be tried here, with bailOut false, but in most cases it will just throw so we still need to + // have the timings as in SHORT_WAIT etc as a fallack) + + Maybe<T> result = null; try { - Maybe<T> result = execImmediate(exec, v); - if (result!=null) return result; - if (bailOutAfterImmediateExecution) { - throw new ImmediateSupplier.ImmediateUnsupportedException("Cannot get immediately: "+v); - } + result = exec.getImmediately(v); + + return (result.isPresent()) + ? recursive + ? new ValueResolver<T>(result.get(), type, this).getMaybe() + : result + : result; } catch (ImmediateSupplier.ImmediateUnsupportedException e) { if (bailOutAfterImmediateExecution) { - throw new ImmediateSupplier.ImmediateUnsupportedException("Cannot get immediately: "+v, e); + throw new ImmediateSupplier.ImmediateUnsupportedException("Cannot get immediately: "+v); } - // else proceed to below - log.debug("Unable to resolve-immediately for "+description+" ("+v+", unsupported, type "+v.getClass()+"); falling back to executing with timeout: "+e); - } catch (InterruptingImmediateSupplier.InterruptingImmediateSupplierNotSupportedForObject e) { + // ignore, continue below - log.debug("Unable to resolve-immediately for "+description+" ("+v+", not supported for type "+v.getClass()+"); falling back to executing with timeout: "+e); ++ if (log.isTraceEnabled()) { ++ log.trace("Unable to resolve-immediately for "+description+" ("+v+", unsupported, type "+v.getClass()+"); falling back to executing with timeout: "+e); ++ } + } catch (ImmediateSupplier.ImmediateValueNotAvailableException e) { + // definitively not available + return ImmediateSupplier.ImmediateValueNotAvailableException.newAbsentWithExceptionSupplier(); - } + } } if (v instanceof Task) { @@@ -559,6 -564,21 +562,21 @@@ } } - /** tries to get immediately, then resolve recursively (including for casting) if {@link #recursive} is set - * - * @throws InterruptingImmediateSupplier.InterruptingImmediateSupplierNotSupportedForObject - * ImmediateSupplier.ImmediateUnsupportedException - * if underlying call to {@link ExecutionContext#getImmediately(Object)} does so */ - protected Maybe<T> execImmediate(ExecutionContext exec, Object immediateSupplierOrImmediateTask) { - Maybe<T> result = exec.getImmediately(immediateSupplierOrImmediateTask); - - return (result.isPresent()) - ? recursive - ? new ValueResolver<T>(result.get(), type, this).getMaybe() - : result - : result; - } ++// /** tries to get immediately, then resolve recursively (including for casting) if {@link #recursive} is set ++// * ++// * @throws InterruptingImmediateSupplier.InterruptingImmediateSupplierNotSupportedForObject ++// * ImmediateSupplier.ImmediateUnsupportedException ++// * if underlying call to {@link ExecutionContext#getImmediately(Object)} does so */ ++// protected Maybe<T> execImmediate(ExecutionContext exec, Object immediateSupplierOrImmediateTask) { ++// Maybe<T> result = exec.getImmediately(immediateSupplierOrImmediateTask); ++// ++// return (result.isPresent()) ++// ? recursive ++// ? new ValueResolver<T>(result.get(), type, this).getMaybe() ++// : result ++// : result; ++// } + protected String getDescription() { return description!=null ? description : ""+value; } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ce094d75/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java ---------------------------------------------------------------------- diff --cc core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java index c9c76fb,64cb024..6e57c84 --- a/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java +++ b/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java @@@ -286,15 -274,57 +290,57 @@@ public class ValueResolverTest extends }); } + public void testTaskFactoryGetImmediatelyDoesNotBlockWithNestedTasks() { + final int NUM_CALLS = 3; + final AtomicInteger executingCount = new AtomicInteger(); + final List<SequentialTask<?>> outerTasks = Lists.newArrayList(); + + TaskFactory<Task<?>> taskFactory = new TaskFactory<Task<?>>() { + @Override public Task<?> newTask() { + SequentialTask<?> result = new SequentialTask<>(ImmutableList.of(new Callable<String>() { + public String call() { + executingCount.incrementAndGet(); + try { + Time.sleep(Duration.ONE_MINUTE); + return "myval"; + } finally { + executingCount.decrementAndGet(); + } + }})); + outerTasks.add(result); + return result; + } + }; + for (int i = 0; i < NUM_CALLS; i++) { + Maybe<String> result = Tasks.resolving(taskFactory).as(String.class).context(app).immediately(true).getMaybe(); + Asserts.assertTrue(result.isAbsent(), "result="+result); + } + // the call below default times out after 30s while the task above is still running + Asserts.succeedsEventually(new Runnable() { + public void run() { + Asserts.assertEquals(outerTasks.size(), NUM_CALLS); + for (Task<?> task : outerTasks) { + Asserts.assertTrue(task.isDone()); + Asserts.assertTrue(task.isCancelled()); + } + } + }); + Asserts.succeedsEventually(new Runnable() { + public void run() { + Asserts.assertEquals(executingCount.get(), 0); + } + }); + } + private static class MyImmediateAndDeferredSupplier implements ImmediateSupplier<CallInfo>, DeferredSupplier<CallInfo> { - private final boolean failImmediately; + private final RuntimeException failImmediately; public MyImmediateAndDeferredSupplier() { - this(false); + this(null); } - public MyImmediateAndDeferredSupplier(boolean simulateImmediateUnsupported) { - this.failImmediately = simulateImmediateUnsupported; + public MyImmediateAndDeferredSupplier(RuntimeException failImmediately) { + this.failImmediately = failImmediately; } @Override
