
org.ow2.bonita.runtime.event.EventExecutor Maven / Gradle / Ivy
/**
* Copyright (C) 2009-20102 BonitaSoft S.A.
* BonitaSoft, 31 rue Gustave Eiffel - 38000 Grenoble
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation
* version 2.1 of the License.
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
**/
package org.ow2.bonita.runtime.event;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.ow2.bonita.facade.uuid.ProcessInstanceUUID;
import org.ow2.bonita.services.CommandService;
import org.ow2.bonita.util.EnvTool;
import org.ow2.bonita.util.Misc;
import org.ow2.bonita.util.ReflectUtil;
/**
*
* @author Charles Souillard, Matthieu Chaffotte
*
*/
public class EventExecutor implements Serializable {
private static final Logger LOG = Logger.getLogger(EventExecutor.class.getName());
private static final long serialVersionUID = 1L;
// injected
transient CommandService commandService;
int nbrOfThreads = 3;
int idleMillis = 5000; // default normal poll interval is 5 seconds
int lockMillis = 120000; // default max lock time is 2 minutes
int minimumInterval = 50;
int retries = 1;
boolean expressionMessageMatcherEnable = true;
boolean mainMatcherEnable = true;
String name;
private transient ThreadPoolExecutor threadPool;
private transient EventMatcher eventMatcher = null;
private transient ExpressionMessageEventMatcher expressionMessageMatcher = null;
String jobExecutorClassName;
private transient JobExecutor jobExecutor = null;
int maxParallelJobs = 50;
boolean cleanLocks = false;
private boolean isActive = false;
public synchronized void start() {
final String domain = commandService.execute(new GetDomainCommand());
name = EventExecutor.class.getSimpleName() + "-" + Misc.getHostName() + "-" + domain;
if (isActive) {
LOG.severe("Cannot start event executor '" + name + "' because it is already running...");
return;
}
if (!isActive) {
isActive = true;
if (LOG.isLoggable(Level.INFO)) {
LOG.info("starting event executor threads for event executor '" + name + "'...");
}
threadPool = new ThreadPoolExecutor(nbrOfThreads, nbrOfThreads, 0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue(nbrOfThreads), EventRejectionHandler.INSTANCE);
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Starting job dispatcher thread for executing events '" + name + "'...");
}
final Class jobExecutorClass = (Class) ReflectUtil.loadClass(Thread.currentThread()
.getContextClassLoader(), jobExecutorClassName);
final Constructor constructor = ReflectUtil.getConstructor(jobExecutorClass, new Class[] {
EventExecutor.class, String.class });
jobExecutor = ReflectUtil.newInstance(constructor, new Object[] { this,
JobExecutorThread.class.getSimpleName() + "-" + Misc.getHostName() + "-" + domain });
jobExecutor.setMaxParallelJobs(maxParallelJobs);
jobExecutor.setCleanLocks(cleanLocks);
jobExecutor.start();
if (expressionMessageMatcherEnable) {
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Starting matcher of message correlation based on an expression '" + name + "'...");
}
expressionMessageMatcher = new ExpressionMessageEventMatcher(this,
ExpressionMessageEventMatcher.class.getSimpleName() + "-" + Misc.getHostName() + "-" + domain);
expressionMessageMatcher.start();
}
if (mainMatcherEnable) {
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Starting matcher of message correlation based on correlation keys/no expression '" + name + "'...");
}
eventMatcher = new EventMatcher(this, EventMatcher.class.getSimpleName() + "-" + Misc.getHostName() + "-"
+ domain);
eventMatcher.start();
}
}
}
static final class EventRejectionHandler implements RejectedExecutionHandler {
static final EventRejectionHandler INSTANCE = new EventRejectionHandler();
@Override
public void rejectedExecution(final Runnable task, final ThreadPoolExecutor executor) {
try {
executor.getQueue().put(task);
} catch (final InterruptedException e) {
throw new RejectedExecutionException("queuing " + task + " got interrupted", e);
}
}
}
public boolean isActive() {
return isActive;
}
public synchronized void stop() {
stop(false);
}
public synchronized void stop(final boolean join) {
if (LOG.isLoggable(Level.INFO)) {
LOG.info("stopping event executor");
}
if (isActive) {
isActive = false;
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Event executor: deactivating job dispatcher thread...");
}
jobExecutor.deactivate(true);
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Event executor: job dispatcher thread deactivated...");
}
if (eventMatcher != null) {
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Event executor: deactivating event matcher...");
}
eventMatcher.deactivate(true);
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Event executor: message event deactivated...");
}
}
if (expressionMessageMatcher != null) {
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Event executor: deactivating expression message matcher...");
}
expressionMessageMatcher.deactivate(true);
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Event executor: expression message matcher deactivated...");
}
}
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Event executor: shutdown threadpool...");
}
threadPool.shutdown();
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Event executor: threadpool shutdowned...");
}
if (join) {
try {
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Event executor: waiting for threadPool termination...");
}
threadPool.awaitTermination(1000 * 60 * 5, TimeUnit.MILLISECONDS);
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Event executor: threadPool termination OK...");
}
} catch (final InterruptedException e) {
LOG.severe("joining got interrupted");
}
}
} else if (LOG.isLoggable(Level.FINE)) {
LOG.fine("ignoring stop: event executor '" + name + "' not started");
}
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Event executor stopped");
}
}
public int getNbrOfThreads() {
return nbrOfThreads;
}
public ThreadPoolExecutor getThreadPool() {
return threadPool;
}
public int getIdleMillis() {
return idleMillis;
}
public int getLockMillis() {
return lockMillis;
}
public CommandService getCommandService() {
return commandService;
}
public int getMinimumInterval() {
return minimumInterval;
}
public int getRetries() {
return retries;
}
public void setCommandService(final CommandService commandService) {
this.commandService = commandService;
}
public void notifyJobThreadFinished(final ProcessInstanceUUID rootInstanceUUID) {
jobExecutor.notifyThreadFinished(rootInstanceUUID);
}
public void internalJobExecutorRefresh() {
if (jobExecutor != null && jobExecutor.isActive()) {
jobExecutor.refresh();
}
}
public void internalExpressionMessageEventMatcherRefresh() {
if (expressionMessageMatcher != null && expressionMessageMatcher.isActive()) {
expressionMessageMatcher.refresh();
}
}
public void internalEventMatcherRefresh() {
if (eventMatcher != null && eventMatcher.isActive()) {
eventMatcher.refresh();
}
}
public void refreshJobExecutor() {
EnvTool.getTransaction().registerSynchronization(new NewJobNotification(this));
}
public void refreshExpressionMessageEventMatcher() {
EnvTool.getTransaction().registerSynchronization(new ExpressionMessageEventAddedNotification(this));
}
public void refreshMatchers() {
EnvTool.getTransaction().registerSynchronization(new ExpressionMessageEventAddedNotification(this));
EnvTool.getTransaction().registerSynchronization(new EventAddedNotification(this));
}
public void refreshEventMatcher() {
EnvTool.getTransaction().registerSynchronization(new EventAddedNotification(this));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy