@Override protected void doRunExample(final Engine engine) throws Exception { final int[] toSort = createRandomArray(10, new Random()); final Task<int[]> mergeSort = mergeSort(toSort, new Range(0, toSort.length)); engine.run(mergeSort); mergeSort.await(); System.out.println("Before sort: " + Arrays.toString(toSort)); System.out.println("After sort: " + Arrays.toString(mergeSort.get())); Arrays.sort(toSort); System.out.println("Java sort: " + Arrays.toString(toSort)); ExampleUtil.printTracingResults(mergeSort); }
@Test public void testShutdownWithNoTasks() throws InterruptedException { _engine.shutdown(); assertTrue(_engine.isShutdown()); assertTrue(_engine.awaitTermination(50, TimeUnit.MILLISECONDS)); assertTrue(_engine.isTerminated()); assertTrue(_engine.isShutdown()); }
@Override public void runTask(Engine engine, Task<?> t) { engine.blockingRun(t); }
/** * Runs the given task. Task passed in as a parameter becomes a root on a new Plan. * All tasks created and started as a consequence of a root task will belong to that plan and will share a Trace. * <p> * This method blocks until Engine has a capacity to run the task. Engine's capacity is * specified by a {@value #MAX_CONCURRENT_PLANS} configuration property. Use * {@link EngineBuilder#setEngineProperty(String, Object)} to set this property. * For the sake of backwards compatibility default value for a {@value #MAX_CONCURRENT_PLANS} is * {@value #DEFUALT_MAX_CONCURRENT_PLANS} which essentially means "unbounded capacity". * * @param task the task to run */ public void blockingRun(final Task<?> task) { blockingRun(task, defaultPlanClass(task)); }
/** * Runs the given task if Engine has a capacity to start new plan as specified by * {@value #MAX_CONCURRENT_PLANS} configuration parameter. * For the sake of backwards compatibility default value for a {@value #MAX_CONCURRENT_PLANS} is * {@value #DEFUALT_MAX_CONCURRENT_PLANS} which essentially means "unbounded capacity". * Task passed in as a parameter becomes a root on a new Plan. * All tasks created and started as a consequence of a root task will belong to that plan and will share a Trace. * This method returns immediately and does not block. It returns {@code true} if Plan was successfully started. * @param task the task to run * @return true if Plan was started */ public boolean tryRun(final Task<?> task) { return tryRun(task, defaultPlanClass(task)); }
/** * Runs the given task. Task passed in as a parameter becomes a root on a new Plan. * All tasks created and started as a consequence of a root task will belong to that plan and will share a Trace. * <p> * This method throws {@code IllegalStateException} if Engine does not have capacity to run the task. * Engine's capacity is specified by a {@value #MAX_CONCURRENT_PLANS} configuration property. Use * {@link EngineBuilder#setEngineProperty(String, Object)} to set this property. * For the sake of backwards compatibility default value for a {@value #MAX_CONCURRENT_PLANS} is * {@value #DEFUALT_MAX_CONCURRENT_PLANS} which essentially means "unbounded capacity". * * @param task the task to run * @throws IllegalStateException */ public void run(final Task<?> task) { run(task, defaultPlanClass(task)); }
public static void main(String[] args) throws InterruptedException { final long viewerId = 0; final Set<Long> unclassified = new HashSet<Long>(); for (long i = 0; i < 20; i++) { unclassified.add(i); } final ScheduledExecutorService serviceScheduler = Executors.newSingleThreadScheduledExecutor(); final Client restLiClient = new ClientImpl(serviceScheduler); final int numCores = Runtime.getRuntime().availableProcessors(); final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(numCores + 1); final Engine engine = new EngineBuilder().setTaskExecutor(scheduler).setTimerScheduler(scheduler).build(); final ClassifierPlanFactory classifier = new ClassifierPlanFactory(restLiClient); try { final Task<Map<Long, Classification>> classifications = classifier.classify(viewerId, unclassified); engine.run(classifications); classifications.await(); System.out.println(classifications.get()); ExampleUtil.printTracingResults(classifications); } finally { serviceScheduler.shutdownNow(); engine.shutdown(); scheduler.shutdownNow(); } } }
public void runExample() throws Exception { _serviceScheduler = Executors.newScheduledThreadPool(2); final int numCores = Runtime.getRuntime().availableProcessors(); final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(numCores + 1); final EngineBuilder builder = new EngineBuilder().setTaskExecutor(scheduler).setTimerScheduler(scheduler); customizeEngine(builder); final Engine engine = builder.build(); try { doRunExample(engine); } finally { engine.shutdown(); scheduler.shutdownNow(); _serviceScheduler.shutdown(); _serviceScheduler = null; } }
@SuppressWarnings("deprecation") @Test public void testTaskWithoutExecutor() throws InterruptedException { final int numCores = Runtime.getRuntime().availableProcessors(); final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(numCores + 1); final Engine engine = new EngineBuilder().setTaskExecutor(scheduler).setTimerScheduler(scheduler).build(); try { final Task<Integer> task = new AsyncCallableTask<Integer>(new Callable<Integer>() { @Override public Integer call() throws Exception { return 1; } }); engine.run(task); assertTrue(task.await(5, TimeUnit.SECONDS)); assertTrue(task.isFailed()); assertTrue(task.getError() instanceof IllegalStateException); } finally { engine.shutdown(); engine.awaitTermination(1, TimeUnit.SECONDS); scheduler.shutdownNow(); } } }
@AfterMethod public void tearDown() throws Exception { _engine.shutdown(); _engine.awaitTermination(50, TimeUnit.MILLISECONDS); _engine = null; _scheduler.shutdownNow(); _scheduler = null; }
/** * Runs the given task. Task passed in as a parameter becomes a root on a new Plan. * All tasks created and started as a consequence of a root task will belong to that plan and will share a Trace. * <p> * This method throws {@code IllegalStateException} if Engine does not have capacity to run the task. * Engine's capacity is specified by a {@value #MAX_CONCURRENT_PLANS} configuration property. Use * {@link EngineBuilder#setEngineProperty(String, Object)} to set this property. * For the sake of backwards compatibility default value for a {@value #MAX_CONCURRENT_PLANS} is * {@value #DEFUALT_MAX_CONCURRENT_PLANS} which essentially means "unbounded capacity". * * @param task the task to run * @param planClass string that identifies a "class" of the Plan. Plan class ends up in a ParSeq * Trace and can be used to group traces into "classes" when traces are statistically analyzed. * @throws IllegalStateException */ public void run(final Task<?> task, final String planClass) { if (!tryRun(task, planClass)) { throw new IllegalStateException("Starting new plan rejected, exceeded limit of concurrent plans: " + _maxConcurrentPlans); } }
_taskQueueFactory = createTaskQueueFactory(properties, taskQueueFactory); _maxRelationshipsPerTrace = (Integer) getProperty(MAX_RELATIONSHIPS_PER_TRACE); } else { _maxRelationshipsPerTrace = DEFUALT_MAX_RELATIONSHIPS_PER_TRACE; _maxConcurrentPlans = (Integer) getProperty(MAX_CONCURRENT_PLANS); } else { _maxConcurrentPlans = DEFUALT_MAX_CONCURRENT_PLANS; _drainSerialExecutorQueue = (Boolean) getProperty(DRAIN_SERIAL_EXECUTOR_QUEUE); } else { _drainSerialExecutorQueue = DEFAULT_DRAIN_SERIAL_EXECUTOR_QUEUE; tryTransitionTerminate(); maxMonitors = (Integer) getProperty(MAX_EXECUTION_MONITORS); durationThresholdNano = (Long) getProperty(EXECUTION_MONITOR_DURATION_THRESHOLD_NANO); checkIntervalNano = (Long) getProperty(EXECUTION_MONITOR_CHECK_INTERVAL_NANO); idleDurationNano = (Long) getProperty(EXECUTION_MONITOR_IDLE_DURATION_NANO); loggingIntervalNano = (Long) getProperty(EXECUTION_MONITOR_LOGGING_INTERVAL_NANO); minStallNano = (Long) getProperty(EXECUTION_MONITOR_MIN_STALL_NANO); stallsHistorySize = (Integer) getProperty(EXECUTION_MONITOR_STALLS_HISTORY_SIZE);
/** * Runs the given task. Task passed in as a parameter becomes a root on a new Plan. * All tasks created and started as a consequence of a root task will belong to that plan and will share a Trace. * <p> * This method blocks until Engine has a capacity to run the task. Engine's capacity is * specified by a {@value #MAX_CONCURRENT_PLANS} configuration property. Use * {@link EngineBuilder#setEngineProperty(String, Object)} to set this property. * For the sake of backwards compatibility default value for a {@value #MAX_CONCURRENT_PLANS} is * {@value #DEFUALT_MAX_CONCURRENT_PLANS} which essentially means "unbounded capacity". * * @param task the task to run * @param planClass string that identifies a "class" of the Plan. Plan class ends up in a ParSeq * Trace and can be used to group traces into "classes" when traces are statistically analyzed. */ public void blockingRun(final Task<?> task, final String planClass) { try { acquirePermit(planClass); runWithPermit(task, planClass); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }
/** * Checks that the require configuration has been set and then constructs * and returns a new {@link Engine}. * * @return a new {@link Engine} using the configuration in this builder. * @throws IllegalStateException if the configuration in this builder is invalid. */ public Engine build() { if (_taskExecutor == null) { throw new IllegalStateException("Task executor is required to create an Engine, but it is not set"); } if (_timerScheduler == null) { throw new IllegalStateException("Timer scheduler is required to create an Engine, but it is not set"); } return new Engine(_taskExecutor, new IndirectDelayedExecutor(_timerScheduler), _loggerFactory != null ? _loggerFactory : new CachedLoggerFactory(LoggerFactory.getILoggerFactory()), _properties, _planDeactivationListener != null ? _planDeactivationListener : planContext -> {}, _planCompletionListener != null ? _planCompletionListener : planContext -> {}, _taskQueueFactory, _planClassRateLimiter); }
public void runExample() throws Exception { _serviceScheduler = Executors.newScheduledThreadPool(2); final int numCores = Runtime.getRuntime().availableProcessors(); final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(numCores + 1); final Engine engine = new EngineBuilder() .setTaskExecutor(scheduler) .setTimerScheduler(scheduler) .build(); try { doRunExample(engine); } finally { engine.shutdown(); scheduler.shutdownNow(); _serviceScheduler.shutdown(); _serviceScheduler = null; } }
@AfterMethod public void tearDown() throws Exception { _engine.shutdown(); _engine.awaitTermination(50, TimeUnit.MILLISECONDS); _engine = null; _scheduler.shutdownNow(); _scheduler = null; }
/** * Runs the given task if Engine has a capacity to start new plan as specified by * {@value #MAX_CONCURRENT_PLANS} configuration parameter within specified amount of time. * For the sake of backwards compatibility default value for a {@value #MAX_CONCURRENT_PLANS} is * {@value #DEFUALT_MAX_CONCURRENT_PLANS} which essentially means "unbounded capacity". * Task passed in as a parameter becomes a root on a new Plan. * All tasks created and started as a consequence of a root task will belong to that plan and will share a Trace. * If Engine does not have capacity to start the task, this method will block up to specified amount of * time waiting for other concurrently running Plans to complete. If there is no capacity to start the task * within specified amount of time this method will return false. It returns {@code true} if Plan was successfully started. * @param task the task to run * @param timeout amount of time to wait for Engine's capacity to run the task * @param unit * @return true if Plan was started within the given waiting time and the current thread has not * been {@linkplain Thread#interrupt interrupted}. */ public boolean tryRun(final Task<?> task, final long timeout, final TimeUnit unit) throws InterruptedException { return tryRun(task, defaultPlanClass(task), timeout, unit); }
@Test public void testTryRunWithinCapacity() throws InterruptedException { final AtomicInteger counter = new AtomicInteger(0); Task<?>[] tasks = new Task<?>[10]; for (int i = 0; i < 10; i++) { tasks[i] = Task.action(counter::incrementAndGet); } for (int i = 0; i < 10; i++) { assertTrue(_engine.tryRun(tasks[i])); } assertTrue(awaitAll(tasks)); assertEquals(10, counter.get()); }
/** * Runs the given task. Task passed in as a parameter becomes a root on a new Plan. * All tasks created and started as a consequence of a root task will belong to that plan and will share a Trace. * <p> * This method blocks until Engine has a capacity to run the task. Engine's capacity is * specified by a {@value #MAX_CONCURRENT_PLANS} configuration property. Use * {@link EngineBuilder#setEngineProperty(String, Object)} to set this property. * For the sake of backwards compatibility default value for a {@value #MAX_CONCURRENT_PLANS} is * {@value #DEFUALT_MAX_CONCURRENT_PLANS} which essentially means "unbounded capacity". * * @param task the task to run */ public void blockingRun(final Task<?> task) { blockingRun(task, defaultPlanClass(task)); }