private void RecomputeGraph(FullPathChanges pathChanges) { _operationProcessor.Execute(new OperationHandlers { OnBeforeExecute = info => OnSnapshotComputing(info), OnError = (info, error) => OnSnapshotComputed(new SnapshotComputedResult { OperationInfo = info, Error = error }), Execute = info => { // Compute and assign new snapshot var oldSnapshot = _fileSystemSnapshot; var newSnapshot = ComputeNewSnapshot(oldSnapshot, pathChanges); // Update of new tree (assert calls are serialized). Debug.Assert(ReferenceEquals(oldSnapshot, _fileSystemSnapshot)); _fileSystemSnapshot = newSnapshot; if (Logger.Info) { Logger.LogInfo("+++++++++++ Collected {0:n0} files in {1:n0} directories", newSnapshot.ProjectRoots.Aggregate(0, (acc, x) => acc + CountFileEntries(x.Directory)), newSnapshot.ProjectRoots.Aggregate(0, (acc, x) => acc + CountDirectoryEntries(x.Directory))); } // Post event OnSnapshotComputed(new SnapshotComputedResult { OperationInfo = info, PreviousSnapshot = oldSnapshot, FullPathChanges = pathChanges, NewSnapshot = newSnapshot }); } }); }
private void FlushFileRegistrationQueueTask() { var entries = _fileRegistrationQueue.DequeueAll(); if (!entries.Any()) { return; } Logger.LogInfo("FlushFileRegistrationQueueTask:"); foreach (var entry in entries) { Logger.LogInfo(" Path=\"{0}\", Kind={1}", entry.Path, entry.Kind); } bool recompute = ValidateKnownFiles(); lock (_lock) { // Take a snapshot of all known project paths before applying changes var projectPaths1 = CollectKnownProjectPathsSorted(_registeredFiles); // Apply changes foreach (var entry in entries) { switch (entry.Kind) { case FileRegistrationKind.Register: _registeredFiles.Add(entry.Path); break; case FileRegistrationKind.Unregister: _registeredFiles.Remove(entry.Path); break; default: throw new ArgumentOutOfRangeException(); } } // Take a snapshot after applying changes, and compare var projectPaths2 = CollectKnownProjectPathsSorted(_registeredFiles); if (!projectPaths1.SequenceEqual(projectPaths2)) { recompute = true; } } // TODO(rpaquay): Be smarter here, don't recompute directory roots // that have not been affected. if (recompute) { // Pass empty changes, as we don't know of any file system changes for // existing entries. For new entries, they don't exist in the snapshot, // so they will be read form disk var emptyChanges = new FullPathChanges(ArrayUtilities.EmptyList <PathChangeEntry> .Instance); RecomputeGraph(emptyChanges); } }
private void FileRegistrationTrackerOnProjectListChanged(object sender, ProjectsEventArgs e) { Logger.LogInfo("List of projects has changed: Enqueuing a partial file system scan"); // If we are queuing a task that requires rescanning the entire file system, // cancel existing tasks (should be only one really) to avoid wasting time _longRunningFileSystemTaskQueue.CancelCurrentTask(); _longRunningFileSystemTaskQueue.Enqueue(ProjectListChangedTaskId, cancellationToken => { // Pass empty changes, as we don't know of any file system changes for // existing entries. For new entries, they don't exist in the snapshot, // so they will be read form disk var emptyChanges = new FullPathChanges(ArrayUtilities.EmptyList <PathChangeEntry> .Instance); RescanFileSystem(e.Projects, emptyChanges, cancellationToken); }); }
private void RescanFileSystem(IList <IProject> projects, FullPathChanges pathChanges /* may be null */, CancellationToken cancellationToken) { _registeredProjects = projects; _operationProcessor.Execute(new OperationHandlers { OnBeforeExecute = info => OnSnapshotScanStarted(info), OnError = (info, error) => { if (!error.IsCanceled()) { Logger.LogError(error, "File system rescan error"); } OnSnapshotScanFinished(new SnapshotScanResult { OperationInfo = info, Error = error }); }, Execute = info => { // Compute and assign new snapshot var oldSnapshot = _currentSnapshot; var newSnapshot = BuildNewFileSystemSnapshot(projects, oldSnapshot, pathChanges, cancellationToken); // Update of new tree (assert calls are serialized). Invariants.Assert(ReferenceEquals(oldSnapshot, _currentSnapshot)); _currentSnapshot = newSnapshot; if (Logger.IsInfoEnabled) { Logger.LogInfo("FileSystemSnapshotManager: New snapshot contains {0:n0} files in {1:n0} directories", newSnapshot.ProjectRoots.Aggregate(0, (acc, x) => acc + CountFileEntries(x.Directory)), newSnapshot.ProjectRoots.Aggregate(0, (acc, x) => acc + CountDirectoryEntries(x.Directory))); } // Post event OnSnapshotScanFinished(new SnapshotScanResult { OperationInfo = info, PreviousSnapshot = oldSnapshot, FullPathChanges = pathChanges, NewSnapshot = newSnapshot }); } }); }
private FileSystemSnapshot BuildNewFileSystemSnapshot(IList <IProject> projects, FileSystemSnapshot oldSnapshot, FullPathChanges pathChanges, CancellationToken cancellationToken) { using (new TimeElapsedLogger("FileSystemSnapshotManager: Computing snapshot delta from list of file changes", cancellationToken, InfoLogger.Instance)) { // Compute new snapshot var newSnapshot = _fileSystemSnapshotBuilder.Compute( _fileSystemNameFactory, oldSnapshot, pathChanges, projects, Interlocked.Increment(ref _version), cancellationToken); // Monitor all project roots for file changes. var newRoots = newSnapshot.ProjectRoots .Select(entry => entry.Directory.DirectoryName.FullPath); _directoryChangeWatcher.WatchDirectories(newRoots); return(newSnapshot); } }
private FileSystemSnapshot BuildNewFileSystemSnapshot(IList <IProject> projects, FileSystemSnapshot oldSnapshot, FullPathChanges pathChanges, CancellationToken cancellationToken) { using (new TimeElapsedLogger("Computing snapshot delta from list of file changes")) { // file name factory var fileNameFactory = _fileSystemNameFactory; if (ReuseFileNameInstances) { if (oldSnapshot.ProjectRoots.Count > 0) { fileNameFactory = new FileSystemTreeSnapshotNameFactory(oldSnapshot, fileNameFactory); } } // Compute new snapshot var newSnapshot = _fileSystemSnapshotBuilder.Compute( fileNameFactory, oldSnapshot, pathChanges, projects, Interlocked.Increment(ref _version), cancellationToken); // Monitor all project roots for file changes. var newRoots = newSnapshot.ProjectRoots .Select(entry => entry.Directory.DirectoryName.FullPath); _directoryChangeWatcher.WatchDirectories(newRoots); return(newSnapshot); } }
private FileSystemTreeSnapshot ComputeNewSnapshot(FileSystemTreeSnapshot oldSnapshot, FullPathChanges pathChanges) { using (new TimeElapsedLogger("Computing snapshot delta from list of file changes")) { // Get list of currently registered files. var rootFiles = new List <FullPath>(); lock (_lock) { ValidateKnownFiles(); rootFiles.AddRange(_registeredFiles); } // file name factory var fileNameFactory = _fileSystemNameFactory; if (ReuseFileNameInstances) { if (_fileSystemSnapshot.ProjectRoots.Count > 0) { fileNameFactory = new FileSystemTreeSnapshotNameFactory(_fileSystemSnapshot, fileNameFactory); } } // Compute new snapshot var newSnapshot = _fileSystemSnapshotBuilder.Compute( fileNameFactory, oldSnapshot, pathChanges, rootFiles, Interlocked.Increment(ref _version)); // Monitor all the Chromium directories for changes. var newRoots = newSnapshot.ProjectRoots .Select(entry => entry.Directory.DirectoryName.FullPath); _directoryChangeWatcher.WatchDirectories(newRoots); return(newSnapshot); } }