Skip to content

Commit 846c1e6

Browse files
ahornaceVladimir Kotal
authored andcommitted
Minor API improvements and some tests
1 parent e8e4015 commit 846c1e6

File tree

8 files changed

+308
-80
lines changed

8 files changed

+308
-80
lines changed

src/org/opensolaris/opengrok/web/api/v1/suggester/provider/service/impl/SuggesterServiceImpl.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.apache.lucene.util.BytesRef;
3333
import org.opengrok.suggest.LookupResultItem;
3434
import org.opengrok.suggest.Suggester;
35+
import org.opengrok.suggest.Suggester.NamedIndexDir;
3536
import org.opengrok.suggest.Suggester.NamedIndexReader;
3637
import org.opengrok.suggest.query.SuggesterQuery;
3738
import org.opensolaris.opengrok.configuration.Configuration;
@@ -189,13 +190,17 @@ public void refresh(final String project) {
189190
logger.log(Level.FINE, "Cannot refresh {0} because suggester is not initialized", project);
190191
return;
191192
}
192-
suggester.rebuild(Collections.singletonList(Paths.get(config.getDataRoot(), IndexDatabase.INDEX_DIR,
193-
p.getPath())));
193+
suggester.rebuild(Collections.singleton(getNamedIndexDir(p)));
194194
} finally {
195195
lock.readLock().unlock();
196196
}
197197
}
198198

199+
private NamedIndexDir getNamedIndexDir(final Project p) {
200+
Path indexPath = Paths.get(env.getConfiguration().getDataRoot(), IndexDatabase.INDEX_DIR, p.getPath());
201+
return new NamedIndexDir(p.getName(), indexPath);
202+
}
203+
199204
/** {@inheritDoc} */
200205
@Override
201206
public void delete(final String project) {
@@ -281,17 +286,15 @@ private void initSuggester() {
281286
}).start();
282287
}
283288

284-
private static List<Path> getAllProjectIndexDirs() {
285-
Configuration config = RuntimeEnvironment.getInstance().getConfiguration();
286-
287-
if (config.isProjectsEnabled()) {
288-
return RuntimeEnvironment.getInstance().getProjectList().stream()
289+
private Collection<NamedIndexDir> getAllProjectIndexDirs() {
290+
if (env.getConfiguration().isProjectsEnabled()) {
291+
return env.getProjectList().stream()
289292
.filter(Project::isIndexed)
290-
.map(project -> Paths.get(config.getDataRoot(), IndexDatabase.INDEX_DIR, project.getPath()))
293+
.map(this::getNamedIndexDir)
291294
.collect(Collectors.toList());
292295
} else {
293-
return Collections.singletonList(Paths.get(
294-
RuntimeEnvironment.getInstance().getDataRootPath(), IndexDatabase.INDEX_DIR));
296+
Path indexDir = Paths.get(env.getDataRootPath(), IndexDatabase.INDEX_DIR);
297+
return Collections.singleton(new NamedIndexDir("", indexDir));
295298
}
296299
}
297300

suggester/pom.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515
<groupId>org.apache.lucene</groupId>
1616
<artifactId>lucene-core</artifactId>
1717
</dependency>
18+
1819
<dependency>
1920
<groupId>org.apache.lucene</groupId>
2021
<artifactId>lucene-analyzers-common</artifactId>
2122
</dependency>
23+
2224
<dependency>
2325
<groupId>org.apache.lucene</groupId>
2426
<artifactId>lucene-queryparser</artifactId>
2527
</dependency>
28+
2629
<dependency>
2730
<groupId>org.apache.lucene</groupId>
2831
<artifactId>lucene-suggest</artifactId>
@@ -72,6 +75,13 @@
7275
<version>1.7.25</version>
7376
</dependency>
7477

78+
<dependency>
79+
<groupId>org.awaitility</groupId>
80+
<artifactId>awaitility</artifactId>
81+
<version>3.1.0</version>
82+
<scope>test</scope>
83+
</dependency>
84+
7585
</dependencies>
7686

7787
<build>
@@ -103,6 +113,7 @@
103113
</execution>
104114
</executions>
105115
</plugin>
116+
106117
<plugin>
107118
<groupId>org.apache.maven.plugins</groupId>
108119
<artifactId>maven-surefire-plugin</artifactId>

suggester/src/main/java/org/opengrok/suggest/Suggester.java

Lines changed: 81 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public final class Suggester implements Closeable {
6363

6464
private static final Logger logger = Logger.getLogger(Suggester.class.getName());
6565

66-
private final Map<String, FieldWFSTCollection> projectData = new ConcurrentHashMap<>();
66+
private final Map<String, SuggesterProjectData> projectData = new ConcurrentHashMap<>();
6767

6868
private final Object lock = new Object();
6969

@@ -115,9 +115,9 @@ public Suggester(
115115

116116
/**
117117
* 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
119119
*/
120-
public void init(final Collection<Path> luceneIndexes) {
120+
public void init(final Collection<NamedIndexDir> luceneIndexes) {
121121
if (luceneIndexes == null || luceneIndexes.isEmpty()) {
122122
logger.log(Level.INFO, "No index directories found, exiting...");
123123
return;
@@ -131,17 +131,17 @@ public void init(final Collection<Path> luceneIndexes) {
131131

132132
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
133133

134-
for (Path indexDir : luceneIndexes) {
134+
for (NamedIndexDir indexDir : luceneIndexes) {
135135
submitInitIfIndexExists(executorService, indexDir);
136136
}
137137

138138
shutdownAndAwaitTermination(executorService, "Suggester successfully initialized");
139139
}
140140
}
141141

142-
private void submitInitIfIndexExists(final ExecutorService executorService, final Path indexDir) {
142+
private void submitInitIfIndexExists(final ExecutorService executorService, final NamedIndexDir indexDir) {
143143
try {
144-
if (indexExists(indexDir)) {
144+
if (indexExists(indexDir.path)) {
145145
executorService.submit(getInitRunnable(indexDir));
146146
} else {
147147
logger.log(Level.FINE, "Index in {0} directory does not exist, skipping...", indexDir);
@@ -151,17 +151,17 @@ private void submitInitIfIndexExists(final ExecutorService executorService, fina
151151
}
152152
}
153153

154-
private Runnable getInitRunnable(final Path indexDir) {
154+
private Runnable getInitRunnable(final NamedIndexDir indexDir) {
155155
return () -> {
156156
try {
157157
Instant start = Instant.now();
158158
logger.log(Level.FINE, "Initializing {0}", indexDir);
159159

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);
162162
wfst.init();
163163
if (projectsEnabled) {
164-
projectData.put(indexDir.getFileName().toString(), wfst);
164+
projectData.put(indexDir.name, wfst);
165165
} else {
166166
projectData.put(PROJECTS_DISABLED_KEY, wfst);
167167
}
@@ -174,9 +174,9 @@ private Runnable getInitRunnable(final Path indexDir) {
174174
};
175175
}
176176

177-
private Path getSuggesterDir(final Path indexDir) {
177+
private Path getSuggesterDir(final String indexDirName) {
178178
if (projectsEnabled) {
179-
return suggesterDir.toPath().resolve(indexDir.getFileName());
179+
return suggesterDir.toPath().resolve(indexDirName);
180180
} else {
181181
return this.suggesterDir.toPath();
182182
}
@@ -200,9 +200,9 @@ private void shutdownAndAwaitTermination(final ExecutorService executorService,
200200

201201
/**
202202
* 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
204204
*/
205-
public void rebuild(final List<Path> indexDirs) {
205+
public void rebuild(final Collection<NamedIndexDir> indexDirs) {
206206
if (indexDirs == null || indexDirs.isEmpty()) {
207207
logger.log(Level.INFO, "Not rebuilding suggester data because no index directories were specified");
208208
return;
@@ -213,10 +213,10 @@ public void rebuild(final List<Path> indexDirs) {
213213

214214
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
215215

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));
220220
} else {
221221
submitInitIfIndexExists(executorService, indexDir);
222222
}
@@ -226,36 +226,35 @@ public void rebuild(final List<Path> indexDirs) {
226226
}
227227
}
228228

229-
private Runnable getRebuildRunnable(final FieldWFSTCollection fieldsWFST) {
229+
private Runnable getRebuildRunnable(final SuggesterProjectData data) {
230230
return () -> {
231231
try {
232232
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();
235235

236236
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});
238238
} catch (Exception e) {
239239
logger.log(Level.SEVERE, "Could not rebuild suggester", e);
240240
}
241241
};
242242
}
243243

244244
/**
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
248247
*/
249-
public void remove(final Iterable<String> projectNames) {
250-
if (projectNames == null) {
248+
public void remove(final Iterable<String> names) {
249+
if (names == null) {
251250
return;
252251
}
253252

254253
synchronized (lock) {
255-
logger.log(Level.INFO, "Removing following suggesters: {0}", projectNames);
254+
logger.log(Level.INFO, "Removing following suggesters: {0}", names);
256255

257-
for (String suggesterName : projectNames) {
258-
FieldWFSTCollection collection = projectData.get(suggesterName);
256+
for (String suggesterName : names) {
257+
SuggesterProjectData collection = projectData.get(suggesterName);
259258
if (collection == null) {
260259
logger.log(Level.WARNING, "Unknown suggester {0}", suggesterName);
261260
continue;
@@ -290,7 +289,7 @@ public List<LookupResultItem> search(
290289

291290
List<LookupResultItem> results = readers.parallelStream().flatMap(namedIndexReader -> {
292291

293-
FieldWFSTCollection data = projectData.get(namedIndexReader.name);
292+
SuggesterProjectData data = projectData.get(namedIndexReader.name);
294293
if (data == null) {
295294
logger.log(Level.FINE, "{0} not yet initialized", namedIndexReader.name);
296295
return Stream.empty();
@@ -385,7 +384,7 @@ public void increaseSearchCount(final String project, final Term term, final int
385384
if (!allowMostPopular) {
386385
return;
387386
}
388-
FieldWFSTCollection data;
387+
SuggesterProjectData data;
389388
if (!projectsEnabled) {
390389
data = projectData.get(PROJECTS_DISABLED_KEY);
391390
} else {
@@ -408,7 +407,7 @@ public List<Entry<BytesRef, Integer>> getSearchCounts(
408407
final int page,
409408
final int pageSize
410409
) {
411-
FieldWFSTCollection data = projectData.get(project);
410+
SuggesterProjectData data = projectData.get(project);
412411
if (data == null) {
413412
logger.log(Level.FINE, "Cannot retrieve search counts because data for project {0} were not found",
414413
project);
@@ -432,16 +431,65 @@ public void close() {
432431
});
433432
}
434433

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+
435470
/**
436471
* Model class to hold the project name and its {@link IndexReader}.
437472
*/
438473
public static class NamedIndexReader {
439474

475+
/**
476+
* Name of the project.
477+
*/
440478
private final String name;
441479

480+
/**
481+
* IndexReader of the project with {@link #name}.
482+
*/
442483
private final IndexReader reader;
443484

444485
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+
445493
this.name = name;
446494
this.reader = reader;
447495
}

suggester/src/main/java/org/opengrok/suggest/FieldWFSTCollection.java renamed to suggester/src/main/java/org/opengrok/suggest/SuggesterProjectData.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@
6464
/**
6565
* Holds all the necessary data for one index directory. In the context of OpenGrok it is one project.
6666
*/
67-
class FieldWFSTCollection implements Closeable {
67+
class SuggesterProjectData implements Closeable {
6868

69-
private static final Logger logger = Logger.getLogger(FieldWFSTCollection.class.getName());
69+
private static final Logger logger = Logger.getLogger(SuggesterProjectData.class.getName());
7070

7171
private static final int MAX_TERM_SIZE = Short.MAX_VALUE - 3;
7272

@@ -98,7 +98,7 @@ class FieldWFSTCollection implements Closeable {
9898

9999
private Set<String> fields;
100100

101-
FieldWFSTCollection(
101+
SuggesterProjectData(
102102
final Directory indexDir,
103103
final Path suggesterDir,
104104
final boolean allowMostPopular,
@@ -275,6 +275,7 @@ private void createSuggesterDir() throws IOException {
275275
}
276276

277277
private void initSearchCountMap() throws IOException {
278+
searchCountMaps.values().forEach(PopularityMap::close);
278279
searchCountMaps.clear();
279280

280281
for (String field : fields) {
@@ -325,6 +326,7 @@ private double getAverageLength(final String field) {
325326
if (averageLengths.containsKey(field)) {
326327
return averageLengths.get(field);
327328
}
329+
logger.log(Level.FINE, "Could not determine average length for field {0}, using default one", field);
328330
return AVERAGE_LENGTH_DEFAULT;
329331
}
330332

@@ -509,7 +511,7 @@ public List<Entry<BytesRef, Integer>> getSearchCountsSorted(final String field,
509511

510512
@Override
511513
public String toString() {
512-
return "FieldWFSTCollection{" +
514+
return "SuggesterProjectData{" +
513515
"indexDir=" + indexDir +
514516
", suggesterDir=" + suggesterDir +
515517
", allowMostPopular=" + allowMostPopular +

suggester/src/main/java/org/opengrok/suggest/SuggesterSearcher.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class SuggesterSearcher extends IndexSearcher {
7676

7777
/**
7878
* Returns the suggestions for generic {@link SuggesterQuery} (almost all except lone
79-
* {@link org.opengrok.suggest.query.SuggesterPrefixQuery} for which check {@link FieldWFSTCollection}).
79+
* {@link org.opengrok.suggest.query.SuggesterPrefixQuery} for which see {@link SuggesterProjectData}).
8080
* @param query query on which the suggestions depend
8181
* @param project name of the project
8282
* @param suggesterQuery query for the suggestions

suggester/src/main/java/org/opengrok/suggest/popular/PopularityMap.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,8 @@ public interface PopularityMap extends PopularityCounter, AutoCloseable {
4747
*/
4848
List<Entry<BytesRef, Integer>> getPopularityData(int page, int pageSize);
4949

50+
/** {@inheritDoc} */
51+
@Override
52+
void close();
53+
5054
}

0 commit comments

Comments
 (0)