From 31ec6e316c5647ca61602da8fd0f1d851cce3e1e Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Tue, 23 Aug 2011 16:51:54 -0400 Subject: [PATCH] First implementation of JobRunInfo -- onExecutionDone(Map(QFunction, JobRunInfo)) is the new signature, so that you can walk over your jobs and inspect their success/failure and runtime characteristics --- .../sting/queue/QCommandLine.scala | 2 +- .../broadinstitute/sting/queue/QScript.scala | 4 +- .../sting/queue/engine/FunctionEdge.scala | 3 + .../sting/queue/engine/JobRunInfo.scala | 75 +++++++++++++++++++ .../sting/queue/engine/JobRunner.scala | 5 ++ .../sting/queue/engine/QGraph.scala | 13 ++++ 6 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 public/scala/src/org/broadinstitute/sting/queue/engine/JobRunInfo.scala diff --git a/public/scala/src/org/broadinstitute/sting/queue/QCommandLine.scala b/public/scala/src/org/broadinstitute/sting/queue/QCommandLine.scala index 14e4adbf8..94a6408c6 100755 --- a/public/scala/src/org/broadinstitute/sting/queue/QCommandLine.scala +++ b/public/scala/src/org/broadinstitute/sting/queue/QCommandLine.scala @@ -114,7 +114,7 @@ class QCommandLine extends CommandLineProgram with Logging { // walk over each script, calling onExecutionDone for (script <- allQScripts) { - script.onExecutionDone(script.functions, qGraph.success) + script.onExecutionDone(qGraph.getFunctionsAndStatus(script.functions), qGraph.success) } if (!qGraph.success) { diff --git a/public/scala/src/org/broadinstitute/sting/queue/QScript.scala b/public/scala/src/org/broadinstitute/sting/queue/QScript.scala index 27f3e275b..3120d5d62 100755 --- a/public/scala/src/org/broadinstitute/sting/queue/QScript.scala +++ b/public/scala/src/org/broadinstitute/sting/queue/QScript.scala @@ -24,6 +24,7 @@ package org.broadinstitute.sting.queue +import engine.JobRunInfo import org.broadinstitute.sting.queue.function.QFunction import annotation.target.field import io.Source @@ -61,8 +62,9 @@ trait QScript extends Logging with PrimitiveOptionConversions with StringFileCon * A default handler for the onExecutionDone() function. By default this doesn't do anything * except print out a fine status message. */ - def onExecutionDone(jobs: List[QFunction], success: Boolean) { + def onExecutionDone(jobs: Map[QFunction, JobRunInfo], success: Boolean) { logger.info("Script %s with %d total jobs".format(if (success) "completed successfully" else "failed", jobs.size)) + for ( (f, info) <- jobs ) logger.info(" %s %s".format(f.jobName, info)) } /** diff --git a/public/scala/src/org/broadinstitute/sting/queue/engine/FunctionEdge.scala b/public/scala/src/org/broadinstitute/sting/queue/engine/FunctionEdge.scala index 68bc7ae61..39354c5a4 100644 --- a/public/scala/src/org/broadinstitute/sting/queue/engine/FunctionEdge.scala +++ b/public/scala/src/org/broadinstitute/sting/queue/engine/FunctionEdge.scala @@ -23,6 +23,8 @@ class FunctionEdge(val function: QFunction, val inputs: QNode, val outputs: QNod */ var depth = -1 + var runInfo: JobRunInfo = JobRunInfo.default // todo: replace after testing with _ + /** * Initializes with the current status of the function. */ @@ -88,6 +90,7 @@ class FunctionEdge(val function: QFunction, val inputs: QNode, val outputs: QNod tailError() } else if (currentStatus == RunnerStatus.DONE) { try { + runInfo = runner.getRunInfo runner.cleanup() function.doneOutputs.foreach(_.createNewFile()) } catch { diff --git a/public/scala/src/org/broadinstitute/sting/queue/engine/JobRunInfo.scala b/public/scala/src/org/broadinstitute/sting/queue/engine/JobRunInfo.scala new file mode 100644 index 000000000..384874613 --- /dev/null +++ b/public/scala/src/org/broadinstitute/sting/queue/engine/JobRunInfo.scala @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011, The Broad Institute + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.broadinstitute.sting.queue.engine + +import java.util.Date + +/* + * Copyright (c) 2011, The Broad Institute + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Base class containing all of the information about a job run. + */ +class JobRunInfo(startTime: Date, doneTime: Date, memUsedInGb: Int, hostName: String, status: RunnerStatus.Value) { + def getStatus = status + def getStartTime = startTime + def getDoneTime = doneTime + def getMemoryUsedInGb = memUsedInGb + def getHostname = hostName + + def getRuntimeInMs: Long = { + getDoneTime.getTime - getStartTime.getTime + } + + override def toString: String = + "started %s ended %s runtime %s on host %s using %d Gb memory".format(getStartTime, getDoneTime, getRuntimeInMs, getHostname, getMemoryUsedInGb) +} + +object JobRunInfo { + def default = new JobRunInfo(new Date(), new Date(), 1, "localhost", RunnerStatus.DONE) + def detailed(startTime: Date, doneTime: Date, memUsedInGb: Int, hostName: String) = + new JobRunInfo(startTime, doneTime, memUsedInGb, hostName, RunnerStatus.DONE) +} \ No newline at end of file diff --git a/public/scala/src/org/broadinstitute/sting/queue/engine/JobRunner.scala b/public/scala/src/org/broadinstitute/sting/queue/engine/JobRunner.scala index de5fbde05..510aa33eb 100644 --- a/public/scala/src/org/broadinstitute/sting/queue/engine/JobRunner.scala +++ b/public/scala/src/org/broadinstitute/sting/queue/engine/JobRunner.scala @@ -69,6 +69,11 @@ trait JobRunner[TFunction <: QFunction] { def cleanup() { } + /** + * Must be overloaded + */ + def getRunInfo: JobRunInfo = JobRunInfo.default + /** * Calls back to a hook that an expert user can setup to modify a job. * @param value Value to modify. diff --git a/public/scala/src/org/broadinstitute/sting/queue/engine/QGraph.scala b/public/scala/src/org/broadinstitute/sting/queue/engine/QGraph.scala index 766d9db94..0baa5dfe2 100755 --- a/public/scala/src/org/broadinstitute/sting/queue/engine/QGraph.scala +++ b/public/scala/src/org/broadinstitute/sting/queue/engine/QGraph.scala @@ -38,6 +38,7 @@ import org.apache.commons.lang.StringUtils import org.broadinstitute.sting.queue.util._ import collection.immutable.{TreeSet, TreeMap} import org.broadinstitute.sting.queue.function.scattergather.{ScatterFunction, CloneFunction, GatherFunction, ScatterGatherableFunction} +import java.util.Date /** * The internal dependency tracker between sets of function input and output files. @@ -939,6 +940,14 @@ class QGraph extends Logging { edges.sorted(functionOrdering).foreach(edge => if (running) f(edge)) } + /** + * Utility function for running a method over all function edges. + * @param edgeFunction Function to run for each FunctionEdge. + */ + private def getFunctionEdges: List[FunctionEdge] = { + jobGraph.edgeSet.toList.filter(_.isInstanceOf[FunctionEdge]).asInstanceOf[List[FunctionEdge]] + } + /** * Utility function for running a method over all functions, but traversing the nodes in order of dependency. * @param edgeFunction Function to run for each FunctionEdge. @@ -1028,6 +1037,10 @@ class QGraph extends Logging { */ def isShutdown = !running + def getFunctionsAndStatus(functions: List[QFunction]): Map[QFunction, JobRunInfo] = { + getFunctionEdges.map(edge => (edge.function, edge.runInfo)).toMap + } + /** * Kills any forked jobs still running. */