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