CheckIfModulesNeedRebuilding( System.Type metaType) { // not all build modes need to determine if modules are up-to-date var evaluationRequiredAttr = metaType.GetCustomAttributes(typeof(EvaluationRequiredAttribute), false) as EvaluationRequiredAttribute[]; if (0 == evaluationRequiredAttr.Length) { Log.DebugMessage("No Bam.Core.EvaluationRequired attribute on build mode metadata, assume rebuilds necessary"); return(false); } if (!evaluationRequiredAttr[0].Enabled) { Log.DebugMessage("Module evaluation disabled"); return(false); } Log.DebugMessage("Module evaluation enabled"); var cancellationSource = new System.Threading.CancellationTokenSource(); var cancellationToken = cancellationSource.Token; // LongRunning is absolutely necessary in order to achieve paralleism var creationOpts = System.Threading.Tasks.TaskCreationOptions.LongRunning; var continuationOpts = System.Threading.Tasks.TaskContinuationOptions.LongRunning; var threadCount = 1; var scheduler = new LimitedConcurrencyLevelTaskScheduler(threadCount); var factory = new System.Threading.Tasks.TaskFactory( cancellationToken, creationOpts, continuationOpts, scheduler); var graph = Graph.Instance; graph.MetaData = factory; foreach (var rank in graph.Reverse()) { foreach (Module module in rank) { module.Evaluate(); } } return(true); }
PerformThreadedEvaluation( Array <Module> modulesNeedEvaluating) { var graph = Graph.Instance; using (var cancellationSource = new System.Threading.CancellationTokenSource()) { var cancellationToken = cancellationSource.Token; // LongRunning is absolutely necessary in order to achieve paralleism var creationOpts = System.Threading.Tasks.TaskCreationOptions.LongRunning; var continuationOpts = System.Threading.Tasks.TaskContinuationOptions.LongRunning; var threadCount = 1; var scheduler = new LimitedConcurrencyLevelTaskScheduler(threadCount); var factory = new System.Threading.Tasks.TaskFactory( cancellationToken, creationOpts, continuationOpts, scheduler); if (null == modulesNeedEvaluating) { Log.DebugMessage("Module evaluation enabled for build mode {0}", graph.Mode); foreach (var rank in graph.Reverse()) { foreach (Module module in rank) { Log.DebugMessage("\tEvaluation for module {0}", module.GetType().ToString()); module.EvaluateAsync(factory); } } } else { Log.DebugMessage("Module evaluation disabled for build mode {0}, but enabled for {1} individual modules:", graph.Mode, modulesNeedEvaluating.Count); foreach (var module in modulesNeedEvaluating) { Log.DebugMessage("\tEvaluation for module {0}", module.GetType().ToString()); module.EvaluateAsync(factory); } } } }
CheckIfModulesNeedRebuilding( System.Type metaType) { var graph = Graph.Instance; var modulesNeedEvaluating = new Array <Module>(); // not all build modes need to determine if modules are up-to-date var evaluationRequiredAttr = metaType.GetCustomAttributes(typeof(EvaluationRequiredAttribute), false) as EvaluationRequiredAttribute[]; if (0 == evaluationRequiredAttr.Length) { // query if any individual modules override this foreach (var rank in graph.Reverse()) { foreach (Module module in rank) { var moduleEvaluationRequiredAttr = module.GetType().GetCustomAttributes(typeof(EvaluationRequiredAttribute), true) as EvaluationRequiredAttribute[]; if (moduleEvaluationRequiredAttr.Length > 0 && moduleEvaluationRequiredAttr[0].Enabled) { modulesNeedEvaluating.Add(module); } } } if (0 == modulesNeedEvaluating.Count) { Log.DebugMessage("No Bam.Core.EvaluationRequired attribute on build mode metadata, assume rebuilds necessary"); return(false); } } if ((evaluationRequiredAttr.Length > 0) && !evaluationRequiredAttr[0].Enabled && 0 == modulesNeedEvaluating.Count) { Log.DebugMessage("Module evaluation disabled"); return(false); } using (var cancellationSource = new System.Threading.CancellationTokenSource()) { var cancellationToken = cancellationSource.Token; // LongRunning is absolutely necessary in order to achieve paralleism var creationOpts = System.Threading.Tasks.TaskCreationOptions.LongRunning; var continuationOpts = System.Threading.Tasks.TaskContinuationOptions.LongRunning; var threadCount = 1; var scheduler = new LimitedConcurrencyLevelTaskScheduler(threadCount); var factory = new System.Threading.Tasks.TaskFactory( cancellationToken, creationOpts, continuationOpts, scheduler); graph.MetaData = factory; if (0 == modulesNeedEvaluating.Count) { Log.DebugMessage("Module evaluation enabled for build mode {0}", graph.Mode); foreach (var rank in graph.Reverse()) { foreach (Module module in rank) { module.Evaluate(); } } } else { Log.DebugMessage("Module evaluation disabled for build mode {0}, but enabled for individual modules:", graph.Mode); foreach (var module in modulesNeedEvaluating) { Log.DebugMessage("\tEvaluation for module {0}", module.GetType().ToString()); module.Evaluate(); } } } return(true); }
Run() { Log.Detail("Running build..."); // TODO: should the rank collections be sorted, so that modules with fewest dependencies are first? var graph = Graph.Instance; var metaDataType = graph.BuildModeMetaData.GetType(); var useEvaluation = CheckIfModulesNeedRebuilding(metaDataType); var explainRebuild = CommandLineProcessor.Evaluate(new Options.ExplainBuildReason()); var immediateOutput = CommandLineProcessor.Evaluate(new Options.ImmediateOutput()); ExecutePreBuild(metaDataType); // necessary if built with debug symbols IOWrapper.CreateDirectoryIfNotExists(graph.BuildRoot); var threadCount = CommandLineProcessor.Evaluate(new Options.MultiThreaded()); if (0 == threadCount) { threadCount = System.Environment.ProcessorCount; } System.Exception abortException = null; if (threadCount > 1) { using (var cancellationSource = new System.Threading.CancellationTokenSource()) { var cancellationToken = cancellationSource.Token; // LongRunning is absolutely necessary in order to achieve paralleism var creationOpts = System.Threading.Tasks.TaskCreationOptions.LongRunning; var continuationOpts = System.Threading.Tasks.TaskContinuationOptions.LongRunning; var scheduler = new LimitedConcurrencyLevelTaskScheduler(threadCount); var factory = new System.Threading.Tasks.TaskFactory( cancellationToken, creationOpts, continuationOpts, scheduler); var tasks = new Array <System.Threading.Tasks.Task>(); foreach (var rank in graph.Reverse()) { foreach (var module in rank) { var context = new ExecutionContext(useEvaluation, explainRebuild, immediateOutput); var task = factory.StartNew(() => { if (cancellationToken.IsCancellationRequested) { return; } var depTasks = new Array <System.Threading.Tasks.Task>(); foreach (var dep in module.Dependents) { if (null == dep.ExecutionTask) { continue; } depTasks.Add(dep.ExecutionTask); } foreach (var dep in module.Requirements) { if (null == dep.ExecutionTask) { continue; } depTasks.Add(dep.ExecutionTask); } System.Threading.Tasks.Task.WaitAll(depTasks.ToArray()); if (cancellationToken.IsCancellationRequested) { return; } try { (module as IModuleExecution).Execute(context); } catch (Exception ex) { abortException = ex; cancellationSource.Cancel(); } finally { if (context.OutputStringBuilder != null && context.OutputStringBuilder.Length > 0) { Log.Info(context.OutputStringBuilder.ToString()); } if (context.ErrorStringBuilder != null && context.ErrorStringBuilder.Length > 0) { Log.Info(context.ErrorStringBuilder.ToString()); } } }); tasks.Add(task); module.ExecutionTask = task; } } try { System.Threading.Tasks.Task.WaitAll(tasks.ToArray()); } catch (System.AggregateException exception) { if (!(exception.InnerException is System.Threading.Tasks.TaskCanceledException)) { throw new Exception(exception, "Error during threaded build"); } } } } else { foreach (var rank in graph.Reverse()) { if (null != abortException) { break; } foreach (IModuleExecution module in rank) { var context = new ExecutionContext(useEvaluation, explainRebuild, immediateOutput); try { module.Execute(context); } catch (Exception ex) { abortException = ex; break; } finally { if (context.OutputStringBuilder != null && context.OutputStringBuilder.Length > 0) { Log.Info(context.OutputStringBuilder.ToString()); } if (context.ErrorStringBuilder != null && context.ErrorStringBuilder.Length > 0) { Log.Info(context.ErrorStringBuilder.ToString()); } } } } } if (null != abortException) { throw new Exception(abortException, "Error during {0}threaded build", (threadCount > 1) ? string.Empty : "non-"); } ExecutePostBuild(metaDataType); }