diff --git a/server/src/internalClusterTest/java/org/elasticsearch/snapshots/DedicatedClusterSnapshotRestoreIT.java b/server/src/internalClusterTest/java/org/elasticsearch/snapshots/DedicatedClusterSnapshotRestoreIT.java index 08868bbb330c4..9db06316e942c 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/snapshots/DedicatedClusterSnapshotRestoreIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/snapshots/DedicatedClusterSnapshotRestoreIT.java @@ -11,6 +11,9 @@ import com.carrotsearch.hppc.IntHashSet; import com.carrotsearch.hppc.IntSet; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.elasticsearch.action.ActionFuture; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest; @@ -33,6 +36,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.Priority; import org.elasticsearch.common.Strings; +import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.network.CloseableChannel; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.SettingsFilter; @@ -59,6 +63,7 @@ import org.elasticsearch.test.ESIntegTestCase.ClusterScope; import org.elasticsearch.test.ESIntegTestCase.Scope; import org.elasticsearch.test.InternalTestCluster; +import org.elasticsearch.test.MockLogAppender; import org.elasticsearch.test.disruption.BusyMasterServiceDisruption; import org.elasticsearch.test.disruption.ServiceDisruptionScheme; import org.elasticsearch.test.rest.FakeRestRequest; @@ -1305,6 +1310,38 @@ public void testConcurrentSnapshotAndRepoDelete() throws Exception { } } + public void testDeleteSnapshotsOfDifferentIndexSets() throws IllegalAccessException { + internalCluster().startMasterOnlyNodes(1); + internalCluster().startDataOnlyNode(); + final String repoName = "test-repo"; + createRepository(repoName, "fs"); + + final MockLogAppender mockAppender = new MockLogAppender(); + mockAppender.addExpectation( + new MockLogAppender.UnseenEventExpectation("no warnings", BlobStoreRepository.class.getCanonicalName(), Level.WARN, "*") + ); + mockAppender.start(); + final Logger logger = LogManager.getLogger(BlobStoreRepository.class); + Loggers.addAppender(logger, mockAppender); + try { + final String index1 = "index-1"; + final String index2 = "index-2"; + createIndexWithContent("index-1"); + createIndexWithContent("index-2"); + createFullSnapshot(repoName, "full-snapshot"); + final String snapshot1 = "index-1-snapshot"; + final String snapshot2 = "index-2-snapshot"; + createSnapshot(repoName, snapshot1, org.elasticsearch.core.List.of(index1)); + createSnapshot(repoName, snapshot2, org.elasticsearch.core.List.of(index2)); + + clusterAdmin().prepareDeleteSnapshot(repoName, snapshot1, snapshot2).get(); + mockAppender.assertAllExpectationsMatched(); + } finally { + Loggers.removeAppender(logger, mockAppender); + mockAppender.stop(); + } + } + private long calculateTotalFilesSize(List files) { return files.stream().mapToLong(f -> { try { diff --git a/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java b/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java index 5004171052d24..03260958106aa 100644 --- a/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java +++ b/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java @@ -1004,12 +1004,13 @@ private void writeUpdatedShardMetaDataAndComputeDeletes( ); for (IndexId indexId : indices) { - final Set survivingSnapshots = oldRepositoryData.getSnapshots(indexId) - .stream() + final Set snapshotsWithIndex = org.elasticsearch.core.Set.copyOf(oldRepositoryData.getSnapshots(indexId)); + final Set survivingSnapshots = snapshotsWithIndex.stream() .filter(id -> snapshotIds.contains(id) == false) .collect(Collectors.toSet()); final StepListener> shardCountListener = new StepListener<>(); final Collection indexMetaGenerations = snapshotIds.stream() + .filter(snapshotsWithIndex::contains) .map(id -> oldRepositoryData.indexMetaDataGenerations().indexMetaBlobId(id, indexId)) .collect(Collectors.toSet()); final ActionListener allShardCountsListener = new GroupedActionListener<>(