public R with()

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();
            }
        }
    }