Ignore translog retention policy if soft-deletes enabled (#45473)

Since #45136, we use soft-deletes instead of translog in peer recovery.
There's no need to retain extra translog to increase a chance of
operation-based recoveries. This commit ignores the translog retention
policy if soft-deletes is enabled so we can discard translog more
quickly.

Backport of #45473
Relates #45136
This commit is contained in:
Nhat Nguyen 2019-08-22 16:40:06 -04:00 committed by GitHub
parent 72c6302d12
commit 3393f9599e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 351 additions and 73 deletions

View File

@ -76,12 +76,23 @@ commit point. Defaults to `512mb`.
`index.translog.retention.size`:: `index.translog.retention.size`::
The total size of translog files to keep. Keeping more translog files increases When soft deletes is disabled (enabled by default in 7.0 or later),
the chance of performing an operation based sync when recovering replicas. If `index.translog.retention.size` controls the total size of translog files to keep.
the translog files are not sufficient, replica recovery will fall back to a Keeping more translog files increases the chance of performing an operation based
file based sync. Defaults to `512mb` sync when recovering replicas. If the translog files are not sufficient,
replica recovery will fall back to a file based sync. Defaults to `512mb`
Both `index.translog.retention.size` and `index.translog.retention.age` should not
be specified unless soft deletes is disabled as they will be ignored.
`index.translog.retention.age`:: `index.translog.retention.age`::
The maximum duration for which translog files will be kept. Defaults to `12h`. When soft deletes is disabled (enabled by default in 7.0 or later),
`index.translog.retention.age` controls the maximum duration for which translog
files to keep. Keeping more translog files increases the chance of performing an
operation based sync when recovering replicas. If the translog files are not sufficient,
replica recovery will fall back to a file based sync. Defaults to `12h`
Both `index.translog.retention.size` and `index.translog.retention.age` should not
be specified unless soft deletes is disabled as they will be ignored.

View File

@ -1,14 +1,14 @@
--- ---
setup: "Translog retention without soft_deletes":
- do: - do:
indices.create: indices.create:
index: test index: test
body:
settings:
soft_deletes.enabled: false
- do: - do:
cluster.health: cluster.health:
wait_for_no_initializing_shards: true wait_for_no_initializing_shards: true
---
"Translog retention":
- do: - do:
indices.stats: indices.stats:
metric: [ translog ] metric: [ translog ]
@ -64,6 +64,53 @@ setup:
- lte: { indices.test.primaries.translog.uncommitted_size_in_bytes: $creation_size } - lte: { indices.test.primaries.translog.uncommitted_size_in_bytes: $creation_size }
- match: { indices.test.primaries.translog.uncommitted_operations: 0 } - match: { indices.test.primaries.translog.uncommitted_operations: 0 }
---
"Translog retention with soft_deletes":
- skip:
version: " - 7.3.99"
reason: "start ignoring translog retention policy with soft-deletes enabled in 7.4"
- do:
indices.create:
index: test
body:
settings:
soft_deletes.enabled: true
- do:
cluster.health:
wait_for_no_initializing_shards: true
- do:
indices.stats:
metric: [ translog ]
- set: { indices.test.primaries.translog.size_in_bytes: creation_size }
- do:
index:
index: test
id: 1
body: { "foo": "bar" }
- do:
indices.stats:
metric: [ translog ]
- gt: { indices.test.primaries.translog.size_in_bytes: $creation_size }
- match: { indices.test.primaries.translog.operations: 1 }
- match: { indices.test.primaries.translog.uncommitted_operations: 1 }
# call flush twice to sync the global checkpoint after the last operation so that we can have the safe commit
- do:
indices.flush:
index: test
- do:
indices.flush:
index: test
- do:
indices.stats:
metric: [ translog ]
# after flushing we have one empty translog file while an empty index before flushing has two empty translog files.
- lt: { indices.test.primaries.translog.size_in_bytes: $creation_size }
- match: { indices.test.primaries.translog.operations: 0 }
- lt: { indices.test.primaries.translog.uncommitted_size_in_bytes: $creation_size }
- match: { indices.test.primaries.translog.uncommitted_operations: 0 }
--- ---
"Translog last modified age stats": "Translog last modified age stats":
- skip: - skip:
@ -81,11 +128,20 @@ setup:
- gte: { indices.test.primaries.translog.earliest_last_modified_age: 0 } - gte: { indices.test.primaries.translog.earliest_last_modified_age: 0 }
--- ---
"Translog stats on closed indices": "Translog stats on closed indices without soft-deletes":
- skip: - skip:
version: " - 7.2.99" version: " - 7.2.99"
reason: "closed indices have translog stats starting version 7.3.0" reason: "closed indices have translog stats starting version 7.3.0"
- do:
indices.create:
index: test
body:
settings:
soft_deletes.enabled: false
- do:
cluster.health:
wait_for_no_initializing_shards: true
- do: - do:
index: index:
index: test index: test
@ -123,3 +179,40 @@ setup:
forbid_closed_indices: false forbid_closed_indices: false
- match: { indices.test.primaries.translog.operations: 3 } - match: { indices.test.primaries.translog.operations: 3 }
- match: { indices.test.primaries.translog.uncommitted_operations: 0 } - match: { indices.test.primaries.translog.uncommitted_operations: 0 }
---
"Translog stats on closed indices with soft-deletes":
- skip:
version: " - 7.3.99"
reason: "start ignoring translog retention policy with soft-deletes enabled in 7.4"
- do:
indices.create:
index: test
body:
settings:
soft_deletes.enabled: true
- do:
cluster.health:
wait_for_no_initializing_shards: true
- do:
index:
index: test
id: 1
body: { "foo": "bar" }
- do:
indices.stats:
metric: [ translog ]
- match: { indices.test.primaries.translog.operations: 1 }
- match: { indices.test.primaries.translog.uncommitted_operations: 1 }
- do:
indices.close:
index: test
wait_for_active_shards: 1
- is_true: acknowledged
- do:
indices.stats:
metric: [ translog ]
expand_wildcards: all
forbid_closed_indices: false
- match: { indices.test.primaries.translog.operations: 0 }
- match: { indices.test.primaries.translog.uncommitted_operations: 0 }

View File

@ -195,24 +195,6 @@ public final class IndexSettings {
new ByteSizeValue(Long.MAX_VALUE, ByteSizeUnit.BYTES), new ByteSizeValue(Long.MAX_VALUE, ByteSizeUnit.BYTES),
Property.Dynamic, Property.IndexScope); Property.Dynamic, Property.IndexScope);
/**
* Controls how long translog files that are no longer needed for persistence reasons
* will be kept around before being deleted. A longer retention policy is useful to increase
* the chance of ops based recoveries.
**/
public static final Setting<TimeValue> INDEX_TRANSLOG_RETENTION_AGE_SETTING =
Setting.timeSetting("index.translog.retention.age", TimeValue.timeValueHours(12), TimeValue.timeValueMillis(-1),
Property.Dynamic, Property.IndexScope);
/**
* Controls how many translog files that are no longer needed for persistence reasons
* will be kept around before being deleted. Keeping more files is useful to increase
* the chance of ops based recoveries.
**/
public static final Setting<ByteSizeValue> INDEX_TRANSLOG_RETENTION_SIZE_SETTING =
Setting.byteSizeSetting("index.translog.retention.size", new ByteSizeValue(512, ByteSizeUnit.MB), Property.Dynamic,
Property.IndexScope);
/** /**
* The maximum size of a translog generation. This is independent of the maximum size of * The maximum size of a translog generation. This is independent of the maximum size of
* translog operations that have not been flushed. * translog operations that have not been flushed.
@ -258,6 +240,27 @@ public final class IndexSettings {
Setting.longSetting("index.soft_deletes.retention.operations", 0, 0, Setting.longSetting("index.soft_deletes.retention.operations", 0, 0,
Property.IndexScope, Property.Dynamic); Property.IndexScope, Property.Dynamic);
/**
* Controls how long translog files that are no longer needed for persistence reasons
* will be kept around before being deleted. Keeping more files is useful to increase
* the chance of ops based recoveries for indices with soft-deletes disabled.
* This setting will be ignored if soft-deletes is enabled.
**/
public static final Setting<TimeValue> INDEX_TRANSLOG_RETENTION_AGE_SETTING =
Setting.timeSetting("index.translog.retention.age",
settings -> INDEX_SOFT_DELETES_SETTING.get(settings) ? TimeValue.MINUS_ONE : TimeValue.timeValueHours(12), TimeValue.MINUS_ONE,
Property.Dynamic, Property.IndexScope);
/**
* Controls how many translog files that are no longer needed for persistence reasons
* will be kept around before being deleted. Keeping more files is useful to increase
* the chance of ops based recoveries for indices with soft-deletes disabled.
* This setting will be ignored if soft-deletes is enabled.
**/
public static final Setting<ByteSizeValue> INDEX_TRANSLOG_RETENTION_SIZE_SETTING =
Setting.byteSizeSetting("index.translog.retention.size", settings -> INDEX_SOFT_DELETES_SETTING.get(settings) ? "-1" : "512MB",
Property.Dynamic, Property.IndexScope);
/** /**
* Controls the maximum length of time since a retention lease is created or renewed before it is considered expired. * Controls the maximum length of time since a retention lease is created or renewed before it is considered expired.
*/ */
@ -466,8 +469,6 @@ public final class IndexSettings {
syncInterval = INDEX_TRANSLOG_SYNC_INTERVAL_SETTING.get(settings); syncInterval = INDEX_TRANSLOG_SYNC_INTERVAL_SETTING.get(settings);
refreshInterval = scopedSettings.get(INDEX_REFRESH_INTERVAL_SETTING); refreshInterval = scopedSettings.get(INDEX_REFRESH_INTERVAL_SETTING);
flushThresholdSize = scopedSettings.get(INDEX_TRANSLOG_FLUSH_THRESHOLD_SIZE_SETTING); flushThresholdSize = scopedSettings.get(INDEX_TRANSLOG_FLUSH_THRESHOLD_SIZE_SETTING);
translogRetentionAge = scopedSettings.get(INDEX_TRANSLOG_RETENTION_AGE_SETTING);
translogRetentionSize = scopedSettings.get(INDEX_TRANSLOG_RETENTION_SIZE_SETTING);
generationThresholdSize = scopedSettings.get(INDEX_TRANSLOG_GENERATION_THRESHOLD_SIZE_SETTING); generationThresholdSize = scopedSettings.get(INDEX_TRANSLOG_GENERATION_THRESHOLD_SIZE_SETTING);
mergeSchedulerConfig = new MergeSchedulerConfig(this); mergeSchedulerConfig = new MergeSchedulerConfig(this);
gcDeletesInMillis = scopedSettings.get(INDEX_GC_DELETES_SETTING).getMillis(); gcDeletesInMillis = scopedSettings.get(INDEX_GC_DELETES_SETTING).getMillis();
@ -493,6 +494,8 @@ public final class IndexSettings {
this.indexSortConfig = new IndexSortConfig(this); this.indexSortConfig = new IndexSortConfig(this);
searchIdleAfter = scopedSettings.get(INDEX_SEARCH_IDLE_AFTER); searchIdleAfter = scopedSettings.get(INDEX_SEARCH_IDLE_AFTER);
defaultPipeline = scopedSettings.get(DEFAULT_PIPELINE); defaultPipeline = scopedSettings.get(DEFAULT_PIPELINE);
setTranslogRetentionAge(scopedSettings.get(INDEX_TRANSLOG_RETENTION_AGE_SETTING));
setTranslogRetentionSize(scopedSettings.get(INDEX_TRANSLOG_RETENTION_SIZE_SETTING));
scopedSettings.addSettingsUpdateConsumer(MergePolicyConfig.INDEX_COMPOUND_FORMAT_SETTING, mergePolicyConfig::setNoCFSRatio); scopedSettings.addSettingsUpdateConsumer(MergePolicyConfig.INDEX_COMPOUND_FORMAT_SETTING, mergePolicyConfig::setNoCFSRatio);
scopedSettings.addSettingsUpdateConsumer(MergePolicyConfig.INDEX_MERGE_POLICY_DELETES_PCT_ALLOWED_SETTING, scopedSettings.addSettingsUpdateConsumer(MergePolicyConfig.INDEX_MERGE_POLICY_DELETES_PCT_ALLOWED_SETTING,
@ -553,12 +556,22 @@ public final class IndexSettings {
} }
private void setTranslogRetentionSize(ByteSizeValue byteSizeValue) { private void setTranslogRetentionSize(ByteSizeValue byteSizeValue) {
if (softDeleteEnabled && byteSizeValue.getBytes() >= 0) {
// ignore the translog retention settings if soft-deletes enabled
this.translogRetentionSize = new ByteSizeValue(-1);
} else {
this.translogRetentionSize = byteSizeValue; this.translogRetentionSize = byteSizeValue;
} }
}
private void setTranslogRetentionAge(TimeValue age) { private void setTranslogRetentionAge(TimeValue age) {
if (softDeleteEnabled && age.millis() >= 0) {
// ignore the translog retention settings if soft-deletes enabled
this.translogRetentionAge = TimeValue.MINUS_ONE;
} else {
this.translogRetentionAge = age; this.translogRetentionAge = age;
} }
}
private void setGenerationThresholdSize(final ByteSizeValue generationThresholdSize) { private void setGenerationThresholdSize(final ByteSizeValue generationThresholdSize) {
this.generationThresholdSize = generationThresholdSize; this.generationThresholdSize = generationThresholdSize;
@ -734,13 +747,19 @@ public final class IndexSettings {
/** /**
* Returns the transaction log retention size which controls how much of the translog is kept around to allow for ops based recoveries * Returns the transaction log retention size which controls how much of the translog is kept around to allow for ops based recoveries
*/ */
public ByteSizeValue getTranslogRetentionSize() { return translogRetentionSize; } public ByteSizeValue getTranslogRetentionSize() {
assert softDeleteEnabled == false || translogRetentionSize.getBytes() == -1L : translogRetentionSize;
return translogRetentionSize;
}
/** /**
* Returns the transaction log retention age which controls the maximum age (time from creation) that translog files will be kept * Returns the transaction log retention age which controls the maximum age (time from creation) that translog files will be kept
* around * around
*/ */
public TimeValue getTranslogRetentionAge() { return translogRetentionAge; } public TimeValue getTranslogRetentionAge() {
assert softDeleteEnabled == false || translogRetentionAge.millis() == -1L : translogRetentionSize;
return translogRetentionAge;
}
/** /**
* Returns the generation threshold size. As sequence numbers can cause multiple generations to * Returns the generation threshold size. As sequence numbers can cause multiple generations to

View File

@ -177,11 +177,19 @@ public class TruncateTranslogAction {
final TranslogConfig translogConfig = new TranslogConfig(shardPath.getShardId(), translogPath, final TranslogConfig translogConfig = new TranslogConfig(shardPath.getShardId(), translogPath,
indexSettings, BigArrays.NON_RECYCLING_INSTANCE); indexSettings, BigArrays.NON_RECYCLING_INSTANCE);
long primaryTerm = indexSettings.getIndexMetaData().primaryTerm(shardPath.getShardId().id()); long primaryTerm = indexSettings.getIndexMetaData().primaryTerm(shardPath.getShardId().id());
final TranslogDeletionPolicy translogDeletionPolicy = // We open translog to check for corruption, do not clean anything.
new TranslogDeletionPolicy(indexSettings.getTranslogRetentionSize().getBytes(), final TranslogDeletionPolicy retainAllTranslogPolicy = new TranslogDeletionPolicy(Long.MAX_VALUE, Long.MAX_VALUE) {
indexSettings.getTranslogRetentionAge().getMillis()); @Override
long minTranslogGenRequired(List<TranslogReader> readers, TranslogWriter writer) {
long minGen = writer.generation;
for (TranslogReader reader : readers) {
minGen = Math.min(reader.generation, minGen);
}
return minGen;
}
};
try (Translog translog = new Translog(translogConfig, translogUUID, try (Translog translog = new Translog(translogConfig, translogUUID,
translogDeletionPolicy, () -> translogGlobalCheckpoint, () -> primaryTerm, seqNo -> {}); retainAllTranslogPolicy, () -> translogGlobalCheckpoint, () -> primaryTerm, seqNo -> {});
Translog.Snapshot snapshot = translog.newSnapshot()) { Translog.Snapshot snapshot = translog.newSnapshot()) {
//noinspection StatementWithEmptyBody we are just checking that we can iterate through the whole snapshot //noinspection StatementWithEmptyBody we are just checking that we can iterate through the whole snapshot
while (snapshot.next() != null) { while (snapshot.next() != null) {

View File

@ -396,15 +396,20 @@ public class IndexServiceTests extends ESSingleNodeTestCase {
final Path translogPath = translog.getConfig().getTranslogPath(); final Path translogPath = translog.getConfig().getTranslogPath();
final String translogUuid = translog.getTranslogUUID(); final String translogUuid = translog.getTranslogUUID();
int translogOps = 0;
final int numDocs = scaledRandomIntBetween(10, 100); final int numDocs = scaledRandomIntBetween(10, 100);
for (int i = 0; i < numDocs; i++) { for (int i = 0; i < numDocs; i++) {
client().prepareIndex().setIndex(indexName).setId(String.valueOf(i)).setSource("{\"foo\": \"bar\"}", XContentType.JSON).get(); client().prepareIndex().setIndex(indexName).setId(String.valueOf(i)).setSource("{\"foo\": \"bar\"}", XContentType.JSON).get();
translogOps++;
if (randomBoolean()) { if (randomBoolean()) {
client().admin().indices().prepareFlush(indexName).get(); client().admin().indices().prepareFlush(indexName).get();
if (indexService.getIndexSettings().isSoftDeleteEnabled()) {
translogOps = 0;
} }
} }
assertThat(translog.totalOperations(), equalTo(numDocs)); }
assertThat(translog.stats().estimatedNumberOfOperations(), equalTo(numDocs)); assertThat(translog.totalOperations(), equalTo(translogOps));
assertThat(translog.stats().estimatedNumberOfOperations(), equalTo(translogOps));
assertAcked(client().admin().indices().prepareClose("test").setWaitForActiveShards(ActiveShardCount.DEFAULT)); assertAcked(client().admin().indices().prepareClose("test").setWaitForActiveShards(ActiveShardCount.DEFAULT));
indexService = getInstanceFromNode(IndicesService.class).indexServiceSafe(indexService.index()); indexService = getInstanceFromNode(IndicesService.class).indexServiceSafe(indexService.index());

View File

@ -26,6 +26,7 @@ import org.elasticsearch.common.settings.IndexScopedSettings;
import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.translog.Translog; import org.elasticsearch.index.translog.Translog;
@ -577,4 +578,64 @@ public class IndexSettingsTests extends ESTestCase {
assertFalse(IndexSettings.INDEX_SOFT_DELETES_SETTING.get(settings)); assertFalse(IndexSettings.INDEX_SOFT_DELETES_SETTING.get(settings));
} }
} }
public void testIgnoreTranslogRetentionSettingsIfSoftDeletesEnabled() {
Settings.Builder settings = Settings.builder()
.put(IndexMetaData.SETTING_VERSION_CREATED, VersionUtils.randomVersionBetween(random(), Version.V_7_0_0, Version.CURRENT));
if (randomBoolean()) {
settings.put(IndexSettings.INDEX_TRANSLOG_RETENTION_AGE_SETTING.getKey(), randomPositiveTimeValue());
}
if (randomBoolean()) {
settings.put(IndexSettings.INDEX_TRANSLOG_RETENTION_SIZE_SETTING.getKey(), between(1, 1024) + "b");
}
IndexMetaData metaData = newIndexMeta("index", settings.build());
IndexSettings indexSettings = new IndexSettings(metaData, Settings.EMPTY);
assertThat(indexSettings.getTranslogRetentionAge().millis(), equalTo(-1L));
assertThat(indexSettings.getTranslogRetentionSize().getBytes(), equalTo(-1L));
Settings.Builder newSettings = Settings.builder().put(settings.build());
if (randomBoolean()) {
newSettings.put(IndexSettings.INDEX_TRANSLOG_RETENTION_AGE_SETTING.getKey(), randomPositiveTimeValue());
}
if (randomBoolean()) {
newSettings.put(IndexSettings.INDEX_TRANSLOG_RETENTION_SIZE_SETTING.getKey(), between(1, 1024) + "b");
}
indexSettings.updateIndexMetaData(newIndexMeta("index", newSettings.build()));
assertThat(indexSettings.getTranslogRetentionAge().millis(), equalTo(-1L));
assertThat(indexSettings.getTranslogRetentionSize().getBytes(), equalTo(-1L));
}
public void testUpdateTranslogRetentionSettingsWithSoftDeletesDisabled() {
Settings.Builder settings = Settings.builder()
.put(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), false)
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT);
TimeValue ageSetting = TimeValue.timeValueHours(12);
if (randomBoolean()) {
ageSetting = randomBoolean() ? TimeValue.MINUS_ONE : TimeValue.timeValueMillis(randomIntBetween(0, 10000));
settings.put(IndexSettings.INDEX_TRANSLOG_RETENTION_AGE_SETTING.getKey(), ageSetting);
}
ByteSizeValue sizeSetting = new ByteSizeValue(512, ByteSizeUnit.MB);
if (randomBoolean()) {
sizeSetting = randomBoolean() ? new ByteSizeValue(-1) : new ByteSizeValue(randomIntBetween(0, 1024));
settings.put(IndexSettings.INDEX_TRANSLOG_RETENTION_SIZE_SETTING.getKey(), sizeSetting);
}
IndexMetaData metaData = newIndexMeta("index", settings.build());
IndexSettings indexSettings = new IndexSettings(metaData, Settings.EMPTY);
assertThat(indexSettings.getTranslogRetentionAge(), equalTo(ageSetting));
assertThat(indexSettings.getTranslogRetentionSize(), equalTo(sizeSetting));
Settings.Builder newSettings = Settings.builder().put(settings.build());
if (randomBoolean()) {
ageSetting = randomBoolean() ? TimeValue.MINUS_ONE : TimeValue.timeValueMillis(randomIntBetween(0, 10000));
newSettings.put(IndexSettings.INDEX_TRANSLOG_RETENTION_AGE_SETTING.getKey(), ageSetting);
}
if (randomBoolean()) {
sizeSetting = randomBoolean() ? new ByteSizeValue(-1) : new ByteSizeValue(randomIntBetween(0, 1024));
newSettings.put(IndexSettings.INDEX_TRANSLOG_RETENTION_SIZE_SETTING.getKey(), sizeSetting);
}
indexSettings.updateIndexMetaData(newIndexMeta("index", newSettings.build()));
assertThat(indexSettings.getTranslogRetentionAge(), equalTo(ageSetting));
assertThat(indexSettings.getTranslogRetentionSize(), equalTo(sizeSetting));
}
} }

View File

@ -169,13 +169,14 @@ public class NoOpEngineTests extends EngineTestCase {
tracker.updateFromMaster(1L, Collections.singleton(allocationId.getId()), table); tracker.updateFromMaster(1L, Collections.singleton(allocationId.getId()), table);
tracker.activatePrimaryMode(SequenceNumbers.NO_OPS_PERFORMED); tracker.activatePrimaryMode(SequenceNumbers.NO_OPS_PERFORMED);
boolean softDeleteEnabled = engine.config().getIndexSettings().isSoftDeleteEnabled();
final int numDocs = scaledRandomIntBetween(10, 3000); final int numDocs = scaledRandomIntBetween(10, 3000);
for (int i = 0; i < numDocs; i++) { for (int i = 0; i < numDocs; i++) {
engine.index(indexForDoc(createParsedDoc(Integer.toString(i), null))); engine.index(indexForDoc(createParsedDoc(Integer.toString(i), null)));
tracker.updateLocalCheckpoint(allocationId.getId(), i);
if (rarely()) { if (rarely()) {
engine.flush(); engine.flush();
} }
tracker.updateLocalCheckpoint(allocationId.getId(), i);
} }
engine.flush(true, true); engine.flush(true, true);
@ -195,7 +196,7 @@ public class NoOpEngineTests extends EngineTestCase {
} }
assertThat(Translog.readMinTranslogGeneration(translogPath, translogUuid), equalTo(minFileGeneration)); assertThat(Translog.readMinTranslogGeneration(translogPath, translogUuid), equalTo(minFileGeneration));
assertThat(noOpEngine.getTranslogStats().estimatedNumberOfOperations(), equalTo(numDocs)); assertThat(noOpEngine.getTranslogStats().estimatedNumberOfOperations(), equalTo(softDeleteEnabled ? 0 : numDocs));
assertThat(noOpEngine.getTranslogStats().getUncommittedOperations(), equalTo(0)); assertThat(noOpEngine.getTranslogStats().getUncommittedOperations(), equalTo(0));
noOpEngine.trimUnreferencedTranslogFiles(); noOpEngine.trimUnreferencedTranslogFiles();

View File

@ -250,7 +250,7 @@ public class ReadOnlyEngineTests extends EngineTestCase {
try (Store store = createStore()) { try (Store store = createStore()) {
final AtomicLong globalCheckpoint = new AtomicLong(SequenceNumbers.NO_OPS_PERFORMED); final AtomicLong globalCheckpoint = new AtomicLong(SequenceNumbers.NO_OPS_PERFORMED);
EngineConfig config = config(defaultSettings, store, createTempDir(), newMergePolicy(), null, null, globalCheckpoint::get); EngineConfig config = config(defaultSettings, store, createTempDir(), newMergePolicy(), null, null, globalCheckpoint::get);
final boolean softDeletesEnabled = config.getIndexSettings().isSoftDeleteEnabled();
final int numDocs = frequently() ? scaledRandomIntBetween(10, 200) : 0; final int numDocs = frequently() ? scaledRandomIntBetween(10, 200) : 0;
int uncommittedDocs = 0; int uncommittedDocs = 0;
@ -259,16 +259,17 @@ public class ReadOnlyEngineTests extends EngineTestCase {
ParsedDocument doc = testParsedDocument(Integer.toString(i), null, testDocument(), new BytesArray("{}"), null); ParsedDocument doc = testParsedDocument(Integer.toString(i), null, testDocument(), new BytesArray("{}"), null);
engine.index(new Engine.Index(newUid(doc), doc, i, primaryTerm.get(), 1, null, Engine.Operation.Origin.REPLICA, engine.index(new Engine.Index(newUid(doc), doc, i, primaryTerm.get(), 1, null, Engine.Operation.Origin.REPLICA,
System.nanoTime(), -1, false, SequenceNumbers.UNASSIGNED_SEQ_NO, 0)); System.nanoTime(), -1, false, SequenceNumbers.UNASSIGNED_SEQ_NO, 0));
globalCheckpoint.set(i);
if (rarely()) { if (rarely()) {
engine.flush(); engine.flush();
uncommittedDocs = 0; uncommittedDocs = 0;
} else { } else {
uncommittedDocs += 1; uncommittedDocs += 1;
} }
globalCheckpoint.set(i);
} }
assertThat(engine.getTranslogStats().estimatedNumberOfOperations(), equalTo(numDocs)); assertThat(engine.getTranslogStats().estimatedNumberOfOperations(),
equalTo(softDeletesEnabled ? uncommittedDocs : numDocs));
assertThat(engine.getTranslogStats().getUncommittedOperations(), equalTo(uncommittedDocs)); assertThat(engine.getTranslogStats().getUncommittedOperations(), equalTo(uncommittedDocs));
assertThat(engine.getTranslogStats().getTranslogSizeInBytes(), greaterThan(0L)); assertThat(engine.getTranslogStats().getTranslogSizeInBytes(), greaterThan(0L));
assertThat(engine.getTranslogStats().getUncommittedSizeInBytes(), greaterThan(0L)); assertThat(engine.getTranslogStats().getUncommittedSizeInBytes(), greaterThan(0L));
@ -278,7 +279,7 @@ public class ReadOnlyEngineTests extends EngineTestCase {
} }
try (ReadOnlyEngine readOnlyEngine = new ReadOnlyEngine(config, null, null, true, Function.identity())) { try (ReadOnlyEngine readOnlyEngine = new ReadOnlyEngine(config, null, null, true, Function.identity())) {
assertThat(readOnlyEngine.getTranslogStats().estimatedNumberOfOperations(), equalTo(numDocs)); assertThat(readOnlyEngine.getTranslogStats().estimatedNumberOfOperations(), equalTo(softDeletesEnabled ? 0 : numDocs));
assertThat(readOnlyEngine.getTranslogStats().getUncommittedOperations(), equalTo(0)); assertThat(readOnlyEngine.getTranslogStats().getUncommittedOperations(), equalTo(0));
assertThat(readOnlyEngine.getTranslogStats().getTranslogSizeInBytes(), greaterThan(0L)); assertThat(readOnlyEngine.getTranslogStats().getTranslogSizeInBytes(), greaterThan(0L));
assertThat(readOnlyEngine.getTranslogStats().getUncommittedSizeInBytes(), greaterThan(0L)); assertThat(readOnlyEngine.getTranslogStats().getUncommittedSizeInBytes(), greaterThan(0L));

View File

@ -467,7 +467,12 @@ public class IndexLevelReplicationTests extends ESIndexLevelReplicationTestCase
shards.startReplicas(nReplica); shards.startReplicas(nReplica);
for (IndexShard shard : shards) { for (IndexShard shard : shards) {
try (Translog.Snapshot snapshot = getTranslog(shard).newSnapshot()) { try (Translog.Snapshot snapshot = getTranslog(shard).newSnapshot()) {
// we flush at the end of peer recovery
if (shard.routingEntry().primary() || shard.indexSettings().isSoftDeleteEnabled() == false) {
assertThat(snapshot, SnapshotMatchers.containsOperationsInAnyOrder(expectedTranslogOps)); assertThat(snapshot, SnapshotMatchers.containsOperationsInAnyOrder(expectedTranslogOps));
} else {
assertThat(snapshot.totalOperations(), equalTo(0));
}
} }
try (Translog.Snapshot snapshot = shard.getHistoryOperations("test", 0)) { try (Translog.Snapshot snapshot = shard.getHistoryOperations("test", 0)) {
assertThat(snapshot, SnapshotMatchers.containsOperationsInAnyOrder(expectedTranslogOps)); assertThat(snapshot, SnapshotMatchers.containsOperationsInAnyOrder(expectedTranslogOps));
@ -476,11 +481,16 @@ public class IndexLevelReplicationTests extends ESIndexLevelReplicationTestCase
// the failure replicated directly from the replication channel. // the failure replicated directly from the replication channel.
indexResp = shards.index(new IndexRequest(index.getName(), "type", "any").source("{}", XContentType.JSON)); indexResp = shards.index(new IndexRequest(index.getName(), "type", "any").source("{}", XContentType.JSON));
assertThat(indexResp.getFailure().getCause(), equalTo(indexException)); assertThat(indexResp.getFailure().getCause(), equalTo(indexException));
expectedTranslogOps.add(new Translog.NoOp(1, primaryTerm, indexException.toString())); Translog.NoOp noop2 = new Translog.NoOp(1, primaryTerm, indexException.toString());
expectedTranslogOps.add(noop2);
for (IndexShard shard : shards) { for (IndexShard shard : shards) {
try (Translog.Snapshot snapshot = getTranslog(shard).newSnapshot()) { try (Translog.Snapshot snapshot = getTranslog(shard).newSnapshot()) {
if (shard.routingEntry().primary() || shard.indexSettings().isSoftDeleteEnabled() == false) {
assertThat(snapshot, SnapshotMatchers.containsOperationsInAnyOrder(expectedTranslogOps)); assertThat(snapshot, SnapshotMatchers.containsOperationsInAnyOrder(expectedTranslogOps));
} else {
assertThat(snapshot, SnapshotMatchers.containsOperationsInAnyOrder(Collections.singletonList(noop2)));
}
} }
try (Translog.Snapshot snapshot = shard.getHistoryOperations("test", 0)) { try (Translog.Snapshot snapshot = shard.getHistoryOperations("test", 0)) {
assertThat(snapshot, SnapshotMatchers.containsOperationsInAnyOrder(expectedTranslogOps)); assertThat(snapshot, SnapshotMatchers.containsOperationsInAnyOrder(expectedTranslogOps));

View File

@ -2136,11 +2136,13 @@ public class IndexShardTests extends IndexShardTestCase {
/* This test just verifies that we fill up local checkpoint up to max seen seqID on primary recovery */ /* This test just verifies that we fill up local checkpoint up to max seen seqID on primary recovery */
public void testRecoverFromStoreWithNoOps() throws IOException { public void testRecoverFromStoreWithNoOps() throws IOException {
final IndexShard shard = newStartedShard(true); final Settings settings = Settings.builder()
.put(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), randomBoolean()).build();
final IndexShard shard = newStartedShard(true, settings);
indexDoc(shard, "_doc", "0"); indexDoc(shard, "_doc", "0");
indexDoc(shard, "_doc", "1"); indexDoc(shard, "_doc", "1");
// start a replica shard and index the second doc // start a replica shard and index the second doc
final IndexShard otherShard = newStartedShard(false); final IndexShard otherShard = newStartedShard(false, settings);
updateMappings(otherShard, shard.indexSettings().getIndexMetaData()); updateMappings(otherShard, shard.indexSettings().getIndexMetaData());
SourceToParse sourceToParse = new SourceToParse(shard.shardId().getIndexName(), "_doc", "1", SourceToParse sourceToParse = new SourceToParse(shard.shardId().getIndexName(), "_doc", "1",
new BytesArray("{}"), XContentType.JSON); new BytesArray("{}"), XContentType.JSON);
@ -2179,7 +2181,7 @@ public class IndexShardTests extends IndexShardTestCase {
newShard.markAsRecovering("store", new RecoveryState(newShard.routingEntry(), localNode, null)); newShard.markAsRecovering("store", new RecoveryState(newShard.routingEntry(), localNode, null));
assertTrue(newShard.recoverFromStore()); assertTrue(newShard.recoverFromStore());
try (Translog.Snapshot snapshot = getTranslog(newShard).newSnapshot()) { try (Translog.Snapshot snapshot = getTranslog(newShard).newSnapshot()) {
assertThat(snapshot.totalOperations(), equalTo(2)); assertThat(snapshot.totalOperations(), equalTo(newShard.indexSettings.isSoftDeleteEnabled() ? 0 : 2));
} }
} }
closeShards(newShard, shard); closeShards(newShard, shard);
@ -3801,7 +3803,13 @@ public class IndexShardTests extends IndexShardTestCase {
engineResetLatch.await(); engineResetLatch.await();
assertThat(getShardDocUIDs(shard), equalTo(docBelowGlobalCheckpoint)); assertThat(getShardDocUIDs(shard), equalTo(docBelowGlobalCheckpoint));
assertThat(shard.seqNoStats().getMaxSeqNo(), equalTo(globalCheckpoint)); assertThat(shard.seqNoStats().getMaxSeqNo(), equalTo(globalCheckpoint));
if (shard.indexSettings.isSoftDeleteEnabled()) {
// we might have trimmed some operations if the translog retention policy is ignored (when soft-deletes enabled).
assertThat(shard.translogStats().estimatedNumberOfOperations(),
lessThanOrEqualTo(translogStats.estimatedNumberOfOperations()));
} else {
assertThat(shard.translogStats().estimatedNumberOfOperations(), equalTo(translogStats.estimatedNumberOfOperations())); assertThat(shard.translogStats().estimatedNumberOfOperations(), equalTo(translogStats.estimatedNumberOfOperations()));
}
assertThat(shard.getMaxSeqNoOfUpdatesOrDeletes(), equalTo(maxSeqNoBeforeRollback)); assertThat(shard.getMaxSeqNoOfUpdatesOrDeletes(), equalTo(maxSeqNoBeforeRollback));
done.set(true); done.set(true);
thread.join(); thread.join();

View File

@ -82,7 +82,7 @@ public class RecoveryTests extends ESIndexLevelReplicationTestCase {
shards.startAll(); shards.startAll();
final IndexShard replica = shards.getReplicas().get(0); final IndexShard replica = shards.getReplicas().get(0);
boolean softDeletesEnabled = replica.indexSettings().isSoftDeleteEnabled(); boolean softDeletesEnabled = replica.indexSettings().isSoftDeleteEnabled();
assertThat(getTranslog(replica).totalOperations(), equalTo(softDeletesEnabled ? moreDocs : docs + moreDocs)); assertThat(getTranslog(replica).totalOperations(), equalTo(softDeletesEnabled ? 0 : docs + moreDocs));
shards.assertAllEqual(docs + moreDocs); shards.assertAllEqual(docs + moreDocs);
} }
} }
@ -298,7 +298,7 @@ public class RecoveryTests extends ESIndexLevelReplicationTestCase {
// file based recovery should be made // file based recovery should be made
assertThat(newReplica.recoveryState().getIndex().fileDetails(), not(empty())); assertThat(newReplica.recoveryState().getIndex().fileDetails(), not(empty()));
boolean softDeletesEnabled = replica.indexSettings().isSoftDeleteEnabled(); boolean softDeletesEnabled = replica.indexSettings().isSoftDeleteEnabled();
assertThat(getTranslog(newReplica).totalOperations(), equalTo(softDeletesEnabled ? nonFlushedDocs : numDocs)); assertThat(getTranslog(newReplica).totalOperations(), equalTo(softDeletesEnabled ? 0 : numDocs));
// history uuid was restored // history uuid was restored
assertThat(newReplica.getHistoryUUID(), equalTo(historyUUID)); assertThat(newReplica.getHistoryUUID(), equalTo(historyUUID));
@ -385,7 +385,12 @@ public class RecoveryTests extends ESIndexLevelReplicationTestCase {
shards.recoverReplica(newReplica); shards.recoverReplica(newReplica);
try (Translog.Snapshot snapshot = getTranslog(newReplica).newSnapshot()) { try (Translog.Snapshot snapshot = getTranslog(newReplica).newSnapshot()) {
assertThat("Sequence based recovery should keep existing translog", snapshot, SnapshotMatchers.size(initDocs + moreDocs)); if (newReplica.indexSettings().isSoftDeleteEnabled()) {
assertThat(snapshot.totalOperations(), equalTo(0));
} else {
assertThat("Sequence based recovery should keep existing translog",
snapshot, SnapshotMatchers.size(initDocs + moreDocs));
}
} }
assertThat(newReplica.recoveryState().getTranslog().recoveredOperations(), equalTo(uncommittedDocs + moreDocs)); assertThat(newReplica.recoveryState().getTranslog().recoveredOperations(), equalTo(uncommittedDocs + moreDocs));
assertThat(newReplica.recoveryState().getIndex().fileDetails(), empty()); assertThat(newReplica.recoveryState().getIndex().fileDetails(), empty());

View File

@ -36,6 +36,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus; import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.ESIntegTestCase;
@ -352,11 +353,13 @@ public class OpenCloseIndexIT extends ESIntegTestCase {
} }
} }
public void testTranslogStats() { public void testTranslogStats() throws Exception {
final String indexName = "test"; final String indexName = "test";
createIndex(indexName, Settings.builder() createIndex(indexName, Settings.builder()
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
.build()); .build());
boolean softDeletesEnabled = IndexSettings.INDEX_SOFT_DELETES_SETTING.get(
client().admin().indices().prepareGetSettings(indexName).get().getIndexToSettings().get(indexName));
final int nbDocs = randomIntBetween(0, 50); final int nbDocs = randomIntBetween(0, 50);
int uncommittedOps = 0; int uncommittedOps = 0;
@ -372,17 +375,23 @@ public class OpenCloseIndexIT extends ESIntegTestCase {
} }
} }
final int uncommittedTranslogOps = uncommittedOps;
assertBusy(() -> {
IndicesStatsResponse stats = client().admin().indices().prepareStats(indexName).clear().setTranslog(true).get(); IndicesStatsResponse stats = client().admin().indices().prepareStats(indexName).clear().setTranslog(true).get();
assertThat(stats.getIndex(indexName), notNullValue()); assertThat(stats.getIndex(indexName), notNullValue());
assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().estimatedNumberOfOperations(), equalTo(nbDocs)); assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().estimatedNumberOfOperations(), equalTo(
assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().getUncommittedOperations(), equalTo(uncommittedOps)); softDeletesEnabled ? uncommittedTranslogOps : nbDocs));
assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().getUncommittedOperations(), equalTo(uncommittedTranslogOps));
});
assertAcked(client().admin().indices().prepareClose("test").setWaitForActiveShards(ActiveShardCount.ONE)); assertAcked(client().admin().indices().prepareClose("test").setWaitForActiveShards(ActiveShardCount.ONE));
IndicesOptions indicesOptions = IndicesOptions.STRICT_EXPAND_OPEN_CLOSED; IndicesOptions indicesOptions = IndicesOptions.STRICT_EXPAND_OPEN_CLOSED;
stats = client().admin().indices().prepareStats(indexName).setIndicesOptions(indicesOptions).clear().setTranslog(true).get(); IndicesStatsResponse stats = client().admin().indices().prepareStats(indexName)
.setIndicesOptions(indicesOptions).clear().setTranslog(true).get();
assertThat(stats.getIndex(indexName), notNullValue()); assertThat(stats.getIndex(indexName), notNullValue());
assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().estimatedNumberOfOperations(), equalTo(nbDocs)); assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().estimatedNumberOfOperations(),
equalTo(softDeletesEnabled ? 0 : nbDocs));
assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().getUncommittedOperations(), equalTo(0)); assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().getUncommittedOperations(), equalTo(0));
} }
} }

View File

@ -49,7 +49,8 @@ public class DeprecationChecks {
IndexDeprecationChecks::oldIndicesCheck, IndexDeprecationChecks::oldIndicesCheck,
IndexDeprecationChecks::tooManyFieldsCheck, IndexDeprecationChecks::tooManyFieldsCheck,
IndexDeprecationChecks::chainedMultiFieldsCheck, IndexDeprecationChecks::chainedMultiFieldsCheck,
IndexDeprecationChecks::deprecatedDateTimeFormat IndexDeprecationChecks::deprecatedDateTimeFormat,
IndexDeprecationChecks::translogRetentionSettingCheck
)); ));
static List<BiFunction<DatafeedConfig, NamedXContentRegistry, DeprecationIssue>> ML_SETTINGS_CHECKS = static List<BiFunction<DatafeedConfig, NamedXContentRegistry, DeprecationIssue>> ML_SETTINGS_CHECKS =

View File

@ -231,4 +231,19 @@ public class IndexDeprecationChecks {
return fields; return fields;
} }
static DeprecationIssue translogRetentionSettingCheck(IndexMetaData indexMetaData) {
final boolean softDeletesEnabled = IndexSettings.INDEX_SOFT_DELETES_SETTING.get(indexMetaData.getSettings());
if (softDeletesEnabled) {
if (IndexSettings.INDEX_TRANSLOG_RETENTION_SIZE_SETTING.exists(indexMetaData.getSettings())
|| IndexSettings.INDEX_TRANSLOG_RETENTION_AGE_SETTING.exists(indexMetaData.getSettings())) {
return new DeprecationIssue(DeprecationIssue.Level.WARNING,
"translog retention settings are ignored",
"https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-translog.html",
"translog retention settings [index.translog.retention.size] and [index.translog.retention.age] are ignored " +
"because translog is no longer used in peer recoveries with soft-deletes enabled (default in 7.0 or later)");
}
}
return null;
}
} }

View File

@ -14,6 +14,7 @@ import org.elasticsearch.common.joda.JodaDeprecationPatterns;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.IndexSettings; import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.VersionUtils; import org.elasticsearch.test.VersionUtils;
import org.elasticsearch.xpack.core.deprecation.DeprecationIssue; import org.elasticsearch.xpack.core.deprecation.DeprecationIssue;
@ -27,6 +28,8 @@ import static java.util.Collections.singletonList;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.xpack.deprecation.DeprecationChecks.INDEX_SETTINGS_CHECKS; import static org.elasticsearch.xpack.deprecation.DeprecationChecks.INDEX_SETTINGS_CHECKS;
import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
public class IndexDeprecationChecksTests extends ESTestCase { public class IndexDeprecationChecksTests extends ESTestCase {
public void testOldIndicesCheck() { public void testOldIndicesCheck() {
@ -382,4 +385,31 @@ public class IndexDeprecationChecksTests extends ESTestCase {
} }
mappingBuilder.endObject(); mappingBuilder.endObject();
} }
public void testTranslogRetentionSettings() {
Settings.Builder settings = settings(Version.CURRENT);
settings.put(IndexSettings.INDEX_TRANSLOG_RETENTION_AGE_SETTING.getKey(), randomPositiveTimeValue());
settings.put(IndexSettings.INDEX_TRANSLOG_RETENTION_SIZE_SETTING.getKey(), between(1, 1024) + "b");
IndexMetaData indexMetaData = IndexMetaData.builder("test").settings(settings).numberOfShards(1).numberOfReplicas(0).build();
List<DeprecationIssue> issues = DeprecationChecks.filterChecks(INDEX_SETTINGS_CHECKS, c -> c.apply(indexMetaData));
assertThat(issues, contains(
new DeprecationIssue(DeprecationIssue.Level.WARNING,
"translog retention settings are ignored",
"https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-translog.html",
"translog retention settings [index.translog.retention.size] and [index.translog.retention.age] are ignored " +
"because translog is no longer used in peer recoveries with soft-deletes enabled (default in 7.0 or later)")
));
}
public void testDefaultTranslogRetentionSettings() {
Settings.Builder settings = settings(Version.CURRENT);
if (randomBoolean()) {
settings.put(IndexSettings.INDEX_TRANSLOG_RETENTION_AGE_SETTING.getKey(), randomPositiveTimeValue());
settings.put(IndexSettings.INDEX_TRANSLOG_RETENTION_SIZE_SETTING.getKey(), between(1, 1024) + "b");
settings.put(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), false);
}
IndexMetaData indexMetaData = IndexMetaData.builder("test").settings(settings).numberOfShards(1).numberOfReplicas(0).build();
List<DeprecationIssue> issues = DeprecationChecks.filterChecks(INDEX_SETTINGS_CHECKS, c -> c.apply(indexMetaData));
assertThat(issues, empty());
}
} }

View File

@ -411,7 +411,7 @@ public class FrozenIndexTests extends ESSingleNodeTestCase {
public void testTranslogStats() throws Exception { public void testTranslogStats() throws Exception {
final String indexName = "test"; final String indexName = "test";
createIndex(indexName, Settings.builder() IndexService indexService = createIndex(indexName, Settings.builder()
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
.build()); .build());
@ -420,7 +420,6 @@ public class FrozenIndexTests extends ESSingleNodeTestCase {
for (long i = 0; i < nbDocs; i++) { for (long i = 0; i < nbDocs; i++) {
final IndexResponse indexResponse = client().prepareIndex(indexName, "_doc", Long.toString(i)).setSource("field", i).get(); final IndexResponse indexResponse = client().prepareIndex(indexName, "_doc", Long.toString(i)).setSource("field", i).get();
assertThat(indexResponse.status(), is(RestStatus.CREATED)); assertThat(indexResponse.status(), is(RestStatus.CREATED));
if (rarely()) { if (rarely()) {
client().admin().indices().prepareFlush(indexName).get(); client().admin().indices().prepareFlush(indexName).get();
uncommittedOps = 0; uncommittedOps = 0;
@ -431,7 +430,8 @@ public class FrozenIndexTests extends ESSingleNodeTestCase {
IndicesStatsResponse stats = client().admin().indices().prepareStats(indexName).clear().setTranslog(true).get(); IndicesStatsResponse stats = client().admin().indices().prepareStats(indexName).clear().setTranslog(true).get();
assertThat(stats.getIndex(indexName), notNullValue()); assertThat(stats.getIndex(indexName), notNullValue());
assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().estimatedNumberOfOperations(), equalTo(nbDocs)); assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().estimatedNumberOfOperations(), equalTo(
indexService.getIndexSettings().isSoftDeleteEnabled() ? uncommittedOps : nbDocs));
assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().getUncommittedOperations(), equalTo(uncommittedOps)); assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().getUncommittedOperations(), equalTo(uncommittedOps));
assertAcked(new XPackClient(client()).freeze(new FreezeRequest(indexName))); assertAcked(new XPackClient(client()).freeze(new FreezeRequest(indexName)));
@ -440,7 +440,8 @@ public class FrozenIndexTests extends ESSingleNodeTestCase {
IndicesOptions indicesOptions = IndicesOptions.STRICT_EXPAND_OPEN_CLOSED; IndicesOptions indicesOptions = IndicesOptions.STRICT_EXPAND_OPEN_CLOSED;
stats = client().admin().indices().prepareStats(indexName).setIndicesOptions(indicesOptions).clear().setTranslog(true).get(); stats = client().admin().indices().prepareStats(indexName).setIndicesOptions(indicesOptions).clear().setTranslog(true).get();
assertThat(stats.getIndex(indexName), notNullValue()); assertThat(stats.getIndex(indexName), notNullValue());
assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().estimatedNumberOfOperations(), equalTo(nbDocs)); assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().estimatedNumberOfOperations(),
equalTo(indexService.getIndexSettings().isSoftDeleteEnabled() ? 0 : nbDocs));
assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().getUncommittedOperations(), equalTo(0)); assertThat(stats.getIndex(indexName).getPrimaries().getTranslog().getUncommittedOperations(), equalTo(0));
} }
} }

View File

@ -10,8 +10,8 @@ setup:
--- ---
"Translog stats on frozen indices": "Translog stats on frozen indices":
- skip: - skip:
version: " - 7.2.99" version: " - 7.3.99"
reason: "frozen indices have translog stats starting version 7.3.0" reason: "start ignoring translog retention policy with soft-deletes enabled in 7.4"
- do: - do:
index: index:
@ -47,7 +47,7 @@ setup:
- do: - do:
indices.stats: indices.stats:
metric: [ translog ] metric: [ translog ]
- match: { indices.test.primaries.translog.operations: 3 } - match: { indices.test.primaries.translog.operations: 0 }
- match: { indices.test.primaries.translog.uncommitted_operations: 0 } - match: { indices.test.primaries.translog.uncommitted_operations: 0 }
# unfreeze index # unfreeze index
@ -60,5 +60,5 @@ setup:
- do: - do:
indices.stats: indices.stats:
metric: [ translog ] metric: [ translog ]
- match: { indices.test.primaries.translog.operations: 3 } - match: { indices.test.primaries.translog.operations: 0 }
- match: { indices.test.primaries.translog.uncommitted_operations: 0 } - match: { indices.test.primaries.translog.uncommitted_operations: 0 }