public void ListSimple() { using (var tempFile = new TemporaryFile()) using (var store2 = new ListStore <int>(VirtualFileSystem.OpenStream(tempFile.Path, VirtualFileMode.OpenOrCreate, VirtualFileAccess.ReadWrite, VirtualFileShare.ReadWrite))) using (var store1 = new ListStore <int>(VirtualFileSystem.OpenStream(tempFile.Path, VirtualFileMode.OpenOrCreate, VirtualFileAccess.ReadWrite, VirtualFileShare.ReadWrite))) { store1.UseTransaction = true; // Add a value to store2 and saves it store2.AddValue(1); store2.Save(); // Add a value to store1 without saving store1.AddValue(2); Assert.AreEqual(new[] { 2 }, store1.GetValues()); // Check that store1 contains value from store2 first store1.LoadNewValues(); Assert.AreEqual(new[] { 1, 2 }, store1.GetValues()); // Save and check that results didn't change store1.Save(); Assert.AreEqual(new[] { 1, 2 }, store1.GetValues()); } }
public void ListSimple() { using (var tempFile = new TemporaryFile()) using (var store2 = new ListStore<int>(VirtualFileSystem.OpenStream(tempFile.Path, VirtualFileMode.OpenOrCreate, VirtualFileAccess.ReadWrite, VirtualFileShare.ReadWrite))) using (var store1 = new ListStore<int>(VirtualFileSystem.OpenStream(tempFile.Path, VirtualFileMode.OpenOrCreate, VirtualFileAccess.ReadWrite, VirtualFileShare.ReadWrite))) { store1.UseTransaction = true; // Add a value to store2 and saves it store2.AddValue(1); store2.Save(); // Add a value to store1 without saving store1.AddValue(2); Assert.AreEqual(new[] { 2 }, store1.GetValues()); // Check that store1 contains value from store2 first store1.LoadNewValues(); Assert.AreEqual(new[] { 1, 2 }, store1.GetValues()); // Save and check that results didn't change store1.Save(); Assert.AreEqual(new[] { 1, 2 }, store1.GetValues()); } }
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 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 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()); // Register the cancel callback var cancellationTokenSource = executeContext.CancellationTokenSource; cancellationTokenSource.Token.Register(x => ((Command)x).Cancel(), Command); Command.CancellationToken = cancellationTokenSource.Token; try { status = await StartCommand(executeContext, commandResultEntries, builderContext); } finally { // Restore cancellation token (to avoid memory leak due to previous CancellationToken.Register Command.CancellationToken = CancellationToken.None; } 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); }
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; }
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); ObjectId commandHash; //await Task.Factory.StartNew(() => { // try to retrieve result from one of the object store commandHash = Command.ComputeCommandHash(executeContext); var commandResultsFileStream = executeContext.ResultMap.OpenStream(commandHash, VirtualFileMode.OpenOrCreate, VirtualFileAccess.ReadWrite, VirtualFileShare.ReadWrite); commandResultEntries = new ListStore <CommandResultEntry>(commandResultsFileStream) { AutoLoadNewValues = false }; commandResultEntries.LoadNewValues(); } //); // 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; var status = ResultStatus.NotProcessed; if (ShouldExecute(executeContext, commandResultEntries.GetValues(), commandHash, out matchingResult)) { CommandBuildStep stepInProgress = executeContext.IsCommandCurrentlyRunning(commandHash); if (stepInProgress != null) { Monitor.Exit(executeContext); 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); executeContext.Logger.Debug("Command {0} scheduled...", Command.ToString()); status = await StartCommand(executeContext, commandResultEntries, builderContext); executeContext.NotifyCommandBuildStepFinished(this, commandHash); } } else { Monitor.Exit(executeContext); } // The command has not been executed if (matchingResult != null) { using (commandResultEntries) { // the command was not started because it is already up-to-date (retrieved from cache and no change in external files since last execution) executeContext.Logger.Verbose("Command {0} is up-to-date, skipping...", Command.ToString()); // 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); } // 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); }