Beispiel #1
0
  private void executeDelete(@NotNull VirtualFile file) {
    if (!file.exists()) {
      LOG.error("Deleting a file, which does not exist: " + file.getPath());
      return;
    }
    clearIdCache();

    int id = getFileId(file);

    final VirtualFile parent = file.getParent();
    final int parentId = parent == null ? 0 : getFileId(parent);

    if (parentId == 0) {
      String rootUrl =
          normalizeRootUrl(file.getPath(), (NewVirtualFileSystem) file.getFileSystem());
      myRootsLock.writeLock().lock();
      try {
        myRoots.remove(rootUrl);
        myRootsById.remove(id);
        FSRecords.deleteRootRecord(id);
      } finally {
        myRootsLock.writeLock().unlock();
      }
    } else {
      removeIdFromParentList(parentId, id, parent, file);
      VirtualDirectoryImpl directory = (VirtualDirectoryImpl) file.getParent();
      assert directory != null : file;
      directory.removeChild(file);
    }

    FSRecords.deleteRecordRecursively(id);

    invalidateSubtree(file);
  }
Beispiel #2
0
  @Nullable
  private VirtualFileSystemEntry findFileById(
      int id, boolean cachedOnly, TIntArrayList visited, int mask) {
    VirtualFileSystemEntry cached = myIdToDirCache.get(id);
    if (cached != null) return cached;

    if (visited != null
        && (visited.size() >= DEPTH_LIMIT || (mask & id) == id && visited.contains(id))) {
      @NonNls
      String sb =
          "Dead loop detected in persistent FS (id=" + id + " cached-only=" + cachedOnly + "):";
      for (int i = 0; i < visited.size(); i++) {
        int _id = visited.get(i);
        sb +=
            "\n  "
                + _id
                + " '"
                + getName(_id)
                + "' "
                + String.format("%02x", getFileAttributes(_id))
                + ' '
                + myIdToDirCache.containsKey(_id);
      }
      LOG.error(sb);
      return null;
    }

    int parentId = getParent(id);
    if (parentId >= id) {
      if (visited == null) visited = new TIntArrayList(DEPTH_LIMIT);
    }
    if (visited != null) visited.add(id);

    VirtualFileSystemEntry result;
    if (parentId == 0) {
      myRootsLock.readLock().lock();
      try {
        result = myRootsById.get(id);
      } finally {
        myRootsLock.readLock().unlock();
      }
    } else {
      VirtualFileSystemEntry parentFile = findFileById(parentId, cachedOnly, visited, mask | id);
      if (parentFile instanceof VirtualDirectoryImpl) {
        result = ((VirtualDirectoryImpl) parentFile).findChildById(id, cachedOnly);
      } else {
        result = null;
      }
    }

    if (result != null && result.isDirectory()) {
      VirtualFileSystemEntry old = myIdToDirCache.put(id, result);
      if (old != null) result = old;
    }
    return result;
  }
  private void storeIds(@NotNull ConcurrentIntObjectMap<int[]> fileToForwardIds) {
    int forwardSize = 0;
    int backwardSize = 0;
    final TIntObjectHashMap<TIntArrayList> fileToBackwardIds =
        new TIntObjectHashMap<TIntArrayList>(fileToForwardIds.size());
    for (ConcurrentIntObjectMap.IntEntry<int[]> entry : fileToForwardIds.entries()) {
      int fileId = entry.getKey();
      int[] forwardIds = entry.getValue();
      forwardSize += forwardIds.length;
      for (int forwardId : forwardIds) {
        TIntArrayList backIds = fileToBackwardIds.get(forwardId);
        if (backIds == null) {
          backIds = new TIntArrayList();
          fileToBackwardIds.put(forwardId, backIds);
        }
        backIds.add(fileId);
        backwardSize++;
      }
    }
    log("backwardSize = " + backwardSize);
    log("forwardSize = " + forwardSize);
    log("fileToForwardIds.size() = " + fileToForwardIds.size());
    log("fileToBackwardIds.size() = " + fileToBackwardIds.size());
    assert forwardSize == backwardSize;

    // wrap in read action so that sudden quit (in write action) would not interrupt us
    myApplication.runReadAction(
        () -> {
          if (!myApplication.isDisposed()) {
            fileToBackwardIds.forEachEntry(
                new TIntObjectProcedure<TIntArrayList>() {
                  @Override
                  public boolean execute(int fileId, TIntArrayList backIds) {
                    storage.addAll(fileId, backIds.toNativeArray());
                    return true;
                  }
                });
          }
        });
  }
Beispiel #4
0
  @Override
  @Nullable
  public VirtualFileSystemEntry findRoot(
      @NotNull String basePath, @NotNull NewVirtualFileSystem fs) {
    if (basePath.isEmpty()) {
      LOG.error("Invalid root, fs=" + fs);
      return null;
    }

    String rootUrl = normalizeRootUrl(basePath, fs);

    myRootsLock.readLock().lock();
    try {
      VirtualFileSystemEntry root = myRoots.get(rootUrl);
      if (root != null) return root;
    } finally {
      myRootsLock.readLock().unlock();
    }

    final VirtualFileSystemEntry newRoot;
    int rootId = FSRecords.findRootRecord(rootUrl);

    VfsData.Segment segment = VfsData.getSegment(rootId, true);
    VfsData.DirectoryData directoryData = new VfsData.DirectoryData();
    if (fs instanceof ArchiveFileSystem) {
      String parentPath =
          basePath.substring(0, basePath.indexOf(ArchiveFileSystem.ARCHIVE_SEPARATOR));
      VirtualFile parentFile = LocalFileSystem.getInstance().findFileByPath(parentPath);
      if (parentFile == null) return null;
      FileType type = FileTypeRegistry.getInstance().getFileTypeByFileName(parentFile.getName());
      if (!(type instanceof ArchiveFileType)) return null;
      newRoot = new ArchiveRoot(fs, rootId, segment, directoryData, parentFile);
    } else {
      newRoot = new FsRoot(fs, rootId, segment, directoryData, basePath);
    }

    FileAttributes attributes =
        fs.getAttributes(
            new StubVirtualFile() {
              @NotNull
              @Override
              public String getPath() {
                return newRoot.getPath();
              }

              @Nullable
              @Override
              public VirtualFile getParent() {
                return null;
              }
            });
    if (attributes == null || !attributes.isDirectory()) {
      return null;
    }

    boolean mark = false;

    myRootsLock.writeLock().lock();
    try {
      VirtualFileSystemEntry root = myRoots.get(rootUrl);
      if (root != null) return root;

      VfsData.initFile(rootId, segment, -1, directoryData);
      mark = writeAttributesToRecord(rootId, 0, newRoot, fs, attributes);

      myRoots.put(rootUrl, newRoot);
      myRootsById.put(rootId, newRoot);
    } finally {
      myRootsLock.writeLock().unlock();
    }

    if (!mark && attributes.lastModified != FSRecords.getTimestamp(rootId)) {
      newRoot.markDirtyRecursively();
    }

    LOG.assertTrue(
        rootId == newRoot.getId(),
        "root=" + newRoot + " expected=" + rootId + " actual=" + newRoot.getId());

    return newRoot;
  }
  @Override
  @Nullable
  public VirtualFileSystemEntry findRoot(
      @NotNull String basePath, @NotNull NewVirtualFileSystem fs) {
    String rootUrl = normalizeRootUrl(basePath, fs);
    boolean isFakeRoot = basePath.isEmpty();
    VirtualFileSystemEntry root;

    myRootsLock.readLock().lock();
    try {
      root = isFakeRoot ? mySuperRoot : myRoots.get(rootUrl);
      if (root != null) return root;
    } finally {
      myRootsLock.readLock().unlock();
    }

    myRootsLock.writeLock().lock();
    try {
      root = isFakeRoot ? mySuperRoot : myRoots.get(rootUrl);
      if (root != null) return root;

      int rootId = FSRecords.findRootRecord(rootUrl);
      root = myRootsById.get(rootId);
      if (root != null) return root;

      if (isFakeRoot) {
        // fake super-root
        root = new FakeRoot(fs, rootId);
      } else if (fs instanceof JarFileSystem) {
        // optimization: for jar roots do not store base path in the myName field, use local FS
        // file's getPath()
        String parentPath = basePath.substring(0, basePath.indexOf(JarFileSystem.JAR_SEPARATOR));
        VirtualFile parentLocalFile = LocalFileSystem.getInstance().findFileByPath(parentPath);
        if (parentLocalFile == null) return null;

        // check one more time since the findFileByPath could have created the root (by reentering
        // the findRoot)
        root = myRoots.get(rootUrl);
        if (root != null) return root;
        root = myRootsById.get(rootId);
        if (root != null) return root;

        root = new JarRoot(fs, rootId, parentLocalFile);
      } else {
        root = new FsRoot(fs, rootId, basePath);
      }

      if (isFakeRoot) {
        mySuperRoot = root;
      } else {
        FileAttributes attributes = fs.getAttributes(root);
        if (attributes == null || !attributes.isDirectory()) {
          return null;
        }
        final boolean newRoot = writeAttributesToRecord(rootId, 0, root, fs, attributes);
        if (!newRoot && attributes.lastModified != FSRecords.getTimestamp(rootId)) {
          root.markDirtyRecursively();
        }

        myRoots.put(rootUrl, root);
        myRootsById.put(rootId, root);

        if (rootId != root.getId()) throw new AssertionError();
      }

      return root;
    } finally {
      myRootsLock.writeLock().unlock();
    }
  }