package org.radargun.service;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.radargun.utils.TimeService;
/**
* @author Radim Vansa <rvansa@redhat.com>
*/
public class InfinispanServerLifecycle extends ProcessLifecycle<InfinispanServerService> {
private boolean serverStarted;
private boolean serverStopped;
private static final Pattern START_OK = Pattern.compile(".*\\[org\\.jboss\\.as\\].*started in.*");
private static final Pattern START_ERROR = Pattern.compile(".*\\[org\\.jboss\\.as\\].*started \\(with errors\\) in.*");
private static final Pattern STOPPED = Pattern.compile(".*\\[org\\.jboss\\.as\\].*stopped in.*");
private volatile boolean gracefulStop = true;
public InfinispanServerLifecycle(final InfinispanServerService service) {
super(service);
}
@Override
public void start() {
service.registerAction(START_OK, new ProcessService.OutputListener() {
@Override
public void run(Matcher m) {
setServerStarted();
service.unregisterAction(START_OK);
service.unregisterAction(START_ERROR);
fireAfterStart();
}
});
service.registerAction(START_ERROR, new ProcessService.OutputListener() {
@Override
public void run(Matcher m) {
log.warn("Server started with errors");
setServerStarted();
service.unregisterAction(START_OK);
service.unregisterAction(START_ERROR);
fireAfterStart();
}
});
service.registerAction(STOPPED, new ProcessService.OutputListener() {
@Override
public void run(Matcher m) {
log.error("Server stopped before it started!");
setServerStarted();
setServerStopped();
service.unregisterAction(START_OK);
service.unregisterAction(START_ERROR);
service.unregisterAction(STOPPED);
fireAfterStop(gracefulStop);
}
});
if (isRunning()) {
log.warn("Process is already running");
return;
}
fireBeforeStart();
startInternal();
long startTime = TimeService.currentTimeMillis();
synchronized (this) {
while (!serverStarted) {
try {
long waitTime = startTime + service.startTimeout - TimeService.currentTimeMillis();
if (waitTime <= 0) {
throw new IllegalStateException("Server did not start within timeout");
}
wait(waitTime);
} catch (InterruptedException e) {
throw new IllegalStateException("Interrupted waiting for server to start", e);
}
}
}
// fireAfterStart is called from output listener
}
@Override
public void stop() {
if (!isRunning()) {
log.warn("Process is not running, cannot stop");
return;
}
fireBeforeStop(true);
gracefulStop = true;
stopInternal();
stopReaders();
}
@Override
public void kill() {
gracefulStop = false;
Runnable waiting = killAsyncInternal();
if (waiting == null) return;
waiting.run();
stopReaders();
}
@Override
public void killAsync() {
gracefulStop = false;
Runnable waiting = killAsyncInternal();
if (waiting == null) {
return;
}
Thread listenerInvoker = new Thread(waiting, "StopListenerInvoker");
listenerInvoker.setDaemon(true);
listenerInvoker.start();
synchronized (this) {
outputReader = null;
errorReader = null;
}
}
private synchronized void stopReaders() {
if (outputReader != null) {
try {
outputReader.join(60000);
} catch (InterruptedException e) {
log.warn("Interrupted waiting for the reader");
Thread.currentThread().interrupt();
}
outputReader = null;
}
if (errorReader != null) {
try {
errorReader.join(60000);
} catch (InterruptedException e) {
log.warn("Interrupted waiting for the reader");
Thread.currentThread().interrupt();
}
errorReader = null;
}
}
private synchronized void setServerStarted() {
serverStarted = true;
serverStopped = false;
notifyAll();
}
private synchronized void setServerStopped() {
// no serverStarted = false!
serverStopped = true;
notifyAll();
}
}