Пример #1
0
 public BuildStepInfo(BuildStep buildStep, long executionId, string description, TimestampLocalLogger logger)
 {
     BuildStep = buildStep;
     ExecutionId = executionId;
     Description = description;
     Logger = logger;
     HasBeenSend = false;
 }
Пример #2
0
 public BuildStepLogger(BuildStep buildStep, ILogger mainLogger, DateTime startTime)
 {
     this.buildStep = buildStep;
     this.mainLogger = mainLogger;
     StepLogger = new TimestampLocalLogger(startTime);
     // Let's receive all level messages, each logger will filter them itself
     ActivateLog(LogMessageType.Debug);
     // StepLogger messages will be forwarded to the monitor, which will also filter itself
     StepLogger.ActivateLog(LogMessageType.Debug);
 }
Пример #3
0
        //private static PluginResolver pluginManager;
        private static void BuildStepsRecursively(BuildEngine.Builder builder, ICollection<BuildStep> steps, int stepsPerLevel, int maxLevel, BuildStep curParent = null, int curLevel = 0)
        {
            if (curLevel == maxLevel)
                return;

            for (var i = 0; i < stepsPerLevel; ++i)
            {
                BuildStep step = builder.Root.Add(new DoNothingCommand());
                if (curParent != null)
                    BuildStep.LinkBuildSteps(curParent, step);
                BuildStepsRecursively(builder, steps, stepsPerLevel, maxLevel, step, curLevel + 1);
                steps.Add(step);
            }
        }
Пример #4
0
 internal void RegisterBuildStep(BuildStep buildStep, TimestampLocalLogger logger)
 {
     lock (buildStepInfosToSend)
     {
         buildStepInfosToSend.Add(new BuildStepInfo(buildStep, buildStep.ExecutionId, buildStep.Description, logger));
     }
 }
Пример #5
0
        /// <summary>
        /// Sets recursively the <see cref="BuildStep.Module"/>.
        /// </summary>
        /// <param name="buildStep">The build step.</param>
        /// <param name="module">The module.</param>
        private void SetModule(BuildStep buildStep, string module)
        {
            if (buildStep.Module == null)
                buildStep.Module = module;

            var enumerableBuildStep = buildStep as EnumerableBuildStep;
            if (enumerableBuildStep != null && enumerableBuildStep.Steps != null)
            {
                foreach (var child in enumerableBuildStep.Steps)
                {
                    SetModule(child, module);
                }
            }
        }
Пример #6
0
        private static IEnumerable<CommandBuildStep> CollectCommandSteps(BuildStep step)
        {
            if (step is CommandBuildStep)
            {
                yield return (CommandBuildStep)step;
            }

            // NOTE: We assume that only EnumerableBuildStep is the base class for sub-steps and that ContentReferencable BuildStep are accessible from them (not through dynamic build step)
            var enumerateBuildStep = step as EnumerableBuildStep;
            if (enumerateBuildStep?.Steps != null)
            {
                foreach (var subStep in enumerateBuildStep.Steps)
                {
                    foreach (var command in CollectCommandSteps(subStep))
                    {
                        yield return command;
                    }
                }
            }
        }
Пример #7
0
 private static void CollectContentReferenceDependencies(BuildStep step, HashSet<string> locations)
 {
     // For each CommandStep for the current build step, collects all dependencies to ContenrReference-BuildStep
     foreach (var commandStep in CollectCommandSteps(step))
     {
         foreach (var inputFile in commandStep.Command.GetInputFiles())
         {
             if (inputFile.Type == UrlType.Content)
             {
                 locations.Add(inputFile.Path);
             }
         }
     }
 }
Пример #8
0
 public void ScheduleBuildStep(BuildStep step)
 {
     builder.ScheduleBuildStep(builderContext, buildStep, step, Variables);
 }
Пример #9
0
        private void ScheduleBuildStep(BuilderContext builderContext, BuildStep instigator, BuildStep buildStep, IDictionary<string, string> variables)
        {
            if (buildStep.ExecutionId == 0)
            {
                if (buildStep.Parent != null && buildStep.Parent != instigator)
                    throw new InvalidOperationException("Scheduling a BuildStep with a different instigator that its parent");
                if (buildStep.Parent == null)
                {
                    buildStep.Parent = instigator;
                }

                // Compute content dependencies before scheduling the build
                GenerateDependencies(buildStep);

                var executeContext = new ExecuteContext(this, builderContext, buildStep) { Variables = new Dictionary<string, string>(variables) };
                //buildStep.ExpandStrings(executeContext);

                if (runMode == Mode.Build)
                {
                    MicroThread microThread = scheduler.Create();

                    // Find priority from this build step, or one of its parent.
                    var buildStepPriority = buildStep;
                    while (buildStepPriority != null)
                    {
                        if (buildStepPriority.Priority.HasValue)
                        {
                            microThread.Priority = buildStepPriority.Priority.Value;
                            break;
                        }

                        buildStepPriority = buildStepPriority.Parent;
                    }

                    buildStep.ExecutionId = microThread.Id;

                    foreach (var threadMonitor in threadMonitors)
                    {
                        threadMonitor.RegisterBuildStep(buildStep, ((BuildStepLogger)executeContext.Logger).StepLogger);
                    }

                    microThread.Name = buildStep.ToString();

                    // Default:
                    // Schedule continuations as early as possible to help EnumerableBuildStep finish when all its task are finished.
                    // Otherwise, it would wait for all leaf to finish first before finishing parent EnumerableBuildStep.
                    // This should also reduce memory usage, and might improve cache coherency as well.
                    microThread.ScheduleMode = ScheduleMode.First;

                    microThread.Start(async () =>
                    {
                        // Wait for prerequisites
                        await Task.WhenAll(buildStep.PrerequisiteSteps.Select(x => x.ExecutedAsync()).ToArray());

                        // Check for failed prerequisites
                        var status = ResultStatus.NotProcessed;

                        if (buildStep.ArePrerequisitesSuccessful)
                        {
                            try
                            {
                                IndexFileCommand.MountDatabase(executeContext.GetOutputObjectsGroups());

                                // Execute
                                status = await buildStep.Execute(executeContext, builderContext);
                            }
                            catch (TaskCanceledException e)
                            {
                                // Benlitz: I'm NOT SURE this is the correct explanation, it might be a more subtle race condition, but I can't manage to reproduce it again
                                executeContext.Logger.Warning("A child task of build step " + buildStep + " triggered a TaskCanceledException that was not caught by the parent task. The command has not handled cancellation gracefully.");
                                executeContext.Logger.Warning(e.Message);
                                status = ResultStatus.Cancelled;
                            }
                            catch (Exception e)
                            {
                                executeContext.Logger.Error("Exception in command " + buildStep + ": " + e);
                                status = ResultStatus.Failed;
                            }
                            finally
                            {
                                IndexFileCommand.UnmountDatabase();
                                
                                // Ensure the command set at least the result status
                                if (status == ResultStatus.NotProcessed)
                                    throw new InvalidDataException("The build step " + buildStep + " returned ResultStatus.NotProcessed after completion.");
                            }
                            if (microThread.Exception != null)
                            {
                                executeContext.Logger.Error("Exception in command " + buildStep + ": " + microThread.Exception);
                                status = ResultStatus.Failed;
                            }
                        }
                        else
                        {
                            status = ResultStatus.NotTriggeredPrerequisiteFailed;
                        }

                        //if (completedTask.IsCanceled)
                        //{
                        //    completedStep.Status = ResultStatus.Cancelled;
                        //}
                        var logType = LogMessageType.Info;
                        string logText = null;
                        
                        switch (status)
                        {
                            case ResultStatus.Successful:
                                logType = LogMessageType.Verbose;
                                logText = "BuildStep {0} was successful.".ToFormat(buildStep.ToString());
                                break;
                            case ResultStatus.Failed:
                                logType = LogMessageType.Error;
                                logText = "BuildStep {0} failed.".ToFormat(buildStep.ToString());
                                break;
                            case ResultStatus.NotTriggeredPrerequisiteFailed:
                                logType = LogMessageType.Error;
                                logText = "BuildStep {0} failed of previous failed prerequisites.".ToFormat(buildStep.ToString());
                                break;
                            case ResultStatus.Cancelled:
                                logType = LogMessageType.Warning;
                                logText = "BuildStep {0} cancelled.".ToFormat(buildStep.ToString());
                                break;
                            case ResultStatus.NotTriggeredWasSuccessful:
                                logType = LogMessageType.Verbose;
                                logText = "BuildStep {0} is up-to-date and has been skipped".ToFormat(buildStep.ToString());
                                break;
                            case ResultStatus.NotProcessed:
                                throw new InvalidDataException("BuildStep has neither succeeded, failed, nor been cancelled");
                        }
                        if (logText != null)
                        {
                            var logMessage = new LogMessage(buildStep.Module, logType, logText);
                            Logger.Log(logMessage);
                        }

                        buildStep.RegisterResult(executeContext, status);
                        stepCounter.AddStepResult(status);
                    });
                }
                else
                {
                    buildStep.Clean(executeContext, builderContext, runMode == Mode.CleanAndDelete);
                }
            }
        }
Пример #10
0
 public void ScheduleBuildStep(BuildStep step)
 {
     builder.ScheduleBuildStep(builderContext, buildStep, step, Variables);
 }
Пример #11
0
 public ExecuteContext(Builder builder, BuilderContext builderContext, BuildStep buildStep)
 {
     Logger = new BuildStepLogger(buildStep, builder.Logger, builder.startTime);
     this.builderContext = builderContext;
     this.builder = builder;
     this.buildStep = buildStep;
     buildTransaction = new BuildTransaction(null, buildStep.GetOutputObjectsGroups());
 }
Пример #12
0
        /// <summary>
        /// Sets recursively the <see cref="BuildStep.Module"/>.
        /// </summary>
        /// <param name="buildStep">The build step.</param>
        /// <param name="module">The module.</param>
        private void SetAssetLogger(BuildStep buildStep, Package package, IReference assetReference, string assetFullPath)
        {
            if (buildStep.TransformExecuteContextLogger == null)
                buildStep.TransformExecuteContextLogger = (ref Logger logger) => logger = new AssetLogger(package, assetReference, assetFullPath, logger);

            var enumerableBuildStep = buildStep as EnumerableBuildStep;
            if (enumerableBuildStep != null && enumerableBuildStep.Steps != null)
            {
                foreach (var child in enumerableBuildStep.Steps)
                {
                    SetAssetLogger(child, package, assetReference, assetFullPath);
                }
            }
        }
Пример #13
0
 public ExecuteContext(Builder builder, BuilderContext builderContext, BuildStep buildStep, Logger logger)
 {
     Logger = logger;
     this.builderContext = builderContext;
     this.builder = builder;
     this.buildStep = buildStep;
     buildTransaction = new BuildTransaction(null, buildStep.GetOutputObjectsGroups());
 }
Пример #14
0
 public BuildStepEventArgs(BuildStep step, ILogger logger)
 {
     Step = step;
     Logger = logger;
 }
Пример #15
0
        private void ScheduleBuildStep(BuilderContext builderContext, BuildStep instigator, BuildStep buildStep, IDictionary <string, string> variables)
        {
            if (buildStep.ExecutionId == 0)
            {
                if (buildStep.Parent != null && buildStep.Parent != instigator)
                {
                    throw new InvalidOperationException("Scheduling a BuildStep with a different instigator that its parent");
                }
                if (buildStep.Parent == null)
                {
                    buildStep.Parent = instigator;
                }

                var executeContext = new ExecuteContext(this, builderContext, buildStep)
                {
                    Variables = new Dictionary <string, string>(variables)
                };
                //buildStep.ExpandStrings(executeContext);

                if (runMode == Mode.Build)
                {
                    MicroThread microThread = scheduler.Create();

                    // Find priority from this build step, or one of its parent.
                    var buildStepPriority = buildStep;
                    while (buildStepPriority != null)
                    {
                        if (buildStepPriority.Priority.HasValue)
                        {
                            microThread.Priority = buildStepPriority.Priority.Value;
                            break;
                        }

                        buildStepPriority = buildStepPriority.Parent;
                    }

                    buildStep.ExecutionId = microThread.Id;

                    foreach (var threadMonitor in threadMonitors)
                    {
                        threadMonitor.RegisterBuildStep(buildStep, ((BuildStepLogger)executeContext.Logger).StepLogger);
                    }

                    microThread.Name = buildStep.ToString();

                    // Default:
                    // Schedule continuations as early as possible to help EnumerableBuildStep finish when all its task are finished.
                    // Otherwise, it would wait for all leaf to finish first before finishing parent EnumerableBuildStep.
                    // This should also reduce memory usage, and might improve cache coherency as well.
                    microThread.ScheduleMode = ScheduleMode.First;

                    microThread.Start(async() =>
                    {
                        // Wait for prerequisites
                        await Task.WhenAll(buildStep.PrerequisiteSteps.Select(x => x.ExecutedAsync()).ToArray());

                        // Check for failed prerequisites
                        var status = ResultStatus.NotProcessed;

                        if (buildStep.ArePrerequisitesSuccessful)
                        {
                            try
                            {
                                IndexFileCommand.MountDatabase(executeContext.GetOutputObjectsGroups());

                                // Execute
                                status = await buildStep.Execute(executeContext, builderContext);
                            }
                            catch (TaskCanceledException e)
                            {
                                // Benlitz: I'm NOT SURE this is the correct explanation, it might be a more subtle race condition, but I can't manage to reproduce it again
                                executeContext.Logger.Warning("A child task of build step " + buildStep + " triggered a TaskCanceledException that was not caught by the parent task. The command has not handled cancellation gracefully.");
                                executeContext.Logger.Warning(e.Message);
                                status = ResultStatus.Cancelled;
                            }
                            catch (Exception e)
                            {
                                executeContext.Logger.Error("Exception in command " + buildStep + ": " + e);
                                status = ResultStatus.Failed;
                            }
                            finally
                            {
                                IndexFileCommand.UnmountDatabase();

                                // Ensure the command set at least the result status
                                if (status == ResultStatus.NotProcessed)
                                {
                                    throw new InvalidDataException("The build step " + buildStep + " returned ResultStatus.NotProcessed after completion.");
                                }
                            }
                            if (microThread.Exception != null)
                            {
                                executeContext.Logger.Error("Exception in command " + buildStep + ": " + microThread.Exception);
                                status = ResultStatus.Failed;
                            }
                        }
                        else
                        {
                            status = ResultStatus.NotTriggeredPrerequisiteFailed;
                        }

                        //if (completedTask.IsCanceled)
                        //{
                        //    completedStep.Status = ResultStatus.Cancelled;
                        //}
                        var logType    = LogMessageType.Info;
                        string logText = null;

                        switch (status)
                        {
                        case ResultStatus.Successful:
                            logType = LogMessageType.Verbose;
                            logText = "BuildStep {0} was successful.".ToFormat(buildStep.ToString());
                            break;

                        case ResultStatus.Failed:
                            logType = LogMessageType.Error;
                            logText = "BuildStep {0} failed.".ToFormat(buildStep.ToString());
                            break;

                        case ResultStatus.Cancelled:
                            logType = LogMessageType.Warning;
                            logText = "BuildStep {0} cancelled.".ToFormat(buildStep.ToString());
                            break;

                        case ResultStatus.NotTriggeredWasSuccessful:
                            logType = LogMessageType.Verbose;
                            logText = "BuildStep {0} is up-to-date and has been skipped".ToFormat(buildStep.ToString());
                            break;

                        case ResultStatus.NotProcessed:
                            throw new InvalidDataException("BuildStep has neither succeeded, failed, nor been cancelled");
                        }
                        if (logText != null)
                        {
                            var logMessage = new LogMessage(buildStep.Module, logType, logText);
                            Logger.Log(logMessage);
                        }

                        buildStep.RegisterResult(executeContext, status);
                        stepCounter.AddStepResult(status);
                    });
                }
                else
                {
                    buildStep.Clean(executeContext, builderContext, runMode == Mode.CleanAndDelete);
                }
            }
        }
Пример #16
0
        /// <summary>
        /// Collects dependencies between <see cref="BuildStep.OutputLocation"/> and fill the <see cref="BuildStep.PrerequisiteSteps"/> accordingly.
        /// </summary>
        /// <param name="rootStep">The root BuildStep</param>
        private void GenerateDependencies(BuildStep rootStep)
        {
            // TODO: Support proper incremental dependecies
            if (rootStep.ProcessedDependencies)
                return;

            rootStep.ProcessedDependencies = true;

            var contentBuildSteps = new Dictionary<string, KeyValuePair<BuildStep, HashSet<string>>>();
            PrepareDependencyGraph(rootStep, contentBuildSteps);
            ComputeDependencyGraph(contentBuildSteps);
        }
Пример #17
0
 private static IEnumerable<BuildStep> EnumerateSpawnedBuildSteps(BuildStep buildStep)
 {
     foreach (var spawnedStep in buildStep.SpawnedSteps)
     {
         yield return spawnedStep;
         foreach (var childSpawnedStep in EnumerateSpawnedBuildSteps(spawnedStep))
         {
             yield return childSpawnedStep;
         }
     }
 }
Пример #18
0
        /// <summary>
        /// Collects dependencies between <see cref="BuildStep.OutputLocation"/> BuildStep. See remarks.
        /// </summary>
        /// <param name="step">The step to compute the dependencies for</param>
        /// <param name="contentBuildSteps">A cache of content reference location to buildsteps </param>
        /// <remarks>
        /// Each BuildStep inheriting from <see cref="BuildStep.OutputLocation"/> is considered as a top-level dependency step that can have depedencies
        /// on other top-level dependency. We are collecting all of them here.
        /// </remarks>
        private static void PrepareDependencyGraph(BuildStep step, Dictionary<string, KeyValuePair<BuildStep, HashSet<string>>> contentBuildSteps)
        {
            step.ProcessedDependencies = true;

            var outputLocation = step.OutputLocation;
            if (outputLocation != null)
            {
                var dependencies = new HashSet<string>();
                if (!contentBuildSteps.ContainsKey(outputLocation))
                {
                    contentBuildSteps.Add(outputLocation, new KeyValuePair<BuildStep, HashSet<string>>(step, dependencies));
                    CollectContentReferenceDependencies(step, dependencies);
                }

                // If we have a reference, we don't need to iterate further
                return;
            }

            // NOTE: We assume that only EnumerableBuildStep is the base class for sub-steps and that ContentReferencable BuildStep are accessible from them (not through dynamic build step)
            var enumerateBuildStep = step as EnumerableBuildStep;
            if (enumerateBuildStep?.Steps != null)
            {
                foreach (var subStep in enumerateBuildStep.Steps)
                {
                    PrepareDependencyGraph(subStep, contentBuildSteps);
                }
            }
        }
Пример #19
0
 public static void LinkBuildSteps(BuildStep parent, BuildStep child)
 {
     lock (child.prerequisiteSteps)
     {
         child.prerequisiteSteps.Add(parent);
     }
 }
Пример #20
0
        //private static PluginResolver pluginManager;
        private static void BuildStepsRecursively(Builder builder, ICollection <BuildStep> steps, int stepsPerLevel, int maxLevel, BuildStep curParent = null, int curLevel = 0)
        {
            if (curLevel == maxLevel)
            {
                return;
            }

            for (var i = 0; i < stepsPerLevel; ++i)
            {
                BuildStep step = builder.Root.Add(new DoNothingCommand());
                if (curParent != null)
                {
                    BuildStep.LinkBuildSteps(curParent, step);
                }
                BuildStepsRecursively(builder, steps, stepsPerLevel, maxLevel, step, curLevel + 1);
                steps.Add(step);
            }
        }