Search in sources :

Example 1 with RetentionLeases

use of org.opensearch.index.seqno.RetentionLeases in project OpenSearch by opensearch-project.

the class SoftDeletesPolicy method getMinRetainedSeqNo.

/**
 * Returns the min seqno that is retained in the Lucene index.
 * Operations whose seq# is least this value should exist in the Lucene index.
 */
synchronized long getMinRetainedSeqNo() {
    /*
         * When an engine is flushed, we need to provide it the latest collection of retention leases even when the soft deletes policy is
         * locked for peer recovery.
         */
    final RetentionLeases retentionLeases = retentionLeasesSupplier.get();
    // do not advance if the retention lock is held
    if (retentionLockCount == 0) {
        /*
             * This policy retains operations for two purposes: peer-recovery and querying changes history.
             *  - Peer-recovery is driven by the local checkpoint of the safe commit. In peer-recovery, the primary transfers a safe commit,
             *    then sends operations after the local checkpoint of that commit. This requires keeping all ops after
             *    localCheckpointOfSafeCommit.
             *  - Changes APIs are driven by a combination of the global checkpoint, retention operations, and retention leases. Here we
             *    prefer using the global checkpoint instead of the maximum sequence number because only operations up to the global
             *    checkpoint are exposed in the changes APIs.
             */
        // calculate the minimum sequence number to retain based on retention leases
        final long minimumRetainingSequenceNumber = retentionLeases.leases().stream().mapToLong(RetentionLease::retainingSequenceNumber).min().orElse(Long.MAX_VALUE);
        /*
             * The minimum sequence number to retain is the minimum of the minimum based on retention leases, and the number of operations
             * below the global checkpoint to retain (index.soft_deletes.retention.operations). The additional increments on the global
             * checkpoint and the local checkpoint of the safe commit are due to the fact that we want to retain all operations above
             * those checkpoints.
             */
        final long minSeqNoForQueryingChanges = Math.min(1 + globalCheckpointSupplier.getAsLong() - retentionOperations, minimumRetainingSequenceNumber);
        final long minSeqNoToRetain = Math.min(minSeqNoForQueryingChanges, 1 + localCheckpointOfSafeCommit);
        /*
             * We take the maximum as minSeqNoToRetain can go backward as the retention operations value can be changed in settings, or from
             * the addition of leases with a retaining sequence number lower than previous retaining sequence numbers.
             */
        minRetainedSeqNo = Math.max(minRetainedSeqNo, minSeqNoToRetain);
    }
    return minRetainedSeqNo;
}
Also used : RetentionLease(org.opensearch.index.seqno.RetentionLease) RetentionLeases(org.opensearch.index.seqno.RetentionLeases)

Example 2 with RetentionLeases

use of org.opensearch.index.seqno.RetentionLeases in project OpenSearch by opensearch-project.

the class IndexRecoveryIT method testUsesFileBasedRecoveryIfOperationsBasedRecoveryWouldBeUnreasonable.

public void testUsesFileBasedRecoveryIfOperationsBasedRecoveryWouldBeUnreasonable() throws Exception {
    internalCluster().ensureAtLeastNumDataNodes(2);
    String indexName = "test-index";
    final Settings.Builder settings = Settings.builder().put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1).put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 1).put(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), true).put(UnassignedInfo.INDEX_DELAYED_NODE_LEFT_TIMEOUT_SETTING.getKey(), "12h").put(IndexService.RETENTION_LEASE_SYNC_INTERVAL_SETTING.getKey(), "100ms");
    final double reasonableOperationsBasedRecoveryProportion;
    if (randomBoolean()) {
        reasonableOperationsBasedRecoveryProportion = randomDoubleBetween(0.05, 0.99, true);
        settings.put(IndexSettings.FILE_BASED_RECOVERY_THRESHOLD_SETTING.getKey(), reasonableOperationsBasedRecoveryProportion);
    } else {
        reasonableOperationsBasedRecoveryProportion = IndexSettings.FILE_BASED_RECOVERY_THRESHOLD_SETTING.get(Settings.EMPTY);
    }
    logger.info("--> performing ops-based recoveries up to [{}%] of docs", reasonableOperationsBasedRecoveryProportion * 100.0);
    createIndex(indexName, settings.build());
    indexRandom(randomBoolean(), false, randomBoolean(), IntStream.range(0, between(0, 100)).mapToObj(n -> client().prepareIndex(indexName).setSource("num", n)).collect(toList()));
    ensureGreen(indexName);
    flush(indexName);
    // wait for all history to be discarded
    assertBusy(() -> {
        for (ShardStats shardStats : client().admin().indices().prepareStats(indexName).get().getShards()) {
            final long maxSeqNo = shardStats.getSeqNoStats().getMaxSeqNo();
            assertTrue(shardStats.getRetentionLeaseStats().retentionLeases() + " should discard history up to " + maxSeqNo, shardStats.getRetentionLeaseStats().retentionLeases().leases().stream().allMatch(l -> l.retainingSequenceNumber() == maxSeqNo + 1));
        }
    });
    // ensure that all operations are in the safe commit
    flush(indexName);
    final ShardStats shardStats = client().admin().indices().prepareStats(indexName).get().getShards()[0];
    final long docCount = shardStats.getStats().docs.getCount();
    assertThat(shardStats.getStats().docs.getDeleted(), equalTo(0L));
    assertThat(shardStats.getSeqNoStats().getMaxSeqNo() + 1, equalTo(docCount));
    final ShardId shardId = new ShardId(resolveIndex(indexName), 0);
    final DiscoveryNodes discoveryNodes = clusterService().state().nodes();
    final IndexShardRoutingTable indexShardRoutingTable = clusterService().state().routingTable().shardRoutingTable(shardId);
    final ShardRouting replicaShardRouting = indexShardRoutingTable.replicaShards().get(0);
    assertTrue("should have lease for " + replicaShardRouting, client().admin().indices().prepareStats(indexName).get().getShards()[0].getRetentionLeaseStats().retentionLeases().contains(ReplicationTracker.getPeerRecoveryRetentionLeaseId(replicaShardRouting)));
    internalCluster().restartNode(discoveryNodes.get(replicaShardRouting.currentNodeId()).getName(), new InternalTestCluster.RestartCallback() {

        @Override
        public Settings onNodeStopped(String nodeName) throws Exception {
            assertFalse(client().admin().cluster().prepareHealth().setWaitForNodes(Integer.toString(discoveryNodes.getSize() - 1)).setWaitForEvents(Priority.LANGUID).get().isTimedOut());
            final int newDocCount = Math.toIntExact(Math.round(Math.ceil((1 + Math.ceil(docCount * reasonableOperationsBasedRecoveryProportion)) / (1 - reasonableOperationsBasedRecoveryProportion))));
            /*
                     *     newDocCount >= (ceil(docCount * p) + 1) / (1-p)
                     *
                     * ==> 0 <= newDocCount * (1-p) - ceil(docCount * p) - 1
                     *       =  newDocCount - (newDocCount * p + ceil(docCount * p) + 1)
                     *       <  newDocCount - (ceil(newDocCount * p) + ceil(docCount * p))
                     *       <= newDocCount -  ceil(newDocCount * p + docCount * p)
                     *
                     * ==> docCount <  newDocCount + docCount - ceil((newDocCount + docCount) * p)
                     *              == localCheckpoint + 1    - ceil((newDocCount + docCount) * p)
                     *              == firstReasonableSeqNo
                     *
                     * The replica has docCount docs, i.e. has operations with seqnos [0..docCount-1], so a seqno-based recovery will start
                     * from docCount < firstReasonableSeqNo
                     *
                     * ==> it is unreasonable to recover the replica using a seqno-based recovery
                     */
            indexRandom(randomBoolean(), randomBoolean(), randomBoolean(), IntStream.range(0, newDocCount).mapToObj(n -> client().prepareIndex(indexName).setSource("num", n)).collect(toList()));
            flush(indexName);
            assertBusy(() -> assertFalse("should no longer have lease for " + replicaShardRouting, client().admin().indices().prepareStats(indexName).get().getShards()[0].getRetentionLeaseStats().retentionLeases().contains(ReplicationTracker.getPeerRecoveryRetentionLeaseId(replicaShardRouting))));
            return super.onNodeStopped(nodeName);
        }
    });
    ensureGreen(indexName);
    // noinspection OptionalGetWithoutIsPresent because it fails the test if absent
    final RecoveryState recoveryState = client().admin().indices().prepareRecoveries(indexName).get().shardRecoveryStates().get(indexName).stream().filter(rs -> rs.getPrimary() == false).findFirst().get();
    assertThat(recoveryState.getIndex().totalFileCount(), greaterThan(0));
}
Also used : ShardStats(org.opensearch.action.admin.indices.stats.ShardStats) OpenSearchRejectedExecutionException(org.opensearch.common.util.concurrent.OpenSearchRejectedExecutionException) SequenceNumbers(org.opensearch.index.seqno.SequenceNumbers) Arrays(java.util.Arrays) IndexResponse(org.opensearch.action.index.IndexResponse) ClusterStateResponse(org.opensearch.action.admin.cluster.state.ClusterStateResponse) SnapshotRecoverySource(org.opensearch.cluster.routing.RecoverySource.SnapshotRecoverySource) Matchers.not(org.hamcrest.Matchers.not) SnapshotState(org.opensearch.snapshots.SnapshotState) ClusterScope(org.opensearch.test.OpenSearchIntegTestCase.ClusterScope) Version(org.opensearch.Version) Strings(org.opensearch.common.Strings) Transport(org.opensearch.transport.Transport) PlainActionFuture(org.opensearch.action.support.PlainActionFuture) Map(java.util.Map) ShardStateAction(org.opensearch.cluster.action.shard.ShardStateAction) Repository(org.opensearch.repositories.Repository) TimeValue(org.opensearch.common.unit.TimeValue) Index(org.opensearch.index.Index) AbstractTokenFilterFactory(org.opensearch.index.analysis.AbstractTokenFilterFactory) TransportRequestOptions(org.opensearch.transport.TransportRequestOptions) Settings(org.opensearch.common.settings.Settings) ReplicationTracker(org.opensearch.index.seqno.ReplicationTracker) Scope(org.opensearch.test.OpenSearchIntegTestCase.Scope) TransportService(org.opensearch.transport.TransportService) Engine(org.opensearch.index.engine.Engine) CountDownLatch(java.util.concurrent.CountDownLatch) UPDATED(org.opensearch.action.DocWriteResponse.Result.UPDATED) NodeStats(org.opensearch.action.admin.cluster.node.stats.NodeStats) IndicesStatsResponse(org.opensearch.action.admin.indices.stats.IndicesStatsResponse) XContentType(org.opensearch.common.xcontent.XContentType) Matchers.greaterThan(org.hamcrest.Matchers.greaterThan) Matchers.is(org.hamcrest.Matchers.is) RepositoriesService(org.opensearch.repositories.RepositoriesService) TransportRequestHandler(org.opensearch.transport.TransportRequestHandler) CHUNK_SIZE_SETTING(org.opensearch.node.RecoverySettingsChunkSizePlugin.CHUNK_SIZE_SETTING) MapperParsingException(org.opensearch.index.mapper.MapperParsingException) Priority(org.opensearch.common.Priority) MockTransportService(org.opensearch.test.transport.MockTransportService) ArrayList(java.util.ArrayList) RecoverySource(org.opensearch.cluster.routing.RecoverySource) RestoreSnapshotResponse(org.opensearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse) ClusterState(org.opensearch.cluster.ClusterState) ShardRoutingState(org.opensearch.cluster.routing.ShardRoutingState) BiConsumer(java.util.function.BiConsumer) Matchers.hasSize(org.hamcrest.Matchers.hasSize) StreamSupport(java.util.stream.StreamSupport) CircuitBreakingException(org.opensearch.common.breaker.CircuitBreakingException) Matchers.greaterThanOrEqualTo(org.hamcrest.Matchers.greaterThanOrEqualTo) TokenStream(org.apache.lucene.analysis.TokenStream) SetOnce(org.apache.lucene.util.SetOnce) IOException(java.io.IOException) IndexService(org.opensearch.index.IndexService) Plugin(org.opensearch.plugins.Plugin) ExecutionException(java.util.concurrent.ExecutionException) RecoveryResponse(org.opensearch.action.admin.indices.recovery.RecoveryResponse) AnalysisModule(org.opensearch.indices.analysis.AnalysisModule) PluginsService(org.opensearch.plugins.PluginsService) RecoveryStats(org.opensearch.index.recovery.RecoveryStats) RetentionLeases(org.opensearch.index.seqno.RetentionLeases) ClusterService(org.opensearch.cluster.service.ClusterService) ShardStats(org.opensearch.action.admin.indices.stats.ShardStats) IndexRequestBuilder(org.opensearch.action.index.IndexRequestBuilder) MockFSIndexStore(org.opensearch.test.store.MockFSIndexStore) StubbableTransport(org.opensearch.test.transport.StubbableTransport) ByteSizeUnit(org.opensearch.common.unit.ByteSizeUnit) OpenSearchException(org.opensearch.OpenSearchException) MoveAllocationCommand(org.opensearch.cluster.routing.allocation.command.MoveAllocationCommand) CircuitBreaker(org.opensearch.common.breaker.CircuitBreaker) CommonStatsFlags(org.opensearch.action.admin.indices.stats.CommonStatsFlags) DiscoveryNode(org.opensearch.cluster.node.DiscoveryNode) OpenSearchAssertions.assertHitCount(org.opensearch.test.hamcrest.OpenSearchAssertions.assertHitCount) Matchers.everyItem(org.hamcrest.Matchers.everyItem) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) NodeClosedException(org.opensearch.node.NodeClosedException) RecoveryRequest(org.opensearch.action.admin.indices.recovery.RecoveryRequest) UnassignedInfo(org.opensearch.cluster.routing.UnassignedInfo) IndexShardRoutingTable(org.opensearch.cluster.routing.IndexShardRoutingTable) Matchers.isOneOf(org.hamcrest.Matchers.isOneOf) ReplicaShardAllocatorIT(org.opensearch.gateway.ReplicaShardAllocatorIT) TransportChannel(org.opensearch.transport.TransportChannel) Matchers.lessThanOrEqualTo(org.hamcrest.Matchers.lessThanOrEqualTo) Collection(java.util.Collection) IndicesService(org.opensearch.indices.IndicesService) Task(org.opensearch.tasks.Task) Store(org.opensearch.index.store.Store) NodeIndicesStats(org.opensearch.indices.NodeIndicesStats) Collectors(java.util.stream.Collectors) List(java.util.List) ClusterHealthResponse(org.opensearch.action.admin.cluster.health.ClusterHealthResponse) CREATED(org.opensearch.action.DocWriteResponse.Result.CREATED) Matchers.equalTo(org.hamcrest.Matchers.equalTo) IndexSettings(org.opensearch.index.IndexSettings) ReplicationResponse(org.opensearch.action.support.replication.ReplicationResponse) ConnectTransportException(org.opensearch.transport.ConnectTransportException) OpenSearchIntegTestCase(org.opensearch.test.OpenSearchIntegTestCase) AllocateEmptyPrimaryAllocationCommand(org.opensearch.cluster.routing.allocation.command.AllocateEmptyPrimaryAllocationCommand) RefreshPolicy(org.opensearch.action.support.WriteRequest.RefreshPolicy) IntStream(java.util.stream.IntStream) DiscoveryNodes(org.opensearch.cluster.node.DiscoveryNodes) IndexMetadata(org.opensearch.cluster.metadata.IndexMetadata) Stage(org.opensearch.indices.recovery.RecoveryState.Stage) TokenFilterFactory(org.opensearch.index.analysis.TokenFilterFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ByteSizeValue(org.opensearch.common.unit.ByteSizeValue) InternalTestCluster(org.opensearch.test.InternalTestCluster) NodeConnectionsService(org.opensearch.cluster.NodeConnectionsService) IndexShard(org.opensearch.index.shard.IndexShard) InternalSettingsPlugin(org.opensearch.test.InternalSettingsPlugin) BackgroundIndexer(org.opensearch.test.BackgroundIndexer) Collections.singletonMap(java.util.Collections.singletonMap) SearchResponse(org.opensearch.action.search.SearchResponse) StoreStats(org.opensearch.index.store.StoreStats) OpenSearchAssertions.assertAcked(org.opensearch.test.hamcrest.OpenSearchAssertions.assertAcked) RepositoryData(org.opensearch.repositories.RepositoryData) CreateSnapshotResponse(org.opensearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse) PeerRecoverySource(org.opensearch.cluster.routing.RecoverySource.PeerRecoverySource) Matchers.empty(org.hamcrest.Matchers.empty) MockEngineFactoryPlugin(org.opensearch.index.MockEngineFactoryPlugin) TransportRequest(org.opensearch.transport.TransportRequest) Semaphore(java.util.concurrent.Semaphore) MockEngineSupport(org.opensearch.test.engine.MockEngineSupport) ActiveShardCount(org.opensearch.action.support.ActiveShardCount) ShardRouting(org.opensearch.cluster.routing.ShardRouting) ShardId(org.opensearch.index.shard.ShardId) Consumer(java.util.function.Consumer) AnalysisPlugin(org.opensearch.plugins.AnalysisPlugin) Collectors.toList(java.util.stream.Collectors.toList) Snapshot(org.opensearch.snapshots.Snapshot) NodesStatsResponse(org.opensearch.action.admin.cluster.node.stats.NodesStatsResponse) RecoverySettingsChunkSizePlugin(org.opensearch.node.RecoverySettingsChunkSizePlugin) Collections(java.util.Collections) IndexShardRoutingTable(org.opensearch.cluster.routing.IndexShardRoutingTable) InternalTestCluster(org.opensearch.test.InternalTestCluster) OpenSearchRejectedExecutionException(org.opensearch.common.util.concurrent.OpenSearchRejectedExecutionException) MapperParsingException(org.opensearch.index.mapper.MapperParsingException) CircuitBreakingException(org.opensearch.common.breaker.CircuitBreakingException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) OpenSearchException(org.opensearch.OpenSearchException) NodeClosedException(org.opensearch.node.NodeClosedException) ConnectTransportException(org.opensearch.transport.ConnectTransportException) ShardId(org.opensearch.index.shard.ShardId) ShardRouting(org.opensearch.cluster.routing.ShardRouting) Settings(org.opensearch.common.settings.Settings) IndexSettings(org.opensearch.index.IndexSettings) DiscoveryNodes(org.opensearch.cluster.node.DiscoveryNodes)

Example 3 with RetentionLeases

use of org.opensearch.index.seqno.RetentionLeases in project OpenSearch by opensearch-project.

the class IndexRecoveryIT method testRecoverLocallyUpToGlobalCheckpoint.

public void testRecoverLocallyUpToGlobalCheckpoint() throws Exception {
    internalCluster().ensureAtLeastNumDataNodes(2);
    List<String> nodes = randomSubsetOf(2, StreamSupport.stream(clusterService().state().nodes().getDataNodes().spliterator(), false).map(node -> node.value.getName()).collect(Collectors.toSet()));
    String indexName = "test-index";
    createIndex(indexName, Settings.builder().put("index.number_of_shards", 1).put("index.number_of_replicas", 1).put(IndexService.GLOBAL_CHECKPOINT_SYNC_INTERVAL_SETTING.getKey(), "12h").put("index.routing.allocation.include._name", String.join(",", nodes)).build());
    ensureGreen(indexName);
    int numDocs = randomIntBetween(0, 100);
    indexRandom(randomBoolean(), false, randomBoolean(), IntStream.range(0, numDocs).mapToObj(n -> client().prepareIndex(indexName).setSource("num", n)).collect(toList()));
    // avoid refresh when we are failing a shard
    client().admin().indices().prepareRefresh(indexName).get();
    String failingNode = randomFrom(nodes);
    PlainActionFuture<StartRecoveryRequest> startRecoveryRequestFuture = new PlainActionFuture<>();
    // Peer recovery fails if the primary does not see the recovering replica in the replication group (when the cluster state
    // update on the primary is delayed). To verify the local recovery stats, we have to manually remember this value in the
    // first try because the local recovery happens once and its stats is reset when the recovery fails.
    SetOnce<Integer> localRecoveredOps = new SetOnce<>();
    for (String node : nodes) {
        MockTransportService transportService = (MockTransportService) internalCluster().getInstance(TransportService.class, node);
        transportService.addSendBehavior((connection, requestId, action, request, options) -> {
            if (action.equals(PeerRecoverySourceService.Actions.START_RECOVERY)) {
                final RecoveryState recoveryState = internalCluster().getInstance(IndicesService.class, failingNode).getShardOrNull(new ShardId(resolveIndex(indexName), 0)).recoveryState();
                assertThat(recoveryState.getTranslog().recoveredOperations(), equalTo(recoveryState.getTranslog().totalLocal()));
                if (startRecoveryRequestFuture.isDone()) {
                    assertThat(recoveryState.getTranslog().totalLocal(), equalTo(0));
                    recoveryState.getTranslog().totalLocal(localRecoveredOps.get());
                    recoveryState.getTranslog().incrementRecoveredOperations(localRecoveredOps.get());
                } else {
                    localRecoveredOps.set(recoveryState.getTranslog().totalLocal());
                    startRecoveryRequestFuture.onResponse((StartRecoveryRequest) request);
                }
            }
            if (action.equals(PeerRecoveryTargetService.Actions.FILE_CHUNK)) {
                RetentionLeases retentionLeases = internalCluster().getInstance(IndicesService.class, node).indexServiceSafe(resolveIndex(indexName)).getShard(0).getRetentionLeases();
                throw new AssertionError("expect an operation-based recovery:" + "retention leases" + Strings.toString(retentionLeases) + "]");
            }
            connection.sendRequest(requestId, action, request, options);
        });
    }
    IndexShard shard = internalCluster().getInstance(IndicesService.class, failingNode).getShardOrNull(new ShardId(resolveIndex(indexName), 0));
    final long lastSyncedGlobalCheckpoint = shard.getLastSyncedGlobalCheckpoint();
    final long localCheckpointOfSafeCommit;
    try (Engine.IndexCommitRef safeCommitRef = shard.acquireSafeIndexCommit()) {
        localCheckpointOfSafeCommit = SequenceNumbers.loadSeqNoInfoFromLuceneCommit(safeCommitRef.getIndexCommit().getUserData().entrySet()).localCheckpoint;
    }
    final long maxSeqNo = shard.seqNoStats().getMaxSeqNo();
    shard.failShard("test", new IOException("simulated"));
    StartRecoveryRequest startRecoveryRequest = startRecoveryRequestFuture.actionGet();
    logger.info("--> start recovery request: starting seq_no {}, commit {}", startRecoveryRequest.startingSeqNo(), startRecoveryRequest.metadataSnapshot().getCommitUserData());
    SequenceNumbers.CommitInfo commitInfoAfterLocalRecovery = SequenceNumbers.loadSeqNoInfoFromLuceneCommit(startRecoveryRequest.metadataSnapshot().getCommitUserData().entrySet());
    assertThat(commitInfoAfterLocalRecovery.localCheckpoint, equalTo(lastSyncedGlobalCheckpoint));
    assertThat(commitInfoAfterLocalRecovery.maxSeqNo, equalTo(lastSyncedGlobalCheckpoint));
    assertThat(startRecoveryRequest.startingSeqNo(), equalTo(lastSyncedGlobalCheckpoint + 1));
    ensureGreen(indexName);
    assertThat((long) localRecoveredOps.get(), equalTo(lastSyncedGlobalCheckpoint - localCheckpointOfSafeCommit));
    for (RecoveryState recoveryState : client().admin().indices().prepareRecoveries().get().shardRecoveryStates().get(indexName)) {
        if (startRecoveryRequest.targetNode().equals(recoveryState.getTargetNode())) {
            assertThat("expect an operation-based recovery", recoveryState.getIndex().fileDetails(), empty());
            assertThat("total recovered translog operations must include both local and remote recovery", recoveryState.getTranslog().recoveredOperations(), greaterThanOrEqualTo(Math.toIntExact(maxSeqNo - localCheckpointOfSafeCommit)));
        }
    }
    for (String node : nodes) {
        MockTransportService transportService = (MockTransportService) internalCluster().getInstance(TransportService.class, node);
        transportService.clearAllRules();
    }
}
Also used : MockTransportService(org.opensearch.test.transport.MockTransportService) SetOnce(org.apache.lucene.util.SetOnce) IndexShard(org.opensearch.index.shard.IndexShard) IndicesService(org.opensearch.indices.IndicesService) IOException(java.io.IOException) RetentionLeases(org.opensearch.index.seqno.RetentionLeases) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ShardId(org.opensearch.index.shard.ShardId) PlainActionFuture(org.opensearch.action.support.PlainActionFuture) TransportService(org.opensearch.transport.TransportService) MockTransportService(org.opensearch.test.transport.MockTransportService) SequenceNumbers(org.opensearch.index.seqno.SequenceNumbers) Engine(org.opensearch.index.engine.Engine)

Example 4 with RetentionLeases

use of org.opensearch.index.seqno.RetentionLeases in project OpenSearch by opensearch-project.

the class EngineConfigFactoryTests method testCreateCodecServiceFromFactory.

public void testCreateCodecServiceFromFactory() {
    IndexMetadata meta = IndexMetadata.builder("test").settings(settings(Version.CURRENT)).numberOfShards(1).numberOfReplicas(1).build();
    List<EnginePlugin> plugins = Arrays.asList(new BakEnginePlugin());
    IndexSettings indexSettings = IndexSettingsModule.newIndexSettings("test", meta.getSettings());
    EngineConfigFactory factory = new EngineConfigFactory(plugins, indexSettings);
    EngineConfig config = factory.newEngineConfig(null, null, indexSettings, null, null, null, null, null, null, null, null, null, null, TimeValue.timeValueMinutes(5), null, null, null, null, null, () -> new RetentionLeases(0, 0, Collections.emptyList()), null, null);
    assertNotNull(config.getCodec());
}
Also used : EnginePlugin(org.opensearch.plugins.EnginePlugin) IndexSettings(org.opensearch.index.IndexSettings) IndexMetadata(org.opensearch.cluster.metadata.IndexMetadata) RetentionLeases(org.opensearch.index.seqno.RetentionLeases)

Example 5 with RetentionLeases

use of org.opensearch.index.seqno.RetentionLeases in project OpenSearch by opensearch-project.

the class InternalEngineTests method testKeepMinRetainedSeqNoByMergePolicy.

public void testKeepMinRetainedSeqNoByMergePolicy() throws IOException {
    IOUtils.close(engine, store);
    Settings.Builder settings = Settings.builder().put(defaultSettings.getSettings()).put(IndexSettings.INDEX_SOFT_DELETES_RETENTION_OPERATIONS_SETTING.getKey(), randomLongBetween(0, 10));
    final IndexMetadata indexMetadata = IndexMetadata.builder(defaultSettings.getIndexMetadata()).settings(settings).build();
    final IndexSettings indexSettings = IndexSettingsModule.newIndexSettings(indexMetadata);
    final AtomicLong globalCheckpoint = new AtomicLong(SequenceNumbers.NO_OPS_PERFORMED);
    final long primaryTerm = randomLongBetween(1, Long.MAX_VALUE);
    final AtomicLong retentionLeasesVersion = new AtomicLong();
    final AtomicReference<RetentionLeases> retentionLeasesHolder = new AtomicReference<>(new RetentionLeases(primaryTerm, retentionLeasesVersion.get(), Collections.emptyList()));
    final List<Engine.Operation> operations = generateSingleDocHistory(true, randomFrom(VersionType.INTERNAL, VersionType.EXTERNAL), 2, 10, 300, "2");
    Randomness.shuffle(operations);
    Set<Long> existingSeqNos = new HashSet<>();
    store = createStore();
    engine = createEngine(config(indexSettings, store, createTempDir(), newMergePolicy(), null, null, globalCheckpoint::get, retentionLeasesHolder::get));
    assertThat(engine.getMinRetainedSeqNo(), equalTo(0L));
    long lastMinRetainedSeqNo = engine.getMinRetainedSeqNo();
    for (Engine.Operation op : operations) {
        final Engine.Result result;
        if (op instanceof Engine.Index) {
            result = engine.index((Engine.Index) op);
        } else {
            result = engine.delete((Engine.Delete) op);
        }
        existingSeqNos.add(result.getSeqNo());
        if (randomBoolean()) {
            // advance persisted local checkpoint
            engine.syncTranslog();
            assertEquals(engine.getProcessedLocalCheckpoint(), engine.getPersistedLocalCheckpoint());
            globalCheckpoint.set(randomLongBetween(globalCheckpoint.get(), engine.getLocalCheckpointTracker().getPersistedCheckpoint()));
        }
        if (randomBoolean()) {
            retentionLeasesVersion.incrementAndGet();
            final int length = randomIntBetween(0, 8);
            final List<RetentionLease> leases = new ArrayList<>(length);
            for (int i = 0; i < length; i++) {
                final String id = randomAlphaOfLength(8);
                final long retainingSequenceNumber = randomLongBetween(0, Math.max(0, globalCheckpoint.get()));
                final long timestamp = randomLongBetween(0L, Long.MAX_VALUE);
                final String source = randomAlphaOfLength(8);
                leases.add(new RetentionLease(id, retainingSequenceNumber, timestamp, source));
            }
            retentionLeasesHolder.set(new RetentionLeases(primaryTerm, retentionLeasesVersion.get(), leases));
        }
        if (rarely()) {
            settings.put(IndexSettings.INDEX_SOFT_DELETES_RETENTION_OPERATIONS_SETTING.getKey(), randomLongBetween(0, 10));
            indexSettings.updateIndexMetadata(IndexMetadata.builder(defaultSettings.getIndexMetadata()).settings(settings).build());
            engine.onSettingsChanged(indexSettings.getTranslogRetentionAge(), indexSettings.getTranslogRetentionSize(), indexSettings.getSoftDeleteRetentionOperations());
        }
        if (rarely()) {
            engine.refresh("test");
        }
        if (rarely()) {
            engine.flush(true, true);
            assertThat(Long.parseLong(engine.getLastCommittedSegmentInfos().userData.get(Engine.MIN_RETAINED_SEQNO)), equalTo(engine.getMinRetainedSeqNo()));
        }
        if (rarely()) {
            engine.forceMerge(randomBoolean(), 1, false, false, false, UUIDs.randomBase64UUID());
        }
        try (Closeable ignored = engine.acquireHistoryRetentionLock()) {
            long minRetainSeqNos = engine.getMinRetainedSeqNo();
            assertThat(minRetainSeqNos, lessThanOrEqualTo(globalCheckpoint.get() + 1));
            Long[] expectedOps = existingSeqNos.stream().filter(seqno -> seqno >= minRetainSeqNos).toArray(Long[]::new);
            Set<Long> actualOps = readAllOperationsInLucene(engine, createMapperService("test")).stream().map(Translog.Operation::seqNo).collect(Collectors.toSet());
            assertThat(actualOps, containsInAnyOrder(expectedOps));
        }
        try (Engine.IndexCommitRef commitRef = engine.acquireSafeIndexCommit()) {
            IndexCommit safeCommit = commitRef.getIndexCommit();
            if (safeCommit.getUserData().containsKey(Engine.MIN_RETAINED_SEQNO)) {
                lastMinRetainedSeqNo = Long.parseLong(safeCommit.getUserData().get(Engine.MIN_RETAINED_SEQNO));
            }
        }
    }
    if (randomBoolean()) {
        engine.close();
    } else {
        engine.flushAndClose();
    }
    try (InternalEngine recoveringEngine = new InternalEngine(engine.config())) {
        assertThat(recoveringEngine.getMinRetainedSeqNo(), equalTo(lastMinRetainedSeqNo));
    }
}
Also used : Term(org.apache.lucene.index.Term) AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) Version(org.opensearch.Version) PEER_RECOVERY(org.opensearch.index.engine.Engine.Operation.Origin.PEER_RECOVERY) MergePolicy(org.apache.lucene.index.MergePolicy) Map(java.util.Map) Mockito.doAnswer(org.mockito.Mockito.doAnswer) DefaultTranslogDeletionPolicy(org.opensearch.index.translog.DefaultTranslogDeletionPolicy) Path(java.nio.file.Path) TimeValue(org.opensearch.common.unit.TimeValue) Matchers.notNullValue(org.hamcrest.Matchers.notNullValue) SoftDeletesRetentionMergePolicy(org.apache.lucene.index.SoftDeletesRetentionMergePolicy) MatchAllDocsQuery(org.apache.lucene.search.MatchAllDocsQuery) PointValues(org.apache.lucene.index.PointValues) CountDownLatch(java.util.concurrent.CountDownLatch) Logger(org.apache.logging.log4j.Logger) Randomness(org.opensearch.common.Randomness) BytesArray(org.opensearch.common.bytes.BytesArray) DocIdAndSeqNo(org.opensearch.common.lucene.uid.VersionsAndSeqNoResolver.DocIdAndSeqNo) XContentType(org.opensearch.common.xcontent.XContentType) CodecService(org.opensearch.index.codec.CodecService) ThreadPool(org.opensearch.threadpool.ThreadPool) LogDocMergePolicy(org.apache.lucene.index.LogDocMergePolicy) FixedBitSet(org.apache.lucene.util.FixedBitSet) RegexFilter(org.apache.logging.log4j.core.filter.RegexFilter) Mockito.spy(org.mockito.Mockito.spy) Supplier(java.util.function.Supplier) LinkedHashMap(java.util.LinkedHashMap) ToLongBiFunction(java.util.function.ToLongBiFunction) IndexWriterMaxDocsChanger(org.apache.lucene.index.IndexWriterMaxDocsChanger) Lock(org.apache.lucene.store.Lock) Mapping(org.opensearch.index.mapper.Mapping) VersionFieldMapper(org.opensearch.index.mapper.VersionFieldMapper) Matchers.hasSize(org.hamcrest.Matchers.hasSize) Bits(org.apache.lucene.util.Bits) TieredMergePolicy(org.apache.lucene.index.TieredMergePolicy) Versions(org.opensearch.common.lucene.uid.Versions) Matchers.greaterThanOrEqualTo(org.hamcrest.Matchers.greaterThanOrEqualTo) TestTranslog(org.opensearch.index.translog.TestTranslog) IOException(java.io.IOException) BrokenBarrierException(java.util.concurrent.BrokenBarrierException) UNASSIGNED_PRIMARY_TERM(org.opensearch.index.seqno.SequenceNumbers.UNASSIGNED_PRIMARY_TERM) SourceFieldMapper(org.opensearch.index.mapper.SourceFieldMapper) AtomicLong(java.util.concurrent.atomic.AtomicLong) Phaser(java.util.concurrent.Phaser) TextField(org.apache.lucene.document.TextField) SeqNoFieldMapper(org.opensearch.index.mapper.SeqNoFieldMapper) Matchers.emptyArray(org.hamcrest.Matchers.emptyArray) AbstractRunnable(org.opensearch.common.util.concurrent.AbstractRunnable) BiFunction(java.util.function.BiFunction) StoredField(org.apache.lucene.document.StoredField) Matchers.hasKey(org.hamcrest.Matchers.hasKey) Matchers.everyItem(org.hamcrest.Matchers.everyItem) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Terms(org.apache.lucene.index.Terms) Matchers.lessThanOrEqualTo(org.hamcrest.Matchers.lessThanOrEqualTo) Store(org.opensearch.index.store.Store) Collectors(java.util.stream.Collectors) Matchers.containsInAnyOrder(org.hamcrest.Matchers.containsInAnyOrder) Matchers.equalTo(org.hamcrest.Matchers.equalTo) LeafReader(org.apache.lucene.index.LeafReader) IndexSettings(org.opensearch.index.IndexSettings) MetadataFieldMapper(org.opensearch.index.mapper.MetadataFieldMapper) ShardUtils(org.opensearch.index.shard.ShardUtils) Queue(java.util.Queue) BigArrays(org.opensearch.common.util.BigArrays) IndexReader(org.apache.lucene.index.IndexReader) IndexSearcher(org.apache.lucene.search.IndexSearcher) IndexSettingsModule(org.opensearch.test.IndexSettingsModule) BytesReference(org.opensearch.common.bytes.BytesReference) IndexMetadata(org.opensearch.cluster.metadata.IndexMetadata) CheckedBiConsumer(org.opensearch.common.CheckedBiConsumer) LOCAL_RESET(org.opensearch.index.engine.Engine.Operation.Origin.LOCAL_RESET) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Function(java.util.function.Function) HashSet(java.util.HashSet) Charset(java.nio.charset.Charset) Translog(org.opensearch.index.translog.Translog) PRIMARY(org.opensearch.index.engine.Engine.Operation.Origin.PRIMARY) IntSupplier(java.util.function.IntSupplier) RetentionLease(org.opensearch.index.seqno.RetentionLease) CoreMatchers.sameInstance(org.hamcrest.CoreMatchers.sameInstance) OpenSearchDirectoryReader(org.opensearch.common.lucene.index.OpenSearchDirectoryReader) Collections.emptyMap(java.util.Collections.emptyMap) Matchers.empty(org.hamcrest.Matchers.empty) Semaphore(java.util.concurrent.Semaphore) Mockito.when(org.mockito.Mockito.when) ShardRouting(org.opensearch.cluster.routing.ShardRouting) IOUtils(org.opensearch.core.internal.io.IOUtils) ShardId(org.opensearch.index.shard.ShardId) TestShardRouting(org.opensearch.cluster.routing.TestShardRouting) VersionsAndSeqNoResolver(org.opensearch.common.lucene.uid.VersionsAndSeqNoResolver) Field(org.apache.lucene.document.Field) TransportActions(org.opensearch.action.support.TransportActions) Comparator(java.util.Comparator) LogManager(org.apache.logging.log4j.LogManager) NoMergePolicy(org.apache.lucene.index.NoMergePolicy) SeqNoStats(org.opensearch.index.seqno.SeqNoStats) SequenceNumbers(org.opensearch.index.seqno.SequenceNumbers) Arrays(java.util.Arrays) LongSupplier(java.util.function.LongSupplier) Matchers.not(org.hamcrest.Matchers.not) Level(org.apache.logging.log4j.Level) ContentPath(org.opensearch.index.mapper.ContentPath) LogEvent(org.apache.logging.log4j.core.LogEvent) ReferenceManager(org.apache.lucene.search.ReferenceManager) Document(org.opensearch.index.mapper.ParseContext.Document) Strings(org.opensearch.common.Strings) CoreMatchers.instanceOf(org.hamcrest.CoreMatchers.instanceOf) RandomNumbers(com.carrotsearch.randomizedtesting.generators.RandomNumbers) REPLICA(org.opensearch.index.engine.Engine.Operation.Origin.REPLICA) TermsEnum(org.apache.lucene.index.TermsEnum) Matchers.nullValue(org.hamcrest.Matchers.nullValue) Lucene(org.opensearch.common.lucene.Lucene) ActionListener(org.opensearch.action.ActionListener) SequentialStoredFieldsLeafReader(org.opensearch.common.lucene.index.SequentialStoredFieldsLeafReader) FieldsVisitor(org.opensearch.index.fieldvisitor.FieldsVisitor) NumericDocValuesField(org.apache.lucene.document.NumericDocValuesField) NO_OPS_PERFORMED(org.opensearch.index.seqno.SequenceNumbers.NO_OPS_PERFORMED) Mockito.atLeastOnce(org.mockito.Mockito.atLeastOnce) Set(java.util.Set) SortedSetSortField(org.apache.lucene.search.SortedSetSortField) Settings(org.opensearch.common.settings.Settings) ReplicationTracker(org.opensearch.index.seqno.ReplicationTracker) BuilderContext(org.opensearch.index.mapper.Mapper.BuilderContext) UncheckedIOException(java.io.UncheckedIOException) VersionType(org.opensearch.index.VersionType) Matchers.contains(org.hamcrest.Matchers.contains) CheckedRunnable(org.opensearch.common.CheckedRunnable) LocalCheckpointTracker(org.opensearch.index.seqno.LocalCheckpointTracker) Matchers.greaterThan(org.hamcrest.Matchers.greaterThan) Matchers.is(org.hamcrest.Matchers.is) Matchers.containsString(org.hamcrest.Matchers.containsString) Matchers.in(org.hamcrest.Matchers.in) TriFunction(org.opensearch.common.TriFunction) IndexCommit(org.apache.lucene.index.IndexCommit) LiveIndexWriterConfig(org.apache.lucene.index.LiveIndexWriterConfig) TranslogDeletionPolicies.createTranslogDeletionPolicy(org.opensearch.index.translog.TranslogDeletionPolicies.createTranslogDeletionPolicy) ArrayList(java.util.ArrayList) UNASSIGNED_SEQ_NO(org.opensearch.index.seqno.SequenceNumbers.UNASSIGNED_SEQ_NO) VersionUtils(org.opensearch.test.VersionUtils) ShardRoutingState(org.opensearch.cluster.routing.ShardRoutingState) ParsedDocument(org.opensearch.index.mapper.ParsedDocument) TopDocs(org.apache.lucene.search.TopDocs) ParseContext(org.opensearch.index.mapper.ParseContext) LongStream(java.util.stream.LongStream) SetOnce(org.apache.lucene.util.SetOnce) Files(java.nio.file.Files) AbstractAppender(org.apache.logging.log4j.core.appender.AbstractAppender) Matchers.hasItem(org.hamcrest.Matchers.hasItem) RetentionLeases(org.opensearch.index.seqno.RetentionLeases) SnapshotMatchers(org.opensearch.index.translog.SnapshotMatchers) LOCAL_TRANSLOG_RECOVERY(org.opensearch.index.engine.Engine.Operation.Origin.LOCAL_TRANSLOG_RECOVERY) Collections.shuffle(java.util.Collections.shuffle) IdFieldMapper(org.opensearch.index.mapper.IdFieldMapper) IndexableField(org.apache.lucene.index.IndexableField) NoneCircuitBreakerService(org.opensearch.indices.breaker.NoneCircuitBreakerService) OpenSearchException(org.opensearch.OpenSearchException) ConcurrentCollections(org.opensearch.common.util.concurrent.ConcurrentCollections) ObjectObjectCursor(com.carrotsearch.hppc.cursors.ObjectObjectCursor) MapperService(org.opensearch.index.mapper.MapperService) Directory(org.apache.lucene.store.Directory) LeafReaderContext(org.apache.lucene.index.LeafReaderContext) TotalHitCountCollector(org.apache.lucene.search.TotalHitCountCollector) IndexShardRoutingTable(org.opensearch.cluster.routing.IndexShardRoutingTable) CyclicBarrier(java.util.concurrent.CyclicBarrier) Sort(org.apache.lucene.search.Sort) BytesRef(org.apache.lucene.util.BytesRef) DirectoryReader(org.apache.lucene.index.DirectoryReader) TranslogConfig(org.opensearch.index.translog.TranslogConfig) TranslogDeletionPolicyFactory(org.opensearch.index.translog.TranslogDeletionPolicyFactory) SegmentInfos(org.apache.lucene.index.SegmentInfos) Tuple(org.opensearch.common.collect.Tuple) IndexWriter(org.apache.lucene.index.IndexWriter) List(java.util.List) MatcherAssert(org.hamcrest.MatcherAssert) IndexWriterConfig(org.apache.lucene.index.IndexWriterConfig) MockDirectoryWrapper(org.apache.lucene.store.MockDirectoryWrapper) Uid(org.opensearch.index.mapper.Uid) LongPoint(org.apache.lucene.document.LongPoint) NumericDocValues(org.apache.lucene.index.NumericDocValues) ByteSizeValue(org.opensearch.common.unit.ByteSizeValue) HashMap(java.util.HashMap) ReleasableLock(org.opensearch.common.util.concurrent.ReleasableLock) AtomicReference(java.util.concurrent.atomic.AtomicReference) Loggers(org.opensearch.common.logging.Loggers) UUIDs(org.opensearch.common.UUIDs) Iterator(java.util.Iterator) Matchers(org.hamcrest.Matchers) RootObjectMapper(org.opensearch.index.mapper.RootObjectMapper) Mockito.verify(org.mockito.Mockito.verify) TimeUnit(java.util.concurrent.TimeUnit) TermQuery(org.apache.lucene.search.TermQuery) Closeable(java.io.Closeable) IndexRequest(org.opensearch.action.index.IndexRequest) Collections(java.util.Collections) IndexSettings(org.opensearch.index.IndexSettings) Closeable(java.io.Closeable) ArrayList(java.util.ArrayList) Matchers.containsString(org.hamcrest.Matchers.containsString) TestTranslog(org.opensearch.index.translog.TestTranslog) Translog(org.opensearch.index.translog.Translog) IndexMetadata(org.opensearch.cluster.metadata.IndexMetadata) IndexSettings(org.opensearch.index.IndexSettings) Settings(org.opensearch.common.settings.Settings) HashSet(java.util.HashSet) AtomicReference(java.util.concurrent.atomic.AtomicReference) LongPoint(org.apache.lucene.document.LongPoint) IndexCommit(org.apache.lucene.index.IndexCommit) RetentionLeases(org.opensearch.index.seqno.RetentionLeases) AtomicLong(java.util.concurrent.atomic.AtomicLong) RetentionLease(org.opensearch.index.seqno.RetentionLease) AtomicLong(java.util.concurrent.atomic.AtomicLong)

Aggregations

RetentionLeases (org.opensearch.index.seqno.RetentionLeases)31 ArrayList (java.util.ArrayList)16 IndexSettings (org.opensearch.index.IndexSettings)16 IndexMetadata (org.opensearch.cluster.metadata.IndexMetadata)14 AtomicLong (java.util.concurrent.atomic.AtomicLong)13 Settings (org.opensearch.common.settings.Settings)13 PlainActionFuture (org.opensearch.action.support.PlainActionFuture)12 RetentionLease (org.opensearch.index.seqno.RetentionLease)12 IndexShard (org.opensearch.index.shard.IndexShard)12 List (java.util.List)11 ActionListener (org.opensearch.action.ActionListener)11 IOException (java.io.IOException)10 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)10 Engine (org.opensearch.index.engine.Engine)10 CountDownLatch (java.util.concurrent.CountDownLatch)9 ShardRouting (org.opensearch.cluster.routing.ShardRouting)9 ReplicationTracker (org.opensearch.index.seqno.ReplicationTracker)8 Translog (org.opensearch.index.translog.Translog)8 Arrays (java.util.Arrays)7 Collections (java.util.Collections)7