public void dbgDisplayIndex(Scheduler dbgScheduler) { List<WaitRecord> waitRecords = new List<WaitRecord>(this.waitingVerbs.Values); for (int i = 0; i < waitRecords.Count(); i++) { WaitRecord wr = waitRecords[i]; List<int> depNums = new List<int>(); List<BuildObject> unknownDeps = new List<BuildObject>(); List<string> unscheduledDeps = new List<string>(); foreach (BuildObject dep in wr.knownDeps) { IVerb depOnVerb = dbgScheduler.getParent(dep); if (depOnVerb == null) { unknownDeps.Add(dep); } else if (!this.waitingVerbs.ContainsKey(depOnVerb)) { unscheduledDeps.Add( string.Format( "{0} waiting on {1} {2}", dep, depOnVerb, dbgScheduler.dbgGetVerbStatus(depOnVerb))); } else { WaitRecord depWr = this.waitingVerbs[depOnVerb]; depNums.Add(waitRecords.IndexOf(depWr)); } } Logger.WriteLine( string.Format( "{0}. {1} waits on ({2}), {3} unknown, {4} unscheduled", i, wr.verb, string.Join(",", depNums), unknownDeps.Count(), unscheduledDeps.Count())); this.dbgPreview("Unknown", unknownDeps.Select(it => it.ToString()), 3); this.dbgPreview("Unscheduled", unscheduledDeps, 20); } }
/// <summary> /// Reports current progress to the scheduler. /// </summary> /// <param name="dbgScheduler">The scheduler.</param> private void dbgUpdateProgress(Scheduler dbgScheduler) { dbgScheduler.dbgUpdateProgress(this.runnableVerbs.Count(), this.runningTasks); }
/// <summary> /// Called by the scheduler to run the verbs which can be run. /// </summary> /// <param name="dbgScheduler"> /// The scheduler calling us (for debugging). /// </param> /// <returns>A list of tasks (verb runs) that have completed.</returns> public List<TaskCompletion> scheduleAndWait(Scheduler dbgScheduler) { while (true) { List<TaskCompletion> taskCompletionBatch; // Loop until something gets done. while (true) { this.dbgUpdateProgress(dbgScheduler); this.taskCompletionsLock.AcquireWriterLock(Timeout.Infinite); taskCompletionBatch = this.taskCompletions; this.taskCompletions = new List<TaskCompletion>(); this.completionEvent.Reset(); this.taskCompletionsLock.ReleaseLock(); bool canProcessCompletedTask = taskCompletionBatch.Count() > 0; bool canStartNewTask = (this.runnableVerbs.Count() > 0) && (this.jobParallelism > this.runningTasks); if (!(canProcessCompletedTask || canStartNewTask)) { // Nothing will change until a running task finishes. Snooze. if (this.runningTasks == 0) { dbgScheduler.dbgDumpWaitIndex(); Util.Assert(false); } this.completionEvent.WaitOne(); continue; } break; } int numCompletedTasks = taskCompletionBatch.Count(); Say(string.Format("marking {0} tasks completing; runningTasks now {1}", numCompletedTasks, this.runningTasks)); this.runningTasks -= numCompletedTasks; int idleTasks = this.jobParallelism - this.runningTasks; if (idleTasks > 0) { this.verbStateLock.AcquireWriterLock(Timeout.Infinite); List<IVerb> runnableVerbsBatch = new List<IVerb>(this.runnableVerbs); Say("AsyncRunner toposorting " + runnableVerbsBatch.Count() + " verbs"); runnableVerbsBatch.Sort(this.verbToposorter); ////Logger.WriteLine(string.Format("verbToposorter({0}) yields:", runnableVerbsBatch.Count)); ////foreach (IVerb verb in runnableVerbsBatch) ////{ //// Logger.WriteLine(" " + verb.ToString() + " @ "+ this.verbToposorter.getDepth(verb)); ////} for (int i = 0; i < idleTasks && i < runnableVerbsBatch.Count(); i++) { IVerb verb = runnableVerbsBatch[i]; this.startTask(verb); this.runnableVerbs.Remove(verb); this.startedVerbs.Add(verb); } this.verbStateLock.ReleaseLock(); } if (taskCompletionBatch.Count() > 0 || this.runningTasks == 0) { // Something actually got done, so the caller could meaningfully schedule more work. return taskCompletionBatch; } } }
/// <summary> /// Called by the scheduler to run the verbs which can be run. /// </summary> /// <param name="dbgScheduler"> /// The scheduler calling us (for debugging). /// </param> /// <returns>A list of tasks (verb runs) that have completed.</returns> public List <TaskCompletion> scheduleAndWait(Scheduler dbgScheduler) { while (true) { List <TaskCompletion> taskCompletionBatch; // Loop until something gets done. while (true) { this.dbgUpdateProgress(dbgScheduler); this.taskCompletionsLock.AcquireWriterLock(Timeout.Infinite); taskCompletionBatch = this.taskCompletions; this.taskCompletions = new List <TaskCompletion>(); this.completionEvent.Reset(); this.taskCompletionsLock.ReleaseLock(); bool canProcessCompletedTask = taskCompletionBatch.Count() > 0; bool canStartNewTask = (this.runnableVerbs.Count() > 0) && (this.jobParallelism > this.runningTasks); if (!(canProcessCompletedTask || canStartNewTask)) { // Nothing will change until a running task finishes. Snooze. if (this.runningTasks == 0) { dbgScheduler.dbgDumpWaitIndex(); Util.Assert(false); } this.completionEvent.WaitOne(); continue; } break; } int numCompletedTasks = taskCompletionBatch.Count(); Say(string.Format("marking {0} tasks completing; runningTasks now {1}", numCompletedTasks, this.runningTasks)); this.runningTasks -= numCompletedTasks; int idleTasks = this.jobParallelism - this.runningTasks; if (idleTasks > 0) { this.verbStateLock.AcquireWriterLock(Timeout.Infinite); List <IVerb> runnableVerbsBatch = new List <IVerb>(this.runnableVerbs); Say("AsyncRunner toposorting " + runnableVerbsBatch.Count() + " verbs"); runnableVerbsBatch.Sort(this.verbToposorter); ////Logger.WriteLine(string.Format("verbToposorter({0}) yields:", runnableVerbsBatch.Count)); ////foreach (IVerb verb in runnableVerbsBatch) ////{ //// Logger.WriteLine(" " + verb.ToString() + " @ "+ this.verbToposorter.getDepth(verb)); ////} for (int i = 0; i < idleTasks && i < runnableVerbsBatch.Count(); i++) { IVerb verb = runnableVerbsBatch[i]; this.startTask(verb); this.runnableVerbs.Remove(verb); this.startedVerbs.Add(verb); } this.verbStateLock.ReleaseLock(); } if (taskCompletionBatch.Count() > 0 || this.runningTasks == 0) { // Something actually got done, so the caller could meaningfully schedule more work. return(taskCompletionBatch); } } }
void main(string[] cmdline_args) { string[] all_args = fetchConfigArgs().Concat(cmdline_args).ToArray(); logNubuildInvocation(all_args); try { parseArgs(all_args); } catch (UserError err) { usage(err.Message); } Scheduler scheduler = new Scheduler(jobParallelism, GetItemCache(), rejectCachedFailures); scheduler.addTargetVerbs(verbs); scheduler.parallelSchedule(); IEnumerable <BuildObject> targets = scheduler.getTargets(); BuildObject outputTarget = null; if (targets.Count() > 0) { outputTarget = targets.First(); } else { Logger.WriteLine("No targets requested."); } if (targets.Count() > 1) { //- TODO need a better story for relaying failure results. Right now //- they get stuck in the results cache, but don't appear where we //- can find them. Emit to a log, or to files in nuobj? Logger.WriteLine("Multiple targets build. First result follows."); } if (outputTarget != null) { Disposition d = scheduler.getObjectDisposition(outputTarget); if (d is Fresh) { ASCIIPresentater ascii = new ASCIIPresentater(); IVerb verb = scheduler.getParent(outputTarget); verb.getPresentation().format(ascii); Logger.Write(ascii.ToString()); if (this.html_output != null) { HTMLPresentater html = new HTMLPresentater(); verb.getPresentation().format(html); try { using (StreamWriter sw = new StreamWriter(this.html_output)) { sw.Write(html.ToString()); } } catch (Exception e) { Logger.WriteLine("Failed to write html output to file: " + html_output); Logger.WriteLine("Exception was: " + e); } } } else { Logger.WriteLine("Build failed."); foreach (string msg in d.getMessages()) { Logger.Write(msg); } } } else if (targets.Count() == 0) { Logger.WriteLine("No targets requested."); } else { Logger.WriteLine("Multiple targets built. Look for results in nuobj/."); } //- - //- We have to explicitly ask the BackgroundWorker thread to exit //- as it will prevent the process from exiting until it does. //- - this.backgroundWorker.StopWork(); //- - //- Report what the background worker accomplished during this run. //- - this.backgroundWorker.WaitForCompletion(); Logger.WriteLine(String.Format("Background Worker completed {0} work items out of {1} queued.", this.backgroundWorker.GetWorkItemsPerformed, this.backgroundWorker.GetWorkItemsQueued)); if (this.backgroundWorker.GetWorkItemsFailed != 0) { Logger.WriteLine(String.Format( "{0} work item procedures failed (threw an exception).", this.backgroundWorker.GetWorkItemsFailed)); } }