package org.kevoree.core.deploy;
import org.kevoree.api.PrimitiveCommand;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.kevoree.log.Log;
import java.util.concurrent.TimeUnit;
import org.kevoree.api.telemetry.TelemetryEvent;
import org.kevoree.core.KevoreeCoreBean;
public class KevoreeParDeployPhase extends KevoreeDeployPhase {
public KevoreeParDeployPhase(KevoreeCoreBean core) {
super(core);
}
public boolean executeAllWorker(List<PrimitiveCommand> ps, Long timeout) {
if (ps.isEmpty()) {
return true;
} else {
ExecutorService pool = Executors.newCachedThreadPool(new WorkerThreadFactory(String.valueOf(System.currentTimeMillis())));
List<Worker> workers = new ArrayList<Worker>();
for (PrimitiveCommand primitive : ps) {
workers.add(new Worker(primitive));
}
try {
Log.trace("Timeout = {}", timeout);
List<Future<Boolean>> futures = pool.invokeAll(workers, timeout, TimeUnit.MILLISECONDS);
for (Future<Boolean> f : futures) {
if (f.isDone() && !f.get()) {
return false;
}
}
return true;
} catch (Exception ignore) {
return false;
} finally {
pool.shutdownNow();
}
}
}
public boolean execute() {
if (primitives.isEmpty()) {
Log.trace("No primitive command to execute");
return true;
}
String overrideTimeout = System.getProperty("kevoree.timeout");
long timeout = maxTimeout;
if (overrideTimeout != null) {
try {
timeout = Long.parseLong(overrideTimeout);
} catch (NumberFormatException e) {
if (originCore.isAnyTelemetryListener()) {
originCore.broadcastTelemetry(TelemetryEvent.Type.LOG_WARNING, "Invalid System.property value for \"kevoree.timeout\". Must be a Long", e);
}
Log.warn("Invalid System.property value for \"kevoree.timeout\". Must be a Long");
}
}
return executeAllWorker(primitives, timeout);
}
public void rollback() {
Log.trace("Rollback phase");
if (successor != null) {
Log.trace("Rollback sucessor first");
successor.rollback();
}
if (!rollbackPerformed) {
List<PrimitiveCommand> clonedPrimitives = new ArrayList<PrimitiveCommand>(primitives);
Collections.reverse(clonedPrimitives);
for (PrimitiveCommand c : clonedPrimitives) {
try {
Log.trace("Undo adaptation command {} ", c.getClass().getName());
c.undo();
} catch (Exception e) {
if (originCore.isAnyTelemetryListener()) {
originCore.broadcastTelemetry(TelemetryEvent.Type.LOG_ERROR, "Error while executing primitive command {}", e);
}
Log.error("Error while executing primitive command {}", c);
}
}
rollbackPerformed = true;
}
}
private class Worker implements Callable<Boolean> {
private PrimitiveCommand cmd;
public Worker(PrimitiveCommand primitive) {
this.cmd = primitive;
}
@Override
public Boolean call() {
try {
boolean result = cmd.execute();
if (!result) {
if (originCore.isAnyTelemetryListener()) {
originCore.broadcastTelemetry(TelemetryEvent.Type.LOG_ERROR, "Cmd:["+cmd.toString()+"]", null);
}
Log.error("Error while executing primitive command {}", cmd);
}
return result;
} catch (Throwable e) {
if (originCore.isAnyTelemetryListener()) {
originCore.broadcastTelemetry(TelemetryEvent.Type.LOG_ERROR, "Cmd:["+cmd.toString()+"]", e);
}
Log.error("Exception while executing primitive command {} ", e, cmd);
e.printStackTrace();
return false;
}
}
}
}