99
1010package org .elasticsearch .action .admin .cluster .snapshots .status ;
1111
12+ import org .elasticsearch .common .xcontent .XContentParserUtils ;
1213import org .elasticsearch .test .AbstractXContentTestCase ;
1314import org .elasticsearch .xcontent .XContentParser ;
1415
@@ -27,6 +28,14 @@ protected SnapshotStats createTestInstance() {
2728 long incrementalSize = ((long ) randomIntBetween (0 , Integer .MAX_VALUE )) * 2 ;
2829 long totalSize = ((long ) randomIntBetween (0 , Integer .MAX_VALUE )) * 2 ;
2930 long processedSize = ((long ) randomIntBetween (0 , Integer .MAX_VALUE )) * 2 ;
31+
32+ // toXContent() omits the "processed" sub-object if processedFileCount == incrementalFileCount, so here we increase the probability
33+ // of that scenario so we can make sure the processed values are set as expected in fromXContent().
34+ if (randomBoolean ()) {
35+ processedFileCount = incrementalFileCount ;
36+ processedSize = incrementalSize ;
37+ }
38+
3039 return new SnapshotStats (
3140 startTime ,
3241 time ,
@@ -41,11 +50,119 @@ protected SnapshotStats createTestInstance() {
4150
4251 @ Override
4352 protected SnapshotStats doParseInstance (XContentParser parser ) throws IOException {
44- return SnapshotStats . fromXContent (parser );
53+ return fromXContent (parser );
4554 }
4655
4756 @ Override
4857 protected boolean supportsUnknownFields () {
4958 return true ;
5059 }
60+
61+ static SnapshotStats fromXContent (XContentParser parser ) throws IOException {
62+ // Parse this old school style instead of using the ObjectParser since there's an impedance mismatch between how the
63+ // object has historically been written as JSON versus how it is structured in Java.
64+ XContentParser .Token token = parser .currentToken ();
65+ if (token == null ) {
66+ token = parser .nextToken ();
67+ }
68+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .START_OBJECT , token , parser );
69+ long startTime = 0 ;
70+ long time = 0 ;
71+ int incrementalFileCount = 0 ;
72+ int totalFileCount = 0 ;
73+ int processedFileCount = Integer .MIN_VALUE ;
74+ long incrementalSize = 0 ;
75+ long totalSize = 0 ;
76+ long processedSize = Long .MIN_VALUE ;
77+ while ((token = parser .nextToken ()) != XContentParser .Token .END_OBJECT ) {
78+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .FIELD_NAME , token , parser );
79+ String currentName = parser .currentName ();
80+ token = parser .nextToken ();
81+ if (currentName .equals (SnapshotStats .Fields .INCREMENTAL )) {
82+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .START_OBJECT , token , parser );
83+ while ((token = parser .nextToken ()) != XContentParser .Token .END_OBJECT ) {
84+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .FIELD_NAME , token , parser );
85+ String innerName = parser .currentName ();
86+ token = parser .nextToken ();
87+ if (innerName .equals (SnapshotStats .Fields .FILE_COUNT )) {
88+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .VALUE_NUMBER , token , parser );
89+ incrementalFileCount = parser .intValue ();
90+ } else if (innerName .equals (SnapshotStats .Fields .SIZE_IN_BYTES )) {
91+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .VALUE_NUMBER , token , parser );
92+ incrementalSize = parser .longValue ();
93+ } else {
94+ // Unknown sub field, skip
95+ if (token == XContentParser .Token .START_OBJECT || token == XContentParser .Token .START_ARRAY ) {
96+ parser .skipChildren ();
97+ }
98+ }
99+ }
100+ } else if (currentName .equals (SnapshotStats .Fields .PROCESSED )) {
101+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .START_OBJECT , token , parser );
102+ while ((token = parser .nextToken ()) != XContentParser .Token .END_OBJECT ) {
103+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .FIELD_NAME , token , parser );
104+ String innerName = parser .currentName ();
105+ token = parser .nextToken ();
106+ if (innerName .equals (SnapshotStats .Fields .FILE_COUNT )) {
107+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .VALUE_NUMBER , token , parser );
108+ processedFileCount = parser .intValue ();
109+ } else if (innerName .equals (SnapshotStats .Fields .SIZE_IN_BYTES )) {
110+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .VALUE_NUMBER , token , parser );
111+ processedSize = parser .longValue ();
112+ } else {
113+ // Unknown sub field, skip
114+ if (token == XContentParser .Token .START_OBJECT || token == XContentParser .Token .START_ARRAY ) {
115+ parser .skipChildren ();
116+ }
117+ }
118+ }
119+ } else if (currentName .equals (SnapshotStats .Fields .TOTAL )) {
120+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .START_OBJECT , token , parser );
121+ while ((token = parser .nextToken ()) != XContentParser .Token .END_OBJECT ) {
122+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .FIELD_NAME , token , parser );
123+ String innerName = parser .currentName ();
124+ token = parser .nextToken ();
125+ if (innerName .equals (SnapshotStats .Fields .FILE_COUNT )) {
126+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .VALUE_NUMBER , token , parser );
127+ totalFileCount = parser .intValue ();
128+ } else if (innerName .equals (SnapshotStats .Fields .SIZE_IN_BYTES )) {
129+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .VALUE_NUMBER , token , parser );
130+ totalSize = parser .longValue ();
131+ } else {
132+ // Unknown sub field, skip
133+ if (token == XContentParser .Token .START_OBJECT || token == XContentParser .Token .START_ARRAY ) {
134+ parser .skipChildren ();
135+ }
136+ }
137+ }
138+ } else if (currentName .equals (SnapshotStats .Fields .START_TIME_IN_MILLIS )) {
139+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .VALUE_NUMBER , token , parser );
140+ startTime = parser .longValue ();
141+ } else if (currentName .equals (SnapshotStats .Fields .TIME_IN_MILLIS )) {
142+ XContentParserUtils .ensureExpectedToken (XContentParser .Token .VALUE_NUMBER , token , parser );
143+ time = parser .longValue ();
144+ } else {
145+ // Unknown field, skip
146+ if (token == XContentParser .Token .START_OBJECT || token == XContentParser .Token .START_ARRAY ) {
147+ parser .skipChildren ();
148+ }
149+ }
150+ }
151+ // Handle the case where the "processed" sub-object is omitted in toXContent() when processedFileCount == incrementalFileCount.
152+ if (processedFileCount == Integer .MIN_VALUE ) {
153+ assert processedSize == Long .MIN_VALUE ;
154+ processedFileCount = incrementalFileCount ;
155+ processedSize = incrementalSize ;
156+ }
157+ return new SnapshotStats (
158+ startTime ,
159+ time ,
160+ incrementalFileCount ,
161+ totalFileCount ,
162+ processedFileCount ,
163+ incrementalSize ,
164+ totalSize ,
165+ processedSize
166+ );
167+ }
51168}
0 commit comments