platform: minor VFS optimization and cleanup

This commit is contained in:
Roman Shevchenko
2014-01-02 11:25:53 +01:00
parent eead8f15e1
commit 63cf5b9762
2 changed files with 77 additions and 78 deletions
@@ -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<String, VirtualFileSystemEntry> myRoots = new THashMap<String, VirtualFileSystemEntry>(FileUtil.PATH_HASHING_STRATEGY);
// root.getId() -> root. guarded by myRootsLock
private final Map<String, VirtualFileSystemEntry> myRoots = ContainerUtil.newTroveMap(FileUtil.PATH_HASHING_STRATEGY);
private final TIntObjectHashMap<VirtualFileSystemEntry> myRootsById = new TIntObjectHashMap<VirtualFileSystemEntry>();
private final ConcurrentIntObjectMap<VirtualFileSystemEntry> myIdToDirCache = new StripedLockIntObjectConcurrentHashMap<VirtualFileSystemEntry>();
@@ -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<VFileContentChangeEvent> 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<VFileEvent> validated = validateEvents(events);
BulkFileListener publisher = myEventsBus.syncPublisher(VirtualFileManager.VFS_CHANGES);
BulkFileListener publisher = myEventBus.syncPublisher(VirtualFileManager.VFS_CHANGES);
publisher.before(validated);
THashMap<VirtualFile, List<VFileEvent>> 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;
@@ -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());