From b312dde1729c09cb39f6e567fc978fde1eb5e140 Mon Sep 17 00:00:00 2001 From: irengrig Date: Mon, 28 Nov 2011 14:45:35 +0400 Subject: [PATCH] IDEA-56157 Sort out performance problem with Perforce changelists refresh IDEA-67375 Files periodically loose their Perforce state P4 local changes provider refactored. 1)We calculated read-only unversioned only on start; after that, we listen to local changes and invalidate changes 2) [for big amount of edited files] when asking "p4 have" for changed files (to get to know their revisions), keep have commands limited by number of arguments --- .../process/CapturingProcessHandler.java | 2 +- .../execution/process/OSProcessHandler.java | 5 ++++ .../testFramework/vcs/MockDirtyScope.java | 5 ++++ .../openapi/vcs/ProjectLevelVcsManager.java | 2 ++ .../vcs/changes/ChangeListManagerGate.java | 2 ++ .../openapi/vcs/changes/VcsDirtyScope.java | 2 ++ .../vcs/changes/VcsModifiableDirtyScope.java | 2 ++ .../intellij/openapi/vcs/FilePathImpl.java | 7 +++++ .../openapi/vcs/changes/ChangeListWorker.java | 9 ++++++ .../vcs/changes/ChangeListsIndexes.java | 4 +++ .../vcs/changes/VcsDirtyScopeImpl.java | 29 +++++++++++++++++++ .../pending/MockChangeListManagerGate.java | 6 ++++ .../vcs/impl/ProjectLevelVcsManagerImpl.java | 5 ++++ .../openapi/vcs/impl/VcsRootIterator.java | 21 ++++++++++++-- .../idea/svn17/integrate/AlienDirtyScope.java | 4 +++ .../SvnChangesCorrectlyRefreshedTest.java | 2 +- .../idea/svn/integrate/AlienDirtyScope.java | 4 +++ 17 files changed, 106 insertions(+), 5 deletions(-) diff --git a/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java b/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java index d6c19c72cec0..6252ffcd6d8b 100644 --- a/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java +++ b/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java @@ -39,7 +39,7 @@ public class CapturingProcessHandler extends OSProcessHandler { } public CapturingProcessHandler(final Process process, final Charset charset, final String commandLine) { - super(process, commandLine); + super(process, commandLine, charset); myCharset = charset; addProcessListener(new ProcessAdapter() { @Override diff --git a/platform/platform-api/src/com/intellij/execution/process/OSProcessHandler.java b/platform/platform-api/src/com/intellij/execution/process/OSProcessHandler.java index 0870c5b6dd9c..7753c3a83499 100644 --- a/platform/platform-api/src/com/intellij/execution/process/OSProcessHandler.java +++ b/platform/platform-api/src/com/intellij/execution/process/OSProcessHandler.java @@ -22,11 +22,16 @@ import com.intellij.openapi.vfs.encoding.EncodingManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.nio.charset.Charset; import java.util.concurrent.Future; public class OSProcessHandler extends BaseOSProcessHandler { private static final Logger LOG = Logger.getInstance("#com.intellij.execution.process.OSProcessHandler"); + public OSProcessHandler(@NotNull final Process process, @Nullable final String commandLine, final Charset defaultCharset) { + super(process, commandLine, defaultCharset); + } + public OSProcessHandler(@NotNull final Process process, @Nullable final String commandLine) { super(process, commandLine, EncodingManager.getInstance().getDefaultCharset()); } diff --git a/platform/testFramework/src/com/intellij/testFramework/vcs/MockDirtyScope.java b/platform/testFramework/src/com/intellij/testFramework/vcs/MockDirtyScope.java index cb37d8d44fb8..8c13650649a3 100644 --- a/platform/testFramework/src/com/intellij/testFramework/vcs/MockDirtyScope.java +++ b/platform/testFramework/src/com/intellij/testFramework/vcs/MockDirtyScope.java @@ -110,6 +110,11 @@ public class MockDirtyScope extends VcsModifiableDirtyScope { throw new UnsupportedOperationException(); } + @Override + public void iterateExistingInsideScope(Processor vf) { + throw new UnsupportedOperationException(); + } + @Override public boolean isEmpty() { return myDirtyFiles.isEmpty(); diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java b/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java index f92ec57d1f81..b2c7e4b3c262 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java @@ -42,6 +42,8 @@ import java.util.List; public abstract class ProjectLevelVcsManager { @NonNls public static final String FILE_VIEW_TOOL_WINDOW_ID = "File View"; + public abstract void iterateVfUnderVcsRoot(VirtualFile file, Processor processor); + /** * Returns the ProjectLevelVcsManager instance for the specified project. * diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManagerGate.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManagerGate.java index 4c9e1a3e4dee..00c8583fe299 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManagerGate.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManagerGate.java @@ -19,6 +19,7 @@ import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.util.Collection; import java.util.List; @@ -40,4 +41,5 @@ public interface ChangeListManagerGate { void moveChanges(final String toList, final Collection changes); void setListsToDisappear(final Collection names); FileStatus getStatus(final VirtualFile file); + FileStatus getStatus(final File file); } diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScope.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScope.java index 5bd81bd0a16e..2e64217dae82 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScope.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScope.java @@ -91,6 +91,8 @@ public abstract class VcsDirtyScope { * @param iterator an iterator to invoke */ public abstract void iterate(Processor iterator); + + public abstract void iterateExistingInsideScope(Processor vf); public abstract boolean isEmpty(); diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsModifiableDirtyScope.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsModifiableDirtyScope.java index 5a67910bb9cd..7f8bc52c6c8f 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsModifiableDirtyScope.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsModifiableDirtyScope.java @@ -17,6 +17,8 @@ package com.intellij.openapi.vcs.changes; import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Processor; import org.jetbrains.annotations.Nullable; public abstract class VcsModifiableDirtyScope extends VcsDirtyScope { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/FilePathImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/FilePathImpl.java index 0238ea12eaf5..2035e149da97 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/FilePathImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/FilePathImpl.java @@ -20,6 +20,7 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; @@ -93,9 +94,15 @@ public class FilePathImpl implements FilePath { return false; } else { + if (! isSpecialName(myName) && ! isSpecialName(((FilePath)o).getName()) && + (! Comparing.equal(myName, ((FilePath)o).getName()))) return false; return myFile.equals(((FilePath)o).getIOFile()); } } + + private boolean isSpecialName(final String name) { + return ".".equals(name) || "..".equals(name); + } public void refresh() { if (!myNonLocal) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java index c16513d7a689..f881ce0cbf7e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java @@ -505,6 +505,10 @@ public class ChangeListWorker implements ChangeListsWriteOperations { return myIdx.getStatus(file); } + public FileStatus getStatus(final File file) { + return myIdx.getStatus(file); + } + public DeletedFilesHolder getLocallyDeleted() { return myLocallyDeleted.copy(); } @@ -771,6 +775,11 @@ public class ChangeListWorker implements ChangeListsWriteOperations { public FileStatus getStatus(VirtualFile file) { return myWorker.getStatus(file); } + + @Override + public FileStatus getStatus(File file) { + return myWorker.getStatus(file); + } } // assumes after revisions are all not null diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListsIndexes.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListsIndexes.java index 7fde7a2827a3..9bbc3b1afd75 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListsIndexes.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListsIndexes.java @@ -55,6 +55,10 @@ public class ChangeListsIndexes { public FileStatus getStatus(final VirtualFile file) { return myFileToStatus.get(new File(file.getPath()).getAbsolutePath()); } + + public FileStatus getStatus(final File file) { + return myFileToStatus.get(file.getAbsolutePath()); + } public void changeAdded(final Change change, final VcsKey key) { addChangeToIdx(change, key); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java index 99c2671c0e0e..52b71febc9d0 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java @@ -270,6 +270,35 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope { } } + @Override + public void iterateExistingInsideScope(Processor processor) { + if (myProject.isDisposed()) return; + + for (VirtualFile root : myAffectedContentRoots) { + THashSet dirsByRoot = myDirtyDirectoriesRecursively.get(root); + if (dirsByRoot != null) { + for (FilePath dir : dirsByRoot) { + final VirtualFile vFile = dir.getVirtualFile(); + if (vFile != null && vFile.isValid()) { + myVcsManager.iterateVfUnderVcsRoot(vFile, processor); + } + } + } + } + + for (FilePath file : myDirtyFiles) { + if (file.getVirtualFile() != null) { + processor.process(file.getVirtualFile()); + } + final VirtualFile vFile = file.getVirtualFile(); + if (vFile != null && vFile.isValid() && vFile.isDirectory()) { + for (VirtualFile child : vFile.getChildren()) { + processor.process(child); + } + } + } + } + @Override public boolean isEmpty() { return myDirtyDirectoriesRecursively.isEmpty() && myDirtyFiles.isEmpty(); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/pending/MockChangeListManagerGate.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/pending/MockChangeListManagerGate.java index f85c3fe25bb8..63a4d9c73487 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/pending/MockChangeListManagerGate.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/pending/MockChangeListManagerGate.java @@ -22,6 +22,7 @@ import com.intellij.openapi.vcs.changes.ChangeListManagerGate; import com.intellij.openapi.vcs.changes.LocalChangeList; import com.intellij.openapi.vfs.VirtualFile; +import java.io.File; import java.util.Collection; import java.util.List; @@ -74,4 +75,9 @@ public class MockChangeListManagerGate implements ChangeListManagerGate { public FileStatus getStatus(VirtualFile file) { return null; } + + @Override + public FileStatus getStatus(File file) { + return null; + } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java index 115f629c4b79..1624d79aae9e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java @@ -179,6 +179,11 @@ public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx impleme return AllVcses.getInstance(myProject).getDescriptor(name); } + @Override + public void iterateVfUnderVcsRoot(VirtualFile file, Processor processor) { + VcsRootIterator.iterateVfUnderVcsRoot(myProject, file, processor); + } + public VcsDescriptor[] getAllVcss() { return AllVcses.getInstance(myProject).getAll(); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsRootIterator.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsRootIterator.java index c4b52b04f87b..13c2e8b1b7ef 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsRootIterator.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsRootIterator.java @@ -57,6 +57,11 @@ public class VcsRootIterator { return true; } + public static boolean iterateVfUnderVcsRoot(Project project, VirtualFile file, Processor processor) { + final MyRootIterator rootIterator = new MyRootIterator(project, file, null, processor, null); + return rootIterator.iterate(); + } + private static class MyRootFilter { private final VirtualFile myRoot; private final String myVcsName; @@ -102,20 +107,22 @@ public class VcsRootIterator { public static boolean iterateVcsRoot(final Project project, final VirtualFile root, final Processor processor, @Nullable PairProcessor directoryFilter) { - final MyRootIterator rootIterator = new MyRootIterator(project, root, processor, directoryFilter); + final MyRootIterator rootIterator = new MyRootIterator(project, root, processor, null, directoryFilter); return rootIterator.iterate(); } private static class MyRootIterator { private final Processor myProcessor; + private final Processor myVfProcessor; @Nullable private final PairProcessor myDirectoryFilter; private final LinkedList myQueue; private final MyRootFilter myRootPresentFilter; private final FileIndexFacade myExcludedFileIndex; - private MyRootIterator(final Project project, final VirtualFile root, final Processor processor, + private MyRootIterator(final Project project, final VirtualFile root, final Processor processor, final Processor vfProcessor, @Nullable PairProcessor directoryFilter) { myProcessor = processor; + myVfProcessor = vfProcessor; myDirectoryFilter = directoryFilter; final ProjectLevelVcsManager plVcsManager = ProjectLevelVcsManager.getInstance(project); @@ -130,7 +137,7 @@ public class VcsRootIterator { public boolean iterate() { while (! myQueue.isEmpty()) { final VirtualFile current = myQueue.removeFirst(); - if (! myProcessor.process(new FilePathImpl(current))) return false; + if (!process(current)) return false; if (current.isDirectory()) { final VirtualFile[] files = current.getChildren(); @@ -145,5 +152,13 @@ public class VcsRootIterator { } return true; } + + private boolean process(VirtualFile current) { + if (myProcessor != null) { + return myProcessor.process(new FilePathImpl(current)); + } else { + return myVfProcessor.process(current); + } + } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn17/integrate/AlienDirtyScope.java b/plugins/svn4idea/src/org/jetbrains/idea/svn17/integrate/AlienDirtyScope.java index b003c9d43b95..bc6114a776f4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn17/integrate/AlienDirtyScope.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn17/integrate/AlienDirtyScope.java @@ -76,6 +76,10 @@ public class AlienDirtyScope extends VcsDirtyScope { public void iterate(final Processor iterator) { } + @Override + public void iterateExistingInsideScope(Processor vf) { + } + @Override public boolean isEmpty() { return myFiles.isEmpty() && myDirs.isEmpty(); diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn17/SvnChangesCorrectlyRefreshedTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn17/SvnChangesCorrectlyRefreshedTest.java index 11597a794369..c5ba085257bd 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn17/SvnChangesCorrectlyRefreshedTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn17/SvnChangesCorrectlyRefreshedTest.java @@ -62,7 +62,7 @@ public class SvnChangesCorrectlyRefreshedTest extends SvnTestCase { private static void sleep300() { try { - Thread.sleep(300); + Thread.sleep(10000); } catch (InterruptedException ignore) { } } diff --git a/plugins/svn4ideaOld/src/org/jetbrains/idea/svn/integrate/AlienDirtyScope.java b/plugins/svn4ideaOld/src/org/jetbrains/idea/svn/integrate/AlienDirtyScope.java index 533c77aee817..24ea09f0b794 100644 --- a/plugins/svn4ideaOld/src/org/jetbrains/idea/svn/integrate/AlienDirtyScope.java +++ b/plugins/svn4ideaOld/src/org/jetbrains/idea/svn/integrate/AlienDirtyScope.java @@ -76,6 +76,10 @@ public class AlienDirtyScope extends VcsDirtyScope { public void iterate(final Processor iterator) { } + @Override + public void iterateExistingInsideScope(Processor vf) { + } + @Override public boolean isEmpty() { return myFiles.isEmpty() && myDirs.isEmpty();