Sending a version of per job status messages.
In addition to outputs, inputs are passed to QStatusMessenger.done() CloneFunction.cloneIndex has a new CloneFunction.cloneCount companion useful for display purposes.
This commit is contained in:
parent
5fac5bf12e
commit
8dfa24df7b
|
|
@ -123,6 +123,8 @@ class QCommandLine extends CommandLineProgram with Logging {
|
||||||
commandPlugin.statusMessenger.started()
|
commandPlugin.statusMessenger.started()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qGraph.messengers = allCommandPlugins.filter(_.statusMessenger != null).map(_.statusMessenger).toSeq
|
||||||
|
|
||||||
// TODO: Default command plugin argument?
|
// TODO: Default command plugin argument?
|
||||||
val remoteFileConverter = (
|
val remoteFileConverter = (
|
||||||
for (commandPlugin <- allCommandPlugins if (commandPlugin.remoteFileConverter != null))
|
for (commandPlugin <- allCommandPlugins if (commandPlugin.remoteFileConverter != null))
|
||||||
|
|
@ -178,14 +180,17 @@ class QCommandLine extends CommandLineProgram with Logging {
|
||||||
qGraph.logFailed()
|
qGraph.logFailed()
|
||||||
for (commandPlugin <- allCommandPlugins)
|
for (commandPlugin <- allCommandPlugins)
|
||||||
if (commandPlugin.statusMessenger != null)
|
if (commandPlugin.statusMessenger != null)
|
||||||
commandPlugin.statusMessenger.exit("Done with errors")
|
commandPlugin.statusMessenger.exit("Done with errors: %s".format(qGraph.formattedStatusCounts))
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
if (settings.run) {
|
if (settings.run) {
|
||||||
allQScripts.foreach(_.pushOutputs())
|
allQScripts.foreach(_.pushOutputs())
|
||||||
for (commandPlugin <- allCommandPlugins)
|
for (commandPlugin <- allCommandPlugins)
|
||||||
if (commandPlugin.statusMessenger != null)
|
if (commandPlugin.statusMessenger != null) {
|
||||||
commandPlugin.statusMessenger.done(allQScripts.map(_.remoteOutputs))
|
val allInputs = allQScripts.map(_.remoteInputs)
|
||||||
|
val allOutputs = allQScripts.map(_.remoteOutputs)
|
||||||
|
commandPlugin.statusMessenger.done(allInputs, allOutputs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -149,8 +149,17 @@ trait QScript extends Logging with PrimitiveOptionConversions with StringFileCon
|
||||||
* List out the remote outputs
|
* List out the remote outputs
|
||||||
* @return the RemoteFile outputs by argument source
|
* @return the RemoteFile outputs by argument source
|
||||||
*/
|
*/
|
||||||
def remoteOutputs: Map[ArgumentSource, Seq[RemoteFile]] =
|
def remoteInputs: Map[ArgumentSource, Seq[RemoteFile]] = remoteFieldMap(inputFields)
|
||||||
outputFields.map(field => (field -> filterRemoteFiles(ClassFieldCache.getFieldFiles(this, field)))).filter(tuple => !tuple._2.isEmpty).toMap
|
|
||||||
|
/**
|
||||||
|
* List out the remote outputs
|
||||||
|
* @return the RemoteFile outputs by argument source
|
||||||
|
*/
|
||||||
|
def remoteOutputs: Map[ArgumentSource, Seq[RemoteFile]] = remoteFieldMap(outputFields)
|
||||||
|
|
||||||
|
private def remoteFieldMap(fields: Seq[ArgumentSource]): Map[ArgumentSource, Seq[RemoteFile]] = {
|
||||||
|
fields.map(field => (field -> filterRemoteFiles(ClassFieldCache.getFieldFiles(this, field)))).filter(tuple => !tuple._2.isEmpty).toMap
|
||||||
|
}
|
||||||
|
|
||||||
private def filterRemoteFiles(fields: Seq[File]): Seq[RemoteFile] =
|
private def filterRemoteFiles(fields: Seq[File]): Seq[RemoteFile] =
|
||||||
fields.filter(field => field != null && field.isInstanceOf[RemoteFile]).map(_.asInstanceOf[RemoteFile])
|
fields.filter(field => field != null && field.isInstanceOf[RemoteFile]).map(_.asInstanceOf[RemoteFile])
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ import java.io.{OutputStreamWriter, File}
|
||||||
*/
|
*/
|
||||||
class QGraph extends Logging {
|
class QGraph extends Logging {
|
||||||
var settings: QGraphSettings = _
|
var settings: QGraphSettings = _
|
||||||
|
var messengers: Seq[QStatusMessenger] = Nil
|
||||||
|
|
||||||
private def dryRun = !settings.run
|
private def dryRun = !settings.run
|
||||||
private var numMissingValues = 0
|
private var numMissingValues = 0
|
||||||
|
|
@ -95,7 +96,7 @@ class QGraph extends Logging {
|
||||||
* The settings aren't necessarily available until after this QGraph object has been constructed, so
|
* The settings aren't necessarily available until after this QGraph object has been constructed, so
|
||||||
* this function must be called once the QGraphSettings have been filled in.
|
* this function must be called once the QGraphSettings have been filled in.
|
||||||
*
|
*
|
||||||
* @param settings
|
* @param settings QGraphSettings
|
||||||
*/
|
*/
|
||||||
def initializeWithSettings(settings: QGraphSettings) {
|
def initializeWithSettings(settings: QGraphSettings) {
|
||||||
this.settings = settings
|
this.settings = settings
|
||||||
|
|
@ -430,6 +431,7 @@ class QGraph extends Logging {
|
||||||
val edge = readyJobs.head
|
val edge = readyJobs.head
|
||||||
edge.runner = newRunner(edge.function)
|
edge.runner = newRunner(edge.function)
|
||||||
edge.start()
|
edge.start()
|
||||||
|
messengers.foreach(_.started(jobShortName(edge.function)))
|
||||||
startedJobs += edge
|
startedJobs += edge
|
||||||
readyJobs -= edge
|
readyJobs -= edge
|
||||||
logNextStatusCounts = true
|
logNextStatusCounts = true
|
||||||
|
|
@ -465,8 +467,14 @@ class QGraph extends Logging {
|
||||||
updateStatus()
|
updateStatus()
|
||||||
|
|
||||||
runningJobs.foreach(edge => edge.status match {
|
runningJobs.foreach(edge => edge.status match {
|
||||||
case RunnerStatus.DONE => doneJobs += edge
|
case RunnerStatus.DONE => {
|
||||||
case RunnerStatus.FAILED => failedJobs += edge
|
doneJobs += edge
|
||||||
|
messengers.foreach(_.done(jobShortName(edge.function)))
|
||||||
|
}
|
||||||
|
case RunnerStatus.FAILED => {
|
||||||
|
failedJobs += edge
|
||||||
|
messengers.foreach(_.exit(jobShortName(edge.function), edge.function.jobErrorLines.mkString("%n".format())))
|
||||||
|
}
|
||||||
case RunnerStatus.RUNNING => /* do nothing while still running */
|
case RunnerStatus.RUNNING => /* do nothing while still running */
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -493,7 +501,7 @@ class QGraph extends Logging {
|
||||||
// incremental
|
// incremental
|
||||||
if ( logNextStatusCounts && INCREMENTAL_JOBS_REPORT ) {
|
if ( logNextStatusCounts && INCREMENTAL_JOBS_REPORT ) {
|
||||||
logger.info("Writing incremental jobs reports...")
|
logger.info("Writing incremental jobs reports...")
|
||||||
writeJobsReport(false)
|
writeJobsReport(plot = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
readyJobs ++= getReadyJobs
|
readyJobs ++= getReadyJobs
|
||||||
|
|
@ -516,9 +524,13 @@ class QGraph extends Logging {
|
||||||
private def nextRunningCheck(lastRunningCheck: Long) =
|
private def nextRunningCheck(lastRunningCheck: Long) =
|
||||||
((30 * 1000L) - (System.currentTimeMillis - lastRunningCheck))
|
((30 * 1000L) - (System.currentTimeMillis - lastRunningCheck))
|
||||||
|
|
||||||
|
def formattedStatusCounts: String = {
|
||||||
|
"%d Pend, %d Run, %d Fail, %d Done".format(
|
||||||
|
statusCounts.pending, statusCounts.running, statusCounts.failed, statusCounts.done)
|
||||||
|
}
|
||||||
|
|
||||||
private def logStatusCounts() {
|
private def logStatusCounts() {
|
||||||
logger.info("%d Pend, %d Run, %d Fail, %d Done".format(
|
logger.info(formattedStatusCounts)
|
||||||
statusCounts.pending, statusCounts.running, statusCounts.failed, statusCounts.done))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -533,6 +545,16 @@ class QGraph extends Logging {
|
||||||
traverseFunctions(edge => recheckDone(edge))
|
traverseFunctions(edge => recheckDone(edge))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Yet another field to add (with overloads) to QFunction?
|
||||||
|
private def jobShortName(function: QFunction): String = {
|
||||||
|
var name = function.analysisName
|
||||||
|
if (function.isInstanceOf[CloneFunction]) {
|
||||||
|
val cloneFunction = function.asInstanceOf[CloneFunction]
|
||||||
|
name += " %d of %d".format(cloneFunction.cloneIndex, cloneFunction.cloneCount)
|
||||||
|
}
|
||||||
|
name
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First pass that checks if an edge is done or if it's an intermediate edge if it can be skipped.
|
* First pass that checks if an edge is done or if it's an intermediate edge if it can be skipped.
|
||||||
* This function may modify the status of previous edges if it discovers that the edge passed in
|
* This function may modify the status of previous edges if it discovers that the edge passed in
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@ import org.broadinstitute.sting.queue.util.RemoteFile
|
||||||
*/
|
*/
|
||||||
trait QStatusMessenger {
|
trait QStatusMessenger {
|
||||||
def started()
|
def started()
|
||||||
def done(files: Seq[Map[ArgumentSource, Seq[RemoteFile]]])
|
def done(inputs: Seq[Map[ArgumentSource, Seq[RemoteFile]]], outputs: Seq[Map[ArgumentSource, Seq[RemoteFile]]])
|
||||||
def exit(message: String)
|
def exit(message: String)
|
||||||
|
|
||||||
|
def started(job: String)
|
||||||
|
def done(job: String)
|
||||||
|
def exit(job: String, message: String)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ object CloneFunction {
|
||||||
class CloneFunction extends CommandLineFunction {
|
class CloneFunction extends CommandLineFunction {
|
||||||
var originalFunction: ScatterGatherableFunction = _
|
var originalFunction: ScatterGatherableFunction = _
|
||||||
var cloneIndex: Int = _
|
var cloneIndex: Int = _
|
||||||
|
var cloneCount: Int = _
|
||||||
|
|
||||||
private var overriddenFields = Map.empty[ArgumentSource, Any]
|
private var overriddenFields = Map.empty[ArgumentSource, Any]
|
||||||
private var withScatterPartCount = 0
|
private var withScatterPartCount = 0
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,7 @@ trait ScatterGatherableFunction extends CommandLineFunction {
|
||||||
cloneFunction.originalFunction = this
|
cloneFunction.originalFunction = this
|
||||||
cloneFunction.analysisName = this.analysisName
|
cloneFunction.analysisName = this.analysisName
|
||||||
cloneFunction.cloneIndex = i
|
cloneFunction.cloneIndex = i
|
||||||
|
cloneFunction.cloneCount = numClones
|
||||||
cloneFunction.commandDirectory = this.scatterGatherTempDir(dirFormat.format(i))
|
cloneFunction.commandDirectory = this.scatterGatherTempDir(dirFormat.format(i))
|
||||||
cloneFunction.jobOutputFile = if (IOUtils.isSpecialFile(this.jobOutputFile)) this.jobOutputFile else new File(this.jobOutputFile.getName)
|
cloneFunction.jobOutputFile = if (IOUtils.isSpecialFile(this.jobOutputFile)) this.jobOutputFile else new File(this.jobOutputFile.getName)
|
||||||
if (this.jobErrorFile != null)
|
if (this.jobErrorFile != null)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue