From 63cf5b9762da844c70c0bad1dce428eeea321e62 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 30 Dec 2013 15:43:21 +0100 Subject: [PATCH] platform: minor VFS optimization and cleanup --- .../newvfs/persistent/PersistentFSImpl.java | 52 ++++----- .../vfs/local/LocalFileSystemTest.java | 103 +++++++++--------- 2 files changed, 77 insertions(+), 78 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java index e6d42d67df93..f1718dd2a533 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java @@ -45,6 +45,7 @@ import org.jetbrains.annotations.TestOnly; import java.io.*; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -54,12 +55,10 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; public class PersistentFSImpl extends PersistentFS implements ApplicationComponent { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.newvfs.persistent.PersistentFS"); - private final MessageBus myEventsBus; + private final MessageBus myEventBus; private final ReadWriteLock myRootsLock = new ReentrantReadWriteLock(); - // (normalized)url -> root. guarded by myRootsLock - private final Map myRoots = new THashMap(FileUtil.PATH_HASHING_STRATEGY); - // root.getId() -> root. guarded by myRootsLock + private final Map myRoots = ContainerUtil.newTroveMap(FileUtil.PATH_HASHING_STRATEGY); private final TIntObjectHashMap myRootsById = new TIntObjectHashMap(); private final ConcurrentIntObjectMap myIdToDirCache = new StripedLockIntObjectConcurrentHashMap(); @@ -67,17 +66,17 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone // the root of all roots. All roots in myRoots and myRootsById maps are children of this super root. guarded by myRootsLock @Nullable private volatile VirtualFileSystemEntry mySuperRoot; - private boolean myShutDown = false; - @SuppressWarnings("UnusedDeclaration") - private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() { - @Override - public void run() { - clearIdCache(); - } - }); - public PersistentFSImpl(@NotNull final MessageBus bus) { - myEventsBus = bus; + private final AtomicBoolean myShutDown = new AtomicBoolean(false); + + public PersistentFSImpl(@NotNull MessageBus bus) { + myEventBus = bus; + LowMemoryWatcher.register(new Runnable() { + @Override + public void run() { + clearIdCache(); + } + }); ShutDownTracker.getInstance().registerShutdownTask(new Runnable() { @Override public void run() { @@ -86,14 +85,18 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone }); } + @Override + public void initComponent() { + FSRecords.connect(); + } + @Override public void disposeComponent() { performShutdown(); } - private synchronized void performShutdown() { - if (!myShutDown) { - myShutDown = true; + private void performShutdown() { + if (myShutDown.compareAndSet(false, true)) { LOG.info("VFS dispose started"); FSRecords.dispose(); LOG.info("VFS dispose completed"); @@ -107,11 +110,6 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone return "app.component.PersistentFS"; } - @Override - public void initComponent() { - FSRecords.connect(); - } - @Override public boolean areChildrenLoaded(@NotNull final VirtualFile dir) { return areChildrenLoaded(getFileId(dir)); @@ -626,7 +624,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone VFileContentChangeEvent event = new VFileContentChangeEvent(requestor, file, file.getModificationStamp(), modStamp, false); List events = Collections.singletonList(event); - BulkFileListener publisher = myEventsBus.syncPublisher(VirtualFileManager.VFS_CHANGES); + BulkFileListener publisher = myEventBus.syncPublisher(VirtualFileManager.VFS_CHANGES); publisher.before(events); NewVirtualFileSystem delegate = getDelegate(file); @@ -743,7 +741,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone List validated = validateEvents(events); - BulkFileListener publisher = myEventsBus.syncPublisher(VirtualFileManager.VFS_CHANGES); + BulkFileListener publisher = myEventBus.syncPublisher(VirtualFileManager.VFS_CHANGES); publisher.before(validated); THashMap> parentToChildrenEventsChanges = null; @@ -869,8 +867,6 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone if (root != null) return root; int rootId = FSRecords.findRootRecord(rootUrl); - root = myRootsById.get(rootId); - if (root != null) return root; if (isFakeRoot) { // fake super-root @@ -885,8 +881,6 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone // 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); } @@ -910,7 +904,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone myRoots.put(rootUrl, root); myRootsById.put(rootId, root); - if (rootId != root.getId()) throw new AssertionError(); + LOG.assertTrue(rootId == root.getId(), "root=" + root + " expected=" + rootId + " actual=" + root.getId()); } return root; diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/LocalFileSystemTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/LocalFileSystemTest.java index 37122a77b349..4442d1caf5ba 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/LocalFileSystemTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/LocalFileSystemTest.java @@ -46,6 +46,8 @@ import java.util.List; import java.util.Locale; public class LocalFileSystemTest extends PlatformLangTestCase { + private LocalFileSystem myFS; + @Override protected void setUp() throws Exception { super.setUp(); @@ -68,13 +70,21 @@ public class LocalFileSystemTest extends PlatformLangTestCase { } } }); + + myFS = LocalFileSystem.getInstance(); + } + + @Override + protected void tearDown() throws Exception { + myFS = null; + super.tearDown(); } public void testChildrenAccessedButNotCached() throws Exception { File dir = createTempDirectory(false); ManagingFS managingFS = ManagingFS.getInstance(); - VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(dir.getPath().replace(File.separatorChar, '/')); + VirtualFile vFile = myFS.refreshAndFindFileByPath(dir.getPath().replace(File.separatorChar, '/')); assertNotNull(vFile); assertFalse(managingFS.areChildrenLoaded(vFile)); assertFalse(managingFS.wereChildrenAccessed(vFile)); @@ -91,12 +101,12 @@ public class LocalFileSystemTest extends PlatformLangTestCase { boolean subChildCreated = subChild.createNewFile(); assertTrue(subChildCreated); - VirtualFile childVFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(child.getPath().replace(File.separatorChar, '/')); + VirtualFile childVFile = myFS.refreshAndFindFileByPath(child.getPath().replace(File.separatorChar, '/')); assertNotNull(childVFile); assertFalse(managingFS.areChildrenLoaded(vFile)); assertTrue(managingFS.wereChildrenAccessed(vFile)); - VirtualFile subdirVFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(subdir.getPath().replace(File.separatorChar, '/')); + VirtualFile subdirVFile = myFS.refreshAndFindFileByPath(subdir.getPath().replace(File.separatorChar, '/')); assertNotNull(subdirVFile); assertFalse(managingFS.areChildrenLoaded(subdirVFile)); assertFalse(managingFS.wereChildrenAccessed(subdirVFile)); @@ -109,7 +119,7 @@ public class LocalFileSystemTest extends PlatformLangTestCase { assertFalse(managingFS.areChildrenLoaded(subdirVFile)); assertFalse(managingFS.wereChildrenAccessed(subdirVFile)); - VirtualFile subChildVFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(subChild.getPath().replace(File.separatorChar, '/')); + VirtualFile subChildVFile = myFS.refreshAndFindFileByPath(subChild.getPath().replace(File.separatorChar, '/')); assertNotNull(subChildVFile); assertTrue(managingFS.areChildrenLoaded(vFile)); assertTrue(managingFS.wereChildrenAccessed(vFile)); @@ -120,7 +130,7 @@ public class LocalFileSystemTest extends PlatformLangTestCase { public void testRefreshAndFindFile() throws Exception { File dir = createTempDirectory(); - VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(dir.getPath().replace(File.separatorChar, '/')); + VirtualFile vFile = myFS.refreshAndFindFileByPath(dir.getPath().replace(File.separatorChar, '/')); assertNotNull(vFile); vFile.getChildren(); @@ -132,7 +142,7 @@ public class LocalFileSystemTest extends PlatformLangTestCase { File subdir = new File(dir, "aaa"); assertTrue(subdir.mkdir()); - VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(subdir.getPath().replace(File.separatorChar, '/')); + VirtualFile file = myFS.refreshAndFindFileByPath(subdir.getPath().replace(File.separatorChar, '/')); assertNotNull(file); } @@ -140,8 +150,8 @@ public class LocalFileSystemTest extends PlatformLangTestCase { File fromDir = createTempDirectory(); File toDir = createTempDirectory(); - VirtualFile fromVDir = LocalFileSystem.getInstance().findFileByPath(fromDir.getPath().replace(File.separatorChar, '/')); - VirtualFile toVDir = LocalFileSystem.getInstance().findFileByPath(toDir.getPath().replace(File.separatorChar, '/')); + VirtualFile fromVDir = myFS.findFileByPath(fromDir.getPath().replace(File.separatorChar, '/')); + VirtualFile toVDir = myFS.findFileByPath(toDir.getPath().replace(File.separatorChar, '/')); assertNotNull(fromVDir); assertNotNull(toVDir); final VirtualFile fileToCopy = fromVDir.createChildData(this, "temp_file"); @@ -157,8 +167,8 @@ public class LocalFileSystemTest extends PlatformLangTestCase { File fromDir = createTempDirectory(); File toDir = createTempDirectory(); - VirtualFile fromVDir = LocalFileSystem.getInstance().findFileByPath(fromDir.getPath().replace(File.separatorChar, '/')); - VirtualFile toVDir = LocalFileSystem.getInstance().findFileByPath(toDir.getPath().replace(File.separatorChar, '/')); + VirtualFile fromVDir = myFS.findFileByPath(fromDir.getPath().replace(File.separatorChar, '/')); + VirtualFile toVDir = myFS.findFileByPath(toDir.getPath().replace(File.separatorChar, '/')); assertNotNull(fromVDir); assertNotNull(toVDir); final VirtualFile dirToCopy = fromVDir.createChildDirectory(this, "dir"); @@ -177,48 +187,48 @@ public class LocalFileSystemTest extends PlatformLangTestCase { boolean created = childFile.createNewFile(); assert created || childFile.exists() : childFile; - final VirtualFile dir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(dirFile); + final VirtualFile dir = myFS.refreshAndFindFileByIoFile(dirFile); assertNotNull(dir); - final VirtualFile child = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(childFile); + final VirtualFile child = myFS.refreshAndFindFileByIoFile(childFile); assertNotNull(child); assertTrue(childFile.delete()); } public void testFindRoot() throws IOException { - VirtualFile root = LocalFileSystem.getInstance().findFileByPath("wrong_path"); + VirtualFile root = myFS.findFileByPath("wrong_path"); assertNull(root); VirtualFile root2; if (SystemInfo.isWindows) { - root = LocalFileSystem.getInstance().findFileByPath("\\\\unit-133"); + root = myFS.findFileByPath("\\\\unit-133"); assertNotNull(root); - root2 = LocalFileSystem.getInstance().findFileByPath("//UNIT-133"); + root2 = myFS.findFileByPath("//UNIT-133"); assertNotNull(root2); assertEquals(String.valueOf(root2), root, root2); RefreshQueue.getInstance().processSingleEvent(new VFileDeleteEvent(this, root, false)); - root = LocalFileSystem.getInstance().findFileByIoFile(new File("\\\\unit-133")); + root = myFS.findFileByIoFile(new File("\\\\unit-133")); assertNotNull(root); RefreshQueue.getInstance().processSingleEvent(new VFileDeleteEvent(this, root, false)); if (new File("c:").exists()) { - root = LocalFileSystem.getInstance().findFileByPath("c:"); + root = myFS.findFileByPath("c:"); assertNotNull(root); assertEquals("C:/", root.getPath()); - root2 = LocalFileSystem.getInstance().findFileByPath("C:\\"); + root2 = myFS.findFileByPath("C:\\"); assertEquals(String.valueOf(root2), root, root2); } } else if (SystemInfo.isUnix) { - root = LocalFileSystem.getInstance().findFileByPath("/"); + root = myFS.findFileByPath("/"); assertNotNull(root); assertEquals(root.getPath(), "/"); } - root = LocalFileSystem.getInstance().findFileByPath(""); + root = myFS.findFileByPath(""); assertNotNull(root); File jarFile = IoTestUtil.createTestJar(); @@ -237,7 +247,7 @@ public class LocalFileSystemTest extends PlatformLangTestCase { public void testFileLength() throws Exception { File file = FileUtil.createTempFile("test", "txt"); FileUtil.writeToFile(file, "hello"); - VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file); + VirtualFile virtualFile = myFS.refreshAndFindFileByIoFile(file); assertNotNull(virtualFile); String s = VfsUtilCore.loadText(virtualFile); assertEquals("hello", s); @@ -266,12 +276,12 @@ public class LocalFileSystemTest extends PlatformLangTestCase { assertTrue(targetFile.createNewFile()); final File hardLinkFile = IoTestUtil.createHardLink(targetFile.getAbsolutePath(), "hardLinkFile"); - final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(targetFile); + final VirtualFile file = myFS.refreshAndFindFileByIoFile(targetFile); assertNotNull(file); file.setBinaryContent("hello".getBytes("UTF-8"), 0, 0, requestor); assertTrue(file.getLength() > 0); - final VirtualFile check = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(hardLinkFile); + final VirtualFile check = myFS.refreshAndFindFileByIoFile(hardLinkFile); assertNotNull(check); assertEquals(file.getLength(), check.getLength()); assertEquals("hello", VfsUtilCore.loadText(check)); @@ -297,7 +307,7 @@ public class LocalFileSystemTest extends PlatformLangTestCase { String parent = FileUtil.toSystemIndependentName(file.getParent()); VirtualDirectoryImpl.allowRootAccess(parent); try { - VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file); + VirtualFile virtualFile = myFS.refreshAndFindFileByIoFile(file); assertNotNull(virtualFile); NewVirtualFileSystem fs = (NewVirtualFileSystem)virtualFile.getFileSystem(); @@ -316,8 +326,7 @@ public class LocalFileSystemTest extends PlatformLangTestCase { String content = ""; FileUtil.writeToFile(new File(testDir, "Foo.java"), content); - LocalFileSystem local = LocalFileSystem.getInstance(); - VirtualFile virtualDir = local.findFileByIoFile(testDir); + VirtualFile virtualDir = myFS.findFileByIoFile(testDir); assert virtualDir != null : testDir; virtualDir.getChildren(); virtualDir.refresh(false, true); @@ -341,7 +350,7 @@ public class LocalFileSystemTest extends PlatformLangTestCase { public void testSingleFileRootRefresh() throws Exception { File file = FileUtil.createTempFile("test.", ".txt"); - VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file); + VirtualFile virtualFile = myFS.refreshAndFindFileByIoFile(file); assertNotNull(virtualFile); assertTrue(virtualFile.exists()); assertTrue(virtualFile.isValid()); @@ -365,22 +374,21 @@ public class LocalFileSystemTest extends PlatformLangTestCase { final File dir = FileUtil.createTempDirectory("test.", ".dir"); final File file = FileUtil.createTempFile(dir, "test\\", "\\txt", true); - final VirtualFile vDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(dir); + final VirtualFile vDir = myFS.refreshAndFindFileByIoFile(dir); assertNotNull(vDir); assertEquals(0, vDir.getChildren().length); ((VirtualFileSystemEntry)vDir).markDirtyRecursively(); vDir.refresh(false, true); - final VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file); + final VirtualFile vFile = myFS.refreshAndFindFileByIoFile(file); assertNull(vFile); } public void testGetAttributesConvertsToAbsolute() throws Exception { - PersistentFS fs = PersistentFS.getInstance(); - LocalFileSystem lfs = LocalFileSystem.getInstance(); - NewVirtualFile fakeRoot = fs.findRoot("", lfs); + NewVirtualFile fakeRoot = PersistentFS.getInstance().findRoot("", myFS); assertNotNull(fakeRoot); + File userDir = new File(System.getProperty("user.dir")); File[] files = userDir.listFiles(); File fileToQuery; @@ -396,14 +404,14 @@ public class LocalFileSystemTest extends PlatformLangTestCase { return; } - FileAttributes attributes = lfs.getAttributes(new FakeVirtualFile(fakeRoot, fileToQuery.getName())); + FileAttributes attributes = myFS.getAttributes(new FakeVirtualFile(fakeRoot, fileToQuery.getName())); assertNull(attributes); - attributes = lfs.getAttributes(new FakeVirtualFile(fakeRoot, "windows")); + attributes = myFS.getAttributes(new FakeVirtualFile(fakeRoot, "windows")); assertNull(attributes); - attributes = lfs.getAttributes(new FakeVirtualFile(fakeRoot, "usr")); + attributes = myFS.getAttributes(new FakeVirtualFile(fakeRoot, "usr")); assertNull(attributes); - attributes = lfs.getAttributes(new FakeVirtualFile(fakeRoot, "Users")); + attributes = myFS.getAttributes(new FakeVirtualFile(fakeRoot, "Users")); assertNull(attributes); } @@ -412,12 +420,11 @@ public class LocalFileSystemTest extends PlatformLangTestCase { File sub = IoTestUtil.createTestDir(top, "sub"); File file = IoTestUtil.createTestFile(top, "file.txt", "hi there"); - LocalFileSystem lfs = LocalFileSystem.getInstance(); - VirtualFile topDir = lfs.refreshAndFindFileByIoFile(top); + VirtualFile topDir = myFS.refreshAndFindFileByIoFile(top); assertNotNull(topDir); - VirtualFile sourceFile = lfs.refreshAndFindFileByIoFile(file); + VirtualFile sourceFile = myFS.refreshAndFindFileByIoFile(file); assertNotNull(sourceFile); - VirtualFile parentDir = lfs.refreshAndFindFileByIoFile(sub); + VirtualFile parentDir = myFS.refreshAndFindFileByIoFile(sub); assertNotNull(parentDir); assertEquals(2, topDir.getChildren().length); @@ -444,10 +451,9 @@ public class LocalFileSystemTest extends PlatformLangTestCase { File file = IoTestUtil.createTestFile(top, "file.txt", "test"); File intermediate = new File(top, "_intermediate_"); - LocalFileSystem lfs = LocalFileSystem.getInstance(); - VirtualFile topDir = lfs.refreshAndFindFileByIoFile(top); + VirtualFile topDir = myFS.refreshAndFindFileByIoFile(top); assertNotNull(topDir); - VirtualFile sourceFile = lfs.refreshAndFindFileByIoFile(file); + VirtualFile sourceFile = myFS.refreshAndFindFileByIoFile(file); assertNotNull(sourceFile); String newName = StringUtil.capitalize(file.getName()); @@ -514,14 +520,13 @@ public class LocalFileSystemTest extends PlatformLangTestCase { File target = IoTestUtil.createTestDir(top, "target"); File link = IoTestUtil.createSymLink(target.getPath(), top.getPath() + "/link"); - LocalFileSystem lfs = LocalFileSystem.getInstance(); - VirtualFile vTop = lfs.refreshAndFindFileByIoFile(top); + VirtualFile vTop = myFS.refreshAndFindFileByIoFile(top); assertNotNull(vTop); assertTrue(vTop.isValid()); - VirtualFile vTarget = lfs.refreshAndFindFileByIoFile(target); + VirtualFile vTarget = myFS.refreshAndFindFileByIoFile(target); assertNotNull(vTarget); assertTrue(vTarget.isValid()); - VirtualFile vLink = lfs.refreshAndFindFileByIoFile(link); + VirtualFile vLink = myFS.refreshAndFindFileByIoFile(link); assertNotNull(vLink); assertTrue(vLink.isValid()); assertTrue(vLink.isDirectory()); @@ -530,7 +535,7 @@ public class LocalFileSystemTest extends PlatformLangTestCase { vTop.refresh(false, true); assertFalse(vTarget.isValid()); assertFalse(vLink.isValid()); - vLink = lfs.refreshAndFindFileByIoFile(link); + vLink = myFS.refreshAndFindFileByIoFile(link); assertNotNull(vLink); assertTrue(vLink.isValid()); assertFalse(vLink.isDirectory()); @@ -538,7 +543,7 @@ public class LocalFileSystemTest extends PlatformLangTestCase { FileUtil.createDirectory(target); vTop.refresh(false, true); assertFalse(vLink.isValid()); - vLink = lfs.refreshAndFindFileByIoFile(link); + vLink = myFS.refreshAndFindFileByIoFile(link); assertNotNull(vLink); assertTrue(vLink.isValid()); assertTrue(vLink.isDirectory());