|
|
@@ -67,6 +67,7 @@ import org.elasticsearch.common.lucene.index.ElasticsearchDirectoryReader;
|
|
|
import org.elasticsearch.common.metrics.CounterMetric;
|
|
|
import org.elasticsearch.common.metrics.MeanMetric;
|
|
|
import org.elasticsearch.common.settings.Settings;
|
|
|
+import org.elasticsearch.common.unit.ByteSizeValue;
|
|
|
import org.elasticsearch.common.unit.TimeValue;
|
|
|
import org.elasticsearch.common.util.BigArrays;
|
|
|
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
|
|
|
@@ -157,6 +158,7 @@ import java.nio.charset.StandardCharsets;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
|
import java.util.EnumSet;
|
|
|
+import java.util.HashSet;
|
|
|
import java.util.List;
|
|
|
import java.util.Locale;
|
|
|
import java.util.Map;
|
|
|
@@ -268,6 +270,7 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
|
|
|
|
|
|
private final AtomicLong lastSearcherAccess = new AtomicLong();
|
|
|
private final AtomicReference<Translog.Location> pendingRefreshLocation = new AtomicReference<>();
|
|
|
+ private volatile boolean useRetentionLeasesInPeerRecovery;
|
|
|
|
|
|
public IndexShard(
|
|
|
final ShardRouting shardRouting,
|
|
|
@@ -364,6 +367,7 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
|
|
|
refreshListeners = buildRefreshListeners();
|
|
|
lastSearcherAccess.set(threadPool.relativeTimeInMillis());
|
|
|
persistMetadata(path, indexSettings, shardRouting, null, logger);
|
|
|
+ this.useRetentionLeasesInPeerRecovery = replicationTracker.hasAllPeerRecoveryRetentionLeases();
|
|
|
}
|
|
|
|
|
|
public ThreadPool getThreadPool() {
|
|
|
@@ -600,6 +604,17 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
|
|
|
if (newRouting.equals(currentRouting) == false) {
|
|
|
indexEventListener.shardRoutingChanged(this, currentRouting, newRouting);
|
|
|
}
|
|
|
+
|
|
|
+ if (indexSettings.isSoftDeleteEnabled() && useRetentionLeasesInPeerRecovery == false) {
|
|
|
+ final RetentionLeases retentionLeases = replicationTracker.getRetentionLeases();
|
|
|
+ final Set<ShardRouting> shardRoutings = new HashSet<>(routingTable.getShards());
|
|
|
+ shardRoutings.addAll(routingTable.assignedShards()); // include relocation targets
|
|
|
+ if (shardRoutings.stream().allMatch(
|
|
|
+ shr -> shr.assignedToNode() && retentionLeases.contains(ReplicationTracker.getPeerRecoveryRetentionLeaseId(shr)))) {
|
|
|
+ useRetentionLeasesInPeerRecovery = true;
|
|
|
+ turnOffTranslogRetention();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -1877,38 +1892,63 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
|
|
|
public void onSettingsChanged() {
|
|
|
Engine engineOrNull = getEngineOrNull();
|
|
|
if (engineOrNull != null) {
|
|
|
- engineOrNull.onSettingsChanged();
|
|
|
+ final boolean useRetentionLeasesInPeerRecovery = this.useRetentionLeasesInPeerRecovery;
|
|
|
+ engineOrNull.onSettingsChanged(
|
|
|
+ useRetentionLeasesInPeerRecovery ? TimeValue.MINUS_ONE : indexSettings.getTranslogRetentionAge(),
|
|
|
+ useRetentionLeasesInPeerRecovery ? new ByteSizeValue(-1) : indexSettings.getTranslogRetentionSize(),
|
|
|
+ indexSettings.getSoftDeleteRetentionOperations()
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void turnOffTranslogRetention() {
|
|
|
+ logger.debug("turn off the translog retention for the replication group {} " +
|
|
|
+ "as it starts using retention leases exclusively in peer recoveries", shardId);
|
|
|
+ // Off to the generic threadPool as pruning the delete tombstones can be expensive.
|
|
|
+ threadPool.generic().execute(new AbstractRunnable() {
|
|
|
+ @Override
|
|
|
+ public void onFailure(Exception e) {
|
|
|
+ if (state != IndexShardState.CLOSED) {
|
|
|
+ logger.warn("failed to turn off translog retention", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void doRun() {
|
|
|
+ onSettingsChanged();
|
|
|
+ trimTranslog();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Acquires a lock on the translog files and Lucene soft-deleted documents to prevent them from being trimmed
|
|
|
*/
|
|
|
- public Closeable acquireRetentionLock() {
|
|
|
- return getEngine().acquireRetentionLock();
|
|
|
+ public Closeable acquireHistoryRetentionLock(Engine.HistorySource source) {
|
|
|
+ return getEngine().acquireHistoryRetentionLock(source);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Returns the estimated number of history operations whose seq# at least the provided seq# in this shard.
|
|
|
*/
|
|
|
- public int estimateNumberOfHistoryOperations(String source, long startingSeqNo) throws IOException {
|
|
|
- return getEngine().estimateNumberOfHistoryOperations(source, mapperService, startingSeqNo);
|
|
|
+ public int estimateNumberOfHistoryOperations(String reason, Engine.HistorySource source, long startingSeqNo) throws IOException {
|
|
|
+ return getEngine().estimateNumberOfHistoryOperations(reason, source, mapperService, startingSeqNo);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Creates a new history snapshot for reading operations since the provided starting seqno (inclusive).
|
|
|
* The returned snapshot can be retrieved from either Lucene index or translog files.
|
|
|
*/
|
|
|
- public Translog.Snapshot getHistoryOperations(String source, long startingSeqNo) throws IOException {
|
|
|
- return getEngine().readHistoryOperations(source, mapperService, startingSeqNo);
|
|
|
+ public Translog.Snapshot getHistoryOperations(String reason, Engine.HistorySource source, long startingSeqNo) throws IOException {
|
|
|
+ return getEngine().readHistoryOperations(reason, source, mapperService, startingSeqNo);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Checks if we have a completed history of operations since the given starting seqno (inclusive).
|
|
|
- * This method should be called after acquiring the retention lock; See {@link #acquireRetentionLock()}
|
|
|
+ * This method should be called after acquiring the retention lock; See {@link #acquireHistoryRetentionLock(Engine.HistorySource)}
|
|
|
*/
|
|
|
- public boolean hasCompleteHistoryOperations(String source, long startingSeqNo) throws IOException {
|
|
|
- return getEngine().hasCompleteOperationHistory(source, mapperService, startingSeqNo);
|
|
|
+ public boolean hasCompleteHistoryOperations(String reason, Engine.HistorySource source, long startingSeqNo) throws IOException {
|
|
|
+ return getEngine().hasCompleteOperationHistory(reason, source, mapperService, startingSeqNo);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -2097,9 +2137,9 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
|
|
|
assert assertPrimaryMode();
|
|
|
verifyNotClosed();
|
|
|
ensureSoftDeletesEnabled("retention leases");
|
|
|
- try (Closeable ignore = acquireRetentionLock()) {
|
|
|
+ try (Closeable ignore = acquireHistoryRetentionLock(Engine.HistorySource.INDEX)) {
|
|
|
final long actualRetainingSequenceNumber =
|
|
|
- retainingSequenceNumber == RETAIN_ALL ? getMinRetainedSeqNo() : retainingSequenceNumber;
|
|
|
+ retainingSequenceNumber == RETAIN_ALL ? getMinRetainedSeqNo() : retainingSequenceNumber;
|
|
|
return replicationTracker.addRetentionLease(id, actualRetainingSequenceNumber, source, listener);
|
|
|
} catch (final IOException e) {
|
|
|
throw new AssertionError(e);
|
|
|
@@ -2119,7 +2159,7 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
|
|
|
assert assertPrimaryMode();
|
|
|
verifyNotClosed();
|
|
|
ensureSoftDeletesEnabled("retention leases");
|
|
|
- try (Closeable ignore = acquireRetentionLock()) {
|
|
|
+ try (Closeable ignore = acquireHistoryRetentionLock(Engine.HistorySource.INDEX)) {
|
|
|
final long actualRetainingSequenceNumber =
|
|
|
retainingSequenceNumber == RETAIN_ALL ? getMinRetainedSeqNo() : retainingSequenceNumber;
|
|
|
return replicationTracker.renewRetentionLease(id, actualRetainingSequenceNumber, source);
|
|
|
@@ -2600,6 +2640,10 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
|
|
|
return replicationTracker.getPeerRecoveryRetentionLeases();
|
|
|
}
|
|
|
|
|
|
+ public boolean useRetentionLeasesInPeerRecovery() {
|
|
|
+ return useRetentionLeasesInPeerRecovery;
|
|
|
+ }
|
|
|
+
|
|
|
private SafeCommitInfo getSafeCommitInfo() {
|
|
|
final Engine engine = getEngineOrNull();
|
|
|
return engine == null ? SafeCommitInfo.EMPTY : engine.getSafeCommitInfo();
|