package org.ow2.choreos.invoker; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import org.apache.log4j.Logger; import org.ow2.choreos.utils.Concurrency; /** * You should use this this class to invoke external systems. * * @author leonardo * */ public class Invoker<T> { public static boolean SAVE_HISTORY = false; private static Logger logger = Logger.getLogger(Invoker.class); private final String taskName; private final Callable<T> task; private final int trials; private final int trialTimeout; private final int pauseBetweenTrials; private final TimeUnit timeUnit; private final InvokerHistory history = InvokerHistory.getInstance(); Invoker(String taskName, Callable<T> task, int trials, int trialTimeout, int pauseBetweenTrials, TimeUnit timeUnit) { this.taskName = taskName; this.task = task; this.trials = trials; this.trialTimeout = trialTimeout; this.pauseBetweenTrials = pauseBetweenTrials; this.timeUnit = timeUnit; } public T invoke() throws InvokerException { Throwable cause = null; for (int tried = 0; tried < trials; tried++) { try { T result = tryToInvoke(); return result; } catch (Exception e) { cause = e; pause(); } } throw new InvokerException(cause); } private T tryToInvoke() throws Exception { ExecutorService executor = Executors.newSingleThreadExecutor(); Future<T> future = executor.submit(task); String errorMessage = "Invoker could not properly invoke " + taskName; long t0 = System.nanoTime(); Concurrency.waitExecutor(executor, trialTimeout, timeUnit, logger, errorMessage); long tf = System.nanoTime(); try { T result = Concurrency.checkAndGetFromFuture(future); logHistory(t0, tf); return result; } catch (ExecutionException e) { Throwable cause = e.getCause(); if (cause instanceof Exception) throw (Exception) e; else throw e; } } // problem(?): do not logging history of successful timeouted invocations private void logHistory(long t0, long tf) { if (SAVE_HISTORY) { long delta = (tf - t0) / 1000000000; history.addTime(taskName, delta); } } private void pause() throws InvokerException { try { timeUnit.sleep(pauseBetweenTrials); } catch (InterruptedException e) { throw new InvokerException(e); } } }