Skip to content

Commit 0f2c03e

Browse files
authored
Fix serialization bug in SearchableSnapshotsStatsResponse (#54864)
SearchableSnapshotsStatsResponse is missing the serialization of the list of SearchableSnapshotShardStats
1 parent 87ea3f3 commit 0f2c03e

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed

x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/action/SearchableSnapshotsStatsResponse.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.elasticsearch.action.support.broadcast.BroadcastResponse;
1010
import org.elasticsearch.cluster.routing.ShardRouting;
1111
import org.elasticsearch.common.io.stream.StreamInput;
12+
import org.elasticsearch.common.io.stream.StreamOutput;
1213
import org.elasticsearch.common.xcontent.XContentBuilder;
1314
import org.elasticsearch.index.Index;
1415
import org.elasticsearch.xpack.core.searchablesnapshots.SearchableSnapshotShardStats;
@@ -45,6 +46,12 @@ public List<SearchableSnapshotShardStats> getStats() {
4546
return stats;
4647
}
4748

49+
@Override
50+
public void writeTo(StreamOutput out) throws IOException {
51+
super.writeTo(out);
52+
out.writeList(stats);
53+
}
54+
4855
@Override
4956
protected void addCustomXContentFields(XContentBuilder builder, Params params) throws IOException {
5057
final List<Index> indices = getStats().stream()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.searchablesnapshots.action;
8+
9+
import org.elasticsearch.Version;
10+
import org.elasticsearch.action.support.DefaultShardOperationFailedException;
11+
import org.elasticsearch.cluster.routing.ShardRouting;
12+
import org.elasticsearch.cluster.routing.ShardRoutingState;
13+
import org.elasticsearch.repositories.IndexId;
14+
import org.elasticsearch.snapshots.SnapshotId;
15+
import org.elasticsearch.test.ESTestCase;
16+
import org.elasticsearch.xpack.core.searchablesnapshots.SearchableSnapshotShardStats;
17+
18+
import java.io.IOException;
19+
import java.util.ArrayList;
20+
import java.util.List;
21+
22+
import static org.elasticsearch.cluster.routing.TestShardRouting.newShardRouting;
23+
import static org.hamcrest.CoreMatchers.equalTo;
24+
25+
public class SearchableSnapshotsStatsResponseTests extends ESTestCase {
26+
27+
public void testSerialization() throws IOException {
28+
for (int i = 0; i < randomIntBetween(10, 50); i++) {
29+
final SearchableSnapshotsStatsResponse testInstance = createTestInstance();
30+
final SearchableSnapshotsStatsResponse deserializedInstance = copyWriteable(
31+
testInstance,
32+
writableRegistry(),
33+
SearchableSnapshotsStatsResponse::new,
34+
Version.CURRENT
35+
);
36+
assertEqualInstances(testInstance, deserializedInstance);
37+
}
38+
}
39+
40+
private void assertEqualInstances(SearchableSnapshotsStatsResponse expected, SearchableSnapshotsStatsResponse actual) {
41+
assertThat(actual.getTotalShards(), equalTo(expected.getTotalShards()));
42+
assertThat(actual.getSuccessfulShards(), equalTo(expected.getSuccessfulShards()));
43+
assertThat(actual.getFailedShards(), equalTo(expected.getFailedShards()));
44+
DefaultShardOperationFailedException[] originalFailures = expected.getShardFailures();
45+
DefaultShardOperationFailedException[] parsedFailures = actual.getShardFailures();
46+
assertThat(originalFailures.length, equalTo(parsedFailures.length));
47+
for (int i = 0; i < originalFailures.length; i++) {
48+
assertThat(originalFailures[i].index(), equalTo(parsedFailures[i].index()));
49+
assertThat(originalFailures[i].shardId(), equalTo(parsedFailures[i].shardId()));
50+
assertThat(originalFailures[i].status(), equalTo(parsedFailures[i].status()));
51+
}
52+
assertThat(actual.getStats(), equalTo(expected.getStats()));
53+
}
54+
55+
private SearchableSnapshotsStatsResponse createTestInstance() {
56+
final int totalShards = randomIntBetween(0, 20);
57+
final int successfulShards = totalShards > 0 ? randomIntBetween(0, totalShards) : 0;
58+
final int failedShards = totalShards - successfulShards;
59+
60+
final String indexName = randomAlphaOfLength(10);
61+
final int replicas = randomIntBetween(0, 2);
62+
final SnapshotId snapshotId = new SnapshotId(randomAlphaOfLength(5), randomAlphaOfLength(5));
63+
final IndexId indexId = new IndexId(randomAlphaOfLength(5), randomAlphaOfLength(5));
64+
65+
final List<SearchableSnapshotShardStats> shardStats = new ArrayList<>();
66+
final List<DefaultShardOperationFailedException> shardFailures = new ArrayList<>();
67+
68+
for (int i = 0; i < totalShards; i++) {
69+
if (i < successfulShards) {
70+
shardStats.add(createSearchableSnapshotShardStats(indexName, i, true, snapshotId, indexId));
71+
for (int j = 0; j < replicas; j++) {
72+
shardStats.add(createSearchableSnapshotShardStats(indexName, i, false, snapshotId, indexId));
73+
}
74+
} else {
75+
shardFailures.add(new DefaultShardOperationFailedException(indexName, i, new Exception()));
76+
}
77+
}
78+
79+
return new SearchableSnapshotsStatsResponse(shardStats, totalShards, successfulShards, failedShards, shardFailures);
80+
}
81+
82+
private static SearchableSnapshotShardStats createSearchableSnapshotShardStats(
83+
String index,
84+
int shardId,
85+
boolean primary,
86+
SnapshotId snapshotId,
87+
IndexId indexId
88+
) {
89+
final ShardRouting shardRouting = newShardRouting(index, shardId, randomAlphaOfLength(5), primary, ShardRoutingState.STARTED);
90+
final List<SearchableSnapshotShardStats.CacheIndexInputStats> inputStats = new ArrayList<>();
91+
for (int j = 0; j < randomInt(10); j++) {
92+
inputStats.add(randomCacheIndexInputStats());
93+
}
94+
return new SearchableSnapshotShardStats(shardRouting, snapshotId, indexId, inputStats);
95+
}
96+
97+
private static SearchableSnapshotShardStats.CacheIndexInputStats randomCacheIndexInputStats() {
98+
return new SearchableSnapshotShardStats.CacheIndexInputStats(
99+
randomAlphaOfLength(10),
100+
randomNonNegativeLong(),
101+
randomNonNegativeLong(),
102+
randomNonNegativeLong(),
103+
randomCounter(),
104+
randomCounter(),
105+
randomCounter(),
106+
randomCounter(),
107+
randomCounter(),
108+
randomCounter(),
109+
randomCounter(),
110+
randomTimedCounter(),
111+
randomTimedCounter(),
112+
randomTimedCounter()
113+
);
114+
}
115+
116+
private static SearchableSnapshotShardStats.Counter randomCounter() {
117+
return new SearchableSnapshotShardStats.Counter(randomLong(), randomLong(), randomLong(), randomLong());
118+
}
119+
120+
private static SearchableSnapshotShardStats.TimedCounter randomTimedCounter() {
121+
return new SearchableSnapshotShardStats.TimedCounter(randomLong(), randomLong(), randomLong(), randomLong(), randomLong());
122+
}
123+
}

0 commit comments

Comments
 (0)