Skip to content

Commit eae84f8

Browse files
committed
Account soft-deletes in FrozenEngine (elastic#51192)
Currently, we do not exclude soft-deleted documents when opening index reader in the FrozenEngine. Relates elastic#50775
1 parent e20459c commit eae84f8

File tree

5 files changed

+81
-5
lines changed

5 files changed

+81
-5
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public NoOpEngine(EngineConfig config) {
5454
super(config, null, null, true, Function.identity());
5555
this.stats = new SegmentsStats();
5656
Directory directory = store.directory();
57-
try (DirectoryReader reader = DirectoryReader.open(directory, OFF_HEAP_READER_ATTRIBUTES)) {
57+
try (DirectoryReader reader = openDirectory(directory, config.getIndexSettings())) {
5858
for (LeafReaderContext ctx : reader.getContext().leaves()) {
5959
SegmentReader segmentReader = Lucene.segmentReader(ctx.reader());
6060
fillSegmentStats(segmentReader, true, stats);

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

+11-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.elasticsearch.common.lucene.index.ElasticsearchDirectoryReader;
3434
import org.elasticsearch.common.util.concurrent.ReleasableLock;
3535
import org.elasticsearch.core.internal.io.IOUtils;
36+
import org.elasticsearch.index.IndexSettings;
3637
import org.elasticsearch.index.mapper.MapperService;
3738
import org.elasticsearch.index.seqno.SeqNoStats;
3839
import org.elasticsearch.index.seqno.SequenceNumbers;
@@ -68,7 +69,7 @@ public class ReadOnlyEngine extends Engine {
6869
* Reader attributes used for read only engines. These attributes prevent loading term dictionaries on-heap even if the field is an
6970
* ID field if we are reading form memory maps.
7071
*/
71-
public static final Map<String, String> OFF_HEAP_READER_ATTRIBUTES = Collections.singletonMap(BlockTreeTermsReader.FST_MODE_KEY,
72+
private static final Map<String, String> OFF_HEAP_READER_ATTRIBUTES = Collections.singletonMap(BlockTreeTermsReader.FST_MODE_KEY,
7273
BlockTreeTermsReader.FSTLoadMode.AUTO.name());
7374
private final SegmentInfos lastCommittedSegmentInfos;
7475
private final SeqNoStats seqNoStats;
@@ -534,4 +535,13 @@ public void advanceMaxSeqNoOfUpdatesOrDeletes(long maxSeqNoOfUpdatesOnPrimary) {
534535
assert maxSeqNoOfUpdatesOnPrimary <= getMaxSeqNoOfUpdatesOrDeletes() :
535536
maxSeqNoOfUpdatesOnPrimary + ">" + getMaxSeqNoOfUpdatesOrDeletes();
536537
}
538+
539+
protected DirectoryReader openDirectory(Directory dir, IndexSettings indexSettings) throws IOException {
540+
final DirectoryReader reader = DirectoryReader.open(dir, OFF_HEAP_READER_ATTRIBUTES);
541+
if (indexSettings.isSoftDeleteEnabled()) {
542+
return new SoftDeletesDirectoryReaderWrapper(reader, Lucene.SOFT_DELETES_FIELD);
543+
} else {
544+
return reader;
545+
}
546+
}
537547
}

x-pack/plugin/frozen-indices/src/main/java/org/elasticsearch/index/engine/FrozenEngine.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public FrozenEngine(EngineConfig config) {
7777

7878
boolean success = false;
7979
Directory directory = store.directory();
80-
try (DirectoryReader reader = DirectoryReader.open(directory, OFF_HEAP_READER_ATTRIBUTES)) {
80+
try (DirectoryReader reader = openDirectory(directory, config.getIndexSettings())) {
8181
canMatchReader = ElasticsearchDirectoryReader.wrap(new RewriteCachingDirectoryReader(directory, reader.leaves()),
8282
config.getShardId());
8383
// we record the segment stats here - that's what the reader needs when it's open and it give the user
@@ -167,7 +167,7 @@ private synchronized ElasticsearchDirectoryReader getOrOpenReader() throws IOExc
167167
for (ReferenceManager.RefreshListener listeners : config ().getInternalRefreshListener()) {
168168
listeners.beforeRefresh();
169169
}
170-
final DirectoryReader dirReader = DirectoryReader.open(engineConfig.getStore().directory(), OFF_HEAP_READER_ATTRIBUTES);
170+
final DirectoryReader dirReader = openDirectory(engineConfig.getStore().directory(), engineConfig.getIndexSettings());
171171
reader = lastOpenedReader = wrapReader(dirReader, Function.identity());
172172
processReader(reader);
173173
reader.getReaderCacheHelper().addClosedListener(this::onReaderClosed);

x-pack/plugin/frozen-indices/src/test/java/org/elasticsearch/index/engine/FrozenEngineTests.java

+28
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import java.util.concurrent.atomic.AtomicInteger;
3434
import java.util.concurrent.atomic.AtomicLong;
3535

36+
import static org.hamcrest.Matchers.equalTo;
37+
3638
public class FrozenEngineTests extends EngineTestCase {
3739

3840
public void testAcquireReleaseReset() throws IOException {
@@ -328,4 +330,30 @@ public void testCanMatch() throws IOException {
328330
}
329331
}
330332
}
333+
334+
public void testSearchers() throws Exception {
335+
IOUtils.close(engine, store);
336+
final AtomicLong globalCheckpoint = new AtomicLong(SequenceNumbers.NO_OPS_PERFORMED);
337+
try (Store store = createStore()) {
338+
EngineConfig config = config(defaultSettings, store, createTempDir(), newMergePolicy(), null, null, null,
339+
globalCheckpoint::get, new NoneCircuitBreakerService());
340+
final int totalDocs;
341+
try (InternalEngine engine = createEngine(config)) {
342+
applyOperations(engine, generateHistoryOnReplica(between(10, 1000), false, randomBoolean(), randomBoolean()));
343+
globalCheckpoint.set(engine.getProcessedLocalCheckpoint());
344+
engine.syncTranslog();
345+
engine.flush();
346+
engine.refresh("test");
347+
try (Engine.Searcher searcher = engine.acquireSearcher("test")) {
348+
totalDocs = searcher.search(new MatchAllDocsQuery(), Integer.MAX_VALUE).scoreDocs.length;
349+
}
350+
}
351+
try (FrozenEngine frozenEngine = new FrozenEngine(config)) {
352+
try (Engine.Searcher searcher = frozenEngine.acquireSearcher("test")) {
353+
TopDocs topDocs = searcher.search(new MatchAllDocsQuery(), Integer.MAX_VALUE);
354+
assertThat(topDocs.scoreDocs.length, equalTo(totalDocs));
355+
}
356+
}
357+
}
358+
}
331359
}

x-pack/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java

+39-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.elasticsearch.common.xcontent.XContentType;
2222
import org.elasticsearch.common.xcontent.json.JsonXContent;
2323
import org.elasticsearch.common.xcontent.support.XContentMapValues;
24+
import org.elasticsearch.index.IndexSettings;
2425
import org.elasticsearch.rest.RestStatus;
2526
import org.elasticsearch.rest.action.document.RestGetAction;
2627
import org.elasticsearch.rest.action.document.RestIndexAction;
@@ -304,7 +305,7 @@ public void testRollupAfterRestart() throws Exception {
304305
assertRollUpJob("rollup-job-test");
305306
}
306307
}
307-
308+
308309
public void testSlmStats() throws IOException {
309310
SnapshotLifecyclePolicy slmPolicy = new SnapshotLifecyclePolicy("test-policy", "test-policy", "* * * 31 FEB ? *", "test-repo",
310311
Collections.singletonMap("indices", Collections.singletonList("*")), null);
@@ -823,4 +824,41 @@ private Map<String, Object> getJob(Map<String, Object> jobsMap, String targetJob
823824
}
824825
return null;
825826
}
827+
828+
public void testFrozenIndexAfterRestarted() throws Exception {
829+
final String index = "test_frozen_index";
830+
if (isRunningAgainstOldCluster()) {
831+
Settings.Builder settings = Settings.builder();
832+
if (randomBoolean()) {
833+
settings.put(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), randomBoolean());
834+
}
835+
String mappings = randomBoolean() ? "\"_source\": { \"enabled\": false}" : null;
836+
createIndex(index, settings.build(), mappings);
837+
ensureGreen(index);
838+
int numDocs = randomIntBetween(10, 500);
839+
for (int i = 0; i < numDocs; i++) {
840+
int id = randomIntBetween(0, 100);
841+
final Request indexRequest = new Request("POST", "/" + index + "/" + "_doc/" + id);
842+
indexRequest.setJsonEntity(Strings.toString(JsonXContent.contentBuilder().startObject().field("f", "v").endObject()));
843+
assertOK(client().performRequest(indexRequest));
844+
if (rarely()) {
845+
flush(index, randomBoolean());
846+
}
847+
}
848+
} else {
849+
ensureGreen(index);
850+
final int totalHits = (int) XContentMapValues.extractValue("hits.total.value",
851+
entityAsMap(client().performRequest(new Request("GET", "/" + index + "/_search"))));
852+
assertOK(client().performRequest(new Request("POST", index + "/_freeze")));
853+
ensureGreen(index);
854+
assertNoFileBasedRecovery(index, n -> true);
855+
final Request request = new Request("GET", "/" + index + "/_search");
856+
request.addParameter("ignore_throttled", "false");
857+
assertThat(XContentMapValues.extractValue("hits.total.value", entityAsMap(client().performRequest(request))),
858+
equalTo(totalHits));
859+
assertOK(client().performRequest(new Request("POST", index + "/_unfreeze")));
860+
ensureGreen(index);
861+
assertNoFileBasedRecovery(index, n -> true);
862+
}
863+
}
826864
}

0 commit comments

Comments
 (0)