Beispiel #1
0
        public FileSystemTreeSnapshot Compute(
            IFileSystemNameFactory fileNameFactory,
            FileSystemTreeSnapshot oldSnapshot,
            FullPathChanges pathChanges /* may be null */,
            List <FullPath> rootFiles,
            int version)
        {
            using (var progress = _progressTrackerFactory.CreateIndeterminateTracker()) {
                var projectRoots =
                    rootFiles
                    .Select(filename => _projectDiscovery.GetProject(filename))
                    .Where(project => project != null)
                    .Distinct(new ProjectPathComparer())
                    .Select(project => {
                    var data = new ProjectProcessingData {
                        FileSystemNameFactory = fileNameFactory,
                        Project     = project,
                        Progress    = progress,
                        OldSnapshot = oldSnapshot,
                        PathChanges = (pathChanges == null ? null : new ProjectPathChanges(project.RootPath, pathChanges.Entries)),
                    };
                    var rootSnapshot = ProcessProject(data);
                    return(new ProjectRootSnapshot(project, rootSnapshot));
                })
                    .OrderBy(projectRoot => projectRoot.Directory.DirectoryName)
                    .ToReadOnlyCollection();

                return(new FileSystemTreeSnapshot(version, projectRoots));
            }
        }
    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();
              }
        }
        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);
        }
    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;
      }
    }
    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);
      }
    }