Skip to content

Commit 0fc54b8

Browse files
howlgeriloveeclipse
authored andcommitted
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 4a4172c commit 0fc54b8

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
*
@@ -629,38 +651,26 @@ public boolean exists() {
629651
/**
630652
* Performs a query search on this index
631653
*/
632-
public void search(ISearchQuery searchQuery, ISearchHitCollector collector)
633-
throws QueryTooComplexException {
634-
try {
635-
if (closed)
636-
return;
637-
registerSearch(Thread.currentThread());
638-
if (closed)
639-
return;
654+
public void search(ISearchQuery searchQuery, ISearchHitCollector collector) throws QueryTooComplexException {
655+
try (var searcherInfo = openSearcher()) {
656+
if (searcherInfo == null)
657+
return; // already closed
640658
QueryBuilder queryBuilder = new QueryBuilder(searchQuery.getSearchWord(), analyzerDescriptor);
641-
Query luceneQuery = queryBuilder.getLuceneQuery(searchQuery.getFieldNames(), searchQuery
642-
.isFieldSearch());
659+
Query luceneQuery = queryBuilder.getLuceneQuery(searchQuery.getFieldNames(), searchQuery.isFieldSearch());
643660
if (HelpPlugin.DEBUG_SEARCH) {
644-
System.out.println("Search Query: " + luceneQuery.toString()); //$NON-NLS-1$
645-
}
646-
String highlightTerms = queryBuilder.gethighlightTerms();
647-
if (luceneQuery != null) {
648-
if (searcher == null) {
649-
openSearcher();
650-
}
651-
TopDocs topDocs = searcher.search(luceneQuery, 1000);
652-
collector.addHits(LocalSearchManager.asList(topDocs, searcher), highlightTerms);
661+
System.out.println("Search Query: " + luceneQuery); //$NON-NLS-1$
653662
}
663+
if (luceneQuery == null)
664+
return;
665+
TopDocs topDocs = searcher.search(luceneQuery, 1000);
666+
collector.addHits(LocalSearchManager.asList(topDocs, searcher), queryBuilder.gethighlightTerms());
654667
} catch (IndexSearcher.TooManyClauses tmc) {
655668
collector.addQTCException(new QueryTooComplexException());
656669
} catch (QueryTooComplexException qe) {
657670
collector.addQTCException(qe);
658671
} catch (Exception e) {
659-
ILog.of(getClass()).error(
660-
"Exception occurred performing search for: " //$NON-NLS-1$
672+
ILog.of(getClass()).error("Exception occurred performing search for: " //$NON-NLS-1$
661673
+ searchQuery.getSearchWord() + ".", e); //$NON-NLS-1$
662-
} finally {
663-
unregisterSearch(Thread.currentThread());
664674
}
665675
}
666676

@@ -806,12 +816,27 @@ public void setInconsistent(boolean inconsistent) {
806816
}
807817

808818
@SuppressWarnings("resource")
809-
public void openSearcher() throws IOException {
810-
synchronized (searcherCreateLock) {
811-
if (searcher == null) {
812-
searcher = new IndexSearcher(DirectoryReader.open(luceneDirectory));
819+
public SearcherInfo openSearcher() {
820+
if (closed)
821+
return null;
822+
synchronized (searches) {
823+
searches.add(Thread.currentThread());
824+
}
825+
if (closed)
826+
return null;
827+
if (searcher == null) {
828+
synchronized (searcherCreateLock) {
829+
if (searcher == null) {
830+
try {
831+
searcher = new IndexSearcher(DirectoryReader.open(luceneDirectory));
832+
} catch (Exception e) {
833+
ILog.of(getClass()).error("Failed to open search index. Index directory: " + indexDir, e); //$NON-NLS-1$
834+
return null;
835+
}
836+
}
813837
}
814838
}
839+
return new SearcherInfo();
815840
}
816841

817842
/**
@@ -929,18 +954,6 @@ public TocManager getTocManager() {
929954
return tocManager;
930955
}
931956

932-
private void registerSearch(Thread t) {
933-
synchronized (searches) {
934-
searches.add(t);
935-
}
936-
}
937-
938-
private void unregisterSearch(Thread t) {
939-
synchronized (searches) {
940-
searches.remove(t);
941-
}
942-
}
943-
944957
/**
945958
* @return Returns the closed.
946959
*/

0 commit comments

Comments
 (0)