package fr.opensagres.mongodb.ide.launching.internal.jobs;
import java.net.UnknownHostException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.osgi.util.NLS;
import com.mongodb.MongoException;
import com.mongodb.tools.driver.MongoDriverHelper;
import fr.opensagres.mongodb.ide.core.IServerListener;
import fr.opensagres.mongodb.ide.core.ServerEvent;
import fr.opensagres.mongodb.ide.core.model.Server;
import fr.opensagres.mongodb.ide.core.model.ServerState;
import fr.opensagres.mongodb.ide.launching.internal.Activator;
import fr.opensagres.mongodb.ide.launching.internal.Messages;
import fr.opensagres.mongodb.ide.launching.internal.ServerLauncherManager;
import fr.opensagres.mongodb.ide.launching.internal.Trace;
public class StopJob extends ServerJob {
protected boolean force;
public StopJob(Server server, boolean force) {
super(server, NLS.bind(Messages.jobStopping, server.getName()));
setRule(server);
this.force = force;
}
protected IStatus run(IProgressMonitor monitor) {
return stopImpl(getServer(), force, monitor);
}
protected IStatus stopImpl(final Server s, boolean force,
IProgressMonitor monitor) {
final Object mutex = new Object();
// add listener to the server
IServerListener listener = new IServerListener() {
public void serverChanged(ServerEvent event) {
int eventKind = event.getKind();
Server server = event.getServer();
if (eventKind == (ServerEvent.SERVER_CHANGE | ServerEvent.STATE_CHANGE)) {
ServerState state = server.getServerState();
if (s == server
&& (state == ServerState.Stopped || state == ServerState.Started)) {
// notify waiter
synchronized (mutex) {
try {
mutex.notifyAll();
} catch (Exception e) {
if (Trace.SEVERE) {
Trace.trace(Trace.STRING_SEVERE,
"Error notifying server stop", e);
}
}
}
}
}
}
};
s.addServerListener(listener);
class Timer {
boolean timeout;
boolean alreadyDone;
}
final Timer timer = new Timer();
final int serverTimeout = s.getStopTimeout() * 1000;
Thread thread = null;
if (serverTimeout > 0) {
thread = new Thread("Server Stop Timeout") {
public void run() {
try {
int totalTimeout = serverTimeout;
if (totalTimeout < 0)
totalTimeout = 1;
int retryPeriod = 1000;
while (totalTimeout > 0 && !timer.alreadyDone) {
Thread.sleep(retryPeriod);
if (serverTimeout > 0)
totalTimeout -= retryPeriod;
}
if (!timer.alreadyDone) {
timer.timeout = true;
// notify waiter
synchronized (mutex) {
if (Trace.FINEST) {
Trace.trace(Trace.STRING_FINEST,
"stop notify timeout");
}
mutex.notifyAll();
}
}
} catch (Exception e) {
if (Trace.SEVERE) {
Trace.trace(Trace.STRING_SEVERE,
"Error notifying server stop timeout", e);
}
}
}
};
}
// stop the server
stopImpl2(s, force);
if (thread != null) {
thread.setDaemon(true);
thread.start();
}
// wait for it! wait for it!
synchronized (mutex) {
try {
while (!timer.timeout
&& s.getServerState() != ServerState.Stopped
&& s.getServerState() != ServerState.Started)
mutex.wait();
} catch (Exception e) {
if (Trace.SEVERE) {
Trace.trace(Trace.STRING_SEVERE,
"Error waiting for server stop", e);
}
}
timer.alreadyDone = true;
}
s.removeServerListener(listener);
// can't throw exceptions
/*
* if (timer.timeout) return new Status(IStatus.ERROR,
* ServerPlugin.PLUGIN_ID, 0, Messages.errorStopTimeout, getName()),
* null); else timer.alreadyDone = true;
*/
if (!monitor.isCanceled() && s.getServerState() == ServerState.Started)
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, NLS.bind(
Messages.errorStopFailed, s.getName()), null);
return Status.OK_STATUS;
}
protected void stopImpl2(Server server, boolean force) {
if (server.getServerState() == ServerState.Stopped)
return;
if (Trace.FINEST) {
Trace.trace(Trace.STRING_FINEST,
"Stopping server: " + server.toString());
}
try {
stop3(server, force);
} catch (RuntimeException e) {
if (Trace.SEVERE) {
Trace.trace(Trace.STRING_SEVERE,
"Error calling delegate stop() " + server.toString(), e);
}
throw e;
} catch (Throwable t) {
if (Trace.SEVERE) {
Trace.trace(Trace.STRING_SEVERE,
"Error calling delegate stop() " + server.toString(), t);
}
throw new RuntimeException(t);
}
}
public void stop3(Server server, boolean force) {
if (force) {
ServerLauncherManager.terminate(server);
return;
}
ServerState state = server.getServerState();
// If stopped or stopping, no need to run stop command again
if (state == ServerState.Stopped || state == ServerState.Stopping)
return;
else if (state == ServerState.Starting) {
ServerLauncherManager.terminate(server);
return;
}
if (state != ServerState.Stopped)
server.setServerState(ServerState.Stopping);
try {
MongoDriverHelper.stopMongoServerAndCloseIt(server.getMongo(),
server.getUsername(), server.getPassword());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MongoException e) {
e.printStackTrace();
} finally {
server.setServerState(ServerState.Stopped);
}
}
}