package codeine.command_peer;
import codeine.api.CommandExecutionStatusInfo;
import codeine.api.CommandStatusJson;
import codeine.api.NodeInfoNameAndAlias;
import codeine.api.NodeWithPeerInfo;
import codeine.configuration.PathHelper;
import codeine.model.Constants;
import codeine.servlet.PrepareForShutdown;
import codeine.utils.FilesUtils;
import codeine.utils.JsonUtils;
import codeine.utils.MiscUtils;
import codeine.utils.exceptions.InShutdownException;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.inject.Provider;
import org.apache.log4j.Logger;
import javax.inject.Inject;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
public class NodesCommandExecuterProvider {
private static final Logger log = Logger.getLogger(NodesCommandExecuterProvider.class);
@Inject private Provider<AllNodesCommandExecuter> allNodesCommandExecuterProvider;
@Inject private PrepareForShutdown prepareForShutdown;
@Inject private PathHelper pathHelper;
private List<AllNodesCommandExecuter> executers = Lists.newArrayList();
public AllNodesCommandExecuter createExecutor() {
if (prepareForShutdown.isSequnceActivated()) {
throw new InShutdownException();
}
cleanAndGet();
AllNodesCommandExecuter executer = allNodesCommandExecuterProvider.get();
synchronized (executers) {
executers.add(executer);
}
return executer;
}
public List<CommandStatusJson> getAllCommands(String projectName, String nodeName) {
List<CommandStatusJson> $ = getActive(projectName, nodeName);
String parentDir = pathHelper.getAllCommandsInProjectOutputDir(projectName);
List<String> filesInDir = FilesUtils.getFilesInDir(parentDir);
for (String dir : filesInDir) {
if (contains($, dir)){
continue;
}
String file = parentDir + "/" + dir + Constants.JSON_COMMAND_FILE_NAME;
if (!FilesUtils.exists(file)) {
continue;
}
try {
CommandExecutionStatusInfo j = JsonUtils.fromJsonFromFile(file, CommandExecutionStatusInfo.class);
if (!shouldShowByNode(j, nodeName)){
continue;
}
int size = j.nodes_list().size();
int successSize = j.success_list().size();
int failSize = j.fail_list().size();
int sizeNotZero = size != 0 ? size : successSize + failSize != 0 ? successSize + failSize : 1;
int successPercent = successSize * 100 / sizeNotZero;
int failPercent = failSize * 100 / sizeNotZero;
String alias = j.nodes_list().size() == 1 ? j.nodes_list().get(0).alias() : null;
$.add(new CommandStatusJson(j.command(), projectName, size, successPercent, failPercent, j.start_time(), j.id() ,j.finished(), alias, j.user()));
} catch (Exception e) {
log.warn("failed in command " + dir + " for project " + projectName + " file is '" + file + "' and error is " + e.getMessage());
}
}
Comparator<CommandStatusJson> comp = new Comparator<CommandStatusJson>() {
@Override
public int compare(CommandStatusJson o1, CommandStatusJson o2) {
return (int) (o2.id() - o1.id());
}
};
Collections.sort($, comp);
return $;
}
private boolean shouldShowByNode(CommandExecutionStatusInfo j, String nodeName) {
List<NodeInfoNameAndAlias> nodes_list = j.nodes_list();
return shouldShowByNode(nodeName, nodes_list);
}
private boolean shouldShowByNode(String nodeName, List<? extends NodeInfoNameAndAlias> nodes_list) {
if (nodeName == null) {
return true;
}
for (NodeInfoNameAndAlias node : nodes_list) {
if (node.name().equals(nodeName)) {
return true;
}
}
return false;
}
private boolean contains(List<CommandStatusJson> $, String dir) {
for (CommandStatusJson commandStatusJson : $) {
if (String.valueOf(commandStatusJson.id()).equals(dir)){
return true;
}
}
return false;
}
private List<CommandStatusJson> getActive(final String projectName, final String nodeName) {
Predicate<AllNodesCommandExecuter> filter = new Predicate<AllNodesCommandExecuter>() {
@Override
public boolean apply(AllNodesCommandExecuter c){
return c.project().equals(projectName) && shouldShowByNode(c, nodeName);
}
};
return getActive(filter);
}
private boolean shouldShowByNode(AllNodesCommandExecuter c, String nodeName) {
List<NodeWithPeerInfo> nodes_list = c.nodesList();
return shouldShowByNode(nodeName, nodes_list);
}
public List<CommandStatusJson> getActive(Predicate<AllNodesCommandExecuter> filter) {
return getActiveStatusFromList(Iterables.filter(cleanAndGet(), filter));
}
private List<CommandStatusJson> getActiveStatusFromList(Iterable<AllNodesCommandExecuter> iterable) {
List<CommandStatusJson> $ = Lists.newArrayList();
for (AllNodesCommandExecuter e : iterable) {
String alias;
if (e.nodes() == 1) {
NodeWithPeerInfo nodeWithPeerInfo = e.nodesList().get(0);
alias = nodeWithPeerInfo.alias();
} else {
alias = null;
}
$.add(new CommandStatusJson(e.name(),
e.project(),
e.nodes(),
e.success(),
e.error(),
e.commandData() != null ? e.commandData().start_time() : 0L,
e.commandData() != null ? e.commandData().id() : 0L,
!e.isActive(),
alias,
e.commandExecutionInfo() != null ? e.commandExecutionInfo().user() : "Unknown"));
}
return $;
}
private List<AllNodesCommandExecuter> cleanAndGet() {
List<AllNodesCommandExecuter> $ = Lists.newArrayList();
synchronized (executers) {
for (Iterator<AllNodesCommandExecuter> iterator = executers.iterator(); iterator.hasNext();) {
AllNodesCommandExecuter e = (AllNodesCommandExecuter) iterator.next();
if (e.isActive()){
$.add(e);
}
else {
iterator.remove();
}
}
}
return $;
}
public List<CommandStatusJson> getActive() {
return getActiveStatusFromList(cleanAndGet());
}
public AllNodesCommandExecuter getCommandOrNull(String projectName, String commandName) {
synchronized (executers) {
for (AllNodesCommandExecuter e : executers) {
if (MiscUtils.equals(e.project(), projectName) &&
MiscUtils.equals(String.valueOf(e.id()), commandName)) {
return e;
}
}
}
return null;
}
}