org.fabric3.timer.impl.ExecutorTimerService Maven / Gradle / Ivy
/*
* Fabric3
* Copyright (c) 2009-2015 Metaform Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Portions originally based on Apache Tuscany 2007
* licensed under the Apache 2.0 license.
*/
package org.fabric3.timer.impl;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.fabric3.api.annotation.monitor.Monitor;
import org.fabric3.api.host.Fabric3Exception;
import org.fabric3.spi.management.ManagementService;
import org.fabric3.timer.spi.Task;
import org.fabric3.timer.spi.TimerService;
import org.oasisopen.sca.annotation.Destroy;
import org.oasisopen.sca.annotation.EagerInit;
import org.oasisopen.sca.annotation.Init;
import org.oasisopen.sca.annotation.Property;
import org.oasisopen.sca.annotation.Reference;
import org.oasisopen.sca.annotation.Service;
/**
*
*/
@EagerInit
@Service({TimerService.class, ScheduledExecutorService.class})
public class ExecutorTimerService implements TimerService, ScheduledExecutorService {
private ManagementService managementService;
private TimerServiceMonitor monitor;
private Map executors = new ConcurrentHashMap<>();
private Map statisticsCache = new ConcurrentHashMap<>();
private int defaultPoolSize = 2;
public ExecutorTimerService(@Reference ManagementService managementService, @Monitor TimerServiceMonitor monitor) {
this.managementService = managementService;
this.monitor = monitor;
}
@Property(required = false)
public void setDefaultPoolSize(int defaultCoreSize) {
this.defaultPoolSize = defaultCoreSize;
}
@Init
public void init() throws Fabric3Exception {
allocate(TimerService.DEFAULT_POOL, defaultPoolSize);
}
@Destroy
public void destroy() {
executors.values().forEach(java.util.concurrent.ScheduledExecutorService::shutdownNow);
}
public void allocate(String poolName, int coreSize) throws Fabric3Exception {
if (executors.containsKey(poolName)) {
throw new IllegalStateException("Pool already allocated: " + poolName);
}
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(coreSize);
TimerThreadFactory threadFactory = new TimerThreadFactory(poolName, monitor);
executor.setThreadFactory(threadFactory);
executors.put(poolName, executor);
TimerPoolStatistics statistics = new TimerPoolStatistics(poolName, coreSize);
statistics.start();
statisticsCache.put(poolName, statistics);
if (managementService != null) {
managementService.export(encodeName(poolName), "timer pools", "Timer pools", statistics);
}
}
public void deallocate(String poolName) throws Fabric3Exception {
ScheduledExecutorService executor = executors.remove(poolName);
if (executor == null) {
throw new IllegalStateException("Pool not allocated: " + poolName);
}
if (managementService != null) {
managementService.remove(encodeName(poolName), "timer pools");
}
executor.shutdown();
}
public ScheduledFuture> scheduleRecurring(String poolName, Task task) {
TimerPoolStatistics statistics = this.statisticsCache.get(poolName);
RecurringRunnable recurring = new RecurringRunnable(poolName, task, statistics);
return recurring.schedule();
}
public ScheduledFuture> scheduleAtFixedRate(String poolName, Runnable command, long initialDelay, long period, TimeUnit unit) {
ScheduledExecutorService executor = getExecutor(poolName);
return executor.scheduleAtFixedRate(command, initialDelay, period, unit);
}
public ScheduledFuture> scheduleWithFixedDelay(String poolName, Runnable command, long initialDelay, long delay, TimeUnit unit) {
ScheduledExecutorService executor = executors.get(poolName);
return executor.scheduleWithFixedDelay(command, initialDelay, delay, unit);
}
public ScheduledFuture> schedule(String poolName, Runnable command, long delay, TimeUnit unit) {
ScheduledExecutorService executor = executors.get(poolName);
return executor.schedule(command, delay, unit);
}
public ScheduledFuture schedule(String poolName, Callable callable, long delay, TimeUnit unit) {
ScheduledExecutorService executor = executors.get(poolName);
return executor.schedule(callable, delay, unit);
}
public ScheduledFuture> schedule(Runnable command, long delay, TimeUnit unit) {
return schedule(TimerService.DEFAULT_POOL, command, delay, unit);
}
public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) {
return schedule(TimerService.DEFAULT_POOL, callable, delay, unit);
}
public ScheduledFuture> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
return scheduleAtFixedRate(TimerService.DEFAULT_POOL, command, initialDelay, period, unit);
}
public ScheduledFuture> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
return scheduleWithFixedDelay(TimerService.DEFAULT_POOL, command, initialDelay, delay, unit);
}
public void shutdown() {
throw new UnsupportedOperationException();
}
public List shutdownNow() {
throw new UnsupportedOperationException();
}
public boolean isShutdown() {
return false;
}
public boolean isTerminated() {
return false;
}
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
throw new UnsupportedOperationException();
}
public Future submit(Callable task) {
throw new UnsupportedOperationException();
}
public Future submit(Runnable task, T result) {
throw new UnsupportedOperationException();
}
public Future> submit(Runnable task) {
throw new UnsupportedOperationException();
}
public List> invokeAll(Collection extends Callable> tasks) throws InterruptedException {
throw new UnsupportedOperationException();
}
public List> invokeAll(Collection extends Callable> tasks, long timeout, TimeUnit unit) throws InterruptedException {
throw new UnsupportedOperationException();
}
public T invokeAny(Collection extends Callable> tasks) throws InterruptedException, ExecutionException {
throw new UnsupportedOperationException();
}
public T invokeAny(Collection extends Callable> tasks, long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
throw new UnsupportedOperationException();
}
public void execute(Runnable command) {
throw new UnsupportedOperationException();
}
private ScheduledExecutorService getExecutor(String poolName) {
ScheduledExecutorService executor = executors.get(poolName);
if (executor == null) {
throw new RejectedExecutionException("Pool not allocated: " + poolName);
}
return executor;
}
private String encodeName(String name) {
return "timer/pools/" + name.toLowerCase();
}
/**
* Implements a recurring task by wrapping an runnable and rescheduling with the executor service after an iteration has completed.
*/
private class RecurringRunnable implements Runnable {
private TimerPoolStatistics statistics;
private String poolName;
private Task delegate;
private ScheduledFutureWrapper> currentFuture;
private RecurringRunnable(String poolName, Task delegate, TimerPoolStatistics statistics) {
this.poolName = poolName;
this.delegate = delegate;
this.statistics = statistics;
}
@SuppressWarnings({"unchecked"})
public ScheduledFuture> schedule() {
long interval = delegate.nextInterval();
if (Task.DONE == interval) {
return null;
}
ScheduledExecutorService executor = getExecutor(poolName);
ScheduledFuture future = executor.schedule(this, interval, TimeUnit.MILLISECONDS);
if (currentFuture == null) {
currentFuture = new ScheduledFutureWrapper(future);
} else {
currentFuture.update(future);
}
return currentFuture;
}
public void run() {
long start = System.currentTimeMillis();
try {
delegate.run();
} catch (RuntimeException e) {
monitor.threadError(e);
throw e;
} finally {
long elapsed = System.currentTimeMillis() - start;
statistics.incrementTotalExecutions();
statistics.incrementExecutionTime(elapsed);
if (!currentFuture.isCancelled()) {
schedule();
}
}
}
}
/**
* Returned when a recurring task is scheduled. This class wraps a ScheduledFuture delegate which is updated after the recurring event is rescheduled.
*
* @param The result type returned by this Future's get method
*/
private class ScheduledFutureWrapper implements ScheduledFuture {
private volatile ScheduledFuture delegate;
private ScheduledFutureWrapper(ScheduledFuture delegate) {
this.delegate = delegate;
}
public void update(ScheduledFuture newDelegate) {
delegate = newDelegate;
}
public boolean cancel(boolean mayInterruptIfRunning) {
return delegate.cancel(mayInterruptIfRunning);
}
public boolean isCancelled() {
return delegate.isCancelled();
}
public boolean isDone() {
return delegate.isDone();
}
public V get() throws InterruptedException, ExecutionException {
return delegate.get();
}
public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return delegate.get(timeout, unit);
}
public long getDelay(TimeUnit unit) {
return delegate.getDelay(unit);
}
public int compareTo(Delayed o) {
return delegate.compareTo(o);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy