From 443a3dad641a8c4e61388d9adaff106bd88de3d9 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 18 Feb 2015 10:32:00 +0100 Subject: [PATCH] really concurrent gdsl execution --- .../groovy/dsl/GroovyDslFileIndex.java | 194 +++++++----------- 1 file changed, 76 insertions(+), 118 deletions(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java index 0499332ee732..7fa143f1501b 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java @@ -15,11 +15,10 @@ */ package org.jetbrains.plugins.groovy.dsl; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ex.ApplicationUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.impl.LoadTextUtil; -import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; @@ -45,9 +44,7 @@ import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; -import com.intellij.reference.SoftReference; import com.intellij.util.ConcurrencyUtil; -import com.intellij.util.ExceptionUtil; import com.intellij.util.Function; import com.intellij.util.PathUtil; import com.intellij.util.containers.ConcurrentMultiMap; @@ -56,6 +53,7 @@ import com.intellij.util.containers.MultiMap; import com.intellij.util.indexing.*; import com.intellij.util.io.EnumeratorStringDescriptor; import com.intellij.util.io.KeyDescriptor; +import com.intellij.util.io.URLUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -68,9 +66,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUt import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import java.io.File; -import java.io.IOException; import java.util.*; -import java.util.concurrent.Callable; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -91,7 +87,11 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { private static final MultiMap>> filesInProcessing = new ConcurrentMultiMap>>(); - private static final ThreadPoolExecutor ourPool = new ThreadPoolExecutor(0, 4, 1, TimeUnit.SECONDS, new LinkedBlockingQueue(), ConcurrencyUtil.newNamedThreadFactory("Groovy DSL File Index Executor")); + private static final ThreadPoolExecutor ourPool = new ThreadPoolExecutor(4, 4, 1, TimeUnit.SECONDS, new LinkedBlockingQueue(), ConcurrencyUtil.newNamedThreadFactory("Groovy DSL File Index Executor")); + + static { + ourPool.allowCoreThreadTimeOut(true); + } private final EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); @@ -157,10 +157,16 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { } private static void clearScriptCache() { - for (Project project : ProjectManager.getInstance().getOpenProjects()) { - project.putUserData(SCRIPTS_CACHE, null); - ((PsiModificationTrackerImpl)PsiManager.getInstance(project).getModificationTracker()).incCounter(); - } + Application app = ApplicationManager.getApplication(); + app.invokeLater(new Runnable() { + @Override + public void run() { + for (Project project : ProjectManager.getInstance().getOpenProjects()) { + project.putUserData(SCRIPTS_CACHE, null); + ((PsiModificationTrackerImpl)PsiManager.getInstance(project).getModificationTracker()).incCounter(); + } + } + }, app.getDisposed()); } static void disableFile(final VirtualFile vfile, String error) { @@ -290,101 +296,74 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { return false; } - private static volatile SoftReference>> ourStandardScripts; - - @Nullable - private static List> derefStandardScripts() { - return SoftReference.dereference(ourStandardScripts); - } - - @Nullable - private static List> getStandardScripts() { - List> result = derefStandardScripts(); - if (result != null) { - return result; - } - - final GroovyFrameworkConfigNotification[] extensions = GroovyFrameworkConfigNotification.EP_NAME.getExtensions(); - Callable>> action = new Callable>>() { - @Override - public List> call() throws Exception { - if (GdslUtil.ourGdslStopped) { - return null; - } - - try { - List> pairs = derefStandardScripts(); - if (pairs != null) { - return pairs; - } - - Set classes = new HashSet(ContainerUtil.map2Set(extensions, new Function() { - @Override - public Class fun(GroovyFrameworkConfigNotification notification) { - return notification.getClass(); - } - })); - classes.add(GroovyFrameworkConfigNotification.class); // for default extension - - // perhaps a separate extension for that? - Set scriptFolders = new LinkedHashSet(); - for (Class aClass : classes) { - File jarPath = new File(PathUtil.getJarPathForClass(aClass)); - if (jarPath.isFile()) { - jarPath = jarPath.getParentFile(); - } - scriptFolders.add(new File(jarPath, "standardDsls")); - } + private static final Key>> SCRIPTS_CACHE = Key.create("GdslScriptCache"); - List> executors = new ArrayList>(); - for (File file : scriptFolders) { - if (file.exists()) { - File[] children = file.listFiles(); - if (children != null) { - for (File child : children) { - final String fileName = child.getName(); - if (fileName.endsWith(".gdsl")) { - try { - final String text = new String(FileUtil.loadFileText(child)); - executors.add(Pair.create(child, new GroovyDslExecutor(text, fileName))); - } - catch (IOException e) { - LOG.error("Error while parsing gdsl file " + fileName, e); - } - } - } - } + private static List getGdslFiles(final Project project) { + List result = ContainerUtil.newArrayList(); + + for (File file : getBundledScriptFolders()) { + if (file.exists()) { + File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + final String fileName = child.getName(); + if (fileName.endsWith(".gdsl")) { + String path = FileUtil.toSystemIndependentName(child.getPath()); + String url = VirtualFileManager.constructUrl(URLUtil.FILE_PROTOCOL, path); + ContainerUtil.addIfNotNull(result, VirtualFileManager.getInstance().refreshAndFindFileByUrl(url)); } } - //noinspection AssignmentToStaticFieldFromInstanceMethod - ourStandardScripts = new SoftReference>>(executors); - return executors; - } - catch (Throwable e) { - //noinspection InstanceofCatchParameter - if (e instanceof Error) { - GdslUtil.stopGdsl(); - } - LOG.error(e); - return null; } } - }; + } - try { - if (ApplicationManager.getApplication().isDispatchThread()) { - return action.call(); + final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); + final GlobalSearchScope scope = GlobalSearchScope.allScope(project); + + for (VirtualFile vfile : FileBasedIndex.getInstance().getContainingFiles(NAME, OUR_KEY, scope)) { + if (!vfile.isValid()) { + continue; } - return ApplicationUtil.runWithCheckCanceled(action, new EmptyProgressIndicator(), ourPool); - } - catch (Exception e) { - ExceptionUtil.rethrowUnchecked(e); - LOG.error(e); - return null; + if (vfile.isDirectory() || !vfile.getName().endsWith(".gdsl")) { + LOG.error("Index returned non-gdsl file: " + vfile); + continue; + } + if (fileIndex.isInLibrarySource(vfile)) { + continue; + } + if (!fileIndex.isInLibraryClasses(vfile)) { + if (!fileIndex.isInSourceContent(vfile) || !isActivated(vfile)) { + continue; + } + } + + result.add(vfile); } + return result; } - private static final Key>> SCRIPTS_CACHE = Key.create("GdslScriptCache"); + @NotNull + private static Set getBundledScriptFolders() { + final GroovyFrameworkConfigNotification[] extensions = GroovyFrameworkConfigNotification.EP_NAME.getExtensions(); + Set classes = new HashSet(ContainerUtil.map2Set(extensions, new Function() { + @Override + public Class fun(GroovyFrameworkConfigNotification notification) { + return notification.getClass(); + } + })); + classes.add(GroovyFrameworkConfigNotification.class); // for default extension + + // perhaps a separate extension for that? + Set scriptFolders = new LinkedHashSet(); + for (Class aClass : classes) { + File jarPath = new File(PathUtil.getJarPathForClass(aClass)); + if (jarPath.isFile()) { + jarPath = jarPath.getParentFile(); + } + scriptFolders.add(new File(jarPath, "standardDsls")); + } + return scriptFolders; + } private static List getDslScripts(final Project project) { return CachedValuesManager.getManager(project).getCachedValue(project, SCRIPTS_CACHE, new CachedValueProvider>() { @@ -405,31 +384,10 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { List result = new ArrayList(); - List> standardScripts = getStandardScripts(); - if (standardScripts != null) { - for (Pair pair : standardScripts) { - result.add(new GroovyDslScript(project, null, pair.second, pair.first.getPath())); - } - } - final LinkedBlockingQueue> queue = new LinkedBlockingQueue>(); - final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); - final GlobalSearchScope scope = GlobalSearchScope.allScope(project); - for (VirtualFile vfile : FileBasedIndex.getInstance().getContainingFiles(NAME, OUR_KEY, scope)) { - if (!vfile.isValid()) { - continue; - } - if (fileIndex.isInLibrarySource(vfile)) { - continue; - } - if (!fileIndex.isInLibraryClasses(vfile)) { - if (!fileIndex.isInSourceContent(vfile) || !isActivated(vfile)) { - continue; - } - } - + for (VirtualFile vfile : getGdslFiles(project)) { final long stamp = vfile.getModificationStamp(); final GroovyDslExecutor cached = getCachedExecutor(vfile, stamp); if (cached == null) { -- 2.32.0