Skip to content

Commit 1c56866

Browse files
committed
Fix NPE in segment replicator
IndexStatsIT.testConcurrentIndexingAndStatsRequests sometimes fails with the following NPE: ``` IndexStatsIT > testConcurrentIndexingAndStatsRequests {p0={"cluster.indices.replication.strategy":"SEGMENT"}} FAILED java.lang.AssertionError: Expected: an empty collection but: <[[test][3] failed, reason [BroadcastShardOperationFailedException[operation indices:monitor/stats failed]; nested: NullPointerException[Cannot invoke "java.util.Map$Entry.getValue()" because "highestEntry" is null]; ]]> at __randomizedtesting.SeedInfo.seed([B56C9D0503BD16AE:2FDF6CC817B0190]:0) at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:18) at org.junit.Assert.assertThat(Assert.java:964) at org.junit.Assert.assertThat(Assert.java:930) at org.opensearch.indices.stats.IndexStatsIT.testConcurrentIndexingAndStatsRequests(IndexStatsIT.java:1451) ``` The `isEmpty()` check on the concurrent map is not sufficient because entries can be removed after the check but before retrieving them. Signed-off-by: Andrew Ross <andrross@amazon.com>
1 parent 5f3185c commit 1c56866

File tree

2 files changed

+6
-1
lines changed

2 files changed

+6
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
1010

1111
### Fixed
1212
- Fix unnecessary refreshes on update preparation failures ([#15261](https://github.com/opensearch-project/OpenSearch/issues/15261))
13+
- Fix possible NullPointerException in segment replicator ([]())
1314

1415
### Dependencies
1516

server/src/main/java/org/opensearch/indices/replication/SegmentReplicator.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,17 @@ void startMergedSegmentReplication(final MergedSegmentReplicationTarget target,
160160
*/
161161
public ReplicationStats getSegmentReplicationStats(final ShardId shardId) {
162162
final ConcurrentNavigableMap<Long, ReplicationCheckpointStats> existingCheckpointStats = replicationCheckpointStats.get(shardId);
163-
if (existingCheckpointStats == null || existingCheckpointStats.isEmpty()) {
163+
if (existingCheckpointStats == null) {
164164
return ReplicationStats.empty();
165165
}
166166

167167
Map.Entry<Long, ReplicationCheckpointStats> lowestEntry = existingCheckpointStats.firstEntry();
168168
Map.Entry<Long, ReplicationCheckpointStats> highestEntry = existingCheckpointStats.lastEntry();
169169

170+
if (lowestEntry == null || highestEntry == null) {
171+
return ReplicationStats.empty();
172+
}
173+
170174
long bytesBehind = highestEntry.getValue().getBytesBehind();
171175
long replicationLag = bytesBehind > 0L
172176
? Duration.ofNanos(DateUtils.toLong(Instant.now()) - lowestEntry.getValue().getTimestamp()).toMillis()

0 commit comments

Comments
 (0)