in nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java [105:166]
public <R> R with(final String name, final IndexFunction<Index, R> indexFun)
throws IOException, InterruptedException {
evictIfOverCapacity();
retry:
while (true) {
if (!exists(name)) {
throw new WebApplicationException("Index does not exist", Status.NOT_FOUND);
}
final IndexHolder holder;
synchronized (cache) {
holder = cache.computeIfAbsent(name, (k) -> new IndexHolder());
}
// CachedData pattern from ReentrantReadWriteLock javadoc
holder.lock.readLock().lock();
// Load if not already loaded or remove if Lucene closed the index elsewhere.
if (holder.state == HolderState.NOT_LOADED
|| (holder.state == HolderState.LOADED && !holder.index.isOpen())) {
holder.lock.readLock().unlock();
holder.lock.writeLock().lock();
try {
if (holder.state == HolderState.LOADED && !holder.index.isOpen()) {
LOGGER.info("removing closed index {}", name);
holder.state = HolderState.UNLOADED;
holder.index = null;
synchronized (cache) {
cache.remove(name, holder);
}
continue retry;
}
if (holder.state == HolderState.NOT_LOADED) {
holder.index = load(name);
holder.commitFuture = this.schedulerExecutorService.scheduleWithFixedDelay(
commitFun(name, holder),
commitIntervalSeconds,
commitIntervalSeconds,
TimeUnit.SECONDS);
holder.state = HolderState.LOADED;
}
holder.lock.readLock().lock();
} finally {
holder.lock.writeLock().unlock();
}
}
try {
switch (holder.state) {
case NOT_LOADED:
throw new IllegalStateException();
case UNLOADED:
Thread.sleep(1000);
continue retry;
case LOADED:
return indexFun.apply(holder.index);
}
} finally {
holder.lock.readLock().unlock();
}
}
}