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();
              }
        }
        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);
        }