Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- [Java Agent] Allow JRT protocol URLs in protection domain extraction ([#19683](https://github.com/opensearch-project/OpenSearch/pull/19683))
- Fix potential concurrent modification exception when updating allocation filters ([#19701])(https://github.com/opensearch-project/OpenSearch/pull/19701))
- Fix file-based ingestion consumer to handle start point beyond max line number([#19757])(https://github.com/opensearch-project/OpenSearch/pull/19757))
- Fix NullPointerException when restoring remote snapshot with missing shard size information ([#19684](https://github.com/opensearch-project/OpenSearch/pull/19684))

### Dependencies
- Update to Gradle 9.1 ([#19575](https://github.com/opensearch-project/OpenSearch/pull/19575))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1054,4 +1054,61 @@ private void assertSearchableSnapshotIndexDirectoryExistence(String nodeName, In
assertTrue("index cache path should " + (exists ? "exist" : "not exist"), Files.exists(indexPath) == exists);
}, 30, TimeUnit.SECONDS);
}

public void testRestoreRemoteSnapshotWithNullShardSizes() throws Exception {
final String snapshotName1 = "test-snap-1";
final String snapshotName2 = "test-snap-2";
final String repoName = "test-repo";
final String indexName1 = "test-idx-1";
final String indexName2 = "test-idx-2";
final Client client = client();

// Setup cluster with delayed ClusterInfo updates to simulate null shard sizes
client.admin()
.cluster()
.prepareUpdateSettings()
.setPersistentSettings(Settings.builder().put("cluster.info.update.interval", "60m"))
.get();

internalCluster().ensureAtLeastNumDataNodes(2);

createIndexWithDocsAndEnsureGreen(0, 50, indexName1);
createRepositoryWithSettings(null, repoName);
takeSnapshot(client, snapshotName1, repoName, indexName1);
deleteIndicesAndEnsureGreen(client, indexName1);

createIndexWithDocsAndEnsureGreen(0, 50, indexName2);
takeSnapshot(client, snapshotName2, repoName, indexName2);
deleteIndicesAndEnsureGreen(client, indexName2);

internalCluster().ensureAtLeastNumWarmNodes(2);

RestoreSnapshotRequest firstRestore = new RestoreSnapshotRequest(repoName, snapshotName1).indices(indexName1)
.storageType(RestoreSnapshotRequest.StorageType.REMOTE_SNAPSHOT)
.renamePattern("(.+)")
.renameReplacement("remote-$1")
.waitForCompletion(true);

client.admin().cluster().restoreSnapshot(firstRestore).get();
ensureGreen("remote-" + indexName1);

// Second restore immediately after - ClusterInfo won't have size data for first restore shards
RestoreSnapshotRequest secondRestore = new RestoreSnapshotRequest(repoName, snapshotName2).indices(indexName2)
.storageType(RestoreSnapshotRequest.StorageType.REMOTE_SNAPSHOT)
.renamePattern("(.+)")
.renameReplacement("remote-$1")
.waitForCompletion(true);

client.admin().cluster().restoreSnapshot(secondRestore).get();
ensureGreen("remote-" + indexName2);

assertDocCount("remote-" + indexName1, 50L);
assertDocCount("remote-" + indexName2, 50L);

client.admin()
.cluster()
.prepareUpdateSettings()
.setPersistentSettings(Settings.builder().putNull("cluster.info.update.interval"))
.get();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -909,13 +909,29 @@ private void validateSearchableSnapshotRestorable(long totalRestorableRemoteInde
.routingTable()
.allShardsSatisfyingPredicate(isRemoteSnapshotShard);

long totalRestoredRemoteIndexesSize = shardsIterator.getShardRoutings()
.stream()
.map(clusterInfo::getShardSize)
.mapToLong(Long::longValue)
.sum();
long totalRestoredRemoteIndicesSize = 0;
int missingSizeCount = 0;
List<ShardRouting> routings = shardsIterator.getShardRoutings();

for (ShardRouting shardRouting : routings) {
Long shardSize = clusterInfo.getShardSize(shardRouting);
if (shardSize != null) {
totalRestoredRemoteIndicesSize += shardSize;
} else {
missingSizeCount++;
}
}

if (missingSizeCount > 0) {
logger.warn(
"Size information unavailable for {} out of {} remote snapshot shards. "
+ "File cache validation will use available data only.",
missingSizeCount,
routings.size()
);
}

if (totalRestoredRemoteIndexesSize + totalRestorableRemoteIndexesSize > remoteDataToFileCacheRatio
if (totalRestoredRemoteIndicesSize + totalRestorableRemoteIndexesSize > remoteDataToFileCacheRatio
* totalNodeFileCacheSize) {
throw new SnapshotRestoreException(
snapshot,
Expand Down
Loading