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);
            }
        }
Esempio n. 3
0
        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);
            }
        }
Esempio n. 6
0
        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);
            }
        }