@SuppressWarnings("deprecation") protected void beforeStart(Map flags, Task<?> task) { activeTaskCount.incrementAndGet(); // set thread _before_ start time, so we won't get a null thread when there is a start-time if (log.isTraceEnabled()) log.trace("" + this + " beforeStart, task: " + task); if (!task.isCancelled()) { ((BasicTask) task).thread = Thread.currentThread(); if (RENAME_THREADS) { String newThreadName = "brooklyn-" + CaseFormat.LOWER_HYPHEN.to( CaseFormat.LOWER_CAMEL, task.getDisplayName().replace(" ", "")) + "-" + task.getId().substring(0, 8); ((BasicTask) task).thread.setName(newThreadName); } PerThreadCurrentTaskHolder.perThreadCurrentTask.set(task); ((BasicTask) task).startTimeUtc = System.currentTimeMillis(); } for (Object to : (Collection) flags.get("tagLinkedPreprocessors")) { TaskPreprocessor t = (TaskPreprocessor) to; t.onStart(flags, task); } ExecutionUtils.invoke(flags.get("newTaskStartCallback"), task); }
protected void afterEnd(Map<?, ?> flags, Task<?> task) { activeTaskCount.decrementAndGet(); incompleteTaskCount.decrementAndGet(); if (log.isTraceEnabled()) log.trace(this + " afterEnd, task: " + task); ExecutionUtils.invoke(flags.get("newTaskEndCallback"), task); PerThreadCurrentTaskHolder.perThreadCurrentTask.remove(); ((TaskInternal<?>) task).setEndTimeUtc(System.currentTimeMillis()); // clear thread _after_ endTime set, so we won't get a null thread when there is no end-time if (RENAME_THREADS) { String newThreadName = "brooklyn-" + Identifiers.makeRandomId(8); task.getThread().setName(newThreadName); } ((TaskInternal<?>) task).setThread(null); synchronized (task) { task.notifyAll(); } for (ExecutionListener listener : listeners) { try { listener.onTaskDone(task); } catch (Exception e) { log.warn("Error notifying listener " + listener + " of task " + task + " done", e); } } }
@Test public void testCanCallEffector() { entity = new ExampleJavaEntity(app); app.manage(entity); entity.effector1("val1"); assertEquals(entity.effectorInvocations, ImmutableList.of("val1")); Task<Void> task = entity.invoke(ExampleJavaEntity.EFFECTOR1, ImmutableMap.of("arg0", "val2")); task.blockUntilEnded(); assertEquals(entity.effectorInvocations, ImmutableList.of("val1", "val2")); }
@Test public void testEffectorOnProxyIsRecorded() { Object result = entity.identityEffector("abc"); assertEquals(result, "abc"); Set<Task<?>> tasks = managementContext .getExecutionManager() .getTasksWithAllTags(ImmutableList.of(ManagementContextInternal.EFFECTOR_TAG, entity)); Task<?> task = Iterables.get(tasks, 0); assertEquals(tasks.size(), 1, "tasks=" + tasks); assertTrue(task.getDescription().contains("identityEffector")); }
protected static Object configValueToPersistable(Object value) { // TODO Swapping an attributeWhenReady task for the actual value, if completed. // Long-term, want to just handle task-persistence properly. if (value instanceof Task) { Task<?> task = (Task<?>) value; if (task.isDone() && !task.isError()) { return task.getUnchecked(); } else { // TODO how to record a completed but errored task? return null; } } return value; }
@Test public void testCancelled() throws InterruptedException, ExecutionException { Task<List<?>> t = Tasks.sequential(sayTask("1"), sayTask("2a", Duration.THIRTY_SECONDS, "2b"), sayTask("3")); ec.submit(t); synchronized (messages) { while (messages.size() <= 1) messages.wait(); } Assert.assertEquals(messages, Arrays.asList("1", "2a")); Time.sleep(Duration.millis(50)); t.cancel(true); Assert.assertTrue(t.isDone()); // 2 should get cancelled, and invoke the cancellation semaphore // 3 should get cancelled and not run at all Assert.assertEquals(messages, Arrays.asList("1", "2a")); // Need to ensure that 2 has been started; race where we might cancel it before its run method // is even begun. Hence doing "2a; pause; 2b" where nothing is interruptable before pause. Assert.assertTrue(cancellations.tryAcquire(10, TimeUnit.SECONDS)); Iterator<Task<?>> ci = ((HasTaskChildren) t).getChildren().iterator(); Assert.assertEquals(ci.next().get(), "1"); Task<?> task2 = ci.next(); Assert.assertTrue(task2.isBegun()); Assert.assertTrue(task2.isDone()); Assert.assertTrue(task2.isCancelled()); Task<?> task3 = ci.next(); Assert.assertFalse(task3.isBegun()); Assert.assertTrue(task2.isDone()); Assert.assertTrue(task2.isCancelled()); // but we do _not_ get a mutex from task3 as it does not run (is not interrupted) Assert.assertEquals(cancellations.availablePermits(), 0); }
@SuppressWarnings("deprecation") protected void afterEnd(Map flags, Task<?> task) { activeTaskCount.decrementAndGet(); incompleteTaskCount.decrementAndGet(); if (log.isTraceEnabled()) log.trace(this + " afterEnd, task: " + task); ExecutionUtils.invoke(flags.get("newTaskEndCallback"), task); List l = (List) flags.get("tagLinkedPreprocessors"); Collections.reverse(l); for (Object li : l) { TaskPreprocessor t = (TaskPreprocessor) li; t.onEnd(flags, task); } PerThreadCurrentTaskHolder.perThreadCurrentTask.remove(); ((BasicTask) task).endTimeUtc = System.currentTimeMillis(); // clear thread _after_ endTime set, so we won't get a null thread when there is no end-time if (RENAME_THREADS) { String newThreadName = "brooklyn-" + LanguageUtils.newUid(); ((BasicTask) task).thread.setName(newThreadName); } ((BasicTask) task).thread = null; synchronized (task) { task.notifyAll(); } ExpirationPolicy expirationPolicy = (ExpirationPolicy) flags.get("expirationPolicy"); if (expirationPolicy == null) expirationPolicy = ExpirationPolicy.IMMEDIATE; if (expirationPolicy == ExpirationPolicy.IMMEDIATE) { for (Object t : ((BasicTask) task).tags) { getMutableTasksWithTag(t).remove(task); } } }
protected void doStartPolling() { if (scheduledTask == null || scheduledTask.isDone()) { ScheduledTask task = new ScheduledTask(MutableMap.of("period", getConfig(POLL_PERIOD)), pollingTaskFactory); scheduledTask = ((EntityInternal) entity).getExecutionContext().submit(task); } }
@Test public void testInessentialChildrenFailureDoesNotAbortSecondaryOrFailPrimary() { Task<String> t1 = monitorableTask(null, "1", new FailCallable()); TaskTags.markInessential(t1); Task<String> t = Tasks.<String>builder() .dynamic(true) .body(monitorableJob("main")) .add(t1) .add(monitorableTask("2")) .build(); ec.submit(t); releaseAndWaitForMonitorableJob("1"); Assert.assertFalse(t.blockUntilEnded(TINY_TIME)); releaseAndWaitForMonitorableJob("2"); Assert.assertFalse(t.blockUntilEnded(TINY_TIME)); releaseMonitorableJob("main"); Assert.assertTrue(t.blockUntilEnded(TIMEOUT)); Assert.assertEquals(messages, MutableList.of("1", "2", "main")); Assert.assertTrue( stopwatch.elapsed(TimeUnit.MILLISECONDS) < TIMEOUT.toMilliseconds(), "took too long: " + stopwatch); Assert.assertFalse(t.isError()); Assert.assertTrue(t1.isError()); }
public void stop() { if (log.isDebugEnabled()) log.debug("Stopping poll for {} (using {})", new Object[] {entity, this}); if (!running) { throw new IllegalStateException( String.format("Attempt to stop poller %s of entity %s when not running", this, entity)); } running = false; for (Task<?> task : oneOffTasks) { task.cancel(true); } for (ScheduledTask task : tasks) { task.cancel(); } oneOffTasks.clear(); tasks.clear(); }
protected boolean deleteTaskNonRecursive(Task<?> task) { Set<?> tags = checkNotNull(task, "task").getTags(); for (Object tag : tags) { Set<Task<?>> tasks = getMutableTasksWithTagOrNull(tag); if (tasks != null) tasks.remove(task); } Task<?> removed = tasksById.remove(task.getId()); return removed != null; }
protected void beforeStart(Map<?, ?> flags, Task<?> task) { activeTaskCount.incrementAndGet(); // set thread _before_ start time, so we won't get a null thread when there is a start-time if (log.isTraceEnabled()) log.trace("" + this + " beforeStart, task: " + task); if (!task.isCancelled()) { ((TaskInternal<?>) task).setThread(Thread.currentThread()); if (RENAME_THREADS) { String newThreadName = "brooklyn-" + CaseFormat.LOWER_HYPHEN.to( CaseFormat.LOWER_CAMEL, task.getDisplayName().replace(" ", "")) + "-" + task.getId().substring(0, 8); task.getThread().setName(newThreadName); } PerThreadCurrentTaskHolder.perThreadCurrentTask.set(task); ((TaskInternal<?>) task).setStartTimeUtc(System.currentTimeMillis()); } ExecutionUtils.invoke(flags.get("newTaskStartCallback"), task); }
@Test public void testChildrenRunConcurrentlyWithPrimary() { Task<String> t = Tasks.<String>builder() .dynamic(true) .body(monitorableJob("main")) .add(monitorableTask("1")) .add(monitorableTask("2")) .build(); ec.submit(t); releaseAndWaitForMonitorableJob("1"); releaseAndWaitForMonitorableJob("main"); Assert.assertFalse(t.blockUntilEnded(TINY_TIME)); releaseMonitorableJob("2"); Assert.assertTrue(t.blockUntilEnded(TIMEOUT)); Assert.assertEquals(messages, MutableList.of("1", "main", "2")); Assert.assertTrue( stopwatch.elapsed(TimeUnit.MILLISECONDS) < TIMEOUT.toMilliseconds(), "took too long: " + stopwatch); Assert.assertFalse(t.isError()); }
@SuppressWarnings("unchecked") protected <T> Task<T> submitNewTask(final Map<?, ?> flags, final Task<T> task) { if (task instanceof ScheduledTask) return (Task<T>) submitNewScheduledTask(flags, (ScheduledTask) task); tasksById.put(task.getId(), task); totalTaskCount.incrementAndGet(); beforeSubmit(flags, task); if (((TaskInternal<T>) task).getJob() == null) throw new NullPointerException( "Task " + task + " submitted with with null job: job must be supplied."); Callable<T> job = new Callable<T>() { public T call() { try { T result = null; Throwable error = null; String oldThreadName = Thread.currentThread().getName(); try { if (RENAME_THREADS) { String newThreadName = oldThreadName + "-" + task.getDisplayName() + "[" + task.getId().substring(0, 8) + "]"; Thread.currentThread().setName(newThreadName); } beforeStart(flags, task); if (!task.isCancelled()) { result = ((TaskInternal<T>) task).getJob().call(); } else throw new CancellationException(); } catch (Throwable e) { error = e; } finally { if (RENAME_THREADS) { Thread.currentThread().setName(oldThreadName); } afterEnd(flags, task); } if (error != null) { if (log.isDebugEnabled()) { // debug only here, because we rethrow log.debug( "Exception running task " + task + " (rethrowing): " + error.getMessage(), error); if (log.isTraceEnabled()) log.trace( "Trace for exception running task " + task + " (rethrowing): " + error.getMessage(), error); } throw Exceptions.propagate(error); } return result; } finally { ((TaskInternal<?>) task).runListeners(); } } }; // If there's a scheduler then use that; otherwise execute it directly Set<TaskScheduler> schedulers = null; for (Object tago : task.getTags()) { TaskScheduler scheduler = getTaskSchedulerForTag(tago); if (scheduler != null) { if (schedulers == null) schedulers = new LinkedHashSet<TaskScheduler>(2); schedulers.add(scheduler); } } Future<T> future; if (schedulers != null && !schedulers.isEmpty()) { if (schedulers.size() > 1) log.warn( "multiple schedulers detected, using only the first, for " + task + ": " + schedulers); future = schedulers.iterator().next().submit(job); } else { future = runner.submit(job); } // on completion, listeners get triggered above; here, below we ensure they get triggered on // cancel // (and we make sure the same ExecutionList is used in the future as in the task) ListenableFuture<T> listenableFuture = new ListenableForwardingFuture<T>(future, ((TaskInternal<T>) task).getListeners()) { @Override public boolean cancel(boolean mayInterruptIfRunning) { boolean result = false; if (!task.isCancelled()) result |= task.cancel(mayInterruptIfRunning); result |= super.cancel(mayInterruptIfRunning); ((TaskInternal<?>) task).runListeners(); return result; } }; ((TaskInternal<T>) task).initResult(listenableFuture); return task; }
@Override public void suspend() { scheduledTask.cancel(true); super.suspend(); }