protected <T> Task<T> submitNewTask(final Map flags, final Task<T> task) { if (task instanceof ScheduledTask) return submitNewScheduledTask(flags, (ScheduledTask) task); totalTaskCount.incrementAndGet(); beforeSubmit(flags, task); if (((BasicTask) task).job == null) throw new NullPointerException( "Task " + task + " submitted with with null job: job must be supplied."); Callable job = new Callable() { public Object call() { Object 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 = ((BasicTask) task).job.call(); } else throw new CancellationException(); } catch (Throwable e) { error = e; } finally { if (RENAME_THREADS) { Thread.currentThread().setName(oldThreadName); } afterEnd(flags, task); } if (error != null) { log.warn( "Error while running task " + task + " (rethrowing): " + error.getMessage(), error); throw Throwables.propagate(error); } return result; } }; ((BasicTask) task).initExecutionManager(this); // If there's a scheduler then use that; otherwise execute it directly Set<TaskScheduler> schedulers = null; for (Object tago : ((BasicTask) task).tags) { TaskScheduler scheduler = getTaskSchedulerForTag(tago); if (scheduler != null) { if (schedulers == null) schedulers = new LinkedHashSet(2); schedulers.add(scheduler); } } Future 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); } ((BasicTask) task).initResult(future); return task; }
@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; }