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); } }
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); }
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; }
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)); }
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); }
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; }
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)); } }
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; }
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); } } }
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); }
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; } } }
/// <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); }