Exemple #1
0
        /// <summary>
        /// Creates a new change tracker in the <see cref="FileChangeTrackingState.BuildingInitialChangeTrackingSet"/> state.
        /// The caller may then add tracking for full set of files of interest, for later re-use by
        /// <see cref="ResumeTrackingChanges(LoggingContext,BuildXL.Utilities.FileEnvelopeId,VolumeMap,IChangeJournalAccessor,FileChangeTrackingSet,string)"/>.
        /// </summary>
        public static FileChangeTracker StartTrackingChanges(
            LoggingContext loggingContext,
            VolumeMap volumeMap,
            IChangeJournalAccessor journal,
            string buildEngineFingerprint,
            FileEnvelopeId?correlatedId = default)
        {
            Contract.Requires(loggingContext != null);
            Contract.Requires(volumeMap != null);
            Contract.Requires(journal != null);
            Contract.Ensures(Contract.Result <FileChangeTracker>().TrackingState == FileChangeTrackingState.BuildingInitialChangeTrackingSet);

            var tracker = new FileChangeTracker(
                loggingContext,
                correlatedId ?? FileEnvelopeId.Create(),
                FileChangeTrackingState.BuildingInitialChangeTrackingSet,
                volumeMap,
                journal,
                FileChangeTrackingSet.CreateForAllCapableVolumes(loggingContext, volumeMap, journal),
                buildEngineFingerprint);

            foreach (var gvfsProjectionFile in volumeMap.GvfsProjections)
            {
                var maybeTracking = tracker.TryProbeAndTrackPath(gvfsProjectionFile);
                if (!maybeTracking.Succeeded)
                {
                    Logger.Log.TrackChangesToGvfsProjectionFailed(loggingContext, gvfsProjectionFile, maybeTracking.Failure.DescribeIncludingInnerFailures());
                }
            }

            return(tracker);
        }
Exemple #2
0
        private FileChangeTracker(
            LoggingContext loggingContext,
            FileEnvelopeId fileEnvelopeId,
            FileChangeTrackingState initialState,
            VolumeMap volumeMap,
            IChangeJournalAccessor journal,
            FileChangeTrackingSet currentChangeTrackingSet,
            string buildEngineFingerprint)
        {
            Contract.Requires(loggingContext != null);
            Contract.Requires(fileEnvelopeId.IsValid);
            Contract.Requires(
                initialState == FileChangeTrackingState.BuildingInitialChangeTrackingSet || initialState == FileChangeTrackingState.TrackingChanges);
            Contract.Requires(volumeMap != null);
            Contract.Requires(journal != null);
            Contract.Requires(currentChangeTrackingSet != null);

            FileEnvelopeId           = fileEnvelopeId;
            m_loggingContext         = loggingContext;
            m_volumeMap              = volumeMap;
            m_journal                = journal;
            m_changeTrackingSet      = currentChangeTrackingSet;
            m_trackingStateValue     = (int)initialState;
            Counters                 = m_changeTrackingSet.Counters;
            m_buildEngineFingerprint = buildEngineFingerprint;
        }
Exemple #3
0
        private FileChangeTracker(LoggingContext loggingContext)
        {
            Contract.Requires(loggingContext != null);

            m_loggingContext         = loggingContext;
            m_volumeMap              = null;
            m_journal                = null;
            m_changeTrackingSet      = null;
            m_trackingStateValue     = (int)FileChangeTrackingState.DisabledSinceTrackingIsIncomplete;
            Counters                 = new CounterCollection <FileChangeTrackingCounter>();
            m_buildEngineFingerprint = null;
        }
Exemple #4
0
        public void StartTracking()
        {
            var loggingContext = new LoggingContext("JournalTesting", "Dummy");

            VolumeMap volumeMap = JournalUtils.TryCreateMapOfAllLocalVolumes(loggingContext);

            XAssert.IsNotNull(volumeMap);

            var maybeJournal = JournalUtils.TryGetJournalAccessorForTest(volumeMap);

            XAssert.IsTrue(maybeJournal.Succeeded);
            m_journal = maybeJournal.Result;

            m_changeTracker = FileChangeTrackingSet.CreateForAllCapableVolumes(
                loggingContext,
                volumeMap,
                m_journal);
        }
Exemple #5
0
        /// <summary>
        /// Creates a new change tracker in the <see cref="FileChangeTrackingState.BuildingInitialChangeTrackingSet"/> state.
        /// The caller may then add tracking for full set of files of interest, for later re-use by
        /// <see cref="ResumeTrackingChanges(LoggingContext,BuildXL.Utilities.FileEnvelopeId,VolumeMap,IChangeJournalAccessor,FileChangeTrackingSet,string)"/>.
        /// </summary>
        public static FileChangeTracker StartTrackingChanges(
            LoggingContext loggingContext,
            VolumeMap volumeMap,
            IChangeJournalAccessor journal,
            string buildEngineFingerprint,
            FileEnvelopeId?correlatedId = default)
        {
            Contract.Requires(loggingContext != null);
            Contract.Requires(volumeMap != null);
            Contract.Requires(journal != null);
            Contract.Ensures(Contract.Result <FileChangeTracker>().TrackingState == FileChangeTrackingState.BuildingInitialChangeTrackingSet);

            return(new FileChangeTracker(
                       loggingContext,
                       correlatedId ?? FileEnvelopeId.Create(),
                       FileChangeTrackingState.BuildingInitialChangeTrackingSet,
                       volumeMap,
                       journal,
                       FileChangeTrackingSet.CreateForAllCapableVolumes(loggingContext, volumeMap, journal),
                       buildEngineFingerprint));
        }
Exemple #6
0
        /// <summary>
        /// Creates a new change tracker in the <see cref="FileChangeTrackingState.TrackingChanges"/> state.
        /// The caller may query for new changes since the tracking set was last checkpointed and persisted, and may track additional files.
        /// </summary>
        private static FileChangeTracker ResumeTrackingChanges(
            LoggingContext loggingContext,
            FileEnvelopeId fileEnvelopeId,
            VolumeMap volumeMap,
            IChangeJournalAccessor journal,
            FileChangeTrackingSet previousChangeTrackingSet,
            string buildEngineFingerprint)
        {
            Contract.Requires(loggingContext != null);
            Contract.Requires(volumeMap != null);
            Contract.Requires(journal != null);
            Contract.Requires(previousChangeTrackingSet != null);
            Contract.Requires(fileEnvelopeId.IsValid);

            return(new FileChangeTracker(
                       loggingContext,
                       fileEnvelopeId,
                       FileChangeTrackingState.TrackingChanges,
                       volumeMap,
                       journal,
                       previousChangeTrackingSet,
                       buildEngineFingerprint));
        }
Exemple #7
0
        public static LoadingTrackerResult TryLoad(
            LoggingContext loggingContext,
            string path,
            VolumeMap volumeMap,
            IChangeJournalAccessor journal,
            string buildEngineFingerprint,
            bool loadForAllCapableVolumes = true)
        {
            Contract.Requires(loggingContext != null);
            Contract.Requires(!loadForAllCapableVolumes || volumeMap != null);
            Contract.Requires(!loadForAllCapableVolumes || journal != null);

            Stopwatch stopwatch = Stopwatch.StartNew();

            SafeFileHandle handle;
            OpenFileResult result = FileUtilities.TryCreateOrOpenFile(
                path,
                FileDesiredAccess.GenericRead,
                FileShare.Read | FileShare.Delete,
                FileMode.Open,
                // Ok to evict the file from standby since the file will be overwritten and never reread from disk after this point.
                FileFlagsAndAttributes.FileFlagSequentialScan,
                out handle);

            if (result.Succeeded)
            {
                Contract.Assume(handle != null);
                Contract.Assume(!handle.IsInvalid);

                using (handle)
                {
                    using (var stream = new FileStream(handle, FileAccess.Read))
                    {
                        FileEnvelopeId fileEnvelopeId;

                        try
                        {
                            fileEnvelopeId = FileEnvelope.ReadHeader(stream);
                        }
                        catch (BuildXLException e)
                        {
                            return(LoadingTrackerResult.FailBadFormatMarker(e.Message));
                        }

                        try
                        {
                            return(ExceptionUtilities.HandleRecoverableIOException(
                                       () =>
                            {
                                using (var reader = new BuildXLReader(debug: false, stream: stream, leaveOpen: true))
                                {
                                    bool wasTrackerDisabled = reader.ReadBoolean();

                                    if (wasTrackerDisabled)
                                    {
                                        return LoadingTrackerResult.FailPriorTrackerDisabled();
                                    }

                                    var previousFingerprint = reader.ReadNullable(r => r.ReadString());
                                    // only check for fingerprints match if the supplied fingerprint is valid
                                    // this is to support special cases where we might want to load ChangeTracker
                                    // regardless of the previously stored fingerprint value
                                    if (buildEngineFingerprint != null && !string.Equals(previousFingerprint, buildEngineFingerprint, StringComparison.Ordinal))
                                    {
                                        return LoadingTrackerResult.FailBuildEngineFingerprintMismatch();
                                    }

                                    return FileChangeTrackingSet.TryLoad(
                                        loggingContext,
                                        fileEnvelopeId,
                                        reader,
                                        volumeMap,
                                        journal,
                                        stopwatch,
                                        loadForAllCapableVolumes);
                                }
                            },
                                       ex =>
                            {
                                throw new BuildXLException(ex.Message);
                            }));
                        }
                        catch (Exception e)
                        {
                            // Catch any exception. Failure in loading FileChangeTracker should not
                            // cause build break, or worse, make people stuck on erroneous state.
                            // In such a case, BuildXL simply has to start tracking from scratch.
                            return(LoadingTrackerResult.FailLoadException(e.GetLogEventMessage()));
                        }
                    }
                }
            }

            Contract.Assume(handle == null);
            return(LoadingTrackerResult.FailTrackingSetCannotBeOpened(result.CreateFailureForError().DescribeIncludingInnerFailures()));
        }