diff options
Diffstat (limited to 'platform/platform-impl/src/com/intellij/openapi/vfs')
4 files changed, 82 insertions, 22 deletions
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java index 071a260fe68c..a95597514bb1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java @@ -15,12 +15,14 @@ */ package com.intellij.openapi.vfs.ex.dummy; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerAdapter; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.BidirectionalMap; @@ -32,7 +34,6 @@ import org.jetbrains.annotations.TestOnly; import java.io.IOException; import java.util.Collection; -import java.util.Iterator; import java.util.List; /** @@ -76,11 +77,6 @@ public abstract class DummyCachingFileSystem<T extends VirtualFile> extends Dumm public void projectOpened(final Project project) { onProjectOpened(project); } - - @Override - public void projectClosed(final Project project) { - onProjectClosed(project); - } }); initProjectMap(); } @@ -135,7 +131,16 @@ public abstract class DummyCachingFileSystem<T extends VirtualFile> extends Dumm clearCache(); } - public void onProjectOpened(Project project) { + public void onProjectOpened(final Project project) { + // use Disposer instead of ProjectManagerListener#projectClosed() because Disposer.dispose(project) + // is called later and some cached files should stay valid till the last moment + Disposer.register(project, new Disposable() { + @Override + public void dispose() { + onProjectClosed(project); + } + }); + clearCache(); String projectId = project.getLocationHash(); myProject2Id.put(project, projectId); @@ -157,13 +162,11 @@ public abstract class DummyCachingFileSystem<T extends VirtualFile> extends Dumm } protected void clearInvalidFiles() { - for (Iterator<String> it = myCachedFiles.keySet().iterator(); it.hasNext(); ) { - String path = it.next(); - T t = myCachedFiles.get(path); - if (t == null || !t.isValid()) { - it.remove(); - } + for (T t : myCachedFiles.notNullValues()) { + if (!t.isValid()) myCachedFiles.removeValue(t); } + //noinspection StatementWithEmptyBody + while (myCachedFiles.removeValue(null)) ; } @TestOnly diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsRootAccess.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsRootAccess.java index b6fa97092059..5a0f433c7828 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsRootAccess.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsRootAccess.java @@ -49,7 +49,7 @@ import java.util.Set; public class VfsRootAccess { private static final boolean SHOULD_PERFORM_ACCESS_CHECK = System.getenv("NO_FS_ROOTS_ACCESS_CHECK") == null; // we don't want test subclasses to accidentally remove allowed files, added by base classes - private static final Set<String> ourAdditionalRoots = new THashSet<String>(); + private static final Set<String> ourAdditionalRoots = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY); private static boolean insideGettingRoots; @TestOnly @@ -109,7 +109,7 @@ public class VfsRootAccess { Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); if (openProjects.length == 0) return null; - final Set<String> allowed = new THashSet<String>(); + final Set<String> allowed = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY); allowed.add(FileUtil.toSystemIndependentName(PathManager.getHomePath())); try { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java index b05b7a285e7b..b8a55b333203 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java @@ -29,6 +29,7 @@ import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; import com.intellij.openapi.util.io.ByteSequence; import com.intellij.openapi.util.io.FileAttributes; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.newvfs.FileAttribute; import com.intellij.openapi.vfs.newvfs.impl.FileNameCache; import com.intellij.util.ArrayUtil; import com.intellij.util.SystemProperties; @@ -57,6 +58,7 @@ public class FSRecords implements Forceable { private static final Logger LOG = Logger.getInstance("#com.intellij.vfs.persistent.FSRecords"); public static final boolean weHaveContentHashes = SystemProperties.getBooleanProperty("idea.share.contents", true); + public static final boolean lazyVfsDataCleaning = SystemProperties.getBooleanProperty("idea.lazy.vfs.data.cleaning", true); private static final int VERSION = 20 + (weHaveContentHashes ? 0x10:0) + (IOUtil.ourByteBuffersUseNativeByteOrder ? 0x37:0); private static final int PARENT_OFFSET = 0; @@ -558,6 +560,7 @@ public class FSRecords implements Forceable { return newRecord; } else { + if (lazyVfsDataCleaning) deleteContentAndAttributes(free); DbConnection.cleanRecord(free); return free; } @@ -588,7 +591,33 @@ public class FSRecords implements Forceable { try { w.lock(); incModCount(id); - doDeleteRecursively(id); + if (lazyVfsDataCleaning) { + markAsDeletedRecursively(id); + } else { + doDeleteRecursively(id); + } + } + catch (Throwable e) { + throw DbConnection.handleError(e); + } + finally { + w.unlock(); + } + } + + private static void markAsDeletedRecursively(final int id) { + for (int subrecord : list(id)) { + markAsDeletedRecursively(subrecord); + } + + markAsDeleted(id); + } + + private static void markAsDeleted(final int id) { + try { + w.lock(); + DbConnection.markDirty(); + addToFreeRecordsList(id); } catch (Throwable e) { throw DbConnection.handleError(e); @@ -1206,12 +1235,26 @@ public class FSRecords implements Forceable { } @Nullable - static DataInputStream readAttributeWithLock(int fileId, String attId) { + public static DataInputStream readAttributeWithLock(int fileId, FileAttribute att) { try { - synchronized (attId) { + synchronized (att.getId()) { try { r.lock(); - return readAttribute(fileId, attId); + DataInputStream stream = readAttribute(fileId, att.getId()); + if (stream != null) { + try { + int actualVersion = DataInputOutputUtil.readINT(stream); + if (actualVersion != att.getVersion()) { + stream.close(); + return null; + } + } + catch (IOException e) { + stream.close(); + return null; + } + } + return stream; } finally { r.unlock(); @@ -1280,7 +1323,9 @@ public class FSRecords implements Forceable { private static void checkFileIsValid(int fileId) { assert fileId > 0 : fileId; // TODO: This assertion is a bit timey, will remove when bug is caught. - assert (getFlags(fileId) & FREE_RECORD_FLAG) == 0 : "Accessing attribute of a deleted page: " + fileId + ":" + getName(fileId); + if (!lazyVfsDataCleaning) { + assert (getFlags(fileId) & FREE_RECORD_FLAG) == 0 : "Accessing attribute of a deleted page: " + fileId + ":" + getName(fileId); + } } public static int acquireFileContent(int fileId) { @@ -1374,6 +1419,18 @@ public class FSRecords implements Forceable { return new AttributeOutputStream(fileId, attId, fixedSize); } + @NotNull + public static DataOutputStream writeAttribute(final int fileId, @NotNull FileAttribute att) { + DataOutputStream stream = writeAttribute(fileId, att.getId(), att.isFixedSize()); + try { + DataInputOutputUtil.writeINT(stream, att.getVersion()); + } + catch (IOException e) { + throw new RuntimeException(e); + } + return stream; + } + private static class ContentOutputStream extends DataOutputStream { protected final int myFileId; protected final boolean myFixedSize; 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 db5de4258d41..6e135018d356 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 @@ -223,13 +223,13 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone @Override @Nullable public DataInputStream readAttribute(@NotNull final VirtualFile file, @NotNull final FileAttribute att) { - return FSRecords.readAttributeWithLock(getFileId(file), att.getId()); + return FSRecords.readAttributeWithLock(getFileId(file), att); } @Override @NotNull public DataOutputStream writeAttribute(@NotNull final VirtualFile file, @NotNull final FileAttribute att) { - return FSRecords.writeAttribute(getFileId(file), att.getId(), att.isFixedSize()); + return FSRecords.writeAttribute(getFileId(file), att); } @Nullable |