Skip to content

Commit 6372909

Browse files
committed
Refactor org.eclipse.help.internal.search.SearchIndex#openSearcher()
In `org.eclipse.help.internal.search.SearchIndex`, refactor the `openSearcher()` method to return an `AutoCloseable` object so that it can be used in a try-with-resources statement that implicitly registers and unregisters the search. Minor performance improvement: Use double-checked locking idiom for lazy initialization of the `IndexSearcher`. Grant access to the `searches` and `analyzerDescriptor` fields via `SearcherInfo#getIndexSearcher()` and `SearcherInfo#getAnalyzerDescriptor()`. These two getter methods are not (yet) used internally. Their only purpose is to be able to implement a hybrid search that combines a semantic search with a sparse keyword search. And the sparse keyword search uses the existing `SearchIndex`, which requires access to these fields.
1 parent e64f742 commit 6372909

File tree

1 file changed

+54
-41
lines changed

1 file changed

+54
-41
lines changed

ua/org.eclipse.help.base/src/org/eclipse/help/internal/search/SearchIndex.java

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -133,20 +133,42 @@ public class SearchIndex implements IHelpSearchIndex {
133133

134134
private final HTMLSearchParticipant htmlSearchParticipant;
135135

136-
private IndexSearcher searcher;
136+
private volatile IndexSearcher searcher;
137137

138138
private final Object searcherCreateLock = new Object();
139139

140140
private HelpProperties dependencies;
141141

142142
private volatile boolean closed = false;
143143

144-
// Collection of searches occuring now
144+
// Collection of searches occurring now
145145
private final Collection<Thread> searches = new ArrayList<>();
146146

147147
private FileLock lock;
148148
private RandomAccessFile raf = null;
149149

150+
public class SearcherInfo implements AutoCloseable {
151+
152+
private SearcherInfo() {
153+
}
154+
155+
@Override
156+
public void close() throws Exception {
157+
synchronized (searches) {
158+
searches.remove(Thread.currentThread());
159+
}
160+
}
161+
162+
public IndexSearcher getIndexSearcher() {
163+
return searcher;
164+
}
165+
166+
public AnalyzerDescriptor getAnalyzerDescriptor() {
167+
return analyzerDescriptor;
168+
}
169+
170+
}
171+
150172
/**
151173
* Constructor.
152174
*
@@ -639,38 +661,26 @@ public boolean exists() {
639661
/**
640662
* Performs a query search on this index
641663
*/
642-
public void search(ISearchQuery searchQuery, ISearchHitCollector collector)
643-
throws QueryTooComplexException {
644-
try {
645-
if (closed)
646-
return;
647-
registerSearch(Thread.currentThread());
648-
if (closed)
649-
return;
664+
public void search(ISearchQuery searchQuery, ISearchHitCollector collector) throws QueryTooComplexException {
665+
try (var searcherInfo = openSearcher()) {
666+
if (searcherInfo == null)
667+
return; // already closed
650668
QueryBuilder queryBuilder = new QueryBuilder(searchQuery.getSearchWord(), analyzerDescriptor);
651-
Query luceneQuery = queryBuilder.getLuceneQuery(searchQuery.getFieldNames(), searchQuery
652-
.isFieldSearch());
669+
Query luceneQuery = queryBuilder.getLuceneQuery(searchQuery.getFieldNames(), searchQuery.isFieldSearch());
653670
if (HelpPlugin.DEBUG_SEARCH) {
654-
System.out.println("Search Query: " + luceneQuery.toString()); //$NON-NLS-1$
655-
}
656-
String highlightTerms = queryBuilder.gethighlightTerms();
657-
if (luceneQuery != null) {
658-
if (searcher == null) {
659-
openSearcher();
660-
}
661-
TopDocs topDocs = searcher.search(luceneQuery, 1000);
662-
collector.addHits(LocalSearchManager.asList(topDocs, searcher), highlightTerms);
671+
System.out.println("Search Query: " + luceneQuery); //$NON-NLS-1$
663672
}
673+
if (luceneQuery == null)
674+
return;
675+
TopDocs topDocs = searcher.search(luceneQuery, 1000);
676+
collector.addHits(LocalSearchManager.asList(topDocs, searcher), queryBuilder.gethighlightTerms());
664677
} catch (IndexSearcher.TooManyClauses tmc) {
665678
collector.addQTCException(new QueryTooComplexException());
666679
} catch (QueryTooComplexException qe) {
667680
collector.addQTCException(qe);
668681
} catch (Exception e) {
669-
ILog.of(getClass()).error(
670-
"Exception occurred performing search for: " //$NON-NLS-1$
682+
ILog.of(getClass()).error("Exception occurred performing search for: " //$NON-NLS-1$
671683
+ searchQuery.getSearchWord() + ".", e); //$NON-NLS-1$
672-
} finally {
673-
unregisterSearch(Thread.currentThread());
674684
}
675685
}
676686

@@ -819,12 +829,27 @@ public void setInconsistent(boolean inconsistent) {
819829
}
820830

821831
@SuppressWarnings("resource")
822-
public void openSearcher() throws IOException {
823-
synchronized (searcherCreateLock) {
824-
if (searcher == null) {
825-
searcher = new IndexSearcher(DirectoryReader.open(luceneDirectory));
832+
public SearcherInfo openSearcher() {
833+
if (closed)
834+
return null;
835+
synchronized (searches) {
836+
searches.add(Thread.currentThread());
837+
}
838+
if (closed)
839+
return null;
840+
if (searcher == null) {
841+
synchronized (searcherCreateLock) {
842+
if (searcher == null) {
843+
try {
844+
searcher = new IndexSearcher(DirectoryReader.open(luceneDirectory));
845+
} catch (Exception e) {
846+
ILog.of(getClass()).error("Failed to open search index. Index directory: " + indexDir, e); //$NON-NLS-1$
847+
return null;
848+
}
849+
}
826850
}
827851
}
852+
return new SearcherInfo();
828853
}
829854

830855
/**
@@ -942,18 +967,6 @@ public TocManager getTocManager() {
942967
return tocManager;
943968
}
944969

945-
private void registerSearch(Thread t) {
946-
synchronized (searches) {
947-
searches.add(t);
948-
}
949-
}
950-
951-
private void unregisterSearch(Thread t) {
952-
synchronized (searches) {
953-
searches.remove(t);
954-
}
955-
}
956-
957970
/**
958971
* @return Returns the closed.
959972
*/

0 commit comments

Comments
 (0)