package org.ow2.choreos.ee.nodes;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import org.ow2.choreos.ee.config.CloudConfiguration;
import org.ow2.choreos.ee.nodes.cloudprovider.CloudProvider;
import org.ow2.choreos.ee.nodes.cloudprovider.CloudProviderFactory;
import org.ow2.choreos.nodes.NodeNotDestroyed;
import org.ow2.choreos.nodes.NodeNotFoundException;
import org.ow2.choreos.nodes.datamodel.CloudNode;
import org.ow2.choreos.utils.Concurrency;
import org.ow2.choreos.utils.TimeoutsAndTrials;
public class NodesDestroyer {
private static Logger logger = Logger.getLogger(NodesDestroyer.class);
private final Collection<CloudNode> nodesToDestroy;
private CloudProvider cp;
private List<DestroyTask> tasks = new ArrayList<DestroyTask>();
private ExecutorService executor;
private CloudConfiguration cloudConfiguration;
private final int timeout;
private final int trials;
private List<CloudNode> destroyedNodes = new ArrayList<CloudNode>();
public NodesDestroyer(CloudConfiguration cloudConfiguration, Collection<CloudNode> nodesToDestroy) {
this.nodesToDestroy = nodesToDestroy;
this.timeout = TimeoutsAndTrials.get("NODE_DELETION_TIMEOUT");
this.trials = TimeoutsAndTrials.get("NODE_DELETION_TRIALS");
this.cp = CloudProviderFactory.getFactoryInstance().getCloudProviderInstance(cloudConfiguration);
}
/**
*
* @throws NodeNotDestroyed
* if some node was not destroyed
*/
public List<CloudNode> destroyNodes() throws NodeNotDestroyed {
destroy();
waitDestroy();
check();
return destroyedNodes;
}
public List<CloudNode> getDestroyedNodes() {
return destroyedNodes;
}
public void setDestroyedNodes(List<CloudNode> destroyedNodes) {
this.destroyedNodes = destroyedNodes;
}
private void destroy() {
if (nodesToDestroy == null || nodesToDestroy.isEmpty())
return;
executor = Executors.newFixedThreadPool(nodesToDestroy.size());
tasks = new ArrayList<DestroyTask>();
for (CloudNode node : nodesToDestroy) {
DestroyTask task = new DestroyTask(node);
tasks.add(task);
executor.submit(task);
}
}
private void waitDestroy() {
String erMsg = "Could not wait for nodes destroyment";
int totalTimeout = timeout * trials;
totalTimeout += totalTimeout * 0.2;
int n = nodesToDestroy.size();
totalTimeout += 2 * n; // one req/sec rule
Concurrency.waitExecutor(executor, totalTimeout, TimeUnit.SECONDS, logger, erMsg);
}
private void check() throws NodeNotDestroyed {
int originalSize = nodesToDestroy.size();
int finalSize = destroyedNodes.size();
if (finalSize < originalSize)
throw new NodeNotDestroyed("???");
}
private class DestroyTask implements Callable<Void> {
private CloudNode node;
public DestroyTask(CloudNode node) {
this.node = node;
}
@Override
public Void call() throws NodeNotDestroyed, NodeNotFoundException {
cp.destroyNode(node.getId());
logger.info(node + " destroyed");
destroyedNodes.add(node);
return null;
}
}
}