private void LoadFileContents(FileContentsLoadingInfo loadingInfo)
        {
            using (var logger = new TimeElapsedLogger("Loading file contents from disk")) {
                using (var progress = _progressTrackerFactory.CreateTracker(_files.Count)) {
                    _files.AsParallel().ForAll(fileEntry => {
                        Debug.Assert(fileEntry.Value.FileData.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));
                        }

                        var contents = LoadSingleFileContents(loadingInfo, fileEntry.Value);
                        if (contents != null)
                        {
                            fileEntry.Value.FileData.UpdateContents(contents);
                        }
                    });
                }
            }
            Logger.LogInfo("Loaded {0:n0} text files from disk, skipped {1:n0} binary files.",
                           loadingInfo.LoadedTextFileCount,
                           loadingInfo.LoadedBinaryFileCount);
        }
        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());
            }
        }