Exemple #1
0
 public BuilderContext(string buildPath, string buildProfile, FileVersionTracker inputHashes, int maxParallelProcess, string slaveBuilderPath)
 {
     BuildPath            = buildPath;
     BuildProfile         = buildProfile;
     InputHashes          = inputHashes;
     SlaveBuilderPath     = slaveBuilderPath;
     MaxParallelProcesses = maxParallelProcess;
 }
Exemple #2
0
        /// <summary>
        /// Loads previous versions stored from the specified file path.
        /// </summary>
        /// <param name="filePath">The file path.</param>
        /// <returns>FileVersionTracker.</returns>
        public static FileVersionTracker Load(string filePath)
        {
            // Try to compact it before using it
            FileVersionStorage.Compact(filePath);

            bool isFirstPass = true;

            while (true)
            {
                FileStream fileStream = null;

                // Try to open the file, if we get an exception, this might be due only because someone is locking the file to
                // save it while we are trying to open it
                const int RetryOpenFileStream = 20;
                var       random = new Random();
                for (int i = 0; i < RetryOpenFileStream; i++)
                {
                    try
                    {
                        fileStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
                        break;
                    }
                    catch (Exception)
                    {
                        if ((i + 1) == RetryOpenFileStream)
                        {
                            throw;
                        }

                        Thread.Sleep(50 + random.Next(100));
                    }
                }

                var tracker = new FileVersionTracker(fileStream);
                try
                {
                    tracker.storage.LoadNewValues();
                    return(tracker);
                }
                catch (Exception)
                {
                    // If an exception occurred, we are going to try to recover from it by reseting it.
                    // reset file length to 0
                    fileStream.SetLength(0);
                    tracker.Dispose();
                    if (!isFirstPass)
                    {
                        throw;
                    }
                }
                isFirstPass = false;
            }
        }
Exemple #3
0
        /// <summary>
        /// Gets the default file version tracker for this machine.
        /// </summary>
        /// <returns>FileVersionTracker.</returns>
        public static FileVersionTracker GetDefault()
        {
            lock (lockDefaultTracker)
            {
                if (defaultFileVersionTracker == null)
                {
                    var filePath  = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), DefaultFileVersionTrackerFile);
                    var directory = Path.GetDirectoryName(filePath);
                    if (directory != null && !Directory.Exists(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }

                    // Loads the file version cache
                    defaultFileVersionTracker = Load(filePath);
                }
            }
            return(defaultFileVersionTracker);
        }
Exemple #4
0
        /// <summary>
        /// Runs this instance.
        /// </summary>
        public BuildResultCode Run(Mode mode, bool writeIndexFile = true, bool enableMonitor = true)
        {
            // When we setup the database ourself we have to take responsibility to close it after
            var shouldCloseDatabase = ObjectDatabase == null;

            OpenObjectDatabase(buildPath, indexName);

            PreRun();

            runMode = mode;

            if (IsRunning)
            {
                throw new InvalidOperationException("An instance of this Builder is already running.");
            }

            // reset build cache from previous build run
            var parameters = new BuildParameterCollection();

            cancellationTokenSource = new CancellationTokenSource();
            Cancelled = false;
            IsRunning = true;
            DisableCompressionIds.Clear();

            // Reseting result map
            var inputHashes = FileVersionTracker.GetDefault();

            {
                var builderContext = new BuilderContext(buildPath, buildProfile, inputHashes, parameters, MaxParallelProcesses, SlaveBuilderPath);

                resultMap = ObjectDatabase;

                scheduler = new Scheduler();
                if (enableMonitor)
                {
                    threadMonitors.Add(new BuildThreadMonitor(scheduler, BuilderId));
                    foreach (var monitorPipeName in MonitorPipeNames)
                    {
                        threadMonitors.Add(new BuildThreadMonitor(scheduler, BuilderId, monitorPipeName));
                    }

                    foreach (var threadMonitor in threadMonitors)
                    {
                        threadMonitor.Start();
                    }
                }

                // Schedule the build
                ScheduleBuildStep(builderContext, null, Root, InitialVariables);

                // Create threads
                var threads = Enumerable.Range(0, ThreadCount).Select(x => new Thread(SafeAction.Wrap(RunUntilEnd))
                {
                    IsBackground = true
                }).ToArray();

                // Start threads
                int threadId = 0;
                foreach (var thread in threads)
                {
                    thread.Name = (BuilderName ?? "Builder") + " worker thread " + (++threadId);
                    thread.Start();
                }

                // Wait for all threads to finish
                foreach (var thread in threads)
                {
                    thread.Join();
                }

                foreach (var threadMonitor in threadMonitors)
                {
                    threadMonitor.Finish();
                }

                foreach (var threadMonitor in threadMonitors)
                {
                    threadMonitor.Join();
                }
            }

            threadMonitors.Clear();
            BuildResultCode result;

            if (runMode == Mode.Build)
            {
                if (cancellationTokenSource.IsCancellationRequested)
                {
                    Logger.Error("Build cancelled.");
                    result = BuildResultCode.Cancelled;
                }
                else if (stepCounter.Get(ResultStatus.Failed) > 0 || stepCounter.Get(ResultStatus.NotTriggeredPrerequisiteFailed) > 0)
                {
                    Logger.Error("Build finished in {0} steps. Command results: {1} succeeded, {2} up-to-date, {3} failed, {4} not triggered due to previous failure.",
                                 stepCounter.Total, stepCounter.Get(ResultStatus.Successful), stepCounter.Get(ResultStatus.NotTriggeredWasSuccessful),
                                 stepCounter.Get(ResultStatus.Failed), stepCounter.Get(ResultStatus.NotTriggeredPrerequisiteFailed));

                    Logger.Error("Build failed.");
                    result = BuildResultCode.BuildError;
                }
                else
                {
                    Logger.Info("Build finished in {0} steps. Command results: {1} succeeded, {2} up-to-date, {3} failed, {4} not triggered due to previous failure.",
                                stepCounter.Total, stepCounter.Get(ResultStatus.Successful), stepCounter.Get(ResultStatus.NotTriggeredWasSuccessful),
                                stepCounter.Get(ResultStatus.Failed), stepCounter.Get(ResultStatus.NotTriggeredPrerequisiteFailed));

                    Logger.Info("Build is successful.");
                    result = BuildResultCode.Successful;
                }
            }
            else
            {
                string modeName;
                switch (runMode)
                {
                case Mode.Clean:
                    modeName = "Clean";
                    break;

                case Mode.CleanAndDelete:
                    modeName = "Clean-and-delete";
                    break;

                default:
                    throw new InvalidOperationException("Builder executed in unknown mode.");
                }

                if (cancellationTokenSource.IsCancellationRequested)
                {
                    Logger.Error(modeName + " has been cancelled.");
                    result = BuildResultCode.Cancelled;
                }
                else if (stepCounter.Get(ResultStatus.Failed) > 0 || stepCounter.Get(ResultStatus.NotTriggeredPrerequisiteFailed) > 0)
                {
                    Logger.Error(modeName + " has failed.");
                    result = BuildResultCode.BuildError;
                }
                else
                {
                    Logger.Error(modeName + " has been successfully completed.");
                    result = BuildResultCode.Successful;
                }
            }
            scheduler = null;
            resultMap = null;
            IsRunning = false;

            if (shouldCloseDatabase)
            {
                CloseObjectDatabase();
            }

            return(result);
        }
Exemple #5
0
        /// <summary>
        /// Runs this instance.
        /// </summary>
        public BuildResultCode Run(Mode mode, bool writeIndexFile = true, bool enableMonitor = true)
        {
            runMode = mode;

            if (IsRunning)
            {
                throw new InvalidOperationException("An instance of this Builder is already running.");
            }

            // reset build cache from previous build run
            var parameters = new BuildParameterCollection();

            cancellationTokenSource = new CancellationTokenSource();
            Cancelled = false;
            IsRunning = true;
            DisableCompressionIds.Clear();

            // Reseting result map
            var inputHashes = FileVersionTracker.GetDefault();

            {
                var builderContext = new BuilderContext(buildPath, buildProfile, inputHashes, parameters, MaxParallelProcesses, SlaveBuilderPath);
                if (!string.IsNullOrWhiteSpace(MetadataDatabaseDirectory))
                {
                    var metadataProvider = new QueryMetadataProvider();
                    if (metadataProvider.Open(Path.Combine(MetadataDatabaseDirectory, QueryMetadataProvider.DefaultDatabaseFilename), false))
                    {
                        builderContext.MetadataProvider = metadataProvider;
                    }
                }

                resultMap = IndexFileCommand.ObjectDatabase;

                scheduler = new Scheduler();
                if (enableMonitor)
                {
                    threadMonitors.Add(new BuildThreadMonitor(scheduler, BuilderId));
                    foreach (var monitorPipeName in MonitorPipeNames)
                    {
                        threadMonitors.Add(new BuildThreadMonitor(scheduler, BuilderId, monitorPipeName));
                    }

                    foreach (var threadMonitor in threadMonitors)
                    {
                        threadMonitor.Start();
                    }
                }

                ScheduleBuildStep(builderContext, null, Root, InitialVariables);

                // Create threads
                var threads = Enumerable.Range(0, ThreadCount).Select(x => new Thread(SafeAction.Wrap(RunUntilEnd))
                {
                    IsBackground = true
                }).ToArray();

                // Start threads
                int threadId = 0;
                foreach (var thread in threads)
                {
                    thread.Name = "Builder thread " + (++threadId);
                    thread.Start();
                }

                // Wait for all threads to finish
                foreach (var thread in threads)
                {
                    thread.Join();
                }

                foreach (var threadMonitor in threadMonitors)
                {
                    threadMonitor.Finish();
                }

                foreach (var threadMonitor in threadMonitors)
                {
                    threadMonitor.Join();
                }
            }

            threadMonitors.Clear();
            BuildResultCode result;

            if (runMode == Mode.Build)
            {
                Logger.Info("");
                if (cancellationTokenSource.IsCancellationRequested)
                {
                    Logger.Error("Build cancelled.");
                    result = BuildResultCode.Cancelled;
                }
                else if (stepCounter.Get(ResultStatus.Failed) > 0 || stepCounter.Get(ResultStatus.NotTriggeredPrerequisiteFailed) > 0)
                {
                    Logger.Error("Build finished in {0} steps. Command results: {1} succeeded, {2} up-to-date, {3} failed, {4} not triggered due to previous failure.",
                                 stepCounter.Total, stepCounter.Get(ResultStatus.Successful), stepCounter.Get(ResultStatus.NotTriggeredWasSuccessful),
                                 stepCounter.Get(ResultStatus.Failed), stepCounter.Get(ResultStatus.NotTriggeredPrerequisiteFailed));

                    Logger.Error("Build failed.");
                    result = BuildResultCode.BuildError;
                }
                else
                {
                    Logger.Info("Build finished in {0} steps. Command results: {1} succeeded, {2} up-to-date, {3} failed, {4} not triggered due to previous failure.",
                                stepCounter.Total, stepCounter.Get(ResultStatus.Successful), stepCounter.Get(ResultStatus.NotTriggeredWasSuccessful),
                                stepCounter.Get(ResultStatus.Failed), stepCounter.Get(ResultStatus.NotTriggeredPrerequisiteFailed));

                    Logger.Info("Build is successful.");
                    result = BuildResultCode.Successful;
                }
            }
            else
            {
                // Clean input hashes file
                if (VirtualFileSystem.FileExists(InputHashesFileFullPath))
                {
                    try
                    {
                        VirtualFileSystem.FileDelete(InputHashesFileFullPath);
                    }
                    catch (IOException)
                    {
                        return(BuildResultCode.BuildError);
                    }
                }
                string modeName;
                switch (runMode)
                {
                case Mode.Clean:
                    modeName = "Clean";
                    break;

                case Mode.CleanAndDelete:
                    modeName = "Clean-and-delete";
                    break;

                default:
                    throw new InvalidOperationException("Builder executed in unknown mode.");
                }

                if (cancellationTokenSource.IsCancellationRequested)
                {
                    Logger.Error(modeName + " has been cancelled.");
                    result = BuildResultCode.Cancelled;
                }
                else if (stepCounter.Get(ResultStatus.Failed) > 0 || stepCounter.Get(ResultStatus.NotTriggeredPrerequisiteFailed) > 0)
                {
                    Logger.Error(modeName + " has failed.");
                    result = BuildResultCode.BuildError;
                }
                else
                {
                    Logger.Error(modeName + " has been successfully completed.");
                    result = BuildResultCode.Successful;
                }
            }
            scheduler = null;
            resultMap = null;
            IsRunning = false;

            return(result);
        }