package com.thinkaurelius.faunus.tinkerpop.rexster; import com.thinkaurelius.faunus.FaunusGraph; import com.thinkaurelius.faunus.FaunusPipeline; import com.thinkaurelius.faunus.tinkerpop.gremlin.FaunusGremlinScriptEngine; import com.tinkerpop.rexster.RexsterApplicationGraph; import org.apache.hadoop.conf.Configuration; import org.apache.log4j.Logger; import java.util.Iterator; import java.util.Map; import java.util.UUID; /** * Responsible for executing a Faunus job as triggered from the FaunusRexsterExecutorExtension. * * @author Stephen Mallette (http://stephen.genoprime.com) */ public class FaunusEvaluationJob { private static final Logger logger = Logger.getLogger(FaunusEvaluationJob.class); protected final String script; protected volatile boolean complete = false; protected volatile boolean error = false; private volatile String errorMessage = ""; private UUID jobId; private final RexsterApplicationGraph rag; private final Map<String,String> configOverrides; public FaunusEvaluationJob(final String script, final UUID jobId, final RexsterApplicationGraph rag, final Map<String,String> configOverrides) { this.script = script; this.jobId = jobId; this.rag = rag; this.configOverrides = configOverrides; } public boolean isComplete() { return complete; } public boolean isError() { return error; } public String getErrorMessage() { return errorMessage; } public void performJob() { try { logger.info(String.format("Submit Faunus job [%s]", jobId)); ((FaunusPipeline) getScriptEngine(rag, configOverrides).eval(script)).submit(); } catch (Exception ex) { logger.error(String.format("Error running Faunus job [%s].", jobId), ex); if (ex.getCause() != null) { logger.error("Error details", ex.getCause()); } synchronized (this) { error = true; errorMessage = ex.getMessage(); } } finally { complete = true; } } private static FaunusGremlinScriptEngine getScriptEngine(final RexsterApplicationGraph rag, final Map<String,String> configOverrides) { final FaunusGremlinScriptEngine engine = new FaunusGremlinScriptEngine(); final Configuration configuration = new Configuration(); final Map<String,String> properties = rag.findExtensionConfiguration( FaunusRexsterExecutorExtension.EXTENSION_NAMESPACE, FaunusRexsterExecutorExtension.EXTENSION_NAME) .tryGetMapFromConfiguration(); // add properties from rexster.xml to the configuration applyToConfiguration(configuration, properties); // override rexster.xml values with those from the job request applyToConfiguration(configuration, configOverrides); writeConfigurationToLog(configuration); final FaunusGraph graph = new FaunusGraph(configuration); engine.put("g", graph); return engine; } private static void applyToConfiguration(final Configuration configuration, final Map<String, String> properties) { for (Map.Entry<String, String> entry : properties.entrySet()) { // replace the ".." put in play by apache commons configuration. that's expected behavior // due to parsing key names to xml. final String key = entry.getKey().replace("..", "."); configuration.set(key, entry.getValue()); } } private static void writeConfigurationToLog(final Configuration conf) { final StringBuilder sb = new StringBuilder(); sb.append("Faunus settings:\n"); final Iterator itty = conf.iterator(); while (itty.hasNext()) { final Map.Entry<String,String> e = (Map.Entry<String,String>) itty.next(); sb.append(e.getKey()); sb.append("="); sb.append(e.getValue()); sb.append("\n"); } final String configurationToPrint = sb.toString(); logger.info(configurationToPrint.substring(0, configurationToPrint.length() - 1)); } }