package com.sixsq.slipstream.util;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import org.restlet.data.Status;
import org.restlet.resource.ResourceException;
import com.sixsq.slipstream.configuration.Configuration;
import com.sixsq.slipstream.connector.Connector;
import com.sixsq.slipstream.connector.ConnectorFactory;
import com.sixsq.slipstream.exceptions.CannotAdvanceFromTerminalStateException;
import com.sixsq.slipstream.exceptions.ConfigurationException;
import com.sixsq.slipstream.exceptions.InvalidStateException;
import com.sixsq.slipstream.exceptions.SlipStreamException;
import com.sixsq.slipstream.exceptions.ValidationException;
import com.sixsq.slipstream.metrics.Metrics;
import com.sixsq.slipstream.metrics.MetricsTimer;
import com.sixsq.slipstream.persistence.Parameter;
import com.sixsq.slipstream.persistence.ParameterCategory;
import com.sixsq.slipstream.persistence.PersistenceUtil;
import com.sixsq.slipstream.persistence.Run;
import com.sixsq.slipstream.persistence.User;
import com.sixsq.slipstream.persistence.UserParameter;
import com.sixsq.slipstream.statemachine.StateMachine;
import com.sixsq.slipstream.statemachine.States;
public class Terminator {
/* I WILL BE BACK */
private static MetricsTimer purgeTimer = Metrics.newTimer(Terminator.class, "purge");
public static int purge() throws ConfigurationException, ValidationException {
int runPurged =0;
purgeTimer.start();
try {
List<User> users = User.list();
for (User u: users) {
u = User.loadByName(u.getName());
int timeout = u.getTimeout();
List<Run> old = Run.listOldTransient(u, timeout);
for (Run r : old) {
EntityManager em = PersistenceUtil.createEntityManager();
try {
r = Run.load(r.getResourceUri(), em);
purgeRun(r);
} catch (SlipStreamException e) {
Logger.getLogger("garbage-collector").log(Level.SEVERE, e.getMessage(), e.getCause());
} finally {
em.close();
}
}
runPurged += old.size();
}
} finally {
purgeTimer.stop();
}
return runPurged;
}
public static void purgeRun(Run run) throws SlipStreamException {
Run.abort("The run has timed out", run.getUuid());
boolean isGarbageCollected = Run.isGarbageCollected(run);
Run.setGarbageCollected(run);
run = run.store();
String onErrorKeepRunning = run.getParameterValue(Parameter
.constructKey(ParameterCategory.General.toString(),
UserParameter.KEY_ON_ERROR_RUN_FOREVER), "false");
if (! Boolean.parseBoolean(onErrorKeepRunning) &&
! run.isMutable() &&
(run.getState() == States.Initializing || isGarbageCollected)) {
terminate(run.getResourceUri());
run.postEventGarbageCollectorTerminated();
} else if (!isGarbageCollected) {
run.postEventGarbageCollectorTimedOut();
}
}
public static void terminate(String runResourceUri) throws SlipStreamException {
EntityManager em = PersistenceUtil.createEntityManager();
Run run = Run.load(runResourceUri, em);
User user = User.loadByName(run.getUser());
StateMachine sc = StateMachine.createStateMachine(run);
if (sc.canCancel()) {
sc.tryAdvanceToCancelled();
terminateInstances(run, user);
} else {
if (sc.getState() == States.Ready) {
sc.tryAdvanceToFinalizing();
}
terminateInstances(run, user);
sc.tryAdvanceState(true);
}
em.close();
}
private static void terminateInstances(Run run, User user) throws SlipStreamException {
user.addSystemParametersIntoUser(Configuration.getInstance().getParameters());
for (String cloudServiceName : run.getCloudServiceNamesList()) {
Connector connector = ConnectorFactory.getConnector(cloudServiceName);
connector.terminate(run, user);
}
}
}