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); }
/// <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)); }
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 }); }
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); } }
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()); }
public bool DeleteByQuery(IExecuteContext <T> context) { this.CurrentContext = context; int result = DataBase.Execute(GetExecuteContainer()); return(result > 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); }
public long Count(IExecuteContext <T> context) { this.CurrentContext = context; long count = DataBase.ExecuteScalar <long>(GetExecuteContainer()); return(count); }
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(); }
/// <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++; }
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); }
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)); }
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); }
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); }
/// <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); } }
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; }
/// <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(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); } }
/// <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++; }
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); } }
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 }; }
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)); }
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; }
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); }
/// <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(); } } }
/// <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); }
/// <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> /// 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); } } } }
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++; }
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; }
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; }
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; }