@@ -63,7 +63,7 @@ public final class Suggester implements Closeable {
63
63
64
64
private static final Logger logger = Logger .getLogger (Suggester .class .getName ());
65
65
66
- private final Map <String , FieldWFSTCollection > projectData = new ConcurrentHashMap <>();
66
+ private final Map <String , SuggesterProjectData > projectData = new ConcurrentHashMap <>();
67
67
68
68
private final Object lock = new Object ();
69
69
@@ -115,9 +115,9 @@ public Suggester(
115
115
116
116
/**
117
117
* Initializes suggester data for specified indexes. The data is initialized asynchronously.
118
- * @param luceneIndexes paths where Lucene indexes are stored
118
+ * @param luceneIndexes paths to lucene indexes and name with which the index should be associated
119
119
*/
120
- public void init (final Collection <Path > luceneIndexes ) {
120
+ public void init (final Collection <NamedIndexDir > luceneIndexes ) {
121
121
if (luceneIndexes == null || luceneIndexes .isEmpty ()) {
122
122
logger .log (Level .INFO , "No index directories found, exiting..." );
123
123
return ;
@@ -131,17 +131,17 @@ public void init(final Collection<Path> luceneIndexes) {
131
131
132
132
ExecutorService executorService = Executors .newFixedThreadPool (Runtime .getRuntime ().availableProcessors ());
133
133
134
- for (Path indexDir : luceneIndexes ) {
134
+ for (NamedIndexDir indexDir : luceneIndexes ) {
135
135
submitInitIfIndexExists (executorService , indexDir );
136
136
}
137
137
138
138
shutdownAndAwaitTermination (executorService , "Suggester successfully initialized" );
139
139
}
140
140
}
141
141
142
- private void submitInitIfIndexExists (final ExecutorService executorService , final Path indexDir ) {
142
+ private void submitInitIfIndexExists (final ExecutorService executorService , final NamedIndexDir indexDir ) {
143
143
try {
144
- if (indexExists (indexDir )) {
144
+ if (indexExists (indexDir . path )) {
145
145
executorService .submit (getInitRunnable (indexDir ));
146
146
} else {
147
147
logger .log (Level .FINE , "Index in {0} directory does not exist, skipping..." , indexDir );
@@ -151,17 +151,17 @@ private void submitInitIfIndexExists(final ExecutorService executorService, fina
151
151
}
152
152
}
153
153
154
- private Runnable getInitRunnable (final Path indexDir ) {
154
+ private Runnable getInitRunnable (final NamedIndexDir indexDir ) {
155
155
return () -> {
156
156
try {
157
157
Instant start = Instant .now ();
158
158
logger .log (Level .FINE , "Initializing {0}" , indexDir );
159
159
160
- FieldWFSTCollection wfst = new FieldWFSTCollection (FSDirectory .open (indexDir ),
161
- getSuggesterDir (indexDir ), allowMostPopular , allowedFields );
160
+ SuggesterProjectData wfst = new SuggesterProjectData (FSDirectory .open (indexDir . path ),
161
+ getSuggesterDir (indexDir . name ), allowMostPopular , allowedFields );
162
162
wfst .init ();
163
163
if (projectsEnabled ) {
164
- projectData .put (indexDir .getFileName (). toString () , wfst );
164
+ projectData .put (indexDir .name , wfst );
165
165
} else {
166
166
projectData .put (PROJECTS_DISABLED_KEY , wfst );
167
167
}
@@ -174,9 +174,9 @@ private Runnable getInitRunnable(final Path indexDir) {
174
174
};
175
175
}
176
176
177
- private Path getSuggesterDir (final Path indexDir ) {
177
+ private Path getSuggesterDir (final String indexDirName ) {
178
178
if (projectsEnabled ) {
179
- return suggesterDir .toPath ().resolve (indexDir . getFileName () );
179
+ return suggesterDir .toPath ().resolve (indexDirName );
180
180
} else {
181
181
return this .suggesterDir .toPath ();
182
182
}
@@ -200,9 +200,9 @@ private void shutdownAndAwaitTermination(final ExecutorService executorService,
200
200
201
201
/**
202
202
* Rebuilds the data structures for specified indexes.
203
- * @param indexDirs paths where Lucene indexes are stored
203
+ * @param indexDirs paths to lucene indexes and name with which the index should be associated
204
204
*/
205
- public void rebuild (final List < Path > indexDirs ) {
205
+ public void rebuild (final Collection < NamedIndexDir > indexDirs ) {
206
206
if (indexDirs == null || indexDirs .isEmpty ()) {
207
207
logger .log (Level .INFO , "Not rebuilding suggester data because no index directories were specified" );
208
208
return ;
@@ -213,10 +213,10 @@ public void rebuild(final List<Path> indexDirs) {
213
213
214
214
ExecutorService executorService = Executors .newFixedThreadPool (Runtime .getRuntime ().availableProcessors ());
215
215
216
- for (Path indexDir : indexDirs ) {
217
- FieldWFSTCollection fieldsWFST = projectData .get (indexDir .getFileName (). toString () );
218
- if (fieldsWFST != null ) {
219
- executorService .submit (getRebuildRunnable (fieldsWFST ));
216
+ for (NamedIndexDir indexDir : indexDirs ) {
217
+ SuggesterProjectData data = this . projectData .get (indexDir .name );
218
+ if (data != null ) {
219
+ executorService .submit (getRebuildRunnable (data ));
220
220
} else {
221
221
submitInitIfIndexExists (executorService , indexDir );
222
222
}
@@ -226,36 +226,35 @@ public void rebuild(final List<Path> indexDirs) {
226
226
}
227
227
}
228
228
229
- private Runnable getRebuildRunnable (final FieldWFSTCollection fieldsWFST ) {
229
+ private Runnable getRebuildRunnable (final SuggesterProjectData data ) {
230
230
return () -> {
231
231
try {
232
232
Instant start = Instant .now ();
233
- logger .log (Level .FINE , "Rebuilding {0}" , fieldsWFST );
234
- fieldsWFST .rebuild ();
233
+ logger .log (Level .FINE , "Rebuilding {0}" , data );
234
+ data .rebuild ();
235
235
236
236
Duration d = Duration .between (start , Instant .now ());
237
- logger .log (Level .FINE , "Rebuild of {0} finished, took {1}" , new Object [] {fieldsWFST , d });
237
+ logger .log (Level .FINE , "Rebuild of {0} finished, took {1}" , new Object [] {data , d });
238
238
} catch (Exception e ) {
239
239
logger .log (Level .SEVERE , "Could not rebuild suggester" , e );
240
240
}
241
241
};
242
242
}
243
243
244
244
/**
245
- * Removes the data associated with the names {@code projectNames}.
246
- * @param projectNames names of the indexes to delete (name is determined by the name of the Lucene index
247
- * directory)
245
+ * Removes the data associated with the provided names.
246
+ * @param names names of the indexes to delete
248
247
*/
249
- public void remove (final Iterable <String > projectNames ) {
250
- if (projectNames == null ) {
248
+ public void remove (final Iterable <String > names ) {
249
+ if (names == null ) {
251
250
return ;
252
251
}
253
252
254
253
synchronized (lock ) {
255
- logger .log (Level .INFO , "Removing following suggesters: {0}" , projectNames );
254
+ logger .log (Level .INFO , "Removing following suggesters: {0}" , names );
256
255
257
- for (String suggesterName : projectNames ) {
258
- FieldWFSTCollection collection = projectData .get (suggesterName );
256
+ for (String suggesterName : names ) {
257
+ SuggesterProjectData collection = projectData .get (suggesterName );
259
258
if (collection == null ) {
260
259
logger .log (Level .WARNING , "Unknown suggester {0}" , suggesterName );
261
260
continue ;
@@ -290,7 +289,7 @@ public List<LookupResultItem> search(
290
289
291
290
List <LookupResultItem > results = readers .parallelStream ().flatMap (namedIndexReader -> {
292
291
293
- FieldWFSTCollection data = projectData .get (namedIndexReader .name );
292
+ SuggesterProjectData data = projectData .get (namedIndexReader .name );
294
293
if (data == null ) {
295
294
logger .log (Level .FINE , "{0} not yet initialized" , namedIndexReader .name );
296
295
return Stream .empty ();
@@ -385,7 +384,7 @@ public void increaseSearchCount(final String project, final Term term, final int
385
384
if (!allowMostPopular ) {
386
385
return ;
387
386
}
388
- FieldWFSTCollection data ;
387
+ SuggesterProjectData data ;
389
388
if (!projectsEnabled ) {
390
389
data = projectData .get (PROJECTS_DISABLED_KEY );
391
390
} else {
@@ -408,7 +407,7 @@ public List<Entry<BytesRef, Integer>> getSearchCounts(
408
407
final int page ,
409
408
final int pageSize
410
409
) {
411
- FieldWFSTCollection data = projectData .get (project );
410
+ SuggesterProjectData data = projectData .get (project );
412
411
if (data == null ) {
413
412
logger .log (Level .FINE , "Cannot retrieve search counts because data for project {0} were not found" ,
414
413
project );
@@ -432,16 +431,65 @@ public void close() {
432
431
});
433
432
}
434
433
434
+ /**
435
+ * Model classes for holding project name and path to ist index directory.
436
+ */
437
+ public static class NamedIndexDir {
438
+
439
+ /**
440
+ * Name of the project.
441
+ */
442
+ private final String name ;
443
+
444
+ /**
445
+ * Path to index directory for project with name {@link #name}.
446
+ */
447
+ private final Path path ;
448
+
449
+ public NamedIndexDir (final String name , final Path path ) {
450
+ if (name == null ) {
451
+ throw new IllegalArgumentException ("Name cannot be null" );
452
+ }
453
+ if (path == null ) {
454
+ throw new IllegalArgumentException ("Path cannot be null" );
455
+ }
456
+
457
+ this .name = name ;
458
+ this .path = path ;
459
+ }
460
+
461
+ public String getName () {
462
+ return name ;
463
+ }
464
+
465
+ public Path getPath () {
466
+ return path ;
467
+ }
468
+ }
469
+
435
470
/**
436
471
* Model class to hold the project name and its {@link IndexReader}.
437
472
*/
438
473
public static class NamedIndexReader {
439
474
475
+ /**
476
+ * Name of the project.
477
+ */
440
478
private final String name ;
441
479
480
+ /**
481
+ * IndexReader of the project with {@link #name}.
482
+ */
442
483
private final IndexReader reader ;
443
484
444
485
public NamedIndexReader (final String name , final IndexReader reader ) {
486
+ if (name == null ) {
487
+ throw new IllegalArgumentException ("Name cannot be null" );
488
+ }
489
+ if (reader == null ) {
490
+ throw new IllegalArgumentException ("Reader cannot be null" );
491
+ }
492
+
445
493
this .name = name ;
446
494
this .reader = reader ;
447
495
}
0 commit comments