예제 #1
0
            public static ChangeTrackerSupport Initialize(FileContentTableWithTrackerTests test)
            {
                var loggingContext   = new LoggingContext("Dummy", "Dummy");
                var fileContentTable = FileContentTable.CreateNew();

                VolumeMap volumeMap = JournalUtils.TryCreateMapOfAllLocalVolumes(loggingContext);

                XAssert.IsNotNull(volumeMap);

                var maybeJournal = JournalUtils.TryGetJournalAccessorForTest(volumeMap);

                XAssert.IsTrue(maybeJournal.Succeeded, "Could not connect to journal");

                var fileChangeTracker = FileChangeTracker.StartTrackingChanges(loggingContext, volumeMap, maybeJournal.Result, null);

                return(new ChangeTrackerSupport(
                           loggingContext,
                           test.m_pathTable,
                           fileChangeTracker,
                           fileContentTable,
                           volumeMap,
                           maybeJournal.Result,
                           AbsolutePath.Create(test.m_pathTable, test.TemporaryDirectory),
                           null));
            }
        private void Tracker_UpdatedOnDisk(object sender, EventArgs e)
        {
            FileChangeTracker tracker = (FileChangeTracker)sender;
            var filePath = tracker.FilePath;

            lock (_guard)
            {
                // Once we've created a diagnostic for a given analyzer file, there's
                // no need to keep watching it.
                _fileChangeTrackers.Remove(filePath);
            }

            tracker.Dispose();
            tracker.UpdatedOnDisk -= Tracker_UpdatedOnDisk;

            // Traverse the chain of requesting assemblies to get back to the original analyzer
            // assembly.
            var assemblyPath           = filePath;
            var requestingAssemblyPath = InMemoryAssemblyProvider.TryGetRequestingAssembly(filePath);

            while (requestingAssemblyPath != null)
            {
                assemblyPath           = requestingAssemblyPath;
                requestingAssemblyPath = InMemoryAssemblyProvider.TryGetRequestingAssembly(assemblyPath);
            }

            var projectsWithAnalyzer = _workspace.ProjectTracker.Projects.Where(p => p.CurrentProjectAnalyzersContains(assemblyPath)).ToArray();

            foreach (var project in projectsWithAnalyzer)
            {
                RaiseAnalyzerChangedWarning(project.Id, filePath);
            }
        }
예제 #3
0
        public override int Analyze()
        {
            Console.WriteLine("Loading file change tracker from cache graph directory '{0}'", m_cachedGraphDirectory);

            var loggingContext = new LoggingContext(nameof(FileChangeTrackerAnalyzer));
            FileChangeTracker fileChangeTracker;
            var loadResult = FileChangeTracker.LoadTrackingChanges(
                loggingContext,
                null,
                null,
                m_inputFile,
                // if we do not pass the fingerprint, FileChangeTracker will not check for fingerprint match
                null,
                out fileChangeTracker,
                loadForAllCapableVolumes: false);

            if (!loadResult.Succeeded)
            {
                Console.Error.WriteLine("Unable to load file change tracker '" + m_inputFile + "'");
                return(1);
            }

            using (var writer = File.CreateText(Path.GetFullPath(m_outputFile)))
            {
                fileChangeTracker.WriteText(writer);
            }

            return(0);
        }
예제 #4
0
            private ChangeTrackerSupport(
                LoggingContext loggingContext,
                PathTable pathTable,
                FileChangeTracker fileChangeTracker,
                FileContentTable fileContentTable,
                VolumeMap volumeMap,
                IChangeJournalAccessor journal,
                AbsolutePath temporaryDirectory,
                string buildEngineFingerprint)
            {
                Contract.Requires(loggingContext != null);
                Contract.Requires(pathTable != null);
                Contract.Requires(fileChangeTracker != null);
                Contract.Requires(fileContentTable != null);
                Contract.Requires(temporaryDirectory.IsValid);

                m_loggingContext         = loggingContext;
                m_pathTable              = pathTable;
                m_fileChangeTracker      = fileChangeTracker;
                m_fileContentTable       = fileContentTable;
                m_volumeMap              = volumeMap;
                m_journal                = journal;
                m_fileContentTablePath   = temporaryDirectory.Combine(m_pathTable, FileContentTableName);
                m_fileChangeTrackerPath  = temporaryDirectory.Combine(m_pathTable, FileChangeTrackerName);
                m_buildEngineFingerprint = buildEngineFingerprint;
            }
 private FileChangeTracker CreateChangeTracker(string fileName)
 {
     var tracker = new FileChangeTracker(fileChangeService, fileName);
     tracker.StartFileChangeListeningAsync();
     tracker.UpdatedOnDisk += (sender, args) => OnWorkspaceChanged();
     return tracker;
 }
예제 #6
0
            public static ChangeTrackerSupport Initialize(FileContentTableWithTrackerTests test)
            {
                var loggingContext   = new LoggingContext("Dummy", "Dummy");
                var fileContentTable = FileContentTable.CreateNew();

                VolumeMap volumeMap = VolumeMap.TryCreateMapOfAllLocalVolumes(loggingContext);

                XAssert.IsNotNull(volumeMap);

                var journal = JournalAccessorGetter.TryGetJournalAccessor(loggingContext, volumeMap, AssemblyHelper.GetAssemblyLocation(Assembly.GetExecutingAssembly())).Value;

                XAssert.IsNotNull(journal);

                var fileChangeTracker = FileChangeTracker.StartTrackingChanges(loggingContext, volumeMap, journal, null);

                return(new ChangeTrackerSupport(
                           loggingContext,
                           test.m_pathTable,
                           fileChangeTracker,
                           fileContentTable,
                           volumeMap,
                           journal,
                           AbsolutePath.Create(test.m_pathTable, test.TemporaryDirectory),
                           null));
            }
예제 #7
0
        private void Tracker_UpdatedOnDisk(object sender, EventArgs e)
        {
            FileChangeTracker tracker = (FileChangeTracker)sender;
            var filePath = tracker.FilePath;

            lock (_guard)
            {
                // Once we've created a diagnostic for a given analyzer file, there's
                // no need to keep watching it.
                _fileChangeTrackers.Remove(filePath);
            }

            tracker.Dispose();
            tracker.UpdatedOnDisk -= Tracker_UpdatedOnDisk;

            // Traverse the chain of requesting assemblies to get back to the original analyzer
            // assembly.
            foreach (var project in _workspace.CurrentSolution.Projects)
            {
                var analyzerFileReferences = project.AnalyzerReferences.OfType <AnalyzerFileReference>();

                if (analyzerFileReferences.Any(a => a.FullPath.Equals(filePath, StringComparison.OrdinalIgnoreCase)))
                {
                    RaiseAnalyzerChangedWarning(project.Id, filePath);
                }
            }
        }
        private FileChangeTracker CreateChangeTracker(string fileName)
        {
            var tracker = new FileChangeTracker(fileChangeService, fileName);

            tracker.StartFileChangeListeningAsync();
            tracker.UpdatedOnDisk += (sender, args) => OnWorkspaceChanged();
            return(tracker);
        }
예제 #9
0
            private void Load()
            {
                var loadingTrackerResult = FileChangeTracker.ResumeOrRestartTrackingChanges(
                    m_loggingContext,
                    m_volumeMap,
                    m_journal,
                    m_fileChangeTrackerPath.ToString(m_pathTable),
                    m_buildEngineFingerprint,
                    out m_fileChangeTracker);

                XAssert.IsTrue(loadingTrackerResult.Succeeded);

                m_fileContentTable = FileContentTable.LoadAsync(m_fileContentTablePath.ToString(m_pathTable)).Result;
            }
예제 #10
0
        private void Tracker_UpdatedOnDisk(object sender, EventArgs e)
        {
            FileChangeTracker tracker = (FileChangeTracker)sender;
            var filePath = tracker.FilePath;

            lock (_fileChangeTrackersLock)
            {
                // Once we've created a diagnostic for a given analyzer file, there's
                // no need to keep watching it.
                _fileChangeTrackers.Remove(filePath);
            }

            tracker.Dispose();
            tracker.UpdatedOnDisk -= Tracker_UpdatedOnDisk;

            string id       = ServicesVSResources.WRN_AnalyzerChangedId;
            string category = ServicesVSResources.ErrorCategory;
            string message  = string.Format(ServicesVSResources.WRN_AnalyzerChangedMessage, filePath);

            // Traverse the chain of requesting assemblies to get back to the original analyzer
            // assembly.
            var assemblyPath           = filePath;
            var requestingAssemblyPath = AnalyzerFileReference.TryGetRequestingAssemblyPath(filePath);

            while (requestingAssemblyPath != null)
            {
                assemblyPath           = requestingAssemblyPath;
                requestingAssemblyPath = AnalyzerFileReference.TryGetRequestingAssemblyPath(assemblyPath);
            }

            var projectsWithAnalyzer = _workspace.ProjectTracker.Projects.Where(p => p.CurrentProjectAnalyzersContains(assemblyPath)).ToArray();

            foreach (var project in projectsWithAnalyzer)
            {
                DiagnosticData data = new DiagnosticData(
                    id,
                    category,
                    message,
                    ServicesVSResources.WRN_AnalyzerChangedMessage,
                    severity: DiagnosticSeverity.Warning,
                    defaultSeverity: DiagnosticSeverity.Warning,
                    isEnabledByDefault: true,
                    warningLevel: 0,
                    customTags: ImmutableArray <string> .Empty,
                    workspace: _workspace,
                    projectId: project.Id);

                _updateSource.UpdateDiagnosticsForProject(project.Id, Tuple.Create(s_analyzerChangedErrorId, filePath), SpecializedCollections.SingletonEnumerable(data));
            }
        }
예제 #11
0
        internal void TrackFilePathAndReportErrorIfChanged(string filePath, ProjectId projectId)
        {
            lock (_guard)
            {
                if (!_fileChangeTrackers.TryGetValue(filePath, out var tracker))
                {
                    tracker = new FileChangeTracker(_fileChangeService, filePath);
                    tracker.UpdatedOnDisk += Tracker_UpdatedOnDisk;
                    tracker.StartFileChangeListeningAsync();

                    _fileChangeTrackers.Add(filePath, tracker);
                }

                DateTime assemblyUpdatedTime;

                if (_assemblyUpdatedTimesUtc.TryGetValue(filePath, out assemblyUpdatedTime))
                {
                    var currentFileUpdateTime = GetLastUpdateTimeUtc(filePath);

                    if (currentFileUpdateTime != null)
                    {
                        if (currentFileUpdateTime != assemblyUpdatedTime)
                        {
                            RaiseAnalyzerChangedWarning(projectId, filePath);
                        }

                        // If the the tracker is in place, at this point we can stop checking any further for this assembly
                        if (tracker.PreviousCallToStartFileChangeHasAsynchronouslyCompleted)
                        {
                            _assemblyUpdatedTimesUtc.Remove(filePath);
                        }
                    }
                }
                else
                {
                    // We don't have an assembly updated time. This means we either haven't ever checked it, or we have a file watcher in place.
                    // If the file watcher is in place, then nothing further to do. Otherwise we'll add the update time to the map for future checking
                    if (!tracker.PreviousCallToStartFileChangeHasAsynchronouslyCompleted)
                    {
                        var currentFileUpdateTime = GetLastUpdateTimeUtc(filePath);

                        if (currentFileUpdateTime != null)
                        {
                            _assemblyUpdatedTimesUtc[filePath] = currentFileUpdateTime.Value;
                        }
                    }
                }
            }
        }
        public override int Analyze()
        {
            Console.WriteLine("Loading incremental scheduling state from cache graph directory '{0}'", m_cachedGraphDirectory);

            var loggingContext = new LoggingContext(nameof(IncrementalSchedulingStateAnalyzer));
            var trackerFile    = Path.Combine(m_cachedGraphDirectory, Scheduler.Scheduler.DefaultSchedulerFileChangeTrackerFile);
            FileChangeTracker fileChangeTracker;
            var loadResult = FileChangeTracker.LoadTrackingChanges(
                loggingContext,
                null,
                null,
                default(Utilities.Configuration.FileChangeTrackerSupersedeMode?),
                trackerFile,
                null,
                out fileChangeTracker,
                loadForAllCapableVolumes: false);

            if (!loadResult.Succeeded)
            {
                Console.Error.WriteLine("Unable to load file change tracker '" + trackerFile + "'");
                return(1);
            }

            var incrementalSchedulingStateFile = Path.Combine(m_cachedGraphDirectory, Scheduler.Scheduler.DefaultIncrementalSchedulingStateFile);
            var factory = new IncrementalSchedulingStateFactory(loggingContext, analysisMode: true);

            var incrementalSchedulingState = factory.LoadOrReuse(
                fileChangeTracker.FileEnvelopeId,
                CachedGraph.PipGraph,
                null,
                UnsafeOptions.PreserveOutputsNotUsed,
                incrementalSchedulingStateFile,
                schedulerState: null);

            if (incrementalSchedulingState == null)
            {
                Console.Error.WriteLine("Unable to load incremental scheduling state '" + incrementalSchedulingStateFile + "'");
                return(1);
            }

            using (var writer = File.CreateText(Path.GetFullPath(m_outputFile)))
            {
                incrementalSchedulingState.WriteText(writer);
                writer.WriteLine(string.Empty);
                fileChangeTracker.WriteText(writer);
            }

            return(0);
        }
            private void Load()
            {
                var loadingTrackerResult = FileChangeTracker.ResumeOrRestartTrackingChanges(
                    m_loggingContext,
                    m_volumeMap,
                    m_journal,
                    global::BuildXL.Utilities.Configuration.FileChangeTrackerSupersedeMode.All,
                    m_fileChangeTrackerPath.ToString(m_pathTable),
                    m_buildEngineFingerprint,
                    out m_fileChangeTracker);

                XAssert.IsTrue(loadingTrackerResult.Succeeded);

                m_fileContentTable = FileContentTable.LoadAsync(m_loggingContext, m_fileContentTablePath.ToString(m_pathTable)).Result;
            }
예제 #14
0
        private void AnalyzerFileReference_AssemblyLoad(object sender, AnalyzerAssemblyLoadEventArgs e)
        {
            lock (_fileChangeTrackersLock)
            {
                FileChangeTracker tracker;
                if (!_fileChangeTrackers.TryGetValue(e.Path, out tracker))
                {
                    tracker = new FileChangeTracker(_fileChangeService, e.Path);
                    tracker.UpdatedOnDisk += Tracker_UpdatedOnDisk;
                    tracker.StartFileChangeListeningAsync();

                    _fileChangeTrackers.Add(e.Path, tracker);
                }
            }
        }
예제 #15
0
            public PipQueueTestExecutionEnvironment(BuildXLContext context, IConfiguration configuration, PipTable pipTable, string tempDirectory, ISandboxConnection SandboxConnection = null)
            {
                Contract.Requires(context != null);
                Contract.Requires(configuration != null);

                Context              = context;
                LoggingContext       = CreateLoggingContextForTest();
                Configuration        = configuration;
                FileContentTable     = FileContentTable.CreateNew();
                ContentFingerprinter = new PipContentFingerprinter(
                    context.PathTable,
                    artifact => State.FileContentManager.GetInputContent(artifact).FileContentInfo,
                    ExtraFingerprintSalts.Default(),
                    pathExpander: PathExpander);
                PipTable            = pipTable;
                PipFragmentRenderer = this.CreatePipFragmentRenderer();
                IpcProvider         = IpcFactory.GetProvider();
                var tracker = FileChangeTracker.CreateDisabledTracker(LoggingContext);

                Cache = InMemoryCacheFactory.Create();
                LocalDiskContentStore = new LocalDiskContentStore(LoggingContext, context.PathTable, FileContentTable, tracker);

                m_sandboxConnectionKext  = SandboxConnection;
                m_expectedWrittenContent = new ConcurrentDictionary <FileArtifact, ContentHash>();
                m_wellKnownFiles         = new ConcurrentDictionary <FileArtifact, ContentHash>();
                m_producers      = new ConcurrentDictionary <FileArtifact, Pip>();
                m_filesystemView = new TestPipGraphFilesystemView(Context.PathTable);
                var fileSystemView = new FileSystemView(Context.PathTable, m_filesystemView, LocalDiskContentStore);

                TempCleaner = new TestMoveDeleteCleaner(tempDirectory);

                State = new PipExecutionState(
                    configuration,
                    cache: new PipTwoPhaseCache(LoggingContext, Cache, context, PathExpander),
                    unsafeConfiguration: configuration.Sandbox.UnsafeSandboxConfiguration,
                    preserveOutputsSalt: ContentHashingUtilities.CreateRandom(),
                    fileAccessWhitelist: FileAccessWhitelist,
                    directoryMembershipFingerprinter: this,
                    pathExpander: PathExpander,
                    executionLog: null,
                    fileSystemView: fileSystemView,
                    fileContentManager: new FileContentManager(this, new NullOperationTracker()),
                    directoryMembershipFinterprinterRuleSet: null);

                m_sealContentsById = new ConcurrentBigMap <DirectoryArtifact, int[]>();

                ProcessInContainerManager = new ProcessInContainerManager(LoggingContext, context.PathTable);
            }
예제 #16
0
        internal void AddPath(string filePath)
        {
            lock (_guard)
            {
                if (!_fileChangeTrackers.TryGetValue(filePath, out var tracker))
                {
                    tracker = new FileChangeTracker(_fileChangeService, filePath);
                    tracker.UpdatedOnDisk += Tracker_UpdatedOnDisk;
                    tracker.StartFileChangeListeningAsync();

                    _fileChangeTrackers.Add(filePath, tracker);
                }

                DateTime?fileUpdateTime = GetLastUpdateTimeUtc(filePath);

                if (fileUpdateTime.HasValue)
                {
                    _assemblyUpdatedTimesUtc[filePath] = fileUpdateTime.Value;
                }
            }
        }
        private void AnalyzerFileReference_AssemblyLoad(object sender, InMemoryAssemblyProvider.AssemblyLoadEventArgs e)
        {
            lock (_guard)
            {
                FileChangeTracker tracker;
                if (!_fileChangeTrackers.TryGetValue(e.Path, out tracker))
                {
                    tracker = new FileChangeTracker(_fileChangeService, e.Path);
                    tracker.UpdatedOnDisk += Tracker_UpdatedOnDisk;
                    tracker.StartFileChangeListeningAsync();

                    _fileChangeTrackers.Add(e.Path, tracker);
                }

                DateTime?fileUpdateTime = GetLastUpdateTimeUtc(e.Path);

                if (fileUpdateTime.HasValue)
                {
                    _assemblyUpdatedTimesUtc[e.Path] = fileUpdateTime.Value;
                }
            }
        }
예제 #18
0
        /// <summary>
        /// Creates an execution environment for a single pip. To run pips incrementally, the <paramref name="fileContentTable"/> and <paramref name="pipCache"/> should be specified.
        /// </summary>
        public DummyPipExecutionEnvironment(
            LoggingContext loggingContext,
            PipExecutionContext context,
            IConfiguration config,
            FileContentTable fileContentTable = null,
            EngineCache pipCache = null,
            SemanticPathExpander semanticPathExpander           = null,
            PipContentFingerprinter.PipDataLookup pipDataLookup = null,
            FileAccessWhitelist fileAccessWhitelist             = null,
            bool allowUnspecifiedSealedDirectories = false,
            PipTable pipTable        = null,
            IIpcProvider ipcProvider = null,
            IKextConnection sandboxedKextConnection = null)
        {
            Contract.Requires(context != null);
            Contract.Requires(config != null);

            LoggingContext = loggingContext;
            Context        = context;

            // Ensure paths visible when debugging
            PathTable.DebugPathTable = Context.PathTable;
            Configuration            = config;
            PipTable             = pipTable;
            PathExpander         = semanticPathExpander ?? SemanticPathExpander.Default;
            ContentFingerprinter = new PipContentFingerprinter(
                Context.PathTable,
                artifact => State.FileContentManager.GetInputContent(artifact).FileContentInfo,
                new ExtraFingerprintSalts(config, PipFingerprintingVersion.TwoPhaseV2, fingerprintSalt: null, searchPathToolsHash: null),
                pathExpander: PathExpander,
                pipDataLookup: pipDataLookup);
            PipFragmentRenderer = this.CreatePipFragmentRenderer();
            IpcProvider         = ipcProvider ?? IpcFactory.GetProvider();

            FileContentTable    = fileContentTable ?? FileContentTable.CreateNew();
            Cache               = pipCache;
            FileAccessWhitelist = fileAccessWhitelist;
            m_allowUnspecifiedSealedDirectories = allowUnspecifiedSealedDirectories;
            m_sandboxedKextConnection           = sandboxedKextConnection;

            if (Cache == null)
            {
                Cache = InMemoryCacheFactory.Create(context);
            }

            var tracker = FileChangeTracker.CreateDisabledTracker(LoggingContext);

            LocalDiskContentStore = new LocalDiskContentStore(loggingContext, context.PathTable, FileContentTable, tracker);
            PipGraphView          = new TestPipGraphFilesystemView(Context.PathTable);
            m_operationTracker    = new OperationTracker(loggingContext);

            var fileSystemView = new FileSystemView(Context.PathTable, PipGraphView, LocalDiskContentStore);

            var preserveOutputsSalt = UnsafeOptions.PreserveOutputsNotUsed;

            if (config.Sandbox.UnsafeSandboxConfiguration.PreserveOutputs != PreserveOutputsMode.Disabled)
            {
                preserveOutputsSalt = ContentHashingUtilities.HashString(Guid.NewGuid().ToString());
            }

            State = new PipExecutionState(
                config,
                cache: new PipTwoPhaseCache(loggingContext, Cache, context, PathExpander),
                fileAccessWhitelist: FileAccessWhitelist,
                directoryMembershipFingerprinter: this,
                pathExpander: PathExpander,
                executionLog: ExecutionLogRecorder,
                fileSystemView: fileSystemView,
                fileContentManager: GetFileContentManager(),
                directoryMembershipFinterprinterRuleSet: null,
                unsafeConfiguration: config.Sandbox.UnsafeSandboxConfiguration,
                preserveOutputsSalt: preserveOutputsSalt,
                serviceManager: new DummyServiceManager());

            m_sealContentsById = new ConcurrentBigMap <DirectoryArtifact, int[]>();

            ProcessInContainerManager = new ProcessInContainerManager(LoggingContext, context.PathTable);
        }