public void executeOnCompletion(final IOAsyncTask completion) { if (errorCode != -1) { completion.onError(errorCode, errorMessage); return; } boolean executeNow = false; synchronized (this) { if (tasks == null) { tasks = new LinkedList<TaskHolder>(); minimalReplicated = replicationLineUp.intValue(); minimalStore = storeLineUp.intValue(); minimalPage = pageLineUp.intValue(); } // On this case, we can just execute the context directly if (replicationLineUp.intValue() == replicated && storeLineUp.intValue() == stored && pageLineUp.intValue() == paged) { // We want to avoid the executor if everything is complete... // However, we can't execute the context if there are executions pending // We need to use the executor on this case if (executorsPending.get() == 0) { // No need to use an executor here or a context switch // there are no actions pending.. hence we can just execute the task directly on the same // thread executeNow = true; } else { execute(completion); } } else { tasks.add(new TaskHolder(completion)); } } if (executeNow) { // Executing outside of any locks completion.done(); } }
/** @param task */ private void execute(final IOAsyncTask task) { executorsPending.incrementAndGet(); try { executor.execute( new Runnable() { public void run() { try { // If any IO is done inside the callback, it needs to be done on a new context OperationContextImpl.clearContext(); task.done(); } finally { executorsPending.decrementAndGet(); } } }); } catch (Throwable e) { HornetQServerLogger.LOGGER.errorExecutingIOAsyncTask(e); executorsPending.decrementAndGet(); task.onError( HornetQExceptionType.INTERNAL_ERROR.getCode(), "It wasn't possible to complete IO operation - " + e.getMessage()); } }