Skip to content

Commit 104b723

Browse files
committed
Convert most of the parsing logic over to object parsers.
1 parent c2a591d commit 104b723

File tree

7 files changed

+187
-229
lines changed

7 files changed

+187
-229
lines changed

server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/status/SnapshotIndexShardStatus.java

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@
2222
import org.elasticsearch.ElasticsearchParseException;
2323
import org.elasticsearch.action.support.broadcast.BroadcastShardResponse;
2424
import org.elasticsearch.cluster.metadata.IndexMetaData;
25+
import org.elasticsearch.common.ParseField;
2526
import org.elasticsearch.common.io.stream.StreamInput;
2627
import org.elasticsearch.common.io.stream.StreamOutput;
28+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
29+
import org.elasticsearch.common.xcontent.ObjectParser;
2730
import org.elasticsearch.common.xcontent.ToXContentFragment;
2831
import org.elasticsearch.common.xcontent.XContentBuilder;
2932
import org.elasticsearch.common.xcontent.XContentParser;
@@ -34,6 +37,9 @@
3437

3538
import java.io.IOException;
3639

40+
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
41+
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
42+
3743
public class SnapshotIndexShardStatus extends BroadcastShardResponse implements ToXContentFragment {
3844

3945
private SnapshotIndexShardStage stage = SnapshotIndexShardStage.INIT;
@@ -167,57 +173,50 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
167173
return builder;
168174
}
169175

170-
public static SnapshotIndexShardStatus fromXContent(XContentParser parser, String indexId) throws IOException {
171-
XContentParserUtils.ensureExpectedToken(XContentParser.Token.FIELD_NAME, parser.currentToken(), parser::getTokenLocation);
172-
String shardName = parser.currentName();
173-
int shard;
174-
try {
175-
shard = Integer.parseInt(shardName);
176-
} catch (NumberFormatException nfe) {
177-
throw new ElasticsearchParseException(
178-
"failed to parse snapshot index shard status [{}], expected numeric shard id but got [{}]", indexId, shardName);
179-
}
180-
ShardId shardId = new ShardId(new Index(indexId, IndexMetaData.INDEX_UUID_NA_VALUE), shard);
181-
XContentParser.Token token = parser.nextToken();
182-
XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser::getTokenLocation);
183-
SnapshotIndexShardStage stage = null;
184-
String nodeId = null;
185-
String failure = null;
186-
SnapshotStats stats = null;
187-
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
188-
if (token.equals(XContentParser.Token.FIELD_NAME)) {
189-
String currentName = parser.currentName();
190-
if (currentName.equals(Fields.STAGE)) {
191-
XContentParserUtils.ensureExpectedToken(XContentParser.Token.VALUE_STRING, parser.nextToken(),
192-
parser::getTokenLocation);
193-
try {
194-
stage = SnapshotIndexShardStage.valueOf(parser.text());
195-
} catch (IllegalArgumentException iae) {
196-
throw new ElasticsearchParseException(
197-
"failed to parse snapshot index shard status [{}][{}], unknonwn stage [{}]", indexId, shardId.getId(),
198-
parser.text());
199-
}
200-
} else if (currentName.equals(Fields.NODE)) {
201-
XContentParserUtils.ensureExpectedToken(XContentParser.Token.VALUE_STRING, parser.nextToken(),
202-
parser::getTokenLocation);
203-
nodeId = parser.text();
204-
} else if (currentName.equals(Fields.REASON)) {
205-
XContentParserUtils.ensureExpectedToken(XContentParser.Token.VALUE_STRING, parser.nextToken(),
206-
parser::getTokenLocation);
207-
failure = parser.text();
208-
} else if (currentName.equals(SnapshotStats.Fields.STATS)) {
209-
stats = SnapshotStats.fromXContent(parser);
210-
} else {
176+
static final ObjectParser.NamedObjectParser<SnapshotIndexShardStatus, String> PARSER;
177+
static {
178+
ConstructingObjectParser<SnapshotIndexShardStatus, ShardId> innerParser = new ConstructingObjectParser<>(
179+
"snapshot_index_shard_status", false,
180+
(Object[] parsedObjects, ShardId shard) -> {
181+
int i = 0;
182+
String rawStage = (String) parsedObjects[i++];
183+
String nodeId = (String) parsedObjects[i++];
184+
String failure = (String) parsedObjects[i++];
185+
SnapshotStats stats = (SnapshotStats) parsedObjects[i];
186+
187+
SnapshotIndexShardStage stage;
188+
try {
189+
stage = SnapshotIndexShardStage.valueOf(rawStage);
190+
} catch (IllegalArgumentException iae) {
211191
throw new ElasticsearchParseException(
212-
"failed to parse snapshot index shard status [{}][{}], unknown field [{}]", indexId, shardId.getId(),
213-
currentName);
192+
"failed to parse snapshot index shard status [{}][{}], unknonwn stage [{}]",
193+
shard.getIndex().getName(), shard.getId(), rawStage);
214194
}
215-
} else {
195+
return new SnapshotIndexShardStatus(shard, stage, stats, nodeId, failure);
196+
}
197+
);
198+
innerParser.declareString(constructorArg(), new ParseField(Fields.STAGE));
199+
innerParser.declareString(optionalConstructorArg(), new ParseField(Fields.NODE));
200+
innerParser.declareString(optionalConstructorArg(), new ParseField(Fields.REASON));
201+
innerParser.declareObject(constructorArg(), (p, c) -> SnapshotStats.fromXContent(p), new ParseField(SnapshotStats.Fields.STATS));
202+
PARSER = (p, indexId, shardName) -> {
203+
// Combine the index name in the context with the shard name passed in for the named object parser
204+
// into a ShardId to pass as context for the inner parser.
205+
int shard;
206+
try {
207+
shard = Integer.parseInt(shardName);
208+
} catch (NumberFormatException nfe) {
216209
throw new ElasticsearchParseException(
217-
"failed to parse snapshot index shard status [{}][{}]", indexId, shardId.getId());
210+
"failed to parse snapshot index shard status [{}], expected numeric shard id but got [{}]", indexId, shardName);
218211
}
219-
}
220-
return new SnapshotIndexShardStatus(shardId, stage, stats, nodeId, failure);
212+
ShardId shardId = new ShardId(new Index(indexId, IndexMetaData.INDEX_UUID_NA_VALUE), shard);
213+
return innerParser.parse(p, shardId);
214+
};
215+
}
216+
217+
public static SnapshotIndexShardStatus fromXContent(XContentParser parser, String indexId) throws IOException {
218+
XContentParserUtils.ensureExpectedToken(XContentParser.Token.FIELD_NAME, parser.currentToken(), parser::getTokenLocation);
219+
return PARSER.parse(parser, indexId, parser.currentName());
221220
}
222221

223222
@Override

server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/status/SnapshotIndexStatus.java

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919

2020
package org.elasticsearch.action.admin.cluster.snapshots.status;
2121

22-
import org.elasticsearch.ElasticsearchParseException;
22+
import org.elasticsearch.common.ParseField;
23+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
24+
import org.elasticsearch.common.xcontent.ObjectParser;
2325
import org.elasticsearch.common.xcontent.ToXContentFragment;
2426
import org.elasticsearch.common.xcontent.XContentBuilder;
2527
import org.elasticsearch.common.xcontent.XContentParser;
@@ -29,9 +31,12 @@
2931
import java.util.Collection;
3032
import java.util.HashMap;
3133
import java.util.Iterator;
34+
import java.util.List;
3235
import java.util.Map;
3336

37+
import static java.util.Collections.emptyMap;
3438
import static java.util.Collections.unmodifiableMap;
39+
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
3540

3641
/**
3742
* Represents snapshot status of all shards in the index
@@ -118,37 +123,38 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
118123
return builder;
119124
}
120125

121-
public static SnapshotIndexStatus fromXContent(XContentParser parser) throws IOException {
122-
XContentParserUtils.ensureExpectedToken(XContentParser.Token.FIELD_NAME, parser.currentToken(), parser::getTokenLocation);
123-
String indexName = parser.currentName();
124-
XContentParser.Token token = parser.nextToken();
125-
XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser::getTokenLocation);
126-
SnapshotShardsStats shardsStats = null;
127-
SnapshotStats stats = null;
128-
Map<Integer, SnapshotIndexShardStatus> shards = new HashMap<>();
129-
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
130-
if (token.equals(XContentParser.Token.FIELD_NAME)) {
131-
String currentName = parser.currentName();
132-
if (currentName.equals(SnapshotShardsStats.Fields.SHARDS_STATS)) {
133-
shardsStats = SnapshotShardsStats.fromXContent(parser);
134-
} else if (currentName.equals(SnapshotStats.Fields.STATS)) {
135-
stats = SnapshotStats.fromXContent(parser);
136-
} else if (currentName.equals(Fields.SHARDS)) {
137-
XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(),
138-
parser::getTokenLocation);
139-
while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
140-
SnapshotIndexShardStatus shardStatus = SnapshotIndexShardStatus.fromXContent(parser, indexName);
141-
shards.put(shardStatus.getShardId().getId(), shardStatus);
142-
}
126+
static final ObjectParser.NamedObjectParser<SnapshotIndexStatus, Void> PARSER;
127+
static {
128+
ConstructingObjectParser<SnapshotIndexStatus, String> innerParser = new ConstructingObjectParser<>(
129+
"snapshot_index_status", false,
130+
(Object[] parsedObjects, String index) -> {
131+
int i = 0;
132+
SnapshotShardsStats shardsStats = ((SnapshotShardsStats) parsedObjects[i++]);
133+
SnapshotStats stats = ((SnapshotStats) parsedObjects[i++]);
134+
@SuppressWarnings("unchecked") List<SnapshotIndexShardStatus> shardStatuses = (List<SnapshotIndexShardStatus>) parsedObjects[i];
135+
136+
final Map<Integer, SnapshotIndexShardStatus> indexShards;
137+
if (shardStatuses == null || shardStatuses.isEmpty()) {
138+
indexShards = emptyMap();
143139
} else {
144-
throw new ElasticsearchParseException("failed to parse snapshot index status [{}], unknown field [{}]", indexName,
145-
currentName);
140+
indexShards = new HashMap<>(shardStatuses.size());
141+
for (SnapshotIndexShardStatus shardStatus : shardStatuses) {
142+
indexShards.put(shardStatus.getShardId().getId(), shardStatus);
143+
}
146144
}
147-
} else {
148-
throw new ElasticsearchParseException("failed to parse snapshot index status [{}]", indexName);
149-
}
150-
}
151-
return new SnapshotIndexStatus(indexName, shards, shardsStats, stats);
145+
return new SnapshotIndexStatus(index, indexShards, shardsStats, stats);
146+
});
147+
innerParser.declareObject(constructorArg(), (p, c) -> SnapshotShardsStats.PARSER.apply(p, null),
148+
new ParseField(SnapshotShardsStats.Fields.SHARDS_STATS));
149+
innerParser.declareObject(constructorArg(), (p, c) -> SnapshotStats.fromXContent(p),
150+
new ParseField(SnapshotStats.Fields.STATS));
151+
innerParser.declareNamedObjects(constructorArg(), SnapshotIndexShardStatus.PARSER, new ParseField(Fields.SHARDS));
152+
PARSER = ((p, c, name) -> innerParser.apply(p, name));
153+
}
154+
155+
public static SnapshotIndexStatus fromXContent(XContentParser parser) throws IOException {
156+
XContentParserUtils.ensureExpectedToken(XContentParser.Token.FIELD_NAME, parser.currentToken(), parser::getTokenLocation);
157+
return PARSER.parse(parser, null, parser.currentName());
152158
}
153159

154160
@Override

server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/status/SnapshotShardsStats.java

Lines changed: 27 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,18 @@
1919

2020
package org.elasticsearch.action.admin.cluster.snapshots.status;
2121

22-
import org.elasticsearch.ElasticsearchParseException;
22+
import org.elasticsearch.common.ParseField;
23+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
2324
import org.elasticsearch.common.xcontent.ToXContent;
2425
import org.elasticsearch.common.xcontent.ToXContentFragment;
2526
import org.elasticsearch.common.xcontent.XContentBuilder;
2627
import org.elasticsearch.common.xcontent.XContentParser;
27-
import org.elasticsearch.common.xcontent.XContentParserUtils;
2828

2929
import java.io.IOException;
3030
import java.util.Collection;
3131

32+
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
33+
3234
/**
3335
* Status of a snapshot shards
3436
*/
@@ -141,62 +143,30 @@ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params par
141143
return builder;
142144
}
143145

144-
public static SnapshotShardsStats fromXContent(XContentParser parser) throws IOException {
145-
XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
146-
XContentParser.Token token;
147-
int initializingShards = 0;
148-
int startedShards = 0;
149-
int finalizingShards = 0;
150-
int doneShards = 0;
151-
int failedShards = 0;
152-
int totalShards = 0;
153-
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
154-
if (token == XContentParser.Token.FIELD_NAME) {
155-
String currentName = parser.currentName();
156-
if (currentName.equals(Fields.INITIALIZING)) {
157-
if (parser.nextToken() != XContentParser.Token.VALUE_NUMBER) {
158-
throw new ElasticsearchParseException("failed to parse snapshot shards stats, expected number for field [{}]",
159-
currentName);
160-
}
161-
initializingShards = parser.intValue();
162-
} else if (currentName.equals(Fields.STARTED)) {
163-
if (parser.nextToken() != XContentParser.Token.VALUE_NUMBER) {
164-
throw new ElasticsearchParseException("failed to parse snapshot shards stats, expected number for field [{}]",
165-
currentName);
166-
}
167-
startedShards = parser.intValue();
168-
} else if (currentName.equals(Fields.FINALIZING)) {
169-
if (parser.nextToken() != XContentParser.Token.VALUE_NUMBER) {
170-
throw new ElasticsearchParseException("failed to parse snapshot shards stats, expected number for field [{}]",
171-
currentName);
172-
}
173-
finalizingShards = parser.intValue();
174-
} else if (currentName.equals(Fields.DONE)) {
175-
if (parser.nextToken() != XContentParser.Token.VALUE_NUMBER) {
176-
throw new ElasticsearchParseException("failed to parse snapshot shards stats, expected number for field [{}]",
177-
currentName);
178-
}
179-
doneShards = parser.intValue();
180-
} else if (currentName.equals(Fields.FAILED)) {
181-
if (parser.nextToken() != XContentParser.Token.VALUE_NUMBER) {
182-
throw new ElasticsearchParseException("failed to parse snapshot shards stats, expected number for field [{}]",
183-
currentName);
184-
}
185-
failedShards = parser.intValue();
186-
} else if (currentName.equals(Fields.TOTAL)) {
187-
if (parser.nextToken() != XContentParser.Token.VALUE_NUMBER) {
188-
throw new ElasticsearchParseException("failed to parse snapshot shards stats, expected number for field [{}]",
189-
currentName);
190-
}
191-
totalShards = parser.intValue();
192-
} else {
193-
throw new ElasticsearchParseException("failed to parse snapshot shards stats, unexpected field [{}]", currentName);
194-
}
195-
} else {
196-
throw new ElasticsearchParseException("failed to parse snapshot shards stats");
197-
}
146+
static final ConstructingObjectParser<SnapshotShardsStats, Void> PARSER = new ConstructingObjectParser<>(
147+
Fields.SHARDS_STATS,
148+
(Object[] parsedObjects) -> {
149+
int i = 0;
150+
int initializingShards = (int) parsedObjects[i++];
151+
int startedShards = (int) parsedObjects[i++];
152+
int finalizingShards = (int) parsedObjects[i++];
153+
int doneShards = (int) parsedObjects[i++];
154+
int failedShards = (int) parsedObjects[i++];
155+
int totalShards = (int) parsedObjects[i];
156+
return new SnapshotShardsStats(initializingShards, startedShards, finalizingShards, doneShards, failedShards, totalShards);
198157
}
199-
return new SnapshotShardsStats(initializingShards, startedShards, finalizingShards, doneShards, failedShards, totalShards);
158+
);
159+
static {
160+
PARSER.declareInt(constructorArg(), new ParseField(Fields.INITIALIZING));
161+
PARSER.declareInt(constructorArg(), new ParseField(Fields.STARTED));
162+
PARSER.declareInt(constructorArg(), new ParseField(Fields.FINALIZING));
163+
PARSER.declareInt(constructorArg(), new ParseField(Fields.DONE));
164+
PARSER.declareInt(constructorArg(), new ParseField(Fields.FAILED));
165+
PARSER.declareInt(constructorArg(), new ParseField(Fields.TOTAL));
166+
}
167+
168+
public static SnapshotShardsStats fromXContent(XContentParser parser) throws IOException {
169+
return PARSER.apply(parser, null);
200170
}
201171

202172
@Override

server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/status/SnapshotStats.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,13 @@ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params par
209209
}
210210

211211
public static SnapshotStats fromXContent(XContentParser parser) throws IOException {
212-
XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
213-
XContentParser.Token token;
212+
// Parse this old school style instead of using the ObjectParser since there's an impedance mismatch between how the
213+
// object has historically been written as JSON versus how it is structured in Java.
214+
XContentParser.Token token = parser.currentToken();
215+
if (token == null) {
216+
token = parser.nextToken();
217+
}
218+
XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser::getTokenLocation);
214219
long startTime = 0;
215220
long time = 0;
216221
int incrementalFileCount = 0;

0 commit comments

Comments
 (0)