Skip to content

Commit 8072907

Browse files
committed
introduce Engine#acquireDirectoryReaderSupplier(...)
1 parent ce44c20 commit 8072907

File tree

1 file changed

+70
-5
lines changed

1 file changed

+70
-5
lines changed

server/src/main/java/org/elasticsearch/index/engine/InternalEngine.java

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import org.elasticsearch.core.IOUtils;
7171
import org.elasticsearch.core.Nullable;
7272
import org.elasticsearch.core.Releasable;
73+
import org.elasticsearch.core.Releasables;
7374
import org.elasticsearch.core.SuppressForbidden;
7475
import org.elasticsearch.core.Tuple;
7576
import org.elasticsearch.env.Environment;
@@ -106,6 +107,7 @@
106107

107108
import java.io.Closeable;
108109
import java.io.IOException;
110+
import java.io.UncheckedIOException;
109111
import java.util.Arrays;
110112
import java.util.Collections;
111113
import java.util.List;
@@ -1020,18 +1022,15 @@ private VersionValue resolveDocVersion(final Operation op, boolean loadSeqNo) th
10201022
VersionValue versionValue = getVersionFromMap(op.uid());
10211023
if (versionValue == null) {
10221024
assert incrementIndexVersionLookup(); // used for asserting in tests
1023-
var referenceManager = getReferenceManager(SearcherScope.INTERNAL);
10241025
final VersionsAndSeqNoResolver.DocIdAndVersion docIdAndVersion;
1025-
var indexReader = referenceManager.acquire();
1026-
try {
1026+
try (var directoryReaderSupplier = acquireDirectoryReaderSupplier(SearcherScope.INTERNAL)) {
1027+
var indexReader = directoryReaderSupplier.getDirectoryReader();
10271028
if (engineConfig.getIndexSettings().getMode() == IndexMode.TIME_SERIES) {
10281029
assert engineConfig.getLeafSorter() == DataStream.TIMESERIES_LEAF_READERS_SORTER;
10291030
docIdAndVersion = VersionsAndSeqNoResolver.timeSeriesLoadDocIdAndVersion(indexReader, op.uid(), op.id(), loadSeqNo);
10301031
} else {
10311032
docIdAndVersion = VersionsAndSeqNoResolver.timeSeriesLoadDocIdAndVersion(indexReader, op.uid(), loadSeqNo);
10321033
}
1033-
} finally {
1034-
referenceManager.release(indexReader);
10351034
}
10361035
if (docIdAndVersion != null) {
10371036
versionValue = new IndexVersionValue(null, docIdAndVersion.version, docIdAndVersion.seqNo, docIdAndVersion.primaryTerm);
@@ -3465,4 +3464,70 @@ public LiveVersionMap getLiveVersionMap() {
34653464
protected long getPreCommitSegmentGeneration() {
34663465
return preCommitSegmentGeneration.get();
34673466
}
3467+
3468+
DirectoryReaderSupplier acquireDirectoryReaderSupplier(SearcherScope scope) throws EngineException {
3469+
assert scope == SearcherScope.INTERNAL : "acquireDirectoryReaderSupplier(...) isn't prepared for external usage";
3470+
3471+
/* Acquire order here is store -> manager since we need
3472+
* to make sure that the store is not closed before
3473+
* the searcher is acquired. */
3474+
if (store.tryIncRef() == false) {
3475+
throw new AlreadyClosedException(shardId + " store is closed", failedEngine.get());
3476+
}
3477+
Releasable releasable = store::decRef;
3478+
try {
3479+
ReferenceManager<ElasticsearchDirectoryReader> referenceManager = getReferenceManager(scope);
3480+
ElasticsearchDirectoryReader acquire = referenceManager.acquire();
3481+
releasable = null; // success - hand over the reference to the engine reader
3482+
return new DirectoryReaderSupplier(acquire) {
3483+
3484+
@Override
3485+
void doClose() {
3486+
try {
3487+
referenceManager.release(acquire);
3488+
} catch (IOException e) {
3489+
throw new UncheckedIOException("failed to close", e);
3490+
} catch (AlreadyClosedException e) {
3491+
// This means there's a bug somewhere: don't suppress it
3492+
throw new AssertionError(e);
3493+
} finally {
3494+
store.decRef();
3495+
}
3496+
}
3497+
};
3498+
} catch (AlreadyClosedException ex) {
3499+
throw ex;
3500+
} catch (Exception ex) {
3501+
maybeFailEngine("acquire_reader", ex);
3502+
ensureOpen(ex); // throw EngineCloseException here if we are already closed
3503+
logger.error("failed to acquire reader", ex);
3504+
throw new EngineException(shardId, "failed to acquire reader", ex);
3505+
} finally {
3506+
Releasables.close(releasable);
3507+
}
3508+
}
3509+
3510+
abstract static class DirectoryReaderSupplier implements Releasable {
3511+
private final DirectoryReader directoryReader;
3512+
private final AtomicBoolean released = new AtomicBoolean(false);
3513+
3514+
DirectoryReaderSupplier(DirectoryReader directoryReader) {
3515+
this.directoryReader = directoryReader;
3516+
}
3517+
3518+
public DirectoryReader getDirectoryReader() {
3519+
return directoryReader;
3520+
}
3521+
3522+
@Override
3523+
public final void close() {
3524+
if (released.compareAndSet(false, true)) {
3525+
doClose();
3526+
} else {
3527+
assert false : "DirectoryReaderSupplier was released twice";
3528+
}
3529+
}
3530+
3531+
abstract void doClose();
3532+
}
34683533
}

0 commit comments

Comments
 (0)