package cz.cuni.mff.d3s.been.cluster.query; import static cz.cuni.mff.d3s.been.core.task.TaskExclusivity.NON_EXCLUSIVE; import java.util.List; import org.apache.commons.jxpath.JXPathContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.hazelcast.core.MapEntry; import com.hazelcast.query.Predicate; import cz.cuni.mff.d3s.been.core.ri.RuntimeInfo; import cz.cuni.mff.d3s.been.core.ri.RuntimeInfos; import cz.cuni.mff.d3s.been.core.task.TaskExclusivity; /** * * Predicate for filtering RuntimeInfo based on XPath expression. * * @author Martin Sixta */ public final class XPathPredicate implements Predicate<String, RuntimeInfo> { private static final Logger log = LoggerFactory.getLogger(XPathPredicate.class); private final String xpath; private final TaskExclusivity taskExclusivity; private final String contextId; /** * Creates new XPathPredicate * * @param contextId * ID of the context to take into account while filtering * @param xpath * XPath expression to filter out Host Runtimes * @param taskExclusivity * requested exclusivity of the task */ public XPathPredicate(String contextId, String xpath, TaskExclusivity taskExclusivity) { this.contextId = contextId; this.xpath = xpath; this.taskExclusivity = taskExclusivity; } @Override public boolean apply(MapEntry<String, RuntimeInfo> mapEntry) { RuntimeInfo info = mapEntry.getValue(); if (info.getExclusivity() == null) { // workaround for JAXB not setting default value on elements info.setExclusivity(NON_EXCLUSIVE.toString()); } // Runtime Overload conditions if (RuntimeInfos.isMaxTasksReached(info)) { return false; } if (RuntimeInfos.isMemoryThresholdReached(info)) { return false; } TaskExclusivity runtimeExclusivity; try { runtimeExclusivity = TaskExclusivity.valueOf(info.getExclusivity()); } catch (IllegalArgumentException e) { // something fishy is going on, just skip this host runtime runtimeExclusivity = TaskExclusivity.EXCLUSIVE; } switch (runtimeExclusivity) { case NON_EXCLUSIVE: boolean isExclusive = (taskExclusivity != NON_EXCLUSIVE); boolean hasTasks = (info.getTaskCount() > 0); if (isExclusive && hasTasks) { return false; } break; case CONTEXT_EXCLUSIVE: if (!contextId.equals(info.getExclusiveId())) { return false; // different context } break; case EXCLUSIVE: return false; } JXPathContext context = JXPathContext.newContext(info); List list = context.selectNodes(".[" + xpath + "]"); return (list != null) && (list.size() > 0); } }