Exemple #1
0
        private void LoadFileContents(FileSystemEntities entities, FileContentsLoadingContext loadingContext, CancellationToken cancellationToken)
        {
            using (new TimeElapsedLogger("Loading file contents from disk")) {
                using (var progress = _progressTrackerFactory.CreateTracker(entities.Files.Count)) {
                    entities.Files.AsParallelWrapper().ForAll(fileEntry => {
                        Debug.Assert(fileEntry.Value.FileWithContents.Contents == null);

                        if (progress.Step())
                        {
                            progress.DisplayProgress((i, n) =>
                                                     string.Format("Reading file {0:n0} of {1:n0}: {2}", i, n, fileEntry.Value.FileName.FullPath));

                            // Check for cancellation
                            if (cancellationToken.IsCancellationRequested)
                            {
                                loadingContext.PartialProgressReporter.ReportProgressNow();
                                cancellationToken.ThrowIfCancellationRequested();
                            }
                        }

                        var contents = LoadSingleFileContents(entities, loadingContext, fileEntry.Value);
                        if (contents != null)
                        {
                            fileEntry.Value.FileWithContents.UpdateContents(contents);
                        }
                    });
                }
            }
            Logger.LogInfo("Loaded {0:n0} text files from disk, skipped {1:n0} binary files.",
                           loadingContext.LoadedTextFileCount,
                           loadingContext.LoadedBinaryFileCount);
        }
Exemple #2
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));
        }
Exemple #3
0
        private FileDatabaseSnapshot CreateFileDatabse(FileSystemEntities entities)
        {
            using (new TimeElapsedLogger("Freezing file database state")) {
                var directories = entities.Directories;
                // Note: We cannot use "ReferenceEqualityComparer<FileName>" here because
                // the dictionary will be used in incremental updates where FileName instances
                // may be new instances from a complete file system enumeration.
                var files = new Dictionary <FileName, FileWithContents>(entities.Files.Count);
                var filesWithContentsArray = new FileWithContents[entities.Files.Count];
                int filesWithContentsIndex = 0;
                foreach (var kvp in entities.Files)
                {
                    var fileData = kvp.Value.FileWithContents;
                    files.Add(kvp.Key, fileData);
                    if (fileData.Contents != null && fileData.Contents.ByteLength > 0)
                    {
                        filesWithContentsArray[filesWithContentsIndex++] = fileData;
                    }
                }
                var filesWithContents            = new ListSegment <FileWithContents>(filesWithContentsArray, 0, filesWithContentsIndex);
                var searchableContentsCollection = CreateFilePieces(filesWithContents);
                FileDatabaseDebugLogger.LogFileContentsStats(filesWithContents);

                return(new FileDatabaseSnapshot(
                           entities.ProjectHashes,
                           files,
                           files.Keys.ToArray(),
                           directories,
                           searchableContentsCollection,
                           filesWithContents.Count));
            }
        }
Exemple #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));
        }
Exemple #5
0
        private FileDatabaseSnapshot CreateFileDatabase(FileSystemEntities entities,
                                                        bool notifyProgress,
                                                        CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            using (new TimeElapsedLogger("Freezing file database state", cancellationToken)) {
                var progress = notifyProgress ? _progressTrackerFactory.CreateIndeterminateTracker() : null;
                try {
                    progress?.DisplayProgress((i, n) => "Finalizing index update");

                    var directories = entities.Directories;
                    // Note: We cannot use "ReferenceEqualityComparer<FileName>" here because
                    // the dictionary will be used in incremental updates where FileName instances
                    // may be new instances from a complete file system enumeration.
                    var files = new SlimHashTable <FileName, FileWithContents>(v => v.FileName, entities.Files.Count);
                    foreach (var kvp in entities.Files)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        files.Add(kvp.Key, new FileWithContents(kvp.Value.FileName, kvp.Value.Contents));
                    }

                    return(new FileDatabaseSnapshot(entities.ProjectHashes, directories, files));
                }
                finally {
                    progress?.Dispose();
                }
            }
        }
Exemple #6
0
        private FileContents LoadSingleFileContents(
            FileSystemEntities entities,
            FileContentsLoadingContext loadingContext,
            ProjectFileData projectFileData)
        {
            var fileName    = projectFileData.FileName;
            var oldFileData = loadingContext.OldFileDatabaseSnapshot.Files.GetValue(fileName);

            // If the file was never loaded before, just load it
            if (oldFileData == null || oldFileData.Contents == null)
            {
                return(LoadSingleFileContentsWorker(loadingContext, projectFileData));
            }

            bool isSearchable;

            // If the project configuration is unchanged from the previous file
            // database (and the file was present in it), then it is certainly
            // searchable, so no need to make an expensive call to "IsSearchable"
            // again.
            if (loadingContext.UnchangedProjects.Contains(projectFileData.Project))
            {
                isSearchable = true;
            }
            else
            {
                // If the file is not searchable in the current project, it should be
                // ignored too. Note that "IsSearachable" is a somewhat expensive
                // operation, as the filename is checked against potentially many glob
                // patterns.
                isSearchable = projectFileData.IsSearchable;
            }

            if (!isSearchable)
            {
                return(null);
            }

            // If the file has not changed since the previous snapshot, we can re-use
            // the former file contents snapshot.
            if (IsFileContentsUpToDate(entities, loadingContext.FullPathChanges, oldFileData))
            {
                return(oldFileData.Contents);
            }

            return(LoadSingleFileContentsWorker(loadingContext, projectFileData));
        }
Exemple #7
0
 /// <summary>
 /// Note: Concurrency: Updating an entry of the <see cref="FileSystemEntities.Files"/> table
 /// in this method assumes that 1) the entry exists and 2) the hash table implementation does not
 /// mutate any of its internal state when updating an existing entry.
 ///
 /// <para>
 /// 1) is verified by virtue of the <see cref="LoadFileContents"/> method implementation.</para>
 ///
 /// <para>
 /// 2) is verified because the two possible implementations, <see cref="Dictionary{TKey,TValue}"/>
 ///    and <see cref="SlimHashTable{TKey,TValue}"/> behave that way.</para>
 /// </summary>
 private static void DangerousUpdateFileSystemEntitiesEntry(FileSystemEntities entities,
                                                            KeyValuePair <FileName, ProjectFileData> fileEntry,
                                                            FileContents contents)
 {
     entities.Files[fileEntry.Key] = fileEntry.Value.WithContents(contents);
 }