@Override public void flush(Flush flush) throws EngineException { if (indexWriter == null) { throw new EngineClosedException(shardId); } // check outside the lock as well so we can check without blocking on the write lock if (disableFlushCounter > 0) { throw new FlushNotAllowedEngineException( shardId, "Recovery is in progress, flush is not allowed"); } rwl.writeLock().lock(); try { if (indexWriter == null) { throw new EngineClosedException(shardId); } if (disableFlushCounter > 0) { throw new FlushNotAllowedEngineException( shardId, "Recovery is in progress, flush is not allowed"); } if (flush.full()) { // disable refreshing, not dirty dirty = false; refreshMutex.set(true); try { // that's ok if the index writer failed and is in inconsistent state // we will get an exception on a dirty operation, and will cause the shard // to be allocated to a different node indexWriter.close(); indexWriter = createWriter(); AcquirableResource<ReaderSearcherHolder> current = nrtResource; nrtResource = buildNrtResource(indexWriter); current.markForClose(); translog.newTranslog(newTransactionLogId()); } catch (IOException e) { throw new FlushFailedEngineException(shardId, e); } finally { refreshMutex.set(false); } } else { try { indexWriter.commit(); translog.newTranslog(newTransactionLogId()); } catch (IOException e) { throw new FlushFailedEngineException(shardId, e); } } } finally { rwl.writeLock().unlock(); } if (flush.refresh()) { refresh(new Refresh(false)); } }
@Override public Searcher searcher() throws EngineException { AcquirableResource<ReaderSearcherHolder> holder; for (; ; ) { holder = this.nrtResource; if (holder.acquire()) { break; } Thread.yield(); } return new RobinSearchResult(holder); }
@Override public void refresh(Refresh refresh) throws EngineException { // we obtain a read lock here, since we don't want a flush to happen while we are refreshing // since it flushes the index as well (though, in terms of concurrency, we are allowed to do it) rwl.readLock().lock(); if (indexWriter == null) { throw new EngineClosedException(shardId); } try { // this engine always acts as if waitForOperations=true if (refreshMutex.compareAndSet(false, true)) { IndexWriter currentWriter = indexWriter; if (currentWriter == null) { throw new EngineClosedException(shardId); } try { if (dirty) { dirty = false; AcquirableResource<ReaderSearcherHolder> current = nrtResource; IndexReader newReader = current.resource().reader().reopen(true); if (newReader != current.resource().reader()) { IndexSearcher indexSearcher = new IndexSearcher(newReader); indexSearcher.setSimilarity(similarityService.defaultSearchSimilarity()); nrtResource = newAcquirableResource(new ReaderSearcherHolder(indexSearcher)); current.markForClose(); } } } catch (AlreadyClosedException e) { // an index writer got replaced on us, ignore } catch (Exception e) { if (indexWriter == null) { throw new EngineClosedException(shardId); } else if (currentWriter != indexWriter) { // an index writer got replaced on us, ignore } else { throw new RefreshFailedEngineException(shardId, e); } } finally { refreshMutex.set(false); } } } finally { rwl.readLock().unlock(); } }
@Override public boolean release() throws ElasticSearchException { nrtHolder.release(); return true; }
@Override public IndexSearcher searcher() { return nrtHolder.resource().searcher(); }
@Override public IndexReader reader() { return nrtHolder.resource().reader(); }