* Improve DLTK Source Indexer to use AST cache (DLTK-596)
* Remove DLTK Indexer JobManager wait for 50 milliseconds after each module parse, if there is no search requests.
diff --git a/core/plugins/org.eclipse.dltk.core/model/org/eclipse/dltk/internal/core/ScriptProject.java b/core/plugins/org.eclipse.dltk.core/model/org/eclipse/dltk/internal/core/ScriptProject.java
index 9977cd7..dfe7994 100644
--- a/core/plugins/org.eclipse.dltk.core/model/org/eclipse/dltk/internal/core/ScriptProject.java
+++ b/core/plugins/org.eclipse.dltk.core/model/org/eclipse/dltk/internal/core/ScriptProject.java
@@ -9,20 +9,63 @@
*******************************************************************************/
package org.eclipse.dltk.internal.core;
-import java.io.*;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
import java.net.URI;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.AssertionFailedException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.dltk.compiler.util.ObjectVector;
-import org.eclipse.dltk.core.*;
+import org.eclipse.dltk.core.DLTKCore;
+import org.eclipse.dltk.core.DLTKLanguageManager;
+import org.eclipse.dltk.core.IBuildpathContainer;
+import org.eclipse.dltk.core.IBuildpathEntry;
+import org.eclipse.dltk.core.IDLTKLanguageToolkit;
+import org.eclipse.dltk.core.IModelElement;
+import org.eclipse.dltk.core.IModelMarker;
+import org.eclipse.dltk.core.IModelStatus;
+import org.eclipse.dltk.core.IModelStatusConstants;
+import org.eclipse.dltk.core.IProjectFragment;
+import org.eclipse.dltk.core.IRegion;
+import org.eclipse.dltk.core.IScriptFolder;
+import org.eclipse.dltk.core.IScriptProject;
+import org.eclipse.dltk.core.ISearchableEnvironment;
+import org.eclipse.dltk.core.ISourceModule;
+import org.eclipse.dltk.core.IType;
+import org.eclipse.dltk.core.ITypeHierarchy;
+import org.eclipse.dltk.core.ModelException;
+import org.eclipse.dltk.core.WorkingCopyOwner;
+import org.eclipse.dltk.core.search.indexing.IndexManager;
import org.eclipse.dltk.internal.core.util.MementoTokenizer;
import org.eclipse.dltk.internal.core.util.Messages;
import org.eclipse.dltk.internal.core.util.Util;
@@ -2381,7 +2424,10 @@
throws ModelException {
IProjectFragment[] allRoots = this.getAllProjectFragments();
if (!path.isAbsolute()) {
- throw new IllegalArgumentException(Messages.path_mustBeAbsolute);
+ if (path.segmentCount() == 0
+ || !path.segment(0).equals(IndexManager.SPECIAL_BUILTIN)) {
+ throw new IllegalArgumentException(Messages.path_mustBeAbsolute);
+ }
}
for (int i = 0; i < allRoots.length; i++) {
IProjectFragment buildpathRoot = allRoots[i];
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/BasicSearchEngine.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/BasicSearchEngine.java
index 6c998af..b65afda 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/BasicSearchEngine.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/BasicSearchEngine.java
@@ -304,8 +304,8 @@
int indexMatchLength = indexMatchPaths.length;
SearchDocument[] indexMatches = new SearchDocument[indexMatchLength];
for (int j = 0; j < indexMatchLength; j++) {
- indexMatches[j] = participant
- .getDocument(indexMatchPaths[j]);
+ indexMatches[j] = participant.getDocument(
+ indexMatchPaths[j], null);
}
SearchDocument[] matches = MatchLocator
.addWorkingCopies(pattern, indexMatches,
@@ -408,8 +408,8 @@
int indexMatchLength = indexMatchPaths.length;
SearchDocument[] indexMatches = new SearchDocument[indexMatchLength];
for (int j = 0; j < indexMatchLength; j++) {
- indexMatches[j] = participant
- .getDocument(indexMatchPaths[j]);
+ indexMatches[j] = participant.getDocument(
+ indexMatchPaths[j], null);
}
SearchDocument[] matches = MatchLocator
.addWorkingCopies(pattern, indexMatches,
@@ -1446,7 +1446,9 @@
pattern,
new SearchDocument[] { new DLTKSearchDocument(
enclosingElement.getPath().toString(),
- contents, participant, external) },
+ contents, participant, external,
+ enclosingElement.getScriptProject()
+ .getProject()) },
getWorkingCopies(enclosingElement), participant);
participant.locateMatches(documents, pattern, scope,
requestor, monitor);
@@ -1533,7 +1535,8 @@
/**
* @see SearchEngine#createTypeNameMatch(IType, int) for detailed comment.
*/
- public static MethodNameMatch createMethodNameMatch(IMethod method, int modifiers) {
+ public static MethodNameMatch createMethodNameMatch(IMethod method,
+ int modifiers) {
return new DLTKSearchMethodNameMatch(method, modifiers);
}
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/DLTKSearchParticipant.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/DLTKSearchParticipant.java
index d78c03c..7d913e8 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/DLTKSearchParticipant.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/DLTKSearchParticipant.java
@@ -10,6 +10,7 @@
package org.eclipse.dltk.core.search;
import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
@@ -63,10 +64,10 @@
return "DLTK"; //$NON-NLS-1$
}
- public SearchDocument getDocument(String documentPath) {
+ public SearchDocument getDocument(String documentPath, IProject project) {
return new DLTKSearchDocument(documentPath,
getDocumentContents(documentPath), this,
- isExternal(documentPath));
+ isExternal(documentPath), project);
}
private boolean isExternal(String documentPath) {
@@ -110,7 +111,7 @@
* (non-Javadoc)
*
* @see SearchParticipant#locateMatches(SearchDocument[], SearchPattern,
- * IDLTKSearchScope, SearchRequestor, IProgressMonitor)
+ * IDLTKSearchScope, SearchRequestor, IProgressMonitor)
*/
public void locateMatches(SearchDocument[] indexMatches,
SearchPattern pattern, IDLTKSearchScope scope,
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/SearchDocument.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/SearchDocument.java
index cb67035..cd0f1dc 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/SearchDocument.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/SearchDocument.java
@@ -9,6 +9,8 @@
*******************************************************************************/
package org.eclipse.dltk.core.search;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.dltk.core.search.indexing.InternalSearchDocument;
/**
@@ -23,6 +25,8 @@
public abstract class SearchDocument extends InternalSearchDocument {
private String documentPath;
private SearchParticipant participant;
+ private IProject project;
+ public IPath fullPath;
/**
* Creates a new search document. The given document path is a string that
@@ -35,15 +39,18 @@
* @param participant
* the participant that creates the search document
*/
- protected SearchDocument(String documentPath, SearchParticipant participant) {
+ protected SearchDocument(String documentPath,
+ SearchParticipant participant, IProject project) {
this.documentPath = documentPath;
this.participant = participant;
+ this.project = project;
}
/**
* Adds the given index entry (category and key) coming from this document
* to the index. This method must be called from
- * {@link SearchParticipant#indexDocument(SearchDocument document, org.eclipse.core.runtime.IPath indexPath)}.
+ * {@link SearchParticipant#indexDocument(SearchDocument document, org.eclipse.core.runtime.IPath indexPath)}
+ * .
*
* @param category
* the category of the index entry
@@ -99,7 +106,7 @@
String ret = new String(contents);
return ret;
}
-
+
/**
* Returns the encoding for this document.
* <p>
@@ -134,11 +141,16 @@
/**
* Removes all index entries from the index for the given document. This
* method must be called from
- * {@link SearchParticipant#indexDocument(SearchDocument document, org.eclipse.core.runtime.IPath indexPath)}.
+ * {@link SearchParticipant#indexDocument(SearchDocument document, org.eclipse.core.runtime.IPath indexPath)}
+ * .
*/
public void removeAllIndexEntries() {
super.removeAllIndexEntries();
}
public abstract boolean isExternal();
+
+ public IProject getProject() {
+ return this.project;
+ }
}
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/SearchParticipant.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/SearchParticipant.java
index 8ab3906..f009d98 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/SearchParticipant.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/SearchParticipant.java
@@ -9,6 +9,7 @@
*******************************************************************************/
package org.eclipse.dltk.core.search;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
@@ -22,37 +23,40 @@
import org.eclipse.dltk.internal.core.Model;
import org.eclipse.dltk.internal.core.ModelManager;
-
/**
* A search participant describes a particular extension to a generic search
* mechanism, permitting combined search actions which will involve all required
* participants.
* <p>
- * A search participant is involved in the indexing phase and in the search phase.
- * The indexing phase consists in taking one or more search documents, parse them, and
- * add index entries in an index chosen by the participant. An index is identified by a
- * path on disk.
- * The search phase consists in selecting the indexes corresponding to a search pattern
- * and a search scope, from these indexes the search infrastructure extracts the document paths
- * that match the search pattern asking the search participant for the corresponding document,
- * finally the search participant is asked to locate the matches precisely in these search documents.
+ * A search participant is involved in the indexing phase and in the search
+ * phase. The indexing phase consists in taking one or more search documents,
+ * parse them, and add index entries in an index chosen by the participant. An
+ * index is identified by a path on disk. The search phase consists in selecting
+ * the indexes corresponding to a search pattern and a search scope, from these
+ * indexes the search infrastructure extracts the document paths that match the
+ * search pattern asking the search participant for the corresponding document,
+ * finally the search participant is asked to locate the matches precisely in
+ * these search documents.
* </p>
* <p>
- * This class is intended to be subclassed by clients. During the indexing phase,
- * a subclass will be called with the following requests in order:
+ * This class is intended to be subclassed by clients. During the indexing
+ * phase, a subclass will be called with the following requests in order:
* <ul>
* <li>{@link #scheduleDocumentIndexing(SearchDocument, IPath)}</li>
* <li>{@link #indexDocument(SearchDocument, IPath)}</li>
* </ul>
- * During the search phase, a subclass will be called with the following requests in order:
+ * During the search phase, a subclass will be called with the following
+ * requests in order:
* <ul>
* <li>{@link #selectIndexes(SearchPattern, IJavaSearchScope)}</li>
* <li>one or more {@link #getDocument(String)}</li>
- * <li>{@link #locateMatches(SearchDocument[], SearchPattern, IJavaSearchScope, SearchRequestor, IProgressMonitor)}</li>
+ * <li>
+ * {@link #locateMatches(SearchDocument[], SearchPattern, IJavaSearchScope, SearchRequestor, IProgressMonitor)}
+ * </li>
* </ul>
* </p>
*
- *
+ *
*/
public abstract class SearchParticipant {
@@ -62,12 +66,12 @@
protected SearchParticipant() {
// do nothing
}
-
+
/**
* Notification that this participant's help is needed in a search.
* <p>
- * This method should be re-implemented in subclasses that need to do something
- * when the participant is needed in a search.
+ * This method should be re-implemented in subclasses that need to do
+ * something when the participant is needed in a search.
* </p>
*/
public void beginSearching() {
@@ -77,8 +81,8 @@
/**
* Notification that this participant's help is no longer needed.
* <p>
- * This method should be re-implemented in subclasses that need to do something
- * when the participant is no longer needed in a search.
+ * This method should be re-implemented in subclasses that need to do
+ * something when the participant is no longer needed in a search.
* </p>
*/
public void doneSearching() {
@@ -88,8 +92,8 @@
/**
* Returns a displayable name of this search participant.
* <p>
- * This method should be re-implemented in subclasses that need to
- * display a meaningfull name.
+ * This method should be re-implemented in subclasses that need to display a
+ * meaningfull name.
* </p>
*
* @return the displayable name of this search participant
@@ -99,42 +103,51 @@
}
/**
- * Returns a search document for the given path.
- * The given document path is a string that uniquely identifies the document.
- * Most of the time it is a workspace-relative path, but it can also be a file system path, or a path inside a zip file.
+ * Returns a search document for the given path. The given document path is
+ * a string that uniquely identifies the document. Most of the time it is a
+ * workspace-relative path, but it can also be a file system path, or a path
+ * inside a zip file.
* <p>
- * Implementors of this method can either create an instance of their own subclass of
- * {@link SearchDocument} or return an existing instance of such a subclass.
+ * Implementors of this method can either create an instance of their own
+ * subclass of {@link SearchDocument} or return an existing instance of such
+ * a subclass.
* </p>
*
- * @param documentPath the path of the document.
+ * @param documentPath
+ * the path of the document.
* @return a search document
*/
- public abstract SearchDocument getDocument(String documentPath);
-
+ public abstract SearchDocument getDocument(String documentPath,
+ IProject project);
+
/**
- * Indexes the given document in the given index. A search participant
- * asked to index a document should parse it and call
+ * Indexes the given document in the given index. A search participant asked
+ * to index a document should parse it and call
* {@link SearchDocument#addIndexEntry(char[], char[])} as many times as
* needed to add index entries to the index. If delegating to another
* participant, it should use the original index location (and not the
* delegatee's one). In the particular case of delegating to the default
- * search participant (see {@link SearchEngine#getDefaultSearchParticipant()}),
- * the provided document's path must be a path ending with one of the
- * {@link org.eclipse.dltk.core.DLTKCore#getScriptLikeExtensions() Script-like extensions}
- * or with '.class'.
+ * search participant (see
+ * {@link SearchEngine#getDefaultSearchParticipant()}), the provided
+ * document's path must be a path ending with one of the
+ * {@link org.eclipse.dltk.core.DLTKCore#getScriptLikeExtensions()
+ * Script-like extensions} or with '.class'.
* <p>
- * The given index location must represent a path in the file system to a file that
- * either already exists or is going to be created. If it exists, it must be an index file,
- * otherwise its data might be overwritten.
- * </p><p>
+ * The given index location must represent a path in the file system to a
+ * file that either already exists or is going to be created. If it exists,
+ * it must be an index file, otherwise its data might be overwritten.
+ * </p>
+ * <p>
* Clients are not expected to call this method.
* </p>
*
- * @param document the document to index
- * @param indexLocation the location in the file system to the index
+ * @param document
+ * the document to index
+ * @param indexLocation
+ * the location in the file system to the index
*/
- public abstract void indexDocument(SearchDocument document, IPath indexLocation);
+ public abstract void indexDocument(SearchDocument document,
+ IPath indexLocation);
/**
* Locates the matches in the given documents using the given search pattern
@@ -142,29 +155,44 @@
* method is called by the search engine once it has search documents
* matching the given pattern in the given search scope.
* <p>
- * Note that a participant (e.g. a JSP participant) can pre-process the contents of the given documents,
- * create its own documents whose contents are Script compilation units and delegate the match location
- * to the default participant (see {@link SearchEngine#getDefaultSearchParticipant()}). Passing its own
- * {@link SearchRequestor} this particpant can then map the match positions back to the original
- * contents, create its own matches and report them to the original requestor.
- * </p><p>
- * Implementors of this method should check the progress monitor
- * for cancelation when it is safe and appropriate to do so. The cancelation
- * request should be propagated to the caller by throwing
+ * Note that a participant (e.g. a JSP participant) can pre-process the
+ * contents of the given documents, create its own documents whose contents
+ * are Script compilation units and delegate the match location to the
+ * default participant (see
+ * {@link SearchEngine#getDefaultSearchParticipant()}). Passing its own
+ * {@link SearchRequestor} this particpant can then map the match positions
+ * back to the original contents, create its own matches and report them to
+ * the original requestor.
+ * </p>
+ * <p>
+ * Implementors of this method should check the progress monitor for
+ * cancelation when it is safe and appropriate to do so. The cancelation
+ * request should be propagated to the caller by throwing
* <code>OperationCanceledException</code>.
* </p>
*
- * @param documents the documents to locate matches in
- * @param pattern the search pattern to use when locating matches
- * @param scope the scope to limit the search to
- * @param requestor the requestor to report matches to
- * @param monitor the progress monitor to report progress to,
- * or <code>null</code> if no progress should be reported
- * @throws CoreException if the requestor had problem accepting one of the matches
+ * @param documents
+ * the documents to locate matches in
+ * @param pattern
+ * the search pattern to use when locating matches
+ * @param scope
+ * the scope to limit the search to
+ * @param requestor
+ * the requestor to report matches to
+ * @param monitor
+ * the progress monitor to report progress to, or
+ * <code>null</code> if no progress should be reported
+ * @throws CoreException
+ * if the requestor had problem accepting one of the matches
*/
- public abstract void locateMatches(SearchDocument[] documents, SearchPattern pattern, IDLTKSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException;
+ public abstract void locateMatches(SearchDocument[] documents,
+ SearchPattern pattern, IDLTKSearchScope scope,
+ SearchRequestor requestor, IProgressMonitor monitor)
+ throws CoreException;
+
/**
* Return correct source modules from selected index matches.
+ *
* @param matches
* @param pattern
* @param scope
@@ -173,81 +201,99 @@
*/
public abstract ISourceModule[] locateModules(SearchDocument[] matches,
SearchPattern pattern, IDLTKSearchScope scope,
- IProgressMonitor subMonitor) throws CoreException;
+ IProgressMonitor subMonitor) throws CoreException;
/**
- * Removes the index for a given path.
+ * Removes the index for a given path.
* <p>
- * The given index location must represent a path in the file system to a file that
- * already exists and must be an index file, otherwise nothing will be done.
- * </p><p>
- * It is strongly recommended to use this method instead of deleting file directly
- * otherwise cached index will not be removed.
+ * The given index location must represent a path in the file system to a
+ * file that already exists and must be an index file, otherwise nothing
+ * will be done.
+ * </p>
+ * <p>
+ * It is strongly recommended to use this method instead of deleting file
+ * directly otherwise cached index will not be removed.
* </p>
*
- * @param indexLocation the location in the file system to the index
- *
+ * @param indexLocation
+ * the location in the file system to the index
+ *
*/
- public void removeIndex(IPath indexLocation){
+ public void removeIndex(IPath indexLocation) {
IndexManager manager = ModelManager.getModelManager().getIndexManager();
manager.removeIndexPath(indexLocation);
}
/**
- * Schedules the indexing of the given document.
- * Once the document is ready to be indexed,
- * {@link #indexDocument(SearchDocument, IPath) indexDocument(document, indexPath)}
- * will be called in a different thread than the caller's thread.
+ * Schedules the indexing of the given document. Once the document is ready
+ * to be indexed, {@link #indexDocument(SearchDocument, IPath)
+ * indexDocument(document, indexPath)} will be called in a different thread
+ * than the caller's thread.
* <p>
- * The given index location must represent a path in the file system to a file that
- * either already exists or is going to be created. If it exists, it must be an index file,
- * otherwise its data might be overwritten.
- * </p><p>
- * When the index is no longer needed, clients should use {@link #removeIndex(IPath) }
- * to discard it.
+ * The given index location must represent a path in the file system to a
+ * file that either already exists or is going to be created. If it exists,
+ * it must be an index file, otherwise its data might be overwritten.
+ * </p>
+ * <p>
+ * When the index is no longer needed, clients should use
+ * {@link #removeIndex(IPath) } to discard it.
* </p>
*
- * @param document the document to index
- * @param indexLocation the location on the file system of the index
+ * @param document
+ * the document to index
+ * @param indexLocation
+ * the location on the file system of the index
*/
- public final void scheduleDocumentIndexing(SearchDocument document, IPath indexLocation) {
+ public final void scheduleDocumentIndexing(SearchDocument document,
+ IPath indexLocation) {
IPath documentPath = new Path(document.getPath());
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
Object file = Model.getTarget(root, documentPath, true);
IPath containerPath = documentPath;
if (file instanceof IResource) {
- containerPath = ((IResource)file).getProject().getFullPath();
+ containerPath = ((IResource) file).getProject().getFullPath();
} else if (file == null) {
- containerPath = documentPath.removeLastSegments(documentPath.segmentCount()-1);
+ containerPath = documentPath.removeLastSegments(documentPath
+ .segmentCount() - 1);
}
IndexManager manager = ModelManager.getModelManager().getIndexManager();
String osIndexLocation = indexLocation.toOSString();
- // TODO (frederic) should not have to create index manually, should expose API that recreates index instead
+ // TODO (frederic) should not have to create index manually, should
+ // expose API that recreates index instead
manager.ensureIndexExists(osIndexLocation, containerPath);
- manager.scheduleDocumentIndexing(document, containerPath, osIndexLocation, this);
+ manager.scheduleDocumentIndexing(document, containerPath,
+ osIndexLocation, this);
}
+
/**
* Returns the collection of index locations to consider when performing the
* given search query in the given scope. The search engine calls this
* method before locating matches.
* <p>
- * An index location represents a path in the file system to a file that holds index information.
- * </p><p>
+ * An index location represents a path in the file system to a file that
+ * holds index information.
+ * </p>
+ * <p>
* Clients are not expected to call this method.
* </p>
*
- * @param query the search pattern to consider
- * @param scope the given search scope
+ * @param query
+ * the search pattern to consider
+ * @param scope
+ * the given search scope
* @return the collection of index paths to consider
*/
- public abstract IPath[] selectIndexes(SearchPattern query, IDLTKSearchScope scope);
-
- public abstract IPath[] selectMixinIndexes(SearchPattern query, IDLTKSearchScope scope);
+ public abstract IPath[] selectIndexes(SearchPattern query,
+ IDLTKSearchScope scope);
+
+ public abstract IPath[] selectMixinIndexes(SearchPattern query,
+ IDLTKSearchScope scope);
public abstract void skipNotMixin();
-
+
/**
- * Used then searcj, if selected index are skipped, it not inclouded in search.
+ * Used then searcj, if selected index are skipped, it not inclouded in
+ * search.
*/
public abstract boolean isSkipped(Index index);
}
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/AddBuiltinFolderToIndex.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/AddBuiltinFolderToIndex.java
index fc728d1..c0d6d60 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/AddBuiltinFolderToIndex.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/AddBuiltinFolderToIndex.java
@@ -170,10 +170,11 @@
IPath dpath = new Path(path).setDevice(null);
DLTKSearchDocument entryDocument = new DLTKSearchDocument(dpath
.toString(), Path.EMPTY, contents.toCharArray(), participant,
- true);
+ true, this.project);
entryDocument.parser = parser;
entryDocument.requestor = requestor;
entryDocument.toolkit = toolkit;
+ entryDocument.fullPath = this.containerPath.append(dpath);
this.manager.indexDocument(entryDocument, participant, index,
this.containerPath);
}
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/AddExternalFolderToIndex.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/AddExternalFolderToIndex.java
index 3541711..ef887db 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/AddExternalFolderToIndex.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/AddExternalFolderToIndex.java
@@ -291,7 +291,10 @@
IPath dpath = new Path(path).removeFirstSegments(
containerPath.segmentCount()).setDevice(null);
DLTKSearchDocument entryDocument = new DLTKSearchDocument(dpath
- .toString(), this.containerPath, contents, participant, true);
+ .toString(), this.containerPath, contents, participant, true,
+ project);
+ entryDocument.fullPath = EnvironmentPathUtils.getLocalPath(ffile
+ .getFullPath());
entryDocument.parser = parser;
entryDocument.requestor = requestor;
entryDocument.toolkit = toolkit;
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/IndexManager.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/IndexManager.java
index 7ca4b55..8873fe0 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/IndexManager.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/IndexManager.java
@@ -135,10 +135,11 @@
SearchParticipant participant = SearchEngine
.getDefaultSearchParticipant();
SearchDocument document = participant.getDocument(resource
- .getFullPath().toString());
+ .getFullPath().toString(), resource.getProject());
((InternalSearchDocument) document).parser = parser;
((InternalSearchDocument) document).requestor = requestor;
((InternalSearchDocument) document).toolkit = toolkit;
+ document.fullPath = resource.getFullPath();
String indexLocation = this.computeIndexLocation(containerPath);
this.scheduleDocumentIndexing(document, containerPath, indexLocation,
participant);
@@ -155,7 +156,7 @@
SearchParticipant participant = SearchEngine
.getDefaultSearchParticipant();
SearchDocument document = participant.getDocument(resource
- .getFullPath().toString());
+ .getFullPath().toString(), resource.getProject());
String indexLocation = this.computeIndexLocation(containerPath);
this.scheduleDocumentIndexing(document, containerPath, indexLocation,
participant);
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/SourceIndexer.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/SourceIndexer.java
index 7be221b..f5257ce 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/SourceIndexer.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/indexing/SourceIndexer.java
@@ -15,10 +15,15 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.dltk.core.DLTKCore;
+import org.eclipse.dltk.core.IProjectFragment;
import org.eclipse.dltk.core.IScriptFolder;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceElementParser;
import org.eclipse.dltk.core.ISourceModule;
+import org.eclipse.dltk.core.ISourceModuleInfoCache;
+import org.eclipse.dltk.core.ModelException;
+import org.eclipse.dltk.core.ISourceModuleInfoCache.ISourceModuleInfo;
+import org.eclipse.dltk.core.environment.EnvironmentPathUtils;
import org.eclipse.dltk.core.search.IDLTKSearchScope;
import org.eclipse.dltk.core.search.SearchDocument;
import org.eclipse.dltk.internal.core.ModelManager;
@@ -61,8 +66,12 @@
IPath path = new Path(documentPath);
ISourceElementParser parser = ((InternalSearchDocument) this.document).parser;
if (!this.document.isExternal()) {
- IProject project = ResourcesPlugin.getWorkspace().getRoot()
- .getProject(path.segment(0));
+ IProject project = document.getProject();
+ if (project == null) {
+ project = ResourcesPlugin.getWorkspace().getRoot().getProject(
+ path.segment(0));
+ }
+
IScriptProject scriptProject = DLTKCore.create(project);
if (requestor == null) {
@@ -78,9 +87,9 @@
parser.setRequestor(requestor);
String pkgName = ""; //$NON-NLS-1$
IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
- // ISourceModule sourceModule = null;
+ ISourceModule module = null;
if (file.exists()) {
- ISourceModule module = (ISourceModule) DLTKCore.create(file);
+ module = (ISourceModule) DLTKCore.create(file);
if (module != null) {
// sourceModule = module;
IScriptFolder folder = (IScriptFolder) module.getParent();
@@ -88,6 +97,7 @@
}
}
requestor.setPackageName(pkgName);
+ // We need to get already
// Launch the parser
char[] source = null;
char[] name = null;
@@ -100,18 +110,21 @@
if (source == null || name == null)
return; // could not retrieve document info (e.g. resource was
// discarded)
- parser.parseSourceModule(source, null, name);
+
+ /**
+ * Using cache to build module.
+ */
+ ISourceModuleInfo info = null;
+ ISourceModuleInfoCache cache = ModelManager.getModelManager()
+ .getSourceModuleInfoCache();
+ if (module != null) {
+ info = cache.get(module);
+ }
+
+ parser.parseSourceModule(source, info, name);
} else { // This is for external documents
if (parser == null || requestor == null) {
- // parser =
- // ModelManager.getModelManager().indexManager.
- // getSourceElementParser(scriptProject,
- // requestor);
- if (DLTKCore.DEBUG) {
- System.err
- .println("TODO: Add getSourceElementParser here."); //$NON-NLS-1$
- }
return;
} else {
parser.setRequestor(requestor);
@@ -137,7 +150,55 @@
if (source == null || name == null)
return; // could not retrieve document info (e.g. resource was
// discarded)
- parser.parseSourceModule(source, null, name);
+
+ // We need to obtain ISourceModule handle to do caching. This will
+ // improve parsing performance.
+ ISourceModuleInfo info = null;
+
+ if (document.getProject() != null) {
+ IProject project = document.getProject();
+ IScriptProject scriptProject = DLTKCore.create(project);
+ try {
+ IProjectFragment[] fragments = scriptProject
+ .getProjectFragments();
+ IProjectFragment frag = null;
+ for (int i = 0; i < fragments.length; i++) {
+ IPath fragmentPath = EnvironmentPathUtils
+ .getLocalPath(fragments[i].getPath());
+ if (fragments[i].isExternal()
+ && fragmentPath.isPrefixOf(document.fullPath)) {
+ if (frag != null
+ && frag.getPath().isPrefixOf(
+ fragments[i].getPath())) {
+ frag = fragments[i];
+ } else {
+ frag = fragments[i];
+ }
+ }
+ }
+ if (frag != null) {
+ IPath fragmentRelativePath = document.fullPath
+ .removeFirstSegments(frag.getPath()
+ .segmentCount());
+ IScriptFolder folder = frag
+ .getScriptFolder(fragmentRelativePath
+ .removeLastSegments(1));
+ ISourceModule module = folder
+ .getSourceModule(document.fullPath
+ .lastSegment());
+ if (module.exists()) {
+ info = ModelManager.getModelManager()
+ .getSourceModuleInfoCache().get(module);
+ }
+ }
+ } catch (ModelException e) {
+ if (DLTKCore.DEBUG) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ parser.parseSourceModule(source, info, name);
long ended = System.currentTimeMillis();
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/matching/MatchLocator.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/matching/MatchLocator.java
index dccd987..d6f1d86 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/matching/MatchLocator.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/core/search/matching/MatchLocator.java
@@ -178,7 +178,8 @@
WorkingCopyDocument(org.eclipse.dltk.core.ISourceModule workingCopy,
SearchParticipant participant, boolean external) {
super(workingCopy.getPath().toString(), getContents(workingCopy),
- participant, external);
+ participant, external, workingCopy.getScriptProject()
+ .getProject());
this.workingCopy = workingCopy;
}
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/mixin/MixinBuilder.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/mixin/MixinBuilder.java
index 41909b8..e0414a4 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/mixin/MixinBuilder.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/mixin/MixinBuilder.java
@@ -156,7 +156,8 @@
DLTKSearchDocument document = new DLTKSearchDocument(element
.getPath().toString(), containerPath, null,
- participant, element instanceof ExternalSourceModule);
+ participant, element instanceof ExternalSourceModule,
+ element.getScriptProject().getProject());
// System.out.println("mixin indexing:" + document.getPath());
((InternalSearchDocument) document).toolkit = toolkit;
String containerRelativePath = null;
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/mixin/MixinIndexRequest.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/mixin/MixinIndexRequest.java
index 9dadac7..df4c460 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/mixin/MixinIndexRequest.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/mixin/MixinIndexRequest.java
@@ -88,7 +88,8 @@
final IPath path = module.getPath();
final DLTKSearchDocument document = new DLTKSearchDocument(path
.toString(), containerPath, null, participant,
- module instanceof ExternalSourceModule);
+ module instanceof ExternalSourceModule, module
+ .getScriptProject().getProject());
document.toolkit = toolkit;
final String relativePath = containerRelativePath(containerPath,
module, path);
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/mixin/MixinProjectIndexer.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/mixin/MixinProjectIndexer.java
index b05155e..030f2c5 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/mixin/MixinProjectIndexer.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/mixin/MixinProjectIndexer.java
@@ -49,10 +49,12 @@
try {
final IProjectFragment fragment = project.findProjectFragment(path);
if (fragment != null) {
- final MixinIndexRequest request = new MixinExternalProjectFragmentRequest(
- fragment, DLTKLanguageManager
- .getLanguageToolkit(fragment));
- requestIfNotWaiting(request);
+ if (!path.segment(0).equals(IndexManager.SPECIAL_BUILTIN)) {
+ final MixinIndexRequest request = new MixinExternalProjectFragmentRequest(
+ fragment, DLTKLanguageManager
+ .getLanguageToolkit(fragment));
+ requestIfNotWaiting(request);
+ }
} else {
DLTKCore.warn(NLS.bind(
Messages.MixinIndexer_unknownProjectFragment, path));
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/search/DLTKSearchDocument.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/search/DLTKSearchDocument.java
index 506f9dd..da93150 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/search/DLTKSearchDocument.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/search/DLTKSearchDocument.java
@@ -9,6 +9,7 @@
*******************************************************************************/
package org.eclipse.dltk.internal.core.search;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
@@ -20,20 +21,23 @@
protected char[] charContents;
private boolean external;
- public DLTKSearchDocument(String path,
- char[] contents, SearchParticipant participant, boolean external) {
- super(path, participant);
+ public DLTKSearchDocument(String path, char[] contents,
+ SearchParticipant participant, boolean external, IProject project) {
+ super(path, participant, project);
this.charContents = contents;
this.external = external;
}
-
- public DLTKSearchDocument(String path, IPath containerPath, char[] contents, SearchParticipant participant, boolean external) {
- super(IDLTKSearchScope.FILE_ENTRY_SEPARATOR + path, participant );
+
+ public DLTKSearchDocument(String path, IPath containerPath,
+ char[] contents, SearchParticipant participant, boolean external,
+ IProject project) {
+ super(IDLTKSearchScope.FILE_ENTRY_SEPARATOR + path, participant,
+ project);
this.charContents = contents;
this.external = external;
}
-
- public String getContents() {
+
+ public String getContents() {
return new String(charContents);
}
@@ -53,7 +57,7 @@
public String toString() {
return "SearchDocument for " + getPath(); //$NON-NLS-1$
}
-
+
public boolean isExternal() {
return external;
}
diff --git a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/search/processing/JobManager.java b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/search/processing/JobManager.java
index d3634c9..3dbde95 100644
--- a/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/search/processing/JobManager.java
+++ b/core/plugins/org.eclipse.dltk.core/search/org/eclipse/dltk/internal/core/search/processing/JobManager.java
@@ -19,7 +19,6 @@
import org.eclipse.dltk.internal.core.util.Messages;
import org.eclipse.dltk.internal.core.util.Util;
-
public abstract class JobManager implements Runnable {
/* queue of jobs to execute */
@@ -32,14 +31,16 @@
protected Thread processingThread;
protected Job progressJob;
- /* counter indicating whether job execution is enabled or not, disabled if <= 0
- it cannot go beyond 1 */
+ /*
+ * counter indicating whether job execution is enabled or not, disabled if
+ * <= 0 it cannot go beyond 1
+ */
private int enableCount = 1;
public final static boolean VERBOSE = DLTKCore.VERBOSE_JOBMANAGER;
/* flag indicating that the activation has completed */
public boolean activated = false;
-
+
private int awaitingClients = 0;
/**
@@ -48,30 +49,36 @@
public void activateProcessing() {
this.activated = true;
}
+
/**
* Answer the amount of awaiting jobs.
*/
public synchronized int awaitingJobsCount() {
- // pretend busy in case concurrent job attempts performing before activated
+ // pretend busy in case concurrent job attempts performing before
+ // activated
return this.activated ? this.jobEnd - this.jobStart + 1 : 1;
}
+
/**
* Answers the first job in the queue, or null if there is no job available
- * Until the job has completed, the job manager will keep answering the same job.
+ * Until the job has completed, the job manager will keep answering the same
+ * job.
*/
public synchronized IJob currentJob() {
if (this.enableCount > 0 && this.jobStart <= this.jobEnd)
return this.awaitingJobs[this.jobStart];
return null;
}
+
public void disable() {
this.enableCount--;
if (VERBOSE)
Util.verbose("DISABLING background indexing"); //$NON-NLS-1$
}
+
/**
- * Remove the index from cache for a given project.
- * Passing null as a job family discards them all.
+ * Remove the index from cache for a given project. Passing null as a job
+ * family discards them all.
*/
public void discardJobs(String jobFamily) {
@@ -81,20 +88,22 @@
try {
IJob currentJob;
// cancel current job if it belongs to the given family
- synchronized(this){
+ synchronized (this) {
currentJob = this.currentJob();
disable();
}
- if (currentJob != null && (jobFamily == null || currentJob.belongsTo(jobFamily))) {
+ if (currentJob != null
+ && (jobFamily == null || currentJob.belongsTo(jobFamily))) {
currentJob.cancel();
// wait until current active job has finished
- while (this.processingThread != null && this.executing){
+ while (this.processingThread != null && this.executing) {
try {
if (VERBOSE)
- Util.verbose("-> waiting end of current background job - " + currentJob); //$NON-NLS-1$
+ Util
+ .verbose("-> waiting end of current background job - " + currentJob); //$NON-NLS-1$
Thread.sleep(50);
- } catch(InterruptedException e){
+ } catch (InterruptedException e) {
// ignore
}
}
@@ -102,16 +111,19 @@
// flush and compact awaiting jobs
int loc = -1;
- synchronized(this) {
+ synchronized (this) {
for (int i = this.jobStart; i <= this.jobEnd; i++) {
currentJob = this.awaitingJobs[i];
if (currentJob != null) { // sanity check
this.awaitingJobs[i] = null;
- if (!(jobFamily == null || currentJob.belongsTo(jobFamily))) { // copy down, compacting
+ if (!(jobFamily == null || currentJob
+ .belongsTo(jobFamily))) { // copy down,
+ // compacting
this.awaitingJobs[++loc] = currentJob;
} else {
if (VERBOSE)
- Util.verbose("-> discarding background job - " + currentJob); //$NON-NLS-1$
+ Util
+ .verbose("-> discarding background job - " + currentJob); //$NON-NLS-1$
currentJob.cancel();
}
}
@@ -123,25 +135,33 @@
enable();
}
if (VERBOSE)
- Util.verbose("DISCARD DONE with background job family - " + jobFamily); //$NON-NLS-1$
+ Util
+ .verbose("DISCARD DONE with background job family - " + jobFamily); //$NON-NLS-1$
}
+
public synchronized void enable() {
this.enableCount++;
if (VERBOSE)
Util.verbose("ENABLING background indexing"); //$NON-NLS-1$
- this.notifyAll(); // wake up the background thread if it is waiting (context must be synchronized)
+ this.notifyAll(); // wake up the background thread if it is waiting
+ // (context must be synchronized)
}
+
public synchronized boolean isJobWaiting(IJob request) {
- for (int i = this.jobEnd; i > this.jobStart; i--) // don't check job at jobStart, as it may have already started
- if (request.equals(this.awaitingJobs[i])) return true;
+ for (int i = this.jobEnd; i > this.jobStart; i--)
+ // don't check job at jobStart, as it may have already started
+ if (request.equals(this.awaitingJobs[i]))
+ return true;
return false;
}
+
/**
- * Advance to the next available job, once the current one has been completed.
- * Note: clients awaiting until the job count is zero are still waiting at this point.
+ * Advance to the next available job, once the current one has been
+ * completed. Note: clients awaiting until the job count is zero are still
+ * waiting at this point.
*/
protected synchronized void moveToNextJob() {
- //if (!enabled) return;
+ // if (!enabled) return;
if (this.jobStart <= this.jobEnd) {
this.awaitingJobs[this.jobStart++] = null;
@@ -151,28 +171,31 @@
}
}
}
+
/**
* When idle, give chance to do something
*/
protected void notifyIdle(long idlingTime) {
// do nothing
}
+
/**
- * This API is allowing to run one job in concurrence with background processing.
- * Indeed since other jobs are performed in background, resource sharing might be
- * an issue.Therefore, this functionality allows a given job to be run without
- * colliding with background ones.
- * Note: multiple thread might attempt to perform concurrent jobs at the same time,
- * and should synchronize (it is deliberately left to clients to decide whether
- * concurrent jobs might interfere or not. In general, multiple read jobs are ok).
- *
- * Waiting policy can be:
- * IJobConstants.ForceImmediateSearch
- * IJobConstants.CancelIfNotReadyToSearch
- * IJobConstants.WaitUntilReadyToSearch
- *
+ * This API is allowing to run one job in concurrence with background
+ * processing. Indeed since other jobs are performed in background, resource
+ * sharing might be an issue.Therefore, this functionality allows a given
+ * job to be run without colliding with background ones. Note: multiple
+ * thread might attempt to perform concurrent jobs at the same time, and
+ * should synchronize (it is deliberately left to clients to decide whether
+ * concurrent jobs might interfere or not. In general, multiple read jobs
+ * are ok).
+ *
+ * Waiting policy can be: IJobConstants.ForceImmediateSearch
+ * IJobConstants.CancelIfNotReadyToSearch
+ * IJobConstants.WaitUntilReadyToSearch
+ *
*/
- public boolean performConcurrentJob(IJob searchJob, int waitingPolicy, IProgressMonitor progress) {
+ public boolean performConcurrentJob(IJob searchJob, int waitingPolicy,
+ IProgressMonitor progress) {
if (VERBOSE)
Util.verbose("STARTING concurrent job - " + searchJob); //$NON-NLS-1$
@@ -185,91 +208,103 @@
if (awaitingJobsCount() > 0) {
switch (waitingPolicy) {
- case IJob.ForceImmediate :
- if (VERBOSE)
- Util.verbose("-> NOT READY - forcing immediate - " + searchJob);//$NON-NLS-1$
- try {
- disable(); // pause indexing
- status = searchJob.execute(progress == null ? null : new SubProgressMonitor(progress, concurrentJobWork));
- } finally {
- enable();
- }
- if (VERBOSE)
- Util.verbose("FINISHED concurrent job - " + searchJob); //$NON-NLS-1$
- return status;
+ case IJob.ForceImmediate:
+ if (VERBOSE)
+ Util
+ .verbose("-> NOT READY - forcing immediate - " + searchJob);//$NON-NLS-1$
+ try {
+ disable(); // pause indexing
+ status = searchJob.execute(progress == null ? null
+ : new SubProgressMonitor(progress,
+ concurrentJobWork));
+ } finally {
+ enable();
+ }
+ if (VERBOSE)
+ Util.verbose("FINISHED concurrent job - " + searchJob); //$NON-NLS-1$
+ return status;
- case IJob.CancelIfNotReady :
- if (VERBOSE)
- Util.verbose("-> NOT READY - cancelling - " + searchJob); //$NON-NLS-1$
- if (VERBOSE)
- Util.verbose("CANCELED concurrent job - " + searchJob); //$NON-NLS-1$
- throw new OperationCanceledException();
+ case IJob.CancelIfNotReady:
+ if (VERBOSE)
+ Util.verbose("-> NOT READY - cancelling - " + searchJob); //$NON-NLS-1$
+ if (VERBOSE)
+ Util.verbose("CANCELED concurrent job - " + searchJob); //$NON-NLS-1$
+ throw new OperationCanceledException();
- case IJob.WaitUntilReady :
- int awaitingWork;
- IJob previousJob = null;
- IJob currentJob;
- IProgressMonitor subProgress = null;
- int totalWork = this.awaitingJobsCount();
- if (progress != null && totalWork > 0) {
- subProgress = new SubProgressMonitor(progress, concurrentJobWork / 2);
- subProgress.beginTask("", totalWork); //$NON-NLS-1$
- concurrentJobWork = concurrentJobWork / 2;
+ case IJob.WaitUntilReady:
+ int awaitingWork;
+ IJob previousJob = null;
+ IJob currentJob;
+ IProgressMonitor subProgress = null;
+ int totalWork = this.awaitingJobsCount();
+ if (progress != null && totalWork > 0) {
+ subProgress = new SubProgressMonitor(progress,
+ concurrentJobWork / 2);
+ subProgress.beginTask("", totalWork); //$NON-NLS-1$
+ concurrentJobWork = concurrentJobWork / 2;
+ }
+ // use local variable to avoid potential NPE (see bug 20435 NPE
+ // when searchingscriptmethod
+ // and bug 42760 NullPointerException in JobManager when
+ // searching)
+ Thread t = this.processingThread;
+ int originalPriority = t == null ? -1 : t.getPriority();
+ try {
+ if (t != null)
+ t.setPriority(Thread.currentThread().getPriority());
+ synchronized (this) {
+ this.awaitingClients++;
}
- // use local variable to avoid potential NPE (see bug 20435 NPE when searchingscriptmethod
- // and bug 42760 NullPointerException in JobManager when searching)
- Thread t = this.processingThread;
- int originalPriority = t == null ? -1 : t.getPriority();
- try {
- if (t != null)
- t.setPriority(Thread.currentThread().getPriority());
- synchronized(this) {
- this.awaitingClients++;
- }
- while ((awaitingWork = awaitingJobsCount()) > 0) {
- if (subProgress != null && subProgress.isCanceled())
- throw new OperationCanceledException();
- currentJob = currentJob();
- // currentJob can be null when jobs have been added to the queue but job manager is not enabled
- if (currentJob != null && currentJob != previousJob) {
- if (VERBOSE)
- Util.verbose("-> NOT READY - waiting until ready - " + searchJob);//$NON-NLS-1$
- if (subProgress != null) {
- subProgress.subTask(
- Messages.bind(Messages.manager_filesToIndex, Integer.toString(awaitingWork)));
- subProgress.worked(1);
- }
- previousJob = currentJob;
+ while ((awaitingWork = awaitingJobsCount()) > 0) {
+ if (subProgress != null && subProgress.isCanceled())
+ throw new OperationCanceledException();
+ currentJob = currentJob();
+ // currentJob can be null when jobs have been added to
+ // the queue but job manager is not enabled
+ if (currentJob != null && currentJob != previousJob) {
+ if (VERBOSE)
+ Util
+ .verbose("-> NOT READY - waiting until ready - " + searchJob);//$NON-NLS-1$
+ if (subProgress != null) {
+ subProgress.subTask(Messages.bind(
+ Messages.manager_filesToIndex, Integer
+ .toString(awaitingWork)));
+ subProgress.worked(1);
}
- try {
- if (VERBOSE)
- Util.verbose("-> GOING TO SLEEP - " + searchJob);//$NON-NLS-1$
- Thread.sleep(searchJob instanceof WaitJob ? 250
+ previousJob = currentJob;
+ }
+ try {
+ if (VERBOSE)
+ Util
+ .verbose("-> GOING TO SLEEP - " + searchJob);//$NON-NLS-1$
+ Thread.sleep(searchJob instanceof WaitJob ? 250
: 50);
- } catch (InterruptedException e) {
- // ignore
- }
+ } catch (InterruptedException e) {
+ // ignore
}
- } finally {
- synchronized(this) {
- this.awaitingClients--;
- }
- if (t != null && originalPriority > -1 && t.isAlive())
- t.setPriority(originalPriority);
}
- if (subProgress != null)
- subProgress.done();
+ } finally {
+ synchronized (this) {
+ this.awaitingClients--;
+ }
+ if (t != null && originalPriority > -1 && t.isAlive())
+ t.setPriority(originalPriority);
+ }
+ if (subProgress != null)
+ subProgress.done();
}
}
- status = searchJob.execute(progress == null ? null : new SubProgressMonitor(progress, concurrentJobWork));
+ status = searchJob.execute(progress == null ? null
+ : new SubProgressMonitor(progress, concurrentJobWork));
if (progress != null)
progress.done();
if (VERBOSE)
Util.verbose("FINISHED concurrent job - " + searchJob); //$NON-NLS-1$
return status;
}
+
public abstract String processName();
-
+
private static final class WaitJob implements IJob {
public boolean belongsTo(String jobFamily) {
return false;
@@ -300,9 +335,11 @@
// append the job to the list of ones to process later on
int size = this.awaitingJobs.length;
- if (++this.jobEnd == size) { // when growing, relocate jobs starting at position 0
+ if (++this.jobEnd == size) { // when growing, relocate jobs starting at
+ // position 0
this.jobEnd -= this.jobStart;
- System.arraycopy(this.awaitingJobs, this.jobStart, this.awaitingJobs = new IJob[size * 2], 0, this.jobEnd);
+ System.arraycopy(this.awaitingJobs, this.jobStart,
+ this.awaitingJobs = new IJob[size * 2], 0, this.jobEnd);
this.jobStart = 0;
}
this.awaitingJobs[this.jobEnd] = job;
@@ -312,6 +349,7 @@
}
notifyAll(); // wake up the background thread if it is waiting
}
+
/**
* Flush current state
*/
@@ -325,11 +363,13 @@
/* initiate background processing */
this.processingThread = new Thread(this, this.processName());
this.processingThread.setDaemon(true);
- // less prioritary by default, priority is raised if clients are actively waiting on it
- this.processingThread.setPriority(Thread.NORM_PRIORITY-1);
+ // less prioritary by default, priority is raised if clients are
+ // actively waiting on it
+ this.processingThread.setPriority(Thread.NORM_PRIORITY - 1);
this.processingThread.start();
}
}
+
/**
* Infinite loop performing resource indexing
*/
@@ -342,12 +382,16 @@
ProgressJob(String name) {
super(name);
}
+
protected IStatus run(IProgressMonitor monitor) {
int awaitingJobsCount;
monitor.beginTask(Messages.manager_indexingTask,
IProgressMonitor.UNKNOWN);
- while (!monitor.isCanceled() && (awaitingJobsCount = awaitingJobsCount()) > 0) {
- monitor.subTask(Messages.bind(Messages.manager_filesToIndex, Integer.toString(awaitingJobsCount)));
+ while (!monitor.isCanceled()
+ && (awaitingJobsCount = awaitingJobsCount()) > 0) {
+ monitor.subTask(Messages.bind(
+ Messages.manager_filesToIndex, Integer
+ .toString(awaitingJobsCount)));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
@@ -363,10 +407,13 @@
try {
IJob job;
synchronized (this) {
- // handle shutdown case when notifyAll came before the wait but after the while loop was entered
- if (this.processingThread == null) continue;
+ // handle shutdown case when notifyAll came before the
+ // wait but after the while loop was entered
+ if (this.processingThread == null)
+ continue;
- // must check for new job inside this sync block to avoid timing hole
+ // must check for new job inside this sync block to
+ // avoid timing hole
if ((job = currentJob()) == null) {
if (this.progressJob != null) {
this.progressJob.cancel();
@@ -375,15 +422,18 @@
if (idlingStart < 0)
idlingStart = System.currentTimeMillis();
else
- notifyIdle(System.currentTimeMillis() - idlingStart);
- this.wait(); // wait until a new job is posted (or reenabled:38901)
+ notifyIdle(System.currentTimeMillis()
+ - idlingStart);
+ this.wait(); // wait until a new job is posted (or
+ // reenabled:38901)
} else {
idlingStart = -1;
}
}
if (job == null) {
notifyIdle(System.currentTimeMillis() - idlingStart);
- // just woke up, delay before processing any new jobs, allow some time for the active thread to finish
+ // just woke up, delay before processing any new jobs,
+ // allow some time for the active thread to finish
Thread.sleep(500);
continue;
}
@@ -394,50 +444,56 @@
try {
this.executing = true;
if (this.progressJob == null) {
- this.progressJob = new ProgressJob(Messages.manager_indexingInProgress);
+ this.progressJob = new ProgressJob(
+ Messages.manager_indexingInProgress);
this.progressJob.setPriority(Job.LONG);
// this.progressJob.setSystem(true);
this.progressJob.schedule();
}
- /*boolean status = */job.execute(null);
- //if (status == FAILED) request(job);
+ /* boolean status = */job.execute(null);
+ // if (status == FAILED) request(job);
} finally {
this.executing = false;
if (VERBOSE)
Util.verbose("FINISHED background job - " + job); //$NON-NLS-1$
moveToNextJob();
- if (this.awaitingClients == 0)
- Thread.sleep(50);
+ // if (this.awaitingClients == 0)
+ // Thread.sleep(50);
}
- } catch (InterruptedException e) { // background indexing was interrupted
+ } catch (InterruptedException e) { // background indexing was
+ // interrupted
}
}
} catch (RuntimeException e) {
if (this.processingThread != null) { // if not shutting down
// log exception
Util.log(e, "Background Indexer Crash Recovery"); //$NON-NLS-1$
-
+
// keep job manager alive
this.discardJobs(null);
this.processingThread = null;
- this.reset(); // this will fork a new thread with no waiting jobs, some indexes will be inconsistent
+ this.reset(); // this will fork a new thread with no waiting
+ // jobs, some indexes will be inconsistent
}
throw e;
} catch (Error e) {
if (this.processingThread != null && !(e instanceof ThreadDeath)) {
// log exception
Util.log(e, "Background Indexer Crash Recovery"); //$NON-NLS-1$
-
+
// keep job manager alive
this.discardJobs(null);
this.processingThread = null;
- this.reset(); // this will fork a new thread with no waiting jobs, some indexes will be inconsistent
+ this.reset(); // this will fork a new thread with no waiting
+ // jobs, some indexes will be inconsistent
}
throw e;
}
}
+
/**
- * Stop background processing, and wait until the current job is completed before returning
+ * Stop background processing, and wait until the current job is completed
+ * before returning
*/
public void shutdown() {
@@ -445,12 +501,18 @@
Util.verbose("Shutdown"); //$NON-NLS-1$
disable();
- discardJobs(null); // will wait until current executing job has completed
+ discardJobs(null); // will wait until current executing job has
+ // completed
Thread thread = this.processingThread;
try {
- if (thread != null) { // see http://bugs.eclipse.org/bugs/show_bug.cgi?id=31858
+ if (thread != null) { // see
+ // http://bugs.eclipse.org/bugs/show_bug.cgi
+ // ?id=31858
synchronized (this) {
- this.processingThread = null; // mark the job manager as shutting down so that the thread will stop by itself
+ this.processingThread = null; // mark the job manager as
+ // shutting down so that the
+ // thread will stop by
+ // itself
this.notifyAll(); // ensure its awake so it can be shutdown
}
// in case processing thread is handling a job
@@ -465,14 +527,17 @@
// ignore
}
}
+
public String toString() {
StringBuffer buffer = new StringBuffer(10);
buffer.append("Enable count:").append(this.enableCount).append('\n'); //$NON-NLS-1$
int numJobs = this.jobEnd - this.jobStart + 1;
buffer.append("Jobs in queue:").append(numJobs).append('\n'); //$NON-NLS-1$
for (int i = 0; i < numJobs && i < 15; i++) {
- buffer.append(i).append(" - job["+i+"]: ").append(this.awaitingJobs[this.jobStart+i]).append('\n'); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer
+ .append(i)
+ .append(" - job[" + i + "]: ").append(this.awaitingJobs[this.jobStart + i]).append('\n'); //$NON-NLS-1$ //$NON-NLS-2$
}
return buffer.toString();
- }
+ }
}