Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchQuery.java')
-rw-r--r--org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchQuery.java74
1 files changed, 61 insertions, 13 deletions
diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchQuery.java b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchQuery.java
index b3b4250915d..6204333413c 100644
--- a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchQuery.java
+++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchQuery.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,10 +11,14 @@
* Ulrich Etter, etteru@ethz.ch - 47136 Search view should show match objects
* Roman Fuchs, fuchsro@ethz.ch - 47136 Search view should show match objects
* Christian Walther (Indel AG) - Bug 399094: Add whole word option to file search
+ * Terry Parker <tparker@google.com> (Google Inc.) - Bug 441016 - Speed up text search by parallelizing it using JobGroups
*******************************************************************************/
package org.eclipse.search.internal.ui.text;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.CoreException;
@@ -48,7 +52,8 @@ public class FileSearchQuery implements ISearchQuery {
private final boolean fSearchInBinaries;
private final boolean fIsLightweightAutoRefresh;
- private ArrayList fCachedMatches;
+ private Map fCachedMatches; // map of IFile -> ArrayList of FileMatches
+ private Object fLock= new Object();
private TextSearchResultCollector(AbstractTextSearchResult result, boolean isFileSearchOnly, boolean searchInBinaries) {
fResult= result;
@@ -63,7 +68,9 @@ public class FileSearchQuery implements ISearchQuery {
return false;
if (fIsFileSearchOnly) {
- fResult.addMatch(new FileMatch(file));
+ synchronized (fLock) {
+ fResult.addMatch(new FileMatch(file));
+ }
}
flushMatches();
return true;
@@ -77,22 +84,55 @@ public class FileSearchQuery implements ISearchQuery {
}
public boolean acceptPatternMatch(TextSearchMatchAccess matchRequestor) throws CoreException {
+ ArrayList matches;
+ synchronized(fLock) {
+ // fCachedMatches is set to null when the caller invokes endReporting(),
+ // indicating that no further results are desired/expected, so discard
+ // any additional results.
+ if (fCachedMatches == null) {
+ return false;
+ }
+ matches= (ArrayList) fCachedMatches.get(matchRequestor.getFile());
+ }
+
int matchOffset= matchRequestor.getMatchOffset();
- LineElement lineElement= getLineElement(matchOffset, matchRequestor);
+ /*
+ * Another job may call flushCaches() at any time, which will clear the cached matches.
+ * Any addition of matches to the cache needs to be protected against the flushing of
+ * the cache by other jobs. It is OK to call getLineElement() with an unprotected local
+ * reference to the matches for this file, because getLineElement() uses previous matches
+ * as an optimization when creating new matches but doesn't update the cache directly
+ * (and because each file is processed by at most one job).
+ */
+ LineElement lineElement= getLineElement(matchOffset, matchRequestor, matches);
if (lineElement != null) {
FileMatch fileMatch= new FileMatch(matchRequestor.getFile(), matchOffset, matchRequestor.getMatchLength(), lineElement);
- fCachedMatches.add(fileMatch);
+ synchronized(fLock) {
+ // fCachedMatches is set to null when the caller invokes endReporting(),
+ // indicating that no further results are desired/expected, so discard
+ // any additional results.
+ if (fCachedMatches == null) {
+ return false;
+ }
+ matches= (ArrayList) fCachedMatches.get(matchRequestor.getFile());
+ if (matches == null) {
+ matches= new ArrayList();
+ fCachedMatches.put(matchRequestor.getFile(), matches);
+ }
+ matches.add(fileMatch);
+ }
}
return true;
}
- private LineElement getLineElement(int offset, TextSearchMatchAccess matchRequestor) {
+ private LineElement getLineElement(int offset, TextSearchMatchAccess matchRequestor, ArrayList matches) {
int lineNumber= 1;
int lineStart= 0;
- if (!fCachedMatches.isEmpty()) {
+
+ if (matches != null) {
// match on same line as last?
- FileMatch last= (FileMatch) fCachedMatches.get(fCachedMatches.size() - 1);
+ FileMatch last= (FileMatch) matches.get(matches.size() - 1);
LineElement lineElement= last.getLineElement();
if (lineElement.contains(offset)) {
return lineElement;
@@ -142,18 +182,26 @@ public class FileSearchQuery implements ISearchQuery {
}
public void beginReporting() {
- fCachedMatches= new ArrayList();
+ fCachedMatches= new HashMap();
}
public void endReporting() {
flushMatches();
- fCachedMatches= null;
+ synchronized (fLock) {
+ fCachedMatches= null;
+ }
}
private void flushMatches() {
- if (!fCachedMatches.isEmpty()) {
- fResult.addMatches((Match[]) fCachedMatches.toArray(new Match[fCachedMatches.size()]));
- fCachedMatches.clear();
+ synchronized (fLock) {
+ if (fCachedMatches != null && !fCachedMatches.isEmpty()) {
+ Iterator it = fCachedMatches.values().iterator();
+ while(it.hasNext()) {
+ ArrayList matches= (ArrayList) it.next();
+ fResult.addMatches((Match[]) matches.toArray(new Match[matches.size()]));
+ }
+ fCachedMatches.clear();
+ }
}
}
}

Back to the top