Beispiel #1
0
 protected CommandContextBase(Command command, BuilderContext builderContext)
 {
     CurrentCommand   = command;
     BuildParameters  = builderContext.Parameters;
     ResultEntry      = new CommandResultEntry();
     MetadataProvider = builderContext.MetadataProvider;
 }
 protected CommandContextBase(Command command, BuilderContext builderContext)
 {
     CurrentCommand = command;
     BuildParameters = builderContext.Parameters;
     ResultEntry = new CommandResultEntry();
     MetadataProvider = builderContext.MetadataProvider;
 }
Beispiel #3
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);
        }
Beispiel #4
0
        private void RegisterCommandResult(ListStore <CommandResultEntry> commandResultEntries, CommandResultEntry result, ResultStatus status)
        {
            //foreach (var outputObject in result.OutputObjects.Where(outputObject => outputObject.Key.Type == UrlType.Internal))
            //{
            //    builderContext.AssetIndexMap[outputObject.Key.Path] = outputObject.Value;
            //}

            Result = result;

            // Only save to build cache if compilation was done and successful
            if (status == ResultStatus.Successful)
            {
                commandResultEntries.AddValue(result);
            }
        }
Beispiel #5
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);
        }
Beispiel #6
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());

                        // 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);
        }
Beispiel #7
0
        internal CommandResultEntry FindMatchingResult(IPrepareContext prepareContext, CommandResultEntry[] commandResultCollection)
        {
            if (commandResultCollection == null)
                return null;

            // Then check input dependencies and output versions
            //builderContext.AssetIndexMap.LoadNewValues();

            foreach (CommandResultEntry entry in commandResultCollection)
            {
                bool entryMatch = true;

                foreach (var inputDepVersion in entry.InputDependencyVersions)
                {
                    var hash = prepareContext.ComputeInputHash(inputDepVersion.Key.Type, inputDepVersion.Key.Path);
                    if (hash != inputDepVersion.Value)
                    {
                        entryMatch = false;
                        break;
                    }
                }

                if (!entryMatch)
                    continue;

                if (entry.OutputObjects.Any(outputObject => !VirtualFileSystem.FileExists(FileOdbBackend.BuildUrl(VirtualFileSystem.ApplicationDatabasePath, outputObject.Value))))
                {
                    entryMatch = false;
                }

                if (!entryMatch)
                    continue;

                // TODO/Benlitz: check matching spawned commands if needed

                return entry;
            }

            return null;
        }
Beispiel #8
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;
        }
Beispiel #9
0
        private void RegisterCommandResult(ListStore<CommandResultEntry> commandResultEntries, CommandResultEntry result, ResultStatus status)
        {
            //foreach (var outputObject in result.OutputObjects.Where(outputObject => outputObject.Key.Type == UrlType.Internal))
            //{
            //    builderContext.AssetIndexMap[outputObject.Key.Path] = outputObject.Value;
            //}

            Result = result;

            // Only save to build cache if compilation was done and successful
            if (status == ResultStatus.Successful)
            {
                commandResultEntries.AddValue(result);
            }
        }
        internal bool ShouldExecute(IExecuteContext executeContext, CommandResultEntry[] previousResultCollection, ObjectId commandHash, out CommandResultEntry matchingResult)
        {
            IEnumerable <IDictionary <ObjectUrl, OutputObject> > outputObjectsGroups = executeContext.GetOutputObjectsGroups();

            MicrothreadLocalDatabases.MountDatabase(outputObjectsGroups);
            try
            {
                matchingResult = FindMatchingResult(executeContext, previousResultCollection);
            }
            finally
            {
                MicrothreadLocalDatabases.UnmountDatabase();
            }

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

            return(false);
        }
 public void RegisterResult(CommandResultEntry commandResult)
 {
     Result = commandResult;
 }
Beispiel #12
0
 public void RegisterResult(CommandResultEntry commandResult)
 {
     Result = commandResult;
 }
Beispiel #13
0
 protected CommandContextBase(Command command, BuilderContext builderContext)
 {
     CurrentCommand = command;
     ResultEntry    = new CommandResultEntry();
 }