示例#1
0
        private bool IsFileContentsUpToDate(FileSystemEntities entities, FullPathChanges fullPathChanges, FileWithContents existingFileWithContents)
        {
            Debug.Assert(existingFileWithContents.Contents != null);

            var fullPath = existingFileWithContents.FileName.FullPath;

            if (fullPathChanges != null)
            {
                // We don't get file change events for file in symlinks, so we can't
                // rely on fullPathChanges contents for our heuristic of avoiding file
                // system access.
                if (!FileDatabaseSnapshot.IsContainedInSymLinkHelper(entities.Directories, existingFileWithContents.FileName))
                {
                    return(fullPathChanges.ShouldSkipLoadFileContents(fullPath));
                }
            }

            // Do the "expensive" check by going to the file system.
            var fi = _fileSystem.GetFileInfoSnapshot(fullPath);

            return
                ((fi.Exists) &&
                 (fi.IsFile) &&
                 (fi.LastWriteTimeUtc == existingFileWithContents.Contents.UtcLastModified));
        }
示例#2
0
        public FileSystemSnapshot Compute(IFileSystemNameFactory fileNameFactory,
                                          FileSystemSnapshot oldSnapshot,
                                          FullPathChanges pathChanges /* may be null */,
                                          IList <IProject> projects,
                                          int version,
                                          CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested(); // cancellation
            using (var progress = _progressTrackerFactory.CreateIndeterminateTracker()) {
                var projectRoots =
                    projects
                    .Distinct(new ProjectPathComparer())
                    .Select(project => {
                    cancellationToken.ThrowIfCancellationRequested(); // cancellation

                    var projectSnapshotBuilder = new ProjectRootSnapshotBuilder(
                        _fileSystem, fileNameFactory, oldSnapshot, project, progress,
                        (pathChanges == null ? null : new ProjectPathChanges(project.RootPath, pathChanges.Entries)),
                        cancellationToken);

                    var rootSnapshot = projectSnapshotBuilder.Build();

                    return(new ProjectRootSnapshot(project, rootSnapshot));
                })
                    .OrderBy(projectRoot => projectRoot.Directory.DirectoryName)
                    .ToReadOnlyCollection();

                return(new FileSystemSnapshot(version, projectRoots));
            }
        }
示例#3
0
        private void ComputeNewStateLongTask(FileSystemSnapshot previousSnapshot, FileSystemSnapshot newSnapshot,
                                             FullPathChanges fullPathChanges,
                                             CancellationToken cancellationToken)
        {
            Invariants.Assert(_inTaskQueueTask);

            UpdateFileDatabase(newSnapshot, options => {
                // We only allow incremental updates if the last update was successfully completed
                // and if the file system snapshot version we are based on is the same as the
                // new file system snapshot we are processing
                if (previousSnapshot.Version == _currentFileSystemSnapshotVersion &&
                    options.PreviousUpdateCompleted &&
                    fullPathChanges != null)
                {
                    return(CreateWithFileSystemChanges(newSnapshot, fullPathChanges, options, cancellationToken));
                }
                else
                {
                    Logger.LogInfo($"Starting a full database update: " +
                                   $"CurrentSnapshotVersion={_currentFileSystemSnapshotVersion}, " +
                                   $"PreviousUpdateCompleted={options.PreviousUpdateCompleted}, " +
                                   $"PreviousSnapshotVersion={previousSnapshot.Version}, " +
                                   $"FullPathChanges={fullPathChanges?.Entries.Count ?? -1}.");
                    return(CreateFullScan(newSnapshot, options, cancellationToken));
                }
            });
        }
示例#4
0
        private bool IsFileContentsUpToDate(FileSystemEntities entities,
                                            FullPathChanges fullPathChanges,
                                            FileWithContents existingFileWithContents)
        {
            Invariants.Assert(existingFileWithContents.Contents != null);

            var fullPath = existingFileWithContents.FileName.FullPath;

            if (fullPathChanges != null)
            {
                // We don't get file change events for file in symlinks, so we can't
                // rely on fullPathChanges contents for our heuristic of avoiding file
                // system access.
                // Actually, since we cannot reliable detect changes in symlinks, we enable this
                // optimization anyways, as we rely on the user to manually refresh the index
                // (that results in a "null" value for fullPathChanges)
                //if (!FileDatabaseSnapshot.IsContainedInSymLinkHelper(entities.Directories, existingFileWithContents.FileName)) {
                return(fullPathChanges.ShouldSkipLoadFileContents(fullPath));
                //}
            }

            // Do the "expensive" check by going to the file system.
            var fi = _fileSystem.GetFileInfoSnapshot(fullPath);

            return
                ((fi.Exists) &&
                 (fi.IsFile) &&
                 (fi.LastWriteTimeUtc == existingFileWithContents.Contents.UtcLastModified));
        }
        private bool IsFileContentsUpToDate(FullPathChanges fullPathChanges, FileData oldFileData)
        {
            Debug.Assert(oldFileData.Contents != null);

            var fullPath = oldFileData.FileName.FullPath;

            if (fullPathChanges != null)
            {
                // We don't get file change events for file in symlinks, so we can't
                // rely on fullPathChanges contents for our heuristic of avoiding file
                // system access.
                if (!FileDatabase.IsContainedInSymLinkHelper(_directories, oldFileData.FileName))
                {
                    return(fullPathChanges.GetPathChangeKind(fullPath) == PathChangeKind.None);
                }
            }

            // Do the "expensive" check by going to the file system.
            var fi = _fileSystem.GetFileInfoSnapshot(fullPath);

            return
                ((fi.Exists) &&
                 (fi.IsFile) &&
                 (fi.LastWriteTimeUtc == oldFileData.Contents.UtcLastModified));
        }
示例#6
0
        public IFileDatabaseSnapshot Build(IFileDatabaseSnapshot previousDatabase,
                                           FileSystemSnapshot newSnapshot,
                                           FullPathChanges fullPathChanges,
                                           Action onLoading,
                                           Action onLoaded,
                                           Action <IFileDatabaseSnapshot> onIntermadiateResult,
                                           CancellationToken cancellationToken)
        {
            using (new TimeElapsedLogger("Building file database from previous one and file system tree snapshot",
                                         cancellationToken, InfoLogger.Instance)) {
                using (var progress = _progressTrackerFactory.CreateIndeterminateTracker()) {
                    onLoading();
                    progress.DisplayProgress((i, n) => "Preparing list of files to load from disk");

                    var fileDatabase = (FileDatabaseSnapshot)previousDatabase;

                    // Compute list of files from tree
                    var entities = ComputeFileSystemEntities(newSnapshot, cancellationToken);

                    cancellationToken.ThrowIfCancellationRequested();
                    var unchangedProjects = newSnapshot
                                            .ProjectRoots.Where(x =>
                                                                fileDatabase.ProjectHashes.ContainsKey(x.Project.RootPath) &&
                                                                fileDatabase.ProjectHashes[x.Project.RootPath] == x.Project.VersionHash)
                                            .Select(x => x.Project);

                    cancellationToken.ThrowIfCancellationRequested();
                    var unchangedProjectSet = new HashSet <IProject>(unchangedProjects,
                                                                     // Use reference equality for IProject is safe, as we keep this
                                                                     // dictionary only for the duration of this "Build" call.
                                                                     new ReferenceEqualityComparer <IProject>());

                    cancellationToken.ThrowIfCancellationRequested();
                    var loadingContext = new FileContentsLoadingContext {
                        FullPathChanges         = fullPathChanges,
                        LoadedTextFileCount     = 0,
                        OldFileDatabaseSnapshot = fileDatabase,
                        UnchangedProjects       = unchangedProjectSet,
                        PartialProgressReporter = new PartialProgressReporter(
                            TimeSpan.FromSeconds(5.0),
                            () => {
                            Logger.LogInfo("Creating intermedidate file database for partial progress reporting");
                            var database = CreateFileDatabase(entities, false, cancellationToken);
                            onIntermadiateResult(database);
                        })
                    };

                    // Merge old state in new state and load all missing files
                    LoadFileContents(entities, loadingContext, cancellationToken);

                    var result = CreateFileDatabase(entities, true, cancellationToken);
                    onLoaded();
                    return(result);
                }
            }
        }
示例#7
0
 public IFileDatabase CreateIncremental(
     IFileDatabase previousFileDatabase,
     FileSystemTreeSnapshot previousSnapshot,
     FileSystemTreeSnapshot newSnapshot,
     FullPathChanges fullPathChanges,
     Action <IFileDatabase> onIntermadiateResult)
 {
     return(new FileDatabaseBuilder(_fileSystem, _fileContentsFactory, _progressTrackerFactory)
            .Build(previousFileDatabase, newSnapshot, fullPathChanges, onIntermadiateResult));
 }
        public IFileDatabase Build(
            IFileDatabase previousFileDatabase,
            FileSystemTreeSnapshot newSnapshot,
            FullPathChanges fullPathChanges,
            Action <IFileDatabase> onIntermadiateResult)
        {
            using (var logger = new TimeElapsedLogger("Building file database from previous one and file system tree snapshot")) {
                var fileDatabase = (FileDatabase)previousFileDatabase;

                // Compute list of files from tree
                ComputeFileCollection(newSnapshot);

                var unchangedProjects = newSnapshot
                                        .ProjectRoots.Where(x =>
                                                            fileDatabase.ProjectHashes.ContainsKey(x.Project.RootPath) &&
                                                            fileDatabase.ProjectHashes[x.Project.RootPath] == x.Project.VersionHash)
                                        .Select(x => x.Project);

                var unchangedProjectSet = new HashSet <IProject>(unchangedProjects,
                                                                 // Use reference equality for IProject is safe, as we keep this
                                                                 // dictionary only for the duration of this "Build" call.
                                                                 new ReferenceEqualityComparer <IProject>());

                // Don't use file memoization for now, as benefit is dubvious.
                //IFileContentsMemoization fileContentsMemoization = new FileContentsMemoization();
                IFileContentsMemoization fileContentsMemoization = new NullFileContentsMemoization();

                var loadingInfo = new FileContentsLoadingInfo {
                    FileContentsMemoization = fileContentsMemoization,
                    FullPathChanges         = fullPathChanges,
                    LoadedTextFileCount     = 0,
                    OldFileDatabase         = fileDatabase,
                    UnchangedProjects       = unchangedProjectSet,
                    PartialProgressReporter = new PartialProgressReporter(
                        TimeSpan.FromSeconds(5.0),
                        () => {
                        Logger.LogInfo("Creating intermedidate file database");
                        var database = this.CreateFileDatabse();
                        onIntermadiateResult(database);
                    })
                };

                // Merge old state in new state and load all missing files
                LoadFileContents(loadingInfo);

                return(CreateFileDatabse());
            }
        }
示例#9
0
        private void ComputeNewState(
            FileSystemTreeSnapshot previousSnapshot,
            FileSystemTreeSnapshot newSnapshot,
            FullPathChanges fullPathChanges)
        {
            _operationProcessor.Execute(new OperationHandlers {
                OnBeforeExecute = info =>
                                  OnFilesLoading(info),

                OnError = (info, error) => {
                    _currentTreeVersion = newSnapshot.Version;
                    OnFilesLoaded(new FilesLoadedResult {
                        OperationInfo = info,
                        Error         = error,
                        TreeVersion   = newSnapshot.Version
                    });
                },

                Execute = info => {
                    using (new TimeElapsedLogger("Computing new state of file database")) {
                        var oldState = _currentFileDatabase;
                        var newState = _fileDatabaseFactory.CreateIncremental(
                            oldState,
                            previousSnapshot,
                            newSnapshot,
                            fullPathChanges,
                            fileDatabase => {
                            // Store and activate intermediate new state (atomic operation).
                            _currentFileDatabase = fileDatabase;
                            OnFilesLoadingProgress(info);
                        });
                        // Store and activate final new state (atomic operation).
                        _currentFileDatabase = newState;
                    }
                    _currentTreeVersion = newSnapshot.Version;
                    OnFilesLoaded(new FilesLoadedResult {
                        OperationInfo = info,
                        TreeVersion   = newSnapshot.Version
                    });
                }
            });
        }
        public FileSystemSnapshot Compute(IFileSystemNameFactory fileNameFactory,
                                          FileSystemSnapshot oldSnapshot,
                                          FullPathChanges pathChanges /* may be null */,
                                          IList <IProject> projects,
                                          int version,
                                          CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested(); // cancellation
            using (var progress = _progressTrackerFactory.CreateIndeterminateTracker()) {
                // Clear file name factory intern tables if no projects. We could be
                // more aggressive at the expense of decreasing string interning.
                if (projects.Count == 0)
                {
                    fileNameFactory.ClearInternedStrings();
                }

                var projectRoots =
                    projects
                    .Distinct(new ProjectPathComparer())
                    .Select(project => {
                    cancellationToken.ThrowIfCancellationRequested(); // cancellation

                    var projectSnapshotBuilder = new ProjectRootSnapshotBuilder(
                        _fileSystem, fileNameFactory, oldSnapshot, project, progress,
                        (pathChanges == null ? null : new ProjectPathChanges(project.RootPath, pathChanges.Entries)),
                        cancellationToken);

                    var rootSnapshot = projectSnapshotBuilder.Build();

                    return(new ProjectRootSnapshot(project, rootSnapshot));
                })
                    .OrderBy(projectRoot => projectRoot.Directory.DirectoryName)
                    .ToReadOnlyCollection();

                return(new FileSystemSnapshot(version, projectRoots));
            }
        }
示例#11
0
 private IFileDatabaseSnapshot CreateIncrementalWorker(IFileDatabaseSnapshot previousDatabase,
                                                       FileSystemSnapshot newFileSystemSnapshot, FullPathChanges fullPathChanges,
                                                       Action onLoading, Action onLoaded,
                                                       Action <IFileDatabaseSnapshot> onIntermadiateResult, CancellationToken cancellationToken)
 {
     return(new FileDatabaseBuilder(_fileSystem, _fileContentsFactory, _progressTrackerFactory)
            .Build(previousDatabase, newFileSystemSnapshot, fullPathChanges,
                   onLoading, onLoaded, onIntermadiateResult, cancellationToken));
 }
示例#12
0
 public IFileDatabaseSnapshot CreateIncrementalWithFileSystemUpdates(IFileDatabaseSnapshot previousDatabase,
                                                                     FileSystemSnapshot newFileSystemSnapshot, FullPathChanges fullPathChanges, Action onLoading, Action onLoaded,
                                                                     Action <IFileDatabaseSnapshot> onIntermadiateResult, CancellationToken cancellationToken)
 {
     return(CreateIncrementalWorker(previousDatabase, newFileSystemSnapshot, fullPathChanges, onLoading, onLoaded,
                                    onIntermadiateResult,
                                    cancellationToken));
 }
示例#13
0
        private IFileDatabaseSnapshot CreateWithFileSystemChanges(FileSystemSnapshot newSnapshot, FullPathChanges fullPathChanges,
                                                                  UpdateFileDatabaseOptions options, CancellationToken cancellationToken)
        {
            Invariants.Assert(_inTaskQueueTask);

            return(_fileDatabaseSnapshotFactory.CreateIncrementalWithFileSystemUpdates(
                       options.CurrentFileDatabase,
                       newSnapshot,
                       fullPathChanges,
                       onIntermadiateResult: fileDatabase => {
                ActivateCurrentDatabase(newSnapshot, fileDatabase, false);
                OnFilesLoadingProgress(options.OperationInfo);
            },
                       onLoading: () => OnFilesLoading(options.OperationInfo),
                       onLoaded: () => OnFilesLoaded(new FilesLoadedResult {
                OperationInfo = options.OperationInfo,
                TreeVersion = _currentFileSystemSnapshotVersion,
            }),
                       cancellationToken: cancellationToken));
        }