Skip to content

Commit f04c579

Browse files
IndexShard should not return null stats (#31528)
IndexShard should not return null stats - empty stats or AlreadyCloseException if it's closed is better
1 parent 7313a98 commit f04c579

File tree

8 files changed

+148
-69
lines changed

8 files changed

+148
-69
lines changed

server/src/main/java/org/elasticsearch/action/admin/cluster/stats/TransportClusterStatsAction.java

+15-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.action.admin.cluster.stats;
2121

22+
import org.apache.lucene.store.AlreadyClosedException;
2223
import org.elasticsearch.action.FailedNodeException;
2324
import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
2425
import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
@@ -36,6 +37,8 @@
3637
import org.elasticsearch.common.io.stream.StreamOutput;
3738
import org.elasticsearch.common.settings.Settings;
3839
import org.elasticsearch.index.IndexService;
40+
import org.elasticsearch.index.engine.CommitStats;
41+
import org.elasticsearch.index.seqno.SeqNoStats;
3942
import org.elasticsearch.index.shard.IndexShard;
4043
import org.elasticsearch.indices.IndicesService;
4144
import org.elasticsearch.node.NodeService;
@@ -96,13 +99,23 @@ protected ClusterStatsNodeResponse nodeOperation(ClusterStatsNodeRequest nodeReq
9699
for (IndexShard indexShard : indexService) {
97100
if (indexShard.routingEntry() != null && indexShard.routingEntry().active()) {
98101
// only report on fully started shards
102+
CommitStats commitStats;
103+
SeqNoStats seqNoStats;
104+
try {
105+
commitStats = indexShard.commitStats();
106+
seqNoStats = indexShard.seqNoStats();
107+
} catch (AlreadyClosedException e) {
108+
// shard is closed - no stats is fine
109+
commitStats = null;
110+
seqNoStats = null;
111+
}
99112
shardsStats.add(
100113
new ShardStats(
101114
indexShard.routingEntry(),
102115
indexShard.shardPath(),
103116
new CommonStats(indicesService.getIndicesQueryCache(), indexShard, SHARD_STATS_FLAGS),
104-
indexShard.commitStats(),
105-
indexShard.seqNoStats()));
117+
commitStats,
118+
seqNoStats));
106119
}
107120
}
108121
}

server/src/main/java/org/elasticsearch/action/admin/indices/stats/CommonStats.java

+56-51
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.action.admin.indices.stats;
2121

22+
import org.apache.lucene.store.AlreadyClosedException;
2223
import org.elasticsearch.common.Nullable;
2324
import org.elasticsearch.common.io.stream.StreamInput;
2425
import org.elasticsearch.common.io.stream.StreamOutput;
@@ -167,57 +168,61 @@ public CommonStats(CommonStatsFlags flags) {
167168
public CommonStats(IndicesQueryCache indicesQueryCache, IndexShard indexShard, CommonStatsFlags flags) {
168169
CommonStatsFlags.Flag[] setFlags = flags.getFlags();
169170
for (CommonStatsFlags.Flag flag : setFlags) {
170-
switch (flag) {
171-
case Docs:
172-
docs = indexShard.docStats();
173-
break;
174-
case Store:
175-
store = indexShard.storeStats();
176-
break;
177-
case Indexing:
178-
indexing = indexShard.indexingStats(flags.types());
179-
break;
180-
case Get:
181-
get = indexShard.getStats();
182-
break;
183-
case Search:
184-
search = indexShard.searchStats(flags.groups());
185-
break;
186-
case Merge:
187-
merge = indexShard.mergeStats();
188-
break;
189-
case Refresh:
190-
refresh = indexShard.refreshStats();
191-
break;
192-
case Flush:
193-
flush = indexShard.flushStats();
194-
break;
195-
case Warmer:
196-
warmer = indexShard.warmerStats();
197-
break;
198-
case QueryCache:
199-
queryCache = indicesQueryCache.getStats(indexShard.shardId());
200-
break;
201-
case FieldData:
202-
fieldData = indexShard.fieldDataStats(flags.fieldDataFields());
203-
break;
204-
case Completion:
205-
completion = indexShard.completionStats(flags.completionDataFields());
206-
break;
207-
case Segments:
208-
segments = indexShard.segmentStats(flags.includeSegmentFileSizes());
209-
break;
210-
case Translog:
211-
translog = indexShard.translogStats();
212-
break;
213-
case RequestCache:
214-
requestCache = indexShard.requestCache().stats();
215-
break;
216-
case Recovery:
217-
recoveryStats = indexShard.recoveryStats();
218-
break;
219-
default:
220-
throw new IllegalStateException("Unknown Flag: " + flag);
171+
try {
172+
switch (flag) {
173+
case Docs:
174+
docs = indexShard.docStats();
175+
break;
176+
case Store:
177+
store = indexShard.storeStats();
178+
break;
179+
case Indexing:
180+
indexing = indexShard.indexingStats(flags.types());
181+
break;
182+
case Get:
183+
get = indexShard.getStats();
184+
break;
185+
case Search:
186+
search = indexShard.searchStats(flags.groups());
187+
break;
188+
case Merge:
189+
merge = indexShard.mergeStats();
190+
break;
191+
case Refresh:
192+
refresh = indexShard.refreshStats();
193+
break;
194+
case Flush:
195+
flush = indexShard.flushStats();
196+
break;
197+
case Warmer:
198+
warmer = indexShard.warmerStats();
199+
break;
200+
case QueryCache:
201+
queryCache = indicesQueryCache.getStats(indexShard.shardId());
202+
break;
203+
case FieldData:
204+
fieldData = indexShard.fieldDataStats(flags.fieldDataFields());
205+
break;
206+
case Completion:
207+
completion = indexShard.completionStats(flags.completionDataFields());
208+
break;
209+
case Segments:
210+
segments = indexShard.segmentStats(flags.includeSegmentFileSizes());
211+
break;
212+
case Translog:
213+
translog = indexShard.translogStats();
214+
break;
215+
case RequestCache:
216+
requestCache = indexShard.requestCache().stats();
217+
break;
218+
case Recovery:
219+
recoveryStats = indexShard.recoveryStats();
220+
break;
221+
default:
222+
throw new IllegalStateException("Unknown Flag: " + flag);
223+
}
224+
} catch (AlreadyClosedException e) {
225+
// shard is closed - no stats is fine
221226
}
222227
}
223228
}

server/src/main/java/org/elasticsearch/action/admin/indices/stats/ShardStats.java

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public CommonStats getStats() {
7070
return this.commonStats;
7171
}
7272

73+
@Nullable
7374
public CommitStats getCommitStats() {
7475
return this.commitStats;
7576
}

server/src/main/java/org/elasticsearch/action/admin/indices/stats/TransportIndicesStatsAction.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.action.admin.indices.stats;
2121

22+
import org.apache.lucene.store.AlreadyClosedException;
2223
import org.elasticsearch.action.support.ActionFilters;
2324
import org.elasticsearch.action.support.DefaultShardOperationFailedException;
2425
import org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction;
@@ -33,6 +34,8 @@
3334
import org.elasticsearch.common.io.stream.StreamInput;
3435
import org.elasticsearch.common.settings.Settings;
3536
import org.elasticsearch.index.IndexService;
37+
import org.elasticsearch.index.engine.CommitStats;
38+
import org.elasticsearch.index.seqno.SeqNoStats;
3639
import org.elasticsearch.index.shard.IndexShard;
3740
import org.elasticsearch.index.shard.ShardNotFoundException;
3841
import org.elasticsearch.indices.IndicesService;
@@ -100,7 +103,17 @@ protected ShardStats shardOperation(IndicesStatsRequest request, ShardRouting sh
100103
}
101104

102105
CommonStats commonStats = new CommonStats(indicesService.getIndicesQueryCache(), indexShard, request.flags());
106+
CommitStats commitStats;
107+
SeqNoStats seqNoStats;
108+
try {
109+
commitStats = indexShard.commitStats();
110+
seqNoStats = indexShard.seqNoStats();
111+
} catch (AlreadyClosedException e) {
112+
// shard is closed - no stats is fine
113+
commitStats = null;
114+
seqNoStats = null;
115+
}
103116
return new ShardStats(indexShard.routingEntry(), indexShard.shardPath(), commonStats,
104-
indexShard.commitStats(), indexShard.seqNoStats());
117+
commitStats, seqNoStats);
105118
}
106119
}

server/src/main/java/org/elasticsearch/index/shard/IndexShard.java

+6-10
Original file line numberDiff line numberDiff line change
@@ -868,21 +868,19 @@ public DocsStats docStats() {
868868
}
869869

870870
/**
871-
* @return {@link CommitStats} if engine is open, otherwise null
871+
* @return {@link CommitStats}
872+
* @throws AlreadyClosedException if shard is closed
872873
*/
873-
@Nullable
874874
public CommitStats commitStats() {
875-
Engine engine = getEngineOrNull();
876-
return engine == null ? null : engine.commitStats();
875+
return getEngine().commitStats();
877876
}
878877

879878
/**
880-
* @return {@link SeqNoStats} if engine is open, otherwise null
879+
* @return {@link SeqNoStats}
880+
* @throws AlreadyClosedException if shard is closed
881881
*/
882-
@Nullable
883882
public SeqNoStats seqNoStats() {
884-
Engine engine = getEngineOrNull();
885-
return engine == null ? null : engine.getSeqNoStats(replicationTracker.getGlobalCheckpoint());
883+
return getEngine().getSeqNoStats(replicationTracker.getGlobalCheckpoint());
886884
}
887885

888886
public IndexingStats indexingStats(String... types) {
@@ -912,8 +910,6 @@ public StoreStats storeStats() {
912910
return store.stats();
913911
} catch (IOException e) {
914912
throw new ElasticsearchException("io exception while building 'store stats'", e);
915-
} catch (AlreadyClosedException ex) {
916-
return null; // already closed
917913
}
918914
}
919915

server/src/main/java/org/elasticsearch/indices/IndicesService.java

+15-2
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
import org.elasticsearch.index.IndexSettings;
8080
import org.elasticsearch.index.analysis.AnalysisRegistry;
8181
import org.elasticsearch.index.cache.request.ShardRequestCache;
82+
import org.elasticsearch.index.engine.CommitStats;
8283
import org.elasticsearch.index.engine.EngineFactory;
8384
import org.elasticsearch.index.engine.InternalEngineFactory;
8485
import org.elasticsearch.index.fielddata.IndexFieldDataCache;
@@ -91,6 +92,7 @@
9192
import org.elasticsearch.index.recovery.RecoveryStats;
9293
import org.elasticsearch.index.refresh.RefreshStats;
9394
import org.elasticsearch.index.search.stats.SearchStats;
95+
import org.elasticsearch.index.seqno.SeqNoStats;
9496
import org.elasticsearch.index.shard.IllegalIndexShardStateException;
9597
import org.elasticsearch.index.shard.IndexEventListener;
9698
import org.elasticsearch.index.shard.IndexShard;
@@ -333,13 +335,24 @@ IndexShardStats indexShardStats(final IndicesService indicesService, final Index
333335
return null;
334336
}
335337

338+
CommitStats commitStats;
339+
SeqNoStats seqNoStats;
340+
try {
341+
commitStats = indexShard.commitStats();
342+
seqNoStats = indexShard.seqNoStats();
343+
} catch (AlreadyClosedException e) {
344+
// shard is closed - no stats is fine
345+
commitStats = null;
346+
seqNoStats = null;
347+
}
348+
336349
return new IndexShardStats(indexShard.shardId(),
337350
new ShardStats[] {
338351
new ShardStats(indexShard.routingEntry(),
339352
indexShard.shardPath(),
340353
new CommonStats(indicesService.getIndicesQueryCache(), indexShard, flags),
341-
indexShard.commitStats(),
342-
indexShard.seqNoStats())
354+
commitStats,
355+
seqNoStats)
343356
});
344357
}
345358

server/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java

+34
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import org.elasticsearch.env.NodeEnvironment;
7474
import org.elasticsearch.index.IndexSettings;
7575
import org.elasticsearch.index.VersionType;
76+
import org.elasticsearch.index.engine.CommitStats;
7677
import org.elasticsearch.index.engine.Engine;
7778
import org.elasticsearch.index.engine.EngineException;
7879
import org.elasticsearch.index.engine.EngineTestCase;
@@ -88,6 +89,7 @@
8889
import org.elasticsearch.index.mapper.MappedFieldType;
8990
import org.elasticsearch.index.mapper.SourceToParse;
9091
import org.elasticsearch.index.mapper.Uid;
92+
import org.elasticsearch.index.seqno.SeqNoStats;
9193
import org.elasticsearch.index.seqno.SequenceNumbers;
9294
import org.elasticsearch.index.snapshots.IndexShardSnapshotStatus;
9395
import org.elasticsearch.index.store.Store;
@@ -3082,4 +3084,36 @@ public void onShardInactive(IndexShard indexShard) {
30823084
closeShards(primary);
30833085
}
30843086

3087+
public void testOnCloseStats() throws IOException {
3088+
final IndexShard indexShard = newStartedShard(true);
3089+
3090+
for (int i = 0; i < 3; i++) {
3091+
indexDoc(indexShard, "_doc", "" + i, "{\"foo\" : \"" + randomAlphaOfLength(10) + "\"}");
3092+
indexShard.refresh("test"); // produce segments
3093+
}
3094+
3095+
// check stats on closed and on opened shard
3096+
if (randomBoolean()) {
3097+
closeShards(indexShard);
3098+
3099+
expectThrows(AlreadyClosedException.class, () -> indexShard.seqNoStats());
3100+
expectThrows(AlreadyClosedException.class, () -> indexShard.commitStats());
3101+
expectThrows(AlreadyClosedException.class, () -> indexShard.storeStats());
3102+
3103+
} else {
3104+
final SeqNoStats seqNoStats = indexShard.seqNoStats();
3105+
assertThat(seqNoStats.getLocalCheckpoint(), equalTo(2L));
3106+
3107+
final CommitStats commitStats = indexShard.commitStats();
3108+
assertThat(commitStats.getGeneration(), equalTo(2L));
3109+
3110+
final StoreStats storeStats = indexShard.storeStats();
3111+
3112+
assertThat(storeStats.sizeInBytes(), greaterThan(0L));
3113+
3114+
closeShards(indexShard);
3115+
}
3116+
3117+
}
3118+
30853119
}

test/framework/src/main/java/org/elasticsearch/test/InternalTestCluster.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -1111,17 +1111,21 @@ private void assertSameSyncIdSameDocs() {
11111111
IndicesService indexServices = getInstance(IndicesService.class, nodeAndClient.name);
11121112
for (IndexService indexService : indexServices) {
11131113
for (IndexShard indexShard : indexService) {
1114-
CommitStats commitStats = indexShard.commitStats();
1115-
if (commitStats != null) { // null if the engine is closed or if the shard is recovering
1114+
try {
1115+
CommitStats commitStats = indexShard.commitStats();
11161116
String syncId = commitStats.getUserData().get(Engine.SYNC_COMMIT_ID);
11171117
if (syncId != null) {
11181118
long liveDocsOnShard = commitStats.getNumDocs();
11191119
if (docsOnShards.get(syncId) != null) {
1120-
assertThat("sync id is equal but number of docs does not match on node " + nodeAndClient.name + ". expected " + docsOnShards.get(syncId) + " but got " + liveDocsOnShard, docsOnShards.get(syncId), equalTo(liveDocsOnShard));
1120+
assertThat("sync id is equal but number of docs does not match on node "
1121+
+ nodeAndClient.name + ". expected " + docsOnShards.get(syncId) + " but got "
1122+
+ liveDocsOnShard, docsOnShards.get(syncId), equalTo(liveDocsOnShard));
11211123
} else {
11221124
docsOnShards.put(syncId, liveDocsOnShard);
11231125
}
11241126
}
1127+
} catch (AlreadyClosedException e) {
1128+
// the engine is closed or if the shard is recovering
11251129
}
11261130
}
11271131
}

0 commit comments

Comments
 (0)