Example #1
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;
            }
        }
Example #2
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);
        }
Example #3
0
        /// <summary>
        /// Runs this instance.
        /// </summary>
        public BuildResultCode Run(Mode mode, bool writeIndexFile = true, List <IBuildThreadMonitor> threadMonitors = null)
        {
            // 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
            cancellationTokenSource = new CancellationTokenSource();
            Cancelled = false;
            IsRunning = true;
            DisableCompressionIds.Clear();

            currentThreadMonitors.Clear();
            if (threadMonitors != null)
            {
                foreach (var threadMonitor in threadMonitors)
                {
                    currentThreadMonitors.Add(threadMonitor);
                }
            }

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

            {
                var builderContext = new BuilderContext(inputHashes, TryExecuteRemote);

                resultMap = ObjectDatabase;

                scheduler = new Scheduler();
                foreach (var threadMonitor in currentThreadMonitors)
                {
                    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 currentThreadMonitors)
                {
                    threadMonitor.Finish();
                }

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

            currentThreadMonitors.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 {stepCounter.Total} steps. Command results: {stepCounter.Get(ResultStatus.Successful)} succeeded, {stepCounter.Get(ResultStatus.NotTriggeredWasSuccessful)} up-to-date, {stepCounter.Get(ResultStatus.Failed)} failed, {stepCounter.Get(ResultStatus.NotTriggeredPrerequisiteFailed)} not triggered due to previous failure.");
                    Logger.Error("Build failed.");
                    result = BuildResultCode.BuildError;
                }
                else
                {
                    Logger.Info($"Build finished in {stepCounter.Total} steps. Command results: {stepCounter.Get(ResultStatus.Successful)} succeeded, {stepCounter.Get(ResultStatus.NotTriggeredWasSuccessful)} up-to-date, {stepCounter.Get(ResultStatus.Failed)} failed, {stepCounter.Get(ResultStatus.NotTriggeredPrerequisiteFailed)} not triggered due to previous failure.");
                    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);
        }
Example #4
0
 public BuilderContext(FileVersionTracker inputHashes, CommandBuildStep.TryExecuteRemoteDelegate tryExecuteRemote)
 {
     InputHashes      = inputHashes;
     TryExecuteRemote = tryExecuteRemote;
 }