private async Task CompleteOneBuildStep(IExecuteContext executeContext, List <BuildStep> buildStepsToWait)
        {
            // Too many build steps, wait for one to finish
            var waitHandles = buildStepsToWait.Select(x => ((IAsyncResult)x.ExecutedAsync()).AsyncWaitHandle);

            // Should we listen for new high priority tasks?
            if (buildStepsToWait.Count >= MaxParallelSteps && buildStepsToWait.Count < MaxParallelSteps + MaxHighPriorityParallelSteps)
            {
                waitHandles = waitHandles.Concat(new[] { newWorkAvailable });
            }

            var completedItem = WaitHandle.WaitAny(waitHandles.ToArray());

            var completeBuildStep = completedItem < buildStepsToWait.Count ? buildStepsToWait[completedItem] : null;

            if (completeBuildStep == null)
            {
                // Not an actual task completed, but we've got to check if there is a new high priority task so exit immediatly
                return;
            }

            // wait for completion of all its spawned and dependent steps
            // (probably instant most of the time, but it would be good to have a better ExecutedAsync to check that together as well)
            await ListBuildStep.WaitCommands(new List <BuildStep> {
                completeBuildStep
            });

            // Remove from list of build step to wait
            buildStepsToWait.Remove(completeBuildStep);
        }
Exemple #2
0
        /// <inheritdoc/>
        public override Task <ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
        {
//            var thumbnailCompiler = Command as IThumbnailCommand;
//            if (thumbnailCompiler != null)
//            {
//                var highestLogMessageType = LogMessageType.Debug;
//
//                // Check worst type of log message in BuildStep
//                foreach (var message in dependencies.EnumerateRecursively().SelectMany(x => x.Logger.Messages))
//                {
//                    if (highestLogMessageType < message.Type)
//                        highestLogMessageType = message.Type;
//                }
//
//                // Also, if build step failed, mark it as an error
//                if (highestLogMessageType < LogMessageType.Error && dependencies.Failed)
//                {
//                    highestLogMessageType = LogMessageType.Error;
//                }
//
//                // TODO: This is not serializable (OK for now since thumbnails are never built in a separate process); later, a specific class to store results will be needed
//                thumbnailCompiler.DependencyBuildStatus = highestLogMessageType;
//            }

            return(base.Execute(executeContext, builderContext));
        }
Exemple #3
0
        public PagedList <T> QueryPaged(IExecuteContext <T> context)
        {
            this.CurrentContext = context;
            Page <T> result = null;

            if (null != context.PagingInfo)
            {
                PageDescriptor p = context.PagingInfo;
                result = DataBase.Page <T>(p.PageNumber, p.PageSize, GetExecuteContainer());
            }
            else
            {
                result = DataBase.Page <T>(1, context.TopCount > 0 ? context.TopCount : MaxSearchCount, GetExecuteContainer());
            }
            return(new PagedList <T>
            {
                CurrentPage = result.CurrentPage
                ,
                Items = result.Items
                ,
                ItemsPerPage = result.ItemsPerPage
                ,
                TotalItems = result.TotalItems
                ,
                TotalPages = result.TotalPages
            });
        }
Exemple #4
0
        public Task <ExecuteResult> Execute(IExecuteContext executeContext)
        {
            _ = executeContext ?? throw new ArgumentNullException(nameof(executeContext));
            var traceInfo = new TraceInfo()
            {
                ExecuteContext = executeContext
            };

            this.OnTraceState(traceInfo, ExecuteState.Ready);

            return(Task.Run(() =>
            {
                executeContext.Token.ThrowIfCancellationRequested();
                this.OnTraceState(traceInfo, ExecuteState.Running);
                var result = this.OnExecute(executeContext, traceInfo);
                if (result.IsSuccess)
                {
                    this.OnTraceState(traceInfo, ExecuteState.Success, result);
                }
                else
                {
                    this.OnTraceState(traceInfo, ExecuteState.Failure, result);
                }
                return result;
            }, executeContext.Token));
        }
        public ActivityExecutionResult Execute(IExecuteContext context)
        {
            if (context.IsContinue)
            {
                return(ActivityExecutionResult.Complete);
            }
            var chat = Guid.Parse(context.Resolve(ChatId));
            var msgs = GetMessages().Select(msg =>
            {
                var m = new StorableOutgoingMessage();
                m.Restore(msg, null);
                m.Resolve(context);
                return(new SendMessageMessage(m)
                {
                    BotEngine = BotEngine,
                    BotKey = BotKey,
                    ChatId = chat
                } as Infrastructure.IMessage);
            }).ToList();

            if (Sync)
            {
                var book = context.SetBookmark();
                var rmsg = new ResumeBookmarkMessage(book, new DynamicObject());
                msgs.Add(rmsg);
                context.SendMessagesSequence(msgs.ToArray());
                return(ActivityExecutionResult.Idle);
            }
            else
            {
                context.SendMessagesSequence(msgs.ToArray());
                return(ActivityExecutionResult.Complete);
            }
        }
Exemple #6
0
        public override async Task <ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
        {
            var buildStepsToWait = new List <BuildStep>();

            // Process prerequisites build steps first
            if (PrerequisiteSteps.Count > 0)
            {
                await CompleteCommands(executeContext, PrerequisiteSteps.ToList());
            }

            foreach (var child in Steps)
            {
                // Wait for all the tasks before the WaitBuildStep to be finished
                if (child is WaitBuildStep)
                {
                    await CompleteCommands(executeContext, buildStepsToWait);
                }
                else
                {
                    executeContext.ScheduleBuildStep(child);
                    buildStepsToWait.Add(child);
                }

                executedSteps.Add(child);
            }

            await CompleteCommands(executeContext, buildStepsToWait);

            return(ComputeResultStatusFromExecutedSteps());
        }
Exemple #7
0
        public bool DeleteByQuery(IExecuteContext <T> context)
        {
            this.CurrentContext = context;
            int result = DataBase.Execute(GetExecuteContainer());

            return(result > 0);
        }
Exemple #8
0
        private OutputObject AddOutputObject(IExecuteContext executeContext, ObjectUrl outputObjectUrl, ObjectId outputObjectId, Command command)
        {
            OutputObject outputObject;

            if (!outputObjects.TryGetValue(outputObjectUrl, out outputObject))
            {
                // New item?
                outputObject = new OutputObject(outputObjectUrl, outputObjectId);
                outputObjects.Add(outputObjectUrl, outputObject);
            }
            else
            {
                // ObjectId should be similar (if no Wait happened), otherwise two tasks spawned with same parameters did output different results
                if (outputObject.ObjectId != outputObjectId && outputObject.Counter == mergeCounter)
                {
                    var error = $"Commands {command} and {outputObject.Command} are both writing {outputObjectUrl} at the same time";
                    executeContext.Logger.Error(error);
                    throw new InvalidOperationException(error);
                }

                // Update new ObjectId
                outputObject.ObjectId = outputObjectId;
            }

            // Update Counter so that we know if a wait happened since this output object has been merged.
            outputObject.Counter = mergeCounter;
            outputObject.Command = command;

            return(outputObject);
        }
Exemple #9
0
        public long Count(IExecuteContext <T> context)
        {
            this.CurrentContext = context;
            long count = DataBase.ExecuteScalar <long>(GetExecuteContainer());

            return(count);
        }
Exemple #10
0
        public bool Exists(IExecuteContext <T> context)
        {
            this.CurrentContext = context;
            var result = DataBase.FirstOrDefault <T>(GetExecuteContainer());

            return(result != null);
        }
        private Task RunTask(IActionContext actionContext, TaskDesc taskDesc, GroupInfo groupInfo)
        {
            bool isSubEntryAction = this.IsSubEntryGroup(taskDesc.TaskInfo.Action);

            if (!isSubEntryAction)
            {
                publishValueService.PublishVars(actionContext.Parameters, taskDesc.TaskInfo.Vars);
            }
            IExecuteContext executeContext = CreateExecuteContext(actionContext, taskDesc, isSubEntryAction);

            return(actionExecuterService.Execute(executeContext).ContinueWith((result) =>
            {
                if (result.IsCompleted && result.Exception == null)
                {
                    var executeResult = result.Result;
                    this.PublishResultVars(actionContext, executeResult, taskDesc);
                    PublishGlobalVars(actionContext, executeResult.IsSuccess, taskDesc);
                    List <TaskDesc> nextTasks = GetNextTasks(actionContext, executeResult.IsSuccess, taskDesc, groupInfo);
                    RunTasks(actionContext, nextTasks, groupInfo).Wait();
                }
                else
                {
                    throw WorkflowError.TaskEexcuteError(taskDesc.TaskName, result.Exception);
                }
            }, actionContext.Token, TaskContinuationOptions.None, TaskScheduler.Current));
        }
        public override async Task<ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
        {
            var buildStepsToWait = new List<BuildStep>();

            // Process prerequisites build steps first
            if (PrerequisiteSteps.Count > 0)
                await CompleteCommands(executeContext, PrerequisiteSteps.ToList());

            foreach (var child in Steps)
            {
                // Wait for all the tasks before the WaitBuildStep to be finished
                if (child is WaitBuildStep)
                {
                    await CompleteCommands(executeContext, buildStepsToWait);
                }
                else
                {
                    executeContext.ScheduleBuildStep(child);
                    buildStepsToWait.Add(child);
                }

                executedSteps.Add(child);
            }

            await CompleteCommands(executeContext, buildStepsToWait);
            
            return ComputeResultStatusFromExecutedSteps();
        }
Exemple #13
0
            /// <inheritdoc/>
            public override Task <ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
            {
                var steps = new List <BuildStep>();

                var urlRoot = originalSourcePath.GetParent();

                var fileStream = new FileStream(originalSourcePath.ToWindowsPath(), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);

                using (var recordedEffectCompile = new EffectLogStore(fileStream))
                {
                    recordedEffectCompile.LoadNewValues();

                    foreach (var entry in recordedEffectCompile.GetValues())
                    {
                        var effectCompileRequest = entry.Key;

                        var compilerParameters = new CompilerParameters();
                        effectCompileRequest.UsedParameters.CopyTo(compilerParameters);
                        compilerParameters.Platform = context.GetGraphicsPlatform();
                        compilerParameters.Profile  = context.GetGameSettingsAsset().DefaultGraphicsProfile;
                        steps.Add(new CommandBuildStep(new EffectCompileCommand(context, urlRoot, effectCompileRequest.EffectName, compilerParameters, package)));
                    }
                }

                Steps = steps;

                return(base.Execute(executeContext, builderContext));
            }
        /// <summary>
        /// Processes the results from a <see cref="CommandBuildStep"/>.
        /// </summary>
        /// <param name="executeContext">The execute context.</param>
        /// <param name="buildStep">The build step.</param>
        private void ProcessCommandBuildStepResult(IExecuteContext executeContext, CommandBuildStep buildStep)
        {
            foreach (var resultInputObject in buildStep.Command.GetInputFiles())
            {
                AddInputObject(executeContext, resultInputObject, buildStep.Command);
            }

            if (buildStep.Result != null)
            {
                // Step1: Check inputs/outputs conflicts
                foreach (var resultInputObject in buildStep.Result.InputDependencyVersions)
                {
                    CheckInputObject(executeContext, resultInputObject.Key, buildStep.Command);
                }

                foreach (var resultOutputObject in buildStep.Result.OutputObjects)
                {
                    CheckOutputObject(executeContext, resultOutputObject.Key, resultOutputObject.Value, buildStep.Command);
                }

                // Step2: Add inputs/outputs
                foreach (var resultInputObject in buildStep.Result.InputDependencyVersions)
                {
                    AddInputObject(executeContext, resultInputObject.Key, buildStep.Command);
                }

                foreach (var resultOutputObject in buildStep.Result.OutputObjects)
                {
                    AddOutputObject(executeContext, resultOutputObject.Key, resultOutputObject.Value, buildStep.Command);
                }
            }

            // Process recursively
            // TODO: Wait for completion of spawned step in case Task didn't wait for them
            foreach (var spawnedStep in buildStep.SpawnedSteps)
            {
                ProcessCommandBuildStepResult(executeContext, spawnedStep);
            }

            if (buildStep.Result != null)
            {
                // Resolve tags from TagSymbol
                // TODO: Handle removed tags
                foreach (var tagGroup in buildStep.Result
                         .TagSymbols
                         .Where(x => buildStep.Command.TagSymbols.ContainsKey(x.Value))
                         .GroupBy(x => x.Key, x => buildStep.Command.TagSymbols[x.Value].RealName))
                {
                    var url = tagGroup.Key;

                    // TODO: Improve search complexity?
                    OutputObject outputObject;
                    if (outputObjects.TryGetValue(url, out outputObject))
                    {
                        outputObject.Tags.UnionWith(tagGroup);
                    }
                }
            }
        }
        /// <summary>
        /// Wait for given build steps to finish, then processes their inputs and outputs.
        /// </summary>
        /// <param name="executeContext">The execute context.</param>
        /// <param name="buildStepsToWait">The build steps to wait.</param>
        /// <returns></returns>
        protected async Task CompleteCommands(IExecuteContext executeContext, List <BuildStep> buildStepsToWait)
        {
            // Wait for steps to be finished
            if (buildStepsToWait.Count > 0)
            {
                await Task.WhenAll(buildStepsToWait.Select(x => x.ExecutedAsync()));
            }

            // Wait for spawned steps to be finished
            await Task.WhenAll(buildStepsToWait.SelectMany(EnumerateSpawnedBuildSteps).Select(x => x.ExecutedAsync()));

            // TODO: Merge results of sub lists
            foreach (var buildStep in buildStepsToWait)
            {
                var enumerableBuildStep = buildStep as EnumerableBuildStep;
                if (enumerableBuildStep != null)
                {
                    // Merge results from sub list

                    // Step1: Check inputs/outputs conflicts
                    foreach (var inputObject in enumerableBuildStep.inputObjects)
                    {
                        CheckInputObject(executeContext, inputObject.Key, inputObject.Value.Command);
                    }

                    foreach (var outputObject in enumerableBuildStep.OutputObjects)
                    {
                        CheckOutputObject(executeContext, outputObject.Key, outputObject.Value.ObjectId, outputObject.Value.Command);
                    }

                    // Step2: Add inputs/outputs
                    foreach (var inputObject in enumerableBuildStep.inputObjects)
                    {
                        AddInputObject(executeContext, inputObject.Key, inputObject.Value.Command);
                    }

                    foreach (var outputObject in enumerableBuildStep.OutputObjects)
                    {
                        var newOutputObject = AddOutputObject(executeContext, outputObject.Key, outputObject.Value.ObjectId, outputObject.Value.Command);

                        // Merge tags
                        foreach (var tag in outputObject.Value.Tags)
                        {
                            newOutputObject.Tags.Add(tag);
                        }
                    }
                }

                var commandBuildStep = buildStep as CommandBuildStep;
                if (commandBuildStep != null)
                {
                    // Merge results from spawned step
                    ProcessCommandBuildStepResult(executeContext, commandBuildStep);
                }
            }

            buildStepsToWait.Clear();
            mergeCounter++;
        }
Exemple #16
0
        public override void Clean(IExecuteContext executeContext, BuilderContext builderContext, bool deleteOutput)
        {
            // try to retrieve result from one of the object store
            var commandHash = Command.ComputeCommandHash(executeContext);

            // If there was an error computing the hash, early exit
            if (commandHash == ObjectId.Empty)
            {
                return;
            }

            var commandResultsFileStream = executeContext.ResultMap.OpenStream(commandHash, VirtualFileMode.OpenOrCreate, VirtualFileAccess.ReadWrite, VirtualFileShare.ReadWrite);
            var commandResultEntries     = new ListStore <CommandResultEntry>(commandResultsFileStream)
            {
                AutoLoadNewValues = false
            };

            commandResultEntries.LoadNewValues();
            commandResultsFileStream.Close();

            CommandResultEntry matchingResult = FindMatchingResult(executeContext, commandResultEntries.GetValues());

            if (matchingResult != null)
            {
                if (deleteOutput)
                {
                    foreach (KeyValuePair <ObjectUrl, ObjectId> outputObject in matchingResult.OutputObjects)
                    {
                        switch (outputObject.Key.Type)
                        {
                        case UrlType.File:
                            try
                            {
                                if (File.Exists(outputObject.Key.Path))
                                {
                                    File.Delete(outputObject.Key.Path);
                                }
                            }
                            catch (Exception)
                            {
                                executeContext.Logger.Error("Unable to delete file: " + outputObject.Key.Path);
                            }
                            break;

                        case UrlType.ContentLink:
                        case UrlType.Content:
                            executeContext.ResultMap.Delete(outputObject.Value);
                            break;
                        }
                    }
                }
                foreach (CommandBuildStep spawnedStep in matchingResult.SpawnedCommands.Select(spawnedCommand => new CommandBuildStep(spawnedCommand)))
                {
                    spawnedStep.Clean(executeContext, builderContext, deleteOutput);
                }
            }

            executeContext.ResultMap.Delete(commandHash);
        }
Exemple #17
0
 protected async Task RunStep(IActionContext actionContext, int index, object item, IIdGenService idGenService, IActionExecuterService actionExecuterService)
 {
     _ = actionExecuterService ?? throw new ArgumentNullException(nameof(actionExecuterService));
     _ = actionContext ?? throw new ArgumentNullException(nameof(actionContext));
     _ = idGenService ?? throw new ArgumentNullException(nameof(idGenService));
     IExecuteContext executeContext = this.OnCreateExecuteContext(actionContext, idGenService, index, item);
     var             result         = await actionExecuterService.Execute(executeContext);
 }
 public override Task <ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
 {
     foreach (var message in messages)
     {
         executeContext.Logger.Log(message);
     }
     return(Task.FromResult(ResultStatus.Failed));
 }
Exemple #19
0
        public async override Task <ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
        {
            var buildStepsToWait = new List <BuildStep>();

            while (true)
            {
                // interrupt the build if cancellation is required.
                if (executeContext.CancellationTokenSource.Token.IsCancellationRequested)
                {
                    return(ResultStatus.Cancelled);
                }

                // Clean completed build steps
                for (int index = buildStepsToWait.Count - 1; index >= 0; index--)
                {
                    var buildStepToWait = buildStepsToWait[index];
                    if (buildStepToWait.Processed)
                    {
                        buildStepsToWait.RemoveAt(index);
                    }
                }

                // wait for a task to complete
                if (buildStepsToWait.Count >= MaxParallelSteps)
                {
                    await CompleteOneBuildStep(executeContext, buildStepsToWait);
                }

                // Should we check for all tasks or only high priority tasks? (priority < 0)
                bool checkOnlyForHighPriorityTasks = buildStepsToWait.Count >= MaxParallelSteps;

                // Transform item into build step
                var buildStep = buildStepProvider.GetNextBuildStep(checkOnlyForHighPriorityTasks ? -1 : int.MaxValue);

                // No job => passively wait
                if (buildStep == null)
                {
                    newWorkAvailable.WaitOne();
                    continue;
                }

                // Safeguard if the provided build step is already processed
                if (buildStep.Processed)
                {
                    continue;
                }

                if (buildStep is WaitBuildStep)
                {
                    throw new InvalidOperationException("WaitBuildStep are not supported as direct child of DynamicBuildStep");
                }

                // Schedule build step
                executeContext.ScheduleBuildStep(buildStep);
                buildStepsToWait.Add(buildStep);
            }
        }
        public ActivityExecutionResult Execute(IExecuteContext context)
        {
            var mess = new RegisterBotProcessingMessage(BotEngine, BotKey)
            {
                ChatProcessIdentity = ChatProcessIdentity
            };

            context.SendMessage(mess);
            return(ActivityExecutionResult.Complete);
        }
Exemple #21
0
        internal async Task <ResultStatus> SpawnCommand(Command command, IExecuteContext executeContext)
        {
            var spawnedStep = new CommandBuildStep(command);

            SpawnedStepsList.Add(spawnedStep);

            executeContext.ScheduleBuildStep(spawnedStep);
            var resultStatus = (await spawnedStep.ExecutedAsync()).Status;

            return(resultStatus);
        }
Exemple #22
0
 /// <summary>
 ///   Adds the output object. Will try to detect input/output conflicts, and output with different <see cref="ObjectId" /> conflicts.
 /// </summary>
 /// <param name="executeContext">The execute context.</param>
 /// <param name="outputObjectUrl">The output object URL.</param>
 /// <param name="command">The command that produced the output object.</param>
 /// <exception cref="InvalidOperationException">Two <see cref="CommandBuildStep"/> with the same inputs did output different results.</exception>
 private void CheckOutputObject(IExecuteContext executeContext, ObjectUrl outputObjectUrl, Command command)
 {
     if (inputObjects.TryGetValue(outputObjectUrl, out InputObject inputObject) &&
         inputObject.Command != command &&
         inputObject.Counter == mergeCounter)
     {
         var error = $"Command {command} is writing {outputObjectUrl} while command {inputObject.Command} is reading it.";
         executeContext.Logger.Error(error);
         throw new InvalidOperationException(error);
     }
 }
Exemple #23
0
        public override async Task <ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
        {
            Steps = new List <BuildStep>();
            var files = Enumerable.Empty <string>();

            foreach (string pattern in SearchPattern)
            {
                string path        = Path.GetDirectoryName(pattern);
                string filePattern = Path.GetFileName(pattern);
                if (!string.IsNullOrEmpty(path) && !string.IsNullOrEmpty(filePattern))
                {
                    files = files.Concat(Directory.EnumerateFiles(path, filePattern));
                }
                else
                {
                    files = files.Concat(Directory.EnumerateFiles(pattern));
                }
            }

            var excludes = Enumerable.Empty <string>();

            foreach (string pattern in ExcludePattern)
            {
                string path        = Path.GetDirectoryName(pattern);
                string filePattern = Path.GetFileName(pattern);
                if (!string.IsNullOrEmpty(path) && !string.IsNullOrEmpty(filePattern))
                {
                    excludes = excludes.Concat(Directory.EnumerateFiles(path, filePattern));
                }
                else
                {
                    excludes = excludes.Concat(Directory.EnumerateFiles(pattern));
                }
            }

            var buildStepToWait = new List <BuildStep>();

            lock (Files)
            {
                Files = files.Where(x => !excludes.Contains(x));
                foreach (string file in Files)
                {
                    executeContext.Variables["FILE"] = file;
                    var fileBuildStep = Template.Clone();
                    ((List <BuildStep>)Steps).Add(fileBuildStep);
                    buildStepToWait.Add(fileBuildStep);
                    executeContext.ScheduleBuildStep(fileBuildStep);
                }
            }

            await CompleteCommands(executeContext, buildStepToWait);

            return(ResultStatus.Successful);
        }
        public override async Task<ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
        {
            Steps = new List<BuildStep>();
            var files = Enumerable.Empty<string>();

            foreach (string pattern in SearchPattern)
            {
                string path = Path.GetDirectoryName(pattern);
                string filePattern = Path.GetFileName(pattern);
                if (!string.IsNullOrEmpty(path) && !string.IsNullOrEmpty(filePattern))
                {
                    files = files.Concat(Directory.EnumerateFiles(path, filePattern));
                }
                else
                {
                    files = files.Concat(Directory.EnumerateFiles(pattern));
                }
            }

            var excludes = Enumerable.Empty<string>();

            foreach (string pattern in ExcludePattern)
            {
                string path = Path.GetDirectoryName(pattern);
                string filePattern = Path.GetFileName(pattern);
                if (!string.IsNullOrEmpty(path) && !string.IsNullOrEmpty(filePattern))
                {
                    excludes = excludes.Concat(Directory.EnumerateFiles(path, filePattern));
                }
                else
                {
                    excludes = excludes.Concat(Directory.EnumerateFiles(pattern));
                }
            }

            var buildStepToWait = new List<BuildStep>();
            
            lock (Files)
            {
                Files = files.Where(x => !excludes.Contains(x));
                foreach (string file in Files)
                {
                    executeContext.Variables["FILE"] = file;
                    var fileBuildStep = Template.Clone();
                    ((List<BuildStep>)Steps).Add(fileBuildStep);
                    buildStepToWait.Add(fileBuildStep);
                    executeContext.ScheduleBuildStep(fileBuildStep);
                }
            }

            await CompleteCommands(executeContext, buildStepToWait);

            return ResultStatus.Successful;
        }
Exemple #25
0
        /// <summary>
        /// Adds the output object. Will try to detect input/output conflicts, and output with different <see cref="ObjectId" /> conflicts.
        /// </summary>
        /// <param name="executeContext">The execute context.</param>
        /// <param name="outputObjectUrl">The output object URL.</param>
        /// <param name="outputObjectId">The output object id.</param>
        /// <param name="command">The command that produced the output object.</param>
        /// <exception cref="System.InvalidOperationException">Two CommandBuildStep with same inputs did output different results.</exception>
        private void CheckOutputObject(IExecuteContext executeContext, ObjectUrl outputObjectUrl, ObjectId outputObjectId, Command command)
        {
            InputObject inputObject;

            if (inputObjects.TryGetValue(outputObjectUrl, out inputObject) &&
                inputObject.Command != command &&
                inputObject.Counter == mergeCounter)
            {
                var error = string.Format("Command {0} is writing {1} while command {2} is reading it", command, outputObjectUrl, inputObject.Command);
                executeContext.Logger.Error(error);
                throw new InvalidOperationException(error);
            }
        }
Exemple #26
0
        /// <summary>
        /// Processes the results from a <see cref="CommandBuildStep"/>.
        /// </summary>
        /// <param name="executeContext">The execute context.</param>
        /// <param name="buildStep">The build step.</param>
        private void ProcessCommandBuildStepResult(IExecuteContext executeContext, CommandBuildStep buildStep)
        {
            foreach (var resultInputObject in buildStep.Command.GetInputFiles())
            {
                AddInputObject(resultInputObject, buildStep.Command);
            }

            if (buildStep.Result != null)
            {
                // Step1: Check inputs/outputs conflicts
                foreach (var resultInputObject in buildStep.Result.InputDependencyVersions)
                {
                    CheckInputObject(executeContext, resultInputObject.Key, buildStep.Command);
                }

                foreach (var resultOutputObject in buildStep.Result.OutputObjects)
                {
                    CheckOutputObject(executeContext, resultOutputObject.Key, buildStep.Command);
                }

                // Step2: Add inputs/outputs
                foreach (var resultInputObject in buildStep.Result.InputDependencyVersions)
                {
                    AddInputObject(resultInputObject.Key, buildStep.Command);
                }

                foreach (var resultOutputObject in buildStep.Result.OutputObjects)
                {
                    AddOutputObject(executeContext, resultOutputObject.Key, resultOutputObject.Value, buildStep.Command);
                }
            }

            // Forward logs
            buildStep.Logger.CopyTo(Logger);

            if (buildStep.Result != null)
            {
                // Resolve tags from TagSymbol
                // TODO: Handle removed tags
                foreach (var tag in buildStep.Result.TagSymbols)
                {
                    var url = tag.Key;

                    // TODO: Improve search complexity?
                    if (outputObjects.TryGetValue(url, out var outputObject))
                    {
                        outputObject.Tags.Add(tag.Value);
                    }
                }
            }
        }
        public async override Task <ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
        {
            var buildStepsToWait = new List <BuildStep>();

            while (true)
            {
                // interrupt the build if cancellation is required.
                if (executeContext.CancellationTokenSource.Token.IsCancellationRequested)
                {
                    return(ResultStatus.Cancelled);
                }

                // wait for a task to complete
                if (buildStepsToWait.Count >= MaxParallelism)
                {
                    await CompleteOneBuildStep(executeContext, buildStepsToWait);
                }

                // Transform item into build step
                var buildStep = buildStepProvider.GetNextBuildStep();

                // No job => passively wait
                if (buildStep == null)
                {
                    newWorkAvailable.WaitOne();

                    continue;
                }

                // Safeguard if the provided build step is already processed
                if (buildStep.Processed)
                {
                    continue;
                }

                if (buildStep is WaitBuildStep)
                {
                    // wait for all the task in execution to complete
                    while (buildStepsToWait.Count > 0)
                    {
                        await CompleteOneBuildStep(executeContext, buildStepsToWait);
                    }

                    continue;
                }

                // Schedule build step
                executeContext.ScheduleBuildStep(buildStep);
                buildStepsToWait.Add(buildStep);
            }
        }
Exemple #28
0
        /// <summary>
        ///   Wait for the given build steps to finish, then processes their inputs and outputs.
        /// </summary>
        /// <param name="executeContext">The execute context.</param>
        /// <param name="buildStepsToWait">The build steps to wait.</param>
        /// <returns><see cref="Task"/> wrapping the operation.</returns>
        protected async Task CompleteCommands(IExecuteContext executeContext, List <BuildStep> buildStepsToWait)
        {
            await WaitCommands(buildStepsToWait);

            // TODO: Merge results of sub lists
            foreach (var buildStep in buildStepsToWait)
            {
                var enumerableBuildStep = buildStep as ListBuildStep;
                if (enumerableBuildStep != null)
                {
                    // Merge results from sub list

                    // Step 1: Check inputs/outputs conflicts
                    foreach (var inputObject in enumerableBuildStep.inputObjects)
                    {
                        CheckInputObject(executeContext, inputObject.Key, inputObject.Value.Command);
                    }

                    foreach (var outputObject in enumerableBuildStep.OutputObjects)
                    {
                        CheckOutputObject(executeContext, outputObject.Key, outputObject.Value.Command);
                    }

                    // Step 2: Add inputs/outputs
                    foreach (var inputObject in enumerableBuildStep.inputObjects)
                    {
                        AddInputObject(inputObject.Key, inputObject.Value.Command);
                    }

                    foreach (var outputObject in enumerableBuildStep.OutputObjects)
                    {
                        var newOutputObject = AddOutputObject(executeContext, outputObject.Key, outputObject.Value.ObjectId, outputObject.Value.Command);

                        // Merge tags
                        foreach (var tag in outputObject.Value.Tags)
                        {
                            newOutputObject.Tags.Add(tag);
                        }
                    }
                }

                if (buildStep is CommandBuildStep commandBuildStep)
                {
                    // Merge results from spawned step
                    ProcessCommandBuildStepResult(executeContext, commandBuildStep);
                }
            }

            buildStepsToWait.Clear();
            mergeCounter++;
        }
Exemple #29
0
        public override void Clean(IExecuteContext executeContext, BuilderContext builderContext, bool deleteOutput)
        {
            // try to retrieve result from one of the object store
            var commandHash = Command.ComputeCommandHash(executeContext);
            // If there was an error computing the hash, early exit
            if (commandHash == ObjectId.Empty)
            {
                return;
            }

            var commandResultsFileStream = executeContext.ResultMap.OpenStream(commandHash, VirtualFileMode.OpenOrCreate, VirtualFileAccess.ReadWrite, VirtualFileShare.ReadWrite);
            var commandResultEntries = new ListStore<CommandResultEntry>(commandResultsFileStream) { AutoLoadNewValues = false };
            commandResultEntries.LoadNewValues();
            commandResultsFileStream.Close();

            CommandResultEntry matchingResult = FindMatchingResult(executeContext, commandResultEntries.GetValues());
            if (matchingResult != null)
            {
                if (deleteOutput)
                {
                    foreach (KeyValuePair<ObjectUrl, ObjectId> outputObject in matchingResult.OutputObjects)
                    {
                        switch (outputObject.Key.Type)
                        {
                            case UrlType.File:
                                try
                                {
                                    if (File.Exists(outputObject.Key.Path))
                                        File.Delete(outputObject.Key.Path);
                                }
                                catch (Exception)
                                {
                                    executeContext.Logger.Error("Unable to delete file: " + outputObject.Key.Path);
                                }
                                break;
                            case UrlType.ContentLink:
                            case UrlType.Content:
                                executeContext.ResultMap.Delete(outputObject.Value);
                                break;
                        }
                    }
                }
                foreach (CommandBuildStep spawnedStep in matchingResult.SpawnedCommands.Select(spawnedCommand => new CommandBuildStep(spawnedCommand)))
                {
                    spawnedStep.Clean(executeContext, builderContext, deleteOutput);
                }
            }

            executeContext.ResultMap.Delete(commandHash);
        }
        public async override Task<ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
        {
            var buildStepsToWait = new List<BuildStep>();

            while (true)
            {
                // interrupt the build if cancellation is required.
                if (executeContext.CancellationTokenSource.Token.IsCancellationRequested)
                    return ResultStatus.Cancelled;

                // Clean completed build steps
                for (int index = buildStepsToWait.Count - 1; index >= 0; index--)
                {
                    var buildStepToWait = buildStepsToWait[index];
                    if (buildStepToWait.Processed)
                        buildStepsToWait.RemoveAt(index);
                }

                // wait for a task to complete
                if (buildStepsToWait.Count >= MaxParallelSteps)
                    await CompleteOneBuildStep(executeContext, buildStepsToWait);

                // Should we check for all tasks or only high priority tasks? (priority < 0)
                bool checkOnlyForHighPriorityTasks = buildStepsToWait.Count >= MaxParallelSteps;

                // Transform item into build step
                var buildStep = buildStepProvider.GetNextBuildStep(checkOnlyForHighPriorityTasks ? -1 : int.MaxValue);

                // No job => passively wait
                if (buildStep == null)
                {
                    newWorkAvailable.WaitOne();
                    continue;
                }

                // Safeguard if the provided build step is already processed
                if(buildStep.Processed)
                    continue;

                if (buildStep is WaitBuildStep)
                {
                    throw new InvalidOperationException("WaitBuildStep are not supported as direct child of DynamicBuildStep");
                }

                // Schedule build step
                executeContext.ScheduleBuildStep(buildStep);
                buildStepsToWait.Add(buildStep);
            }
        }
Exemple #31
0
        private void AddInputObject(IExecuteContext executeContext, ObjectUrl inputObjectUrl, Command command)
        {
            OutputObject outputObject;

            if (outputObjects.TryGetValue(inputObjectUrl, out outputObject) &&
                mergeCounter > outputObject.Counter)
            {
                // Object was outputed by ourself, so reading it as input should be ignored.
                return;
            }

            inputObjects[inputObjectUrl] = new InputObject {
                Command = command, Counter = mergeCounter
            };
        }
Exemple #32
0
            public override Task <ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
            {
                // check the status of the import build steps
                if (((ListBuildStep)Parent).Steps.Any(s => s.Failed))
                {
                    return(Task.FromResult(ResultStatus.Successful));
                }

                // Mark System projects as loaded
                foreach (var projectId in importedProjectIds)
                {
                    cachedProject.Add(projectId);
                }

                return(Task.FromResult(ResultStatus.Successful));
            }
Exemple #33
0
 protected virtual IActionContext OnCreateActionContext(IExecuteContext executeContext, IActionName actionName, IActionRuntime actionRuntime, IActionMeta actionMeta)
 {
     _ = executeContext ?? throw new ArgumentNullException(nameof(executeContext));
     return(new ActionContext()
     {
         ExecutePath = executeContext.ExecutePath,
         Token = executeContext.Token,
         MetaInfo = actionMeta,
         RuntimeInfo = actionRuntime,
         ExecuteName = executeContext.ExecuteName,
         ServiceProvider = this.serviceProvider,
         Parameters = this.ConvertParameter(actionMeta, executeContext.ExecuteParameter),
         Logger = new ActionLogger(),
         Name = actionName
     });
 }
        public ActivityExecutionResult Execute(IExecuteContext context)
        {
            if (context.IsContinue)
            {
                return(ActivityExecutionResult.Complete);
            }
            var book = context.SetBookmark();
            var ch   = Guid.Parse(context.Resolve(ChatId));
            var mess = new WaitMessageMessage(ch)
            {
                BookmarkId = book,
                BotEngine  = BotEngine,
                BotKey     = BotKey
            };

            context.SendMessage(mess);
            return(ActivityExecutionResult.Idle);
        }
            /// <inheritdoc/>
            public override Task<ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
            {
                var steps = new List<BuildStep>();

                var urlRoot = originalSourcePath.GetParent();

                var stream = new MemoryStream(Encoding.UTF8.GetBytes(((EffectLogAsset)assetItem.Asset).Text));
                using (var recordedEffectCompile = new EffectLogStore(stream))
                {
                    recordedEffectCompile.LoadNewValues();

                    foreach (var entry in recordedEffectCompile.GetValues())
                    {
                        steps.Add(EffectCompileCommand.FromRequest(context, assetItem.Package, urlRoot, entry.Key));
                    }
                }

                Steps = steps;

                return base.Execute(executeContext, builderContext);
            }
        public override async Task<ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
        {
            Steps = new List<BuildStep>();

            var urls = Enumerable.Empty<string>();

            BuildStep parentList = Parent;
            while (!(parentList is ListBuildStep))
            {
                parentList = parentList.Parent;
            }

            var parentListBuildStep = (ListBuildStep)parentList;


            foreach (string tag in SearchTags)
            {
                urls = urls.Concat(parentListBuildStep.OutputObjects.Where(x => x.Value.Tags.Contains(tag)).Select(x => x.Key.ToString()));
            }

            var buildStepToWait = new List<BuildStep>();

            lock (Urls)
            {
                Urls = urls;
                foreach (string url in Urls)
                {
                    executeContext.Variables["URL"] = url;
                    var fileBuildStep = Template.Clone();
                    ((List<BuildStep>)Steps).Add(fileBuildStep);
                    buildStepToWait.Add(fileBuildStep);
                    executeContext.ScheduleBuildStep(fileBuildStep);
                }
            }

            await CompleteCommands(executeContext, buildStepToWait);

            return ResultStatus.Successful;
        }
        private void AddInputObject(IExecuteContext executeContext, ObjectUrl inputObjectUrl, Command command)
        {
            OutputObject outputObject;
            if (outputObjects.TryGetValue(inputObjectUrl, out outputObject)
                && mergeCounter > outputObject.Counter)
            {
                // Object was outputed by ourself, so reading it as input should be ignored.
                return;
            }

            inputObjects[inputObjectUrl] = new InputObject { Command = command, Counter = mergeCounter };
        }
Exemple #38
0
 public override Task<ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
 {
     // Dependencies are done in ListBuildStep, Execute() should never be called directly.
     return Task.FromResult(ResultStatus.Failed);
 }
Exemple #39
0
        /// <summary>
        /// Associate the given <see cref="ResultStatus" /> object as the result of the current step and execute the <see cref="StepProcessed"/> event.
        /// </summary>
        /// <param name="executeContext">The execute context.</param>
        /// <param name="status">The result status.</param>
        internal void RegisterResult(IExecuteContext executeContext, ResultStatus status)
        {
            Status = status;

            //executeContext.Logger.Debug("Step timer for {0}: callbacks: {1}ms, total: {2}ms", this, CallbackWatch.ElapsedMilliseconds, MicroThreadWatch.ElapsedMilliseconds);

            if (StepProcessed != null)
            {
                try
                {
                    IndexFileCommand.MountDatabase(executeContext.GetOutputObjectsGroups());
                    StepProcessed(this, new BuildStepEventArgs(this, executeContext.Logger));
                }
                catch (Exception ex)
                {
                    executeContext.Logger.Error("Exception in command " + this + ": " + ex);
                }
                finally
                {
                    IndexFileCommand.UnmountDatabase();                    
                }
            }
        }
Exemple #40
0
 /// <summary>
 /// Clean the build, deleting the command cache which is used to determine wheither a command has already been executed, and deleting the output objects if asked.
 /// </summary>
 /// <param name="executeContext">The execute context</param>
 /// <param name="builderContext">The builder context</param>
 /// <param name="deleteOutput">if true, every output object is also deleted, in addition of the command cache.</param>
 public virtual void Clean(IExecuteContext executeContext, BuilderContext builderContext, bool deleteOutput)
 {
     // By default, do the same as Execute. This will apply for flow control steps (lists, enumerations...)
     // Specific implementation exists for CommandBuildStep
     Execute(executeContext, builderContext);
 }
Exemple #41
0
 /// <summary>
 /// Execute the BuildStep, usually resulting in scheduling tasks in the scheduler 
 /// </summary>
 /// <param name="executeContext">The execute context</param>
 /// <param name="builderContext">The builder context</param>
 /// <returns>A task returning <see cref="ResultStatus"/> indicating weither the execution has successed or failed.</returns>
 public abstract Task<ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext);
        private async Task CompleteOneBuildStep(IExecuteContext executeContext, List<BuildStep> buildStepsToWait)
        {
            // Too many build steps, wait for one to finish
            var waitHandles = buildStepsToWait.Select(x => ((IAsyncResult)x.ExecutedAsync()).AsyncWaitHandle);

            // Should we listen for new high priority tasks?
            if (buildStepsToWait.Count >= MaxParallelSteps && buildStepsToWait.Count < MaxParallelSteps + MaxHighPriorityParallelSteps)
            {
                waitHandles = waitHandles.Concat(new[] { newWorkAvailable });
            }

            var completedItem = WaitHandle.WaitAny(waitHandles.ToArray());

            var completeBuildStep = completedItem < buildStepsToWait.Count ? buildStepsToWait[completedItem] : null;
            if (completeBuildStep == null)
            {
                // Not an actual task completed, but we've got to check if there is a new high priority task so exit immediatly
                return;
            }

            // wait for completion of all its spawned and dependent steps
            // (probably instant most of the time, but it would be good to have a better ExecutedAsync to check that together as well)
            await WaitCommands(new List<BuildStep> { completeBuildStep });

            // Remove from list of build step to wait
            buildStepsToWait.Remove(completeBuildStep);
        }
 public LocalCommandContext(IExecuteContext executeContext, CommandBuildStep step, BuilderContext builderContext) : base(step.Command, builderContext)
 {
     this.executeContext = executeContext;
     logger = new ForwardingLoggerResult(executeContext.Logger);
     Step = step;
 }
        internal OutputObject AddOutputObject(IExecuteContext executeContext, ObjectUrl outputObjectUrl, ObjectId outputObjectId, Command command)
        {
            OutputObject outputObject;

            if (!outputObjects.TryGetValue(outputObjectUrl, out outputObject))
            {
                // New item?
                outputObject = new OutputObject(outputObjectUrl, outputObjectId);
                outputObjects.Add(outputObjectUrl, outputObject);
            }
            else
            {
                // ObjectId should be similar (if no Wait happened), otherwise two tasks spawned with same parameters did output different results
                if (outputObject.ObjectId != outputObjectId && outputObject.Counter == mergeCounter)
                {
                    var error = string.Format("Commands {0} and {1} are both writing {2} at the same time", command, outputObject.Command, outputObjectUrl);
                    executeContext.Logger.Error(error);
                    throw new InvalidOperationException(error);
                }

                // Update new ObjectId
                outputObject.ObjectId = outputObjectId;
            }

            // Update Counter so that we know if a wait happened since this output object has been merged.
            outputObject.Counter = mergeCounter;
            outputObject.Command = command;

            return outputObject;
        }
 /// <summary>
 /// Adds the output object. Will try to detect input/output conflicts, and output with different <see cref="ObjectId" /> conflicts.
 /// </summary>
 /// <param name="executeContext">The execute context.</param>
 /// <param name="outputObjectUrl">The output object URL.</param>
 /// <param name="outputObjectId">The output object id.</param>
 /// <param name="command">The command that produced the output object.</param>
 /// <exception cref="System.InvalidOperationException">Two CommandBuildStep with same inputs did output different results.</exception>
 private void CheckOutputObject(IExecuteContext executeContext, ObjectUrl outputObjectUrl, ObjectId outputObjectId, Command command)
 {
     InputObject inputObject;
     if (inputObjects.TryGetValue(outputObjectUrl, out inputObject)
         && inputObject.Command != command
         && inputObject.Counter == mergeCounter)
     {
         var error = string.Format("Command {0} is writing {1} while command {2} is reading it", command, outputObjectUrl, inputObject.Command);
         executeContext.Logger.Error(error);
         throw new InvalidOperationException(error);
     }
 }
        /// <summary>
        /// Processes the results from a <see cref="CommandBuildStep"/>.
        /// </summary>
        /// <param name="executeContext">The execute context.</param>
        /// <param name="buildStep">The build step.</param>
        private void ProcessCommandBuildStepResult(IExecuteContext executeContext, CommandBuildStep buildStep)
        {
            foreach (var resultInputObject in buildStep.Command.GetInputFiles())
            {
                AddInputObject(executeContext, resultInputObject, buildStep.Command);
            }

            if (buildStep.Result != null)
            {
                // Step1: Check inputs/outputs conflicts
                foreach (var resultInputObject in buildStep.Result.InputDependencyVersions)
                {
                    CheckInputObject(executeContext, resultInputObject.Key, buildStep.Command);
                }

                foreach (var resultOutputObject in buildStep.Result.OutputObjects)
                {
                    CheckOutputObject(executeContext, resultOutputObject.Key, resultOutputObject.Value, buildStep.Command);
                }

                // Step2: Add inputs/outputs
                foreach (var resultInputObject in buildStep.Result.InputDependencyVersions)
                {
                    AddInputObject(executeContext, resultInputObject.Key, buildStep.Command);
                }

                foreach (var resultOutputObject in buildStep.Result.OutputObjects)
                {
                    AddOutputObject(executeContext, resultOutputObject.Key, resultOutputObject.Value, buildStep.Command);
                }
            }

            // Forward logs
            buildStep.Logger.CopyTo(Logger);

            // Process recursively
            // TODO: Wait for completion of spawned step in case Task didn't wait for them
            foreach (var spawnedStep in buildStep.SpawnedSteps)
            {
                ProcessCommandBuildStepResult(executeContext, spawnedStep);
            }

            if (buildStep.Result != null)
            {
                // Resolve tags from TagSymbol
                // TODO: Handle removed tags
                foreach (var tagGroup in buildStep.Result
                    .TagSymbols
                    .Where(x => buildStep.Command.TagSymbols.ContainsKey(x.Value))
                    .GroupBy(x => x.Key, x => buildStep.Command.TagSymbols[x.Value].RealName))
                {
                    var url = tagGroup.Key;

                    // TODO: Improve search complexity?
                    OutputObject outputObject;
                    if (outputObjects.TryGetValue(url, out outputObject))
                    {
                        outputObject.Tags.UnionWith(tagGroup);
                    }
                }
            }
        }
Exemple #47
0
        public override async Task<ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
        {
            ListStore<CommandResultEntry> commandResultEntries;

            // Prevent several command build step to evaluate wheither they should start at the same time. This increase the efficiency of the builder by avoiding the same command to be executed several time in parallel
            // NOTE: Careful here, there's no try/finally block around the monitor Enter/Exit, so no non-fatal exception is allowed!
            Monitor.Enter(executeContext);
            bool monitorExited = false;
            var status = ResultStatus.NotProcessed;
            // if any external input has changed since the last execution (or if we don't have a successful execution in cache, trigger the command
            CommandResultEntry matchingResult = null;

            try
            {
                ObjectId commandHash;
                {
                    // try to retrieve result from one of the object store
                    commandHash = Command.ComputeCommandHash(executeContext);
                    // Early exit if the hash of the command failed
                    if (commandHash == ObjectId.Empty)
                    {
                        return ResultStatus.Failed;
                    }

                    var commandResultsFileStream = executeContext.ResultMap.OpenStream(commandHash, VirtualFileMode.OpenOrCreate, VirtualFileAccess.ReadWrite, VirtualFileShare.ReadWrite);
                    commandResultEntries = new ListStore<CommandResultEntry>(commandResultsFileStream) { AutoLoadNewValues = false };
                    commandResultEntries.LoadNewValues();
                }

                if (ShouldExecute(executeContext, commandResultEntries.GetValues(), commandHash, out matchingResult))
                {
                    CommandBuildStep stepInProgress = executeContext.IsCommandCurrentlyRunning(commandHash);
                    if (stepInProgress != null)
                    {
                        Monitor.Exit(executeContext);
                        monitorExited = true;
                        executeContext.Logger.Debug("Command {0} delayed because it is currently running...", Command.ToString());
                        status = (await stepInProgress.ExecutedAsync()).Status;
                        matchingResult = stepInProgress.Result;
                    }
                    else
                    {
                        executeContext.NotifyCommandBuildStepStarted(this, commandHash);
                        Monitor.Exit(executeContext);
                        monitorExited = true;

                        executeContext.Logger.Debug("Command {0} scheduled...", Command.ToString());

                        status = await StartCommand(executeContext, commandResultEntries, builderContext);
                        executeContext.NotifyCommandBuildStepFinished(this, commandHash);
                    }
                }
            }
            finally
            {
                if (!monitorExited)
                {
                    Monitor.Exit(executeContext);
                }
            }

            // The command has not been executed
            if (matchingResult != null)
            {
                using (commandResultEntries)
                {
                    // Replicate triggered builds
                    Debug.Assert(SpawnedStepsList.Count == 0);

                    foreach (Command spawnedCommand in matchingResult.SpawnedCommands)
                    {
                        var spawnedStep = new CommandBuildStep(spawnedCommand);
                        SpawnedStepsList.Add(spawnedStep);
                        executeContext.ScheduleBuildStep(spawnedStep);
                    }

                    // Re-output command log messages
                    foreach (var message in matchingResult.LogMessages)
                    {
                        executeContext.Logger.Log(message);
                    }

                    // Wait for all build steps to complete.
                    // TODO: Ideally, we should store and replicate the behavior of the command that spawned it
                    // (wait if it used ScheduleAndExecute, don't wait if it used RegisterSpawnedCommandWithoutScheduling)
                    await Task.WhenAll(SpawnedSteps.Select(x => x.ExecutedAsync()));

                    status = ResultStatus.NotTriggeredWasSuccessful;
                    RegisterCommandResult(commandResultEntries, matchingResult, status);
                }
            }


            return status;
        }
        /// <summary>
        /// Wait for given build steps to finish, then processes their inputs and outputs.
        /// </summary>
        /// <param name="executeContext">The execute context.</param>
        /// <param name="buildStepsToWait">The build steps to wait.</param>
        /// <returns></returns>
        protected async Task CompleteCommands(IExecuteContext executeContext, List<BuildStep> buildStepsToWait)
        {
            await WaitCommands(buildStepsToWait);

            // TODO: Merge results of sub lists
            foreach (var buildStep in buildStepsToWait)
            {
                var enumerableBuildStep = buildStep as EnumerableBuildStep;
                if (enumerableBuildStep != null)
                {
                    // Merge results from sub list

                    // Step1: Check inputs/outputs conflicts
                    foreach (var inputObject in enumerableBuildStep.inputObjects)
                    {
                        CheckInputObject(executeContext, inputObject.Key, inputObject.Value.Command);
                    }

                    foreach (var outputObject in enumerableBuildStep.OutputObjects)
                    {
                        CheckOutputObject(executeContext, outputObject.Key, outputObject.Value.ObjectId, outputObject.Value.Command);
                    }

                    // Step2: Add inputs/outputs
                    foreach (var inputObject in enumerableBuildStep.inputObjects)
                    {
                        AddInputObject(executeContext, inputObject.Key, inputObject.Value.Command);
                    }

                    foreach (var outputObject in enumerableBuildStep.OutputObjects)
                    {
                        var newOutputObject = AddOutputObject(executeContext, outputObject.Key, outputObject.Value.ObjectId, outputObject.Value.Command);

                        // Merge tags
                        foreach (var tag in outputObject.Value.Tags)
                        {
                            newOutputObject.Tags.Add(tag);
                        }
                    }
                }

                var commandBuildStep = buildStep as CommandBuildStep;
                if (commandBuildStep != null)
                {
                    // Merge results from spawned step
                    ProcessCommandBuildStepResult(executeContext, commandBuildStep);
                }
            }

            buildStepsToWait.Clear();
            mergeCounter++;
        }
Exemple #49
0
        internal async Task<ResultStatus> SpawnCommand(Command command, IExecuteContext executeContext)
        {
            var spawnedStep = new CommandBuildStep(command);
            SpawnedStepsList.Add(spawnedStep);

            executeContext.ScheduleBuildStep(spawnedStep);
            var resultStatus = (await spawnedStep.ExecutedAsync()).Status;

            return resultStatus;
        }
Exemple #50
0
        private async Task<ResultStatus> StartCommand(IExecuteContext executeContext, ListStore<CommandResultEntry> commandResultEntries, BuilderContext builderContext)
        {
            var logger = executeContext.Logger;

            // Register the cancel callback
            var cancellationTokenSource = executeContext.CancellationTokenSource;
            cancellationTokenSource.Token.Register(x => ((Command)x).Cancel(), Command);

            Command.CancellationToken = cancellationTokenSource.Token;

            //await Scheduler.Yield();

            ResultStatus status;

            using (commandResultEntries)
            {
                logger.Debug("Starting command {0}...", Command.ToString());

                // Creating the CommandResult object
                var commandContext = new LocalCommandContext(executeContext, this, builderContext);

                // Actually processing the command
                if (Command.ShouldSpawnNewProcess() && builderContext.MaxParallelProcesses > 0)
                {
                    while (!builderContext.CanSpawnParallelProcess())
                    {
                        await Task.Delay(1, Command.CancellationToken);
                    }

                    var address = "net.pipe://localhost/" + Guid.NewGuid();
                    var arguments = string.Format("--slave=\"{0}\" --build-path=\"{1}\" --profile=\"{2}\"", address, builderContext.BuildPath, builderContext.BuildProfile);

                    var startInfo = new ProcessStartInfo
                        {
                            FileName = builderContext.SlaveBuilderPath,
                            Arguments = arguments,
                            WorkingDirectory = Environment.CurrentDirectory,
                            CreateNoWindow = true,
                            UseShellExecute = false,
                            RedirectStandardOutput = true,
                            RedirectStandardError = true,
                        };

                    // Start WCF pipe for communication with process
                    var processBuilderRemote = new ProcessBuilderRemote(commandContext, Command, builderContext.Parameters);
                    var host = new ServiceHost(processBuilderRemote);
                    host.AddServiceEndpoint(typeof(IProcessBuilderRemote), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None) { MaxReceivedMessageSize = int.MaxValue }, address);
                    host.Open();

                    var output = new List<string>();

                    var process = new Process { StartInfo = startInfo };
                    process.Start();
                    process.OutputDataReceived += (_, args) => LockProcessAndAddDataToList(process, output, args);
                    process.ErrorDataReceived += (_, args) => LockProcessAndAddDataToList(process, output, args);
                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();

                    // Attach debugger to newly created process
                    // Add a reference to EnvDTE80 in the csproj and uncomment this (and also the Thread.Sleep in BuildEngineCmmands), then start the master process without debugger to attach to a slave.
                    //var dte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.11.0");
                    //foreach (EnvDTE.Process dteProcess in dte.Debugger.LocalProcesses)
                    //{
                    //    if (dteProcess.ProcessID == process.Id)
                    //    {
                    //        dteProcess.Attach();
                    //        dte.Debugger.CurrentProcess = dteProcess;
                    //    }
                    //}

                    Task[] tasksToWait = null;

                    while (!process.HasExited)
                    {
                        Thread.Sleep(1);
                        lock (spawnedCommandsToWait)
                        {
                            if (spawnedCommandsToWait.Count > 0)
                            {
                                tasksToWait = spawnedCommandsToWait.ToArray();
                                spawnedCommandsToWait.Clear();
                            }
                        }

                        if (tasksToWait != null)
                        {
                            await Task.WhenAll(tasksToWait);
                            tasksToWait = null;
                        }
                    }
                    host.Close();

                    builderContext.NotifyParallelProcessEnded();

                    if (process.ExitCode != 0)
                    {
                        logger.Debug("Remote command crashed with output:\n{0}", string.Join(Environment.NewLine, output));
                    }

                    if (processBuilderRemote.Result != null)
                    {
                        // Register results back locally
                        foreach (var outputObject in processBuilderRemote.Result.OutputObjects)
                        {
                            commandContext.RegisterOutput(outputObject.Key, outputObject.Value);
                        }

                        // Register log messages
                        foreach (var logMessage in processBuilderRemote.Result.LogMessages)
                        {
                            commandContext.Logger.Log(logMessage);
                        }

                        // Register tags
                        foreach (var tag in processBuilderRemote.Result.TagSymbols)
                        {
                            TagSymbol tagSymbol;

                            // Resolve tag locally
                            if (!Command.TagSymbols.TryGetValue(tag.Value, out tagSymbol))
                            {
                                // Should we ignore silently? (with warning)
                                throw new InvalidOperationException("Could not find tag symbol.");
                            }

                            commandContext.AddTag(tag.Key, tagSymbol);
                        }
                    }

                    status = Command.CancellationToken.IsCancellationRequested ? ResultStatus.Cancelled : (process.ExitCode == 0 ? ResultStatus.Successful : ResultStatus.Failed);
                }
                else
                {
                    Command.PreCommand(commandContext);
                    if (!Command.BasePreCommandCalled)
                        throw new InvalidOperationException("base.PreCommand not called in command " + Command);

                    try
                    {
                        status = await Command.DoCommand(commandContext);
                    }
                    catch (Exception ex)
                    {
                        executeContext.Logger.Error("Exception in command " + this + ": " + ex);
                        status = ResultStatus.Failed;
                    }

                    Command.PostCommand(commandContext, status);
                    if (!Command.BasePostCommandCalled)
                        throw new InvalidOperationException("base.PostCommand not called in command " + Command);
                }

                // Ensure the command set at least the result status
                if (status == ResultStatus.NotProcessed)
                    throw new InvalidDataException("The command " + Command + " returned ResultStatus.NotProcessed after completion.");

                // Registering the result to the build cache
                RegisterCommandResult(commandResultEntries, commandContext.ResultEntry, status);
            }

            return status;
        }
Exemple #51
0
        internal bool ShouldExecute(IExecuteContext executeContext, CommandResultEntry[] previousResultCollection, ObjectId commandHash, out CommandResultEntry matchingResult)
        {
            IndexFileCommand.MountDatabase(executeContext.GetOutputObjectsGroups());
            try
            {
                matchingResult = FindMatchingResult(executeContext, previousResultCollection);
            }
            finally
            {
                IndexFileCommand.UnmountDatabase();
            }

            if (matchingResult == null || Command.ShouldForceExecution())
            {
                // Ensure we ignore existing results if the execution is forced
                matchingResult = null;
                return true;
            }

            return false;
        }