Skip to content

Commit 7eb5e2f

Browse files
author
Vladimir Kotal
authored
convert Statistics to use Jackson for JSON processing (#2620)
1 parent b9dc5c0 commit 7eb5e2f

File tree

11 files changed

+342
-347
lines changed

11 files changed

+342
-347
lines changed

opengrok-indexer/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,16 @@ Portions Copyright (c) 2017-2018, Chris Fraire <[email protected]>.
173173
<artifactId>activation</artifactId>
174174
<version>1.1.1</version>
175175
</dependency>
176+
<dependency>
177+
<groupId>com.fasterxml.jackson.core</groupId>
178+
<artifactId>jackson-databind</artifactId>
179+
<version>${jackson.version}</version>
180+
</dependency>
181+
<dependency>
182+
<groupId>com.fasterxml.jackson.core</groupId>
183+
<artifactId>jackson-annotations</artifactId>
184+
<version>${jackson.version}</version>
185+
</dependency>
176186
</dependencies>
177187

178188
<build>

opengrok-indexer/src/main/java/org/opengrok/indexer/util/StatisticsUtils.java

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,9 @@
2323

2424
package org.opengrok.indexer.util;
2525

26-
import org.json.simple.JSONObject;
27-
import org.json.simple.parser.JSONParser;
28-
import org.json.simple.parser.ParseException;
26+
import com.fasterxml.jackson.databind.ObjectMapper;
2927
import org.opengrok.indexer.configuration.RuntimeEnvironment;
30-
import org.opengrok.indexer.web.Util;
28+
import org.opengrok.indexer.web.Statistics;
3129

3230
import java.io.File;
3331
import java.io.FileInputStream;
@@ -37,6 +35,7 @@
3735
import java.io.InputStream;
3836
import java.io.InputStreamReader;
3937
import java.io.OutputStream;
38+
import java.io.Reader;
4039

4140
public class StatisticsUtils {
4241
/**
@@ -74,16 +73,15 @@ public static void saveStatistics(File out) throws IOException {
7473
* @throws IOException
7574
*/
7675
public static void saveStatistics(OutputStream out) throws IOException {
77-
out.write(Util.statisticToJson(RuntimeEnvironment.getInstance().getStatistics()).toJSONString().getBytes());
76+
out.write(RuntimeEnvironment.getInstance().getStatistics().toJson().getBytes());
7877
}
7978

8079
/**
8180
* Load statistics from JSON file specified in configuration.
8281
*
8382
* @throws IOException
84-
* @throws ParseException
8583
*/
86-
public static void loadStatistics() throws IOException, ParseException {
84+
public static void loadStatistics() throws IOException {
8785
String path = RuntimeEnvironment.getInstance().getStatisticsFilePath();
8886
if (path == null) {
8987
throw new FileNotFoundException("Statistics file is not set (null)");
@@ -96,9 +94,8 @@ public static void loadStatistics() throws IOException, ParseException {
9694
*
9795
* @param in the file with json
9896
* @throws IOException
99-
* @throws ParseException
10097
*/
101-
public static void loadStatistics(File in) throws IOException, ParseException {
98+
public static void loadStatistics(File in) throws IOException {
10299
if (in == null) {
103100
throw new FileNotFoundException("Statistics file is not set (null)");
104101
}
@@ -112,12 +109,19 @@ public static void loadStatistics(File in) throws IOException, ParseException {
112109
*
113110
* @param in the file with json
114111
* @throws IOException
115-
* @throws ParseException
116112
*/
117-
public static void loadStatistics(InputStream in) throws IOException, ParseException {
118-
try (InputStreamReader iReader = new InputStreamReader(in)) {
119-
JSONParser jsonParser = new JSONParser();
120-
RuntimeEnvironment.getInstance().setStatistics(Util.jsonToStatistics((JSONObject) jsonParser.parse(iReader)));
113+
public static void loadStatistics(InputStream in) throws IOException {
114+
try (Reader iReader = new InputStreamReader(in, "UTF-8")) {
115+
StringBuilder outputString = new StringBuilder();
116+
final char[] buf = new char[1024];
117+
int rsz;
118+
while ((rsz = iReader.read(buf, 0, buf.length)) > 0) {
119+
outputString.append(buf, 0, rsz);
120+
}
121+
122+
ObjectMapper mapper = new ObjectMapper();
123+
org.opengrok.indexer.web.Statistics newstats = mapper.readValue(outputString.toString(), Statistics.class);
124+
RuntimeEnvironment.getInstance().setStatistics(newstats);
121125
}
122126
}
123127

opengrok-indexer/src/main/java/org/opengrok/indexer/web/Statistics.java

Lines changed: 55 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,17 @@
2222
*/
2323
package org.opengrok.indexer.web;
2424

25+
import com.fasterxml.jackson.annotation.JsonIgnore;
26+
import com.fasterxml.jackson.annotation.JsonProperty;
27+
import com.fasterxml.jackson.core.JsonProcessingException;
28+
import com.fasterxml.jackson.databind.ObjectMapper;
29+
30+
import java.io.IOException;
2531
import java.util.Calendar;
2632
import java.util.Map;
2733
import java.util.TreeMap;
2834
import java.util.stream.Collectors;
2935
import java.util.stream.LongStream;
30-
import org.json.simple.JSONArray;
31-
import org.json.simple.JSONObject;
3236

3337
/**
3438
* Framework for statistics gathering. So far used only by the webapp.
@@ -51,18 +55,35 @@ public class Statistics {
5155
protected static final String STATISTIC_DAY_HISTOGRAM = "day_histogram";
5256
protected static final String STATISTIC_MONTH_HISTOGRAM = "month_histogram";
5357

58+
@JsonProperty(STATISTIC_REQUEST_CATEGORIES)
5459
private Map<String, Long> requestCategories = new TreeMap<>();
60+
@JsonProperty(STATISTIC_TIMING)
5561
private Map<String, Long> timing = new TreeMap<>();
62+
@JsonProperty(STATISTIC_TIMING_MIN)
5663
private Map<String, Long> timingMin = new TreeMap<>();
64+
@JsonProperty(STATISTIC_TIMING_MAX)
5765
private Map<String, Long> timingMax = new TreeMap<>();
66+
@JsonProperty(STATISTIC_TIMING_AVG)
67+
private Map<String, Double> timingAvg = new TreeMap<>();
68+
@JsonProperty(STATISTIC_DAY_HISTOGRAM)
5869
private long[] dayHistogram = new long[24];
70+
@JsonProperty(STATISTIC_MONTH_HISTOGRAM)
5971
private long[] monthHistogram = new long[31];
60-
private long timeStart = System.currentTimeMillis();
72+
@JsonProperty(STATISTIC_REQUESTS)
6173
private long requests = 0;
74+
@JsonProperty(STATISTIC_MINUTES)
6275
private long minutes = 1;
76+
@JsonProperty(STATISTIC_REQUESTS_PER_MINUTE)
6377
private long requestsPerMinute = 0;
78+
@JsonProperty(STATISTIC_REQUESTS_PER_MINUTE_MIN)
6479
private long requestsPerMinuteMin = Long.MAX_VALUE;
80+
@JsonProperty(STATISTIC_REQUESTS_PER_MINUTE_MAX)
6581
private long requestsPerMinuteMax = Long.MIN_VALUE;
82+
@JsonProperty(STATISTIC_REQUESTS_PER_MINUTE_AVG)
83+
private double requestsPerMinuteAvg = 0;
84+
85+
@JsonIgnore
86+
private long timeStart = System.currentTimeMillis();
6687

6788
/**
6889
* Adds a single request into all requests.
@@ -72,6 +93,7 @@ synchronized public void addRequest() {
7293

7394
requestsPerMinute++;
7495
requests++;
96+
requestsPerMinuteAvg = requests / (double) minutes;
7597

7698
if (requestsPerMinute > requestsPerMinuteMax) {
7799
requestsPerMinuteMax = requestsPerMinute;
@@ -102,6 +124,7 @@ synchronized protected void maybeRefresh() {
102124
* @param category category
103125
*/
104126
synchronized public void addRequest(String category) {
127+
maybeRefresh();
105128
Long val = requestCategories.get(category);
106129
if (val == null) {
107130
val = 0L;
@@ -146,6 +169,10 @@ synchronized public void addRequestTime(String category, long v) {
146169
timing.put(category, val);
147170
timingMin.put(category, min);
148171
timingMax.put(category, max);
172+
173+
// Recompute the average for given category.
174+
timingAvg.put(category,
175+
timing.get(category).doubleValue() / requestCategories.get(category));
149176
}
150177

151178
public Map<String, Long> getRequestCategories() {
@@ -171,11 +198,6 @@ public Map<String, Long> getTimingMax() {
171198
* @return map of averages for each category
172199
*/
173200
public Map<String, Double> getTimingAvg() {
174-
Map<String, Double> timingAvg = new TreeMap<>();
175-
for (Map.Entry<String, Long> entry : timing.entrySet()) {
176-
timingAvg.put(entry.getKey(), entry.getValue().doubleValue()
177-
/ requestCategories.get(entry.getKey()));
178-
}
179201
return timingAvg;
180202
}
181203

@@ -195,6 +217,10 @@ synchronized public void setTimingMax(Map<String, Long> timing_max) {
195217
this.timingMax = timing_max;
196218
}
197219

220+
synchronized public void setTimingAvg(Map<String, Double> timing_avg) {
221+
this.timingAvg = timing_avg;
222+
}
223+
198224
public long getTimeStart() {
199225
return timeStart;
200226
}
@@ -212,7 +238,6 @@ synchronized public void setRequests(long requests) {
212238
}
213239

214240
public long getMinutes() {
215-
maybeRefresh();
216241
return minutes;
217242
}
218243

@@ -221,7 +246,6 @@ synchronized public void setMinutes(long minutes) {
221246
}
222247

223248
public long getRequestsPerMinute() {
224-
maybeRefresh();
225249
return requestsPerMinute;
226250
}
227251

@@ -252,8 +276,11 @@ synchronized public void setRequestsPerMinuteMax(long requestsPerMinuteMax) {
252276
}
253277

254278
public double getRequestsPerMinuteAvg() {
255-
maybeRefresh();
256-
return requests / (double) minutes;
279+
return this.requestsPerMinuteAvg;
280+
}
281+
282+
synchronized public void setRequestsPerMinuteAvg(double value) {
283+
this.requestsPerMinuteAvg = value;
257284
}
258285

259286
public long[] getDayHistogram() {
@@ -273,116 +300,41 @@ synchronized public void setMonthHistogram(long[] monthHistogram) {
273300
}
274301

275302
/**
276-
* Convert this statistics object into JSONObject.
303+
* Convert this {@code Statistics} object into JSON
277304
*
278-
* @return the json object
305+
* @return the JSON string
279306
*/
280-
public JSONObject toJson() {
307+
public String toJson() throws JsonProcessingException {
281308
return toJson(this);
282309
}
283310

284311
/**
285-
* Convert JSONObject object into statistics.
312+
* Convert JSON into {@code Statistics} object.
286313
*
287-
* @param input object containing statistics
288-
* @return the statistics object
314+
* @param jsonString String with JSON
315+
* @return the {@code Statistics} object
289316
*/
290317
@SuppressWarnings("unchecked")
291-
public static Statistics from(JSONObject input) {
292-
Statistics stats = new Statistics();
293-
Object o;
294-
if ((o = input.get(STATISTIC_REQUEST_CATEGORIES)) != null) {
295-
stats.setRequestCategories((Map<String, Long>) o);
296-
}
297-
if ((o = input.get(STATISTIC_TIMING)) != null) {
298-
stats.setTiming((Map<String, Long>) o);
299-
}
300-
if ((o = input.get(STATISTIC_TIMING_MIN)) != null) {
301-
stats.setTimingMin((Map<String, Long>) o);
302-
}
303-
if ((o = input.get(STATISTIC_TIMING_MAX)) != null) {
304-
stats.setTimingMax((Map<String, Long>) o);
305-
}
306-
if ((o = input.get(STATISTIC_REQUESTS)) != null) {
307-
stats.setRequests((long) o);
308-
}
309-
if ((o = input.get(STATISTIC_MINUTES)) != null) {
310-
stats.setMinutes((long) o);
311-
}
312-
if ((o = input.get(STATISTIC_REQUESTS_PER_MINUTE)) != null) {
313-
stats.setRequestsPerMinute((long) o);
314-
}
315-
if ((o = input.get(STATISTIC_REQUESTS_PER_MINUTE_MIN)) != null) {
316-
stats.setRequestsPerMinuteMin((long) o);
317-
}
318-
if ((o = input.get(STATISTIC_REQUESTS_PER_MINUTE_MAX)) != null) {
319-
stats.setRequestsPerMinuteMax((long) o);
320-
}
321-
if ((o = input.get(STATISTIC_DAY_HISTOGRAM)) != null) {
322-
stats.setDayHistogram(convertJSONArrayToArray((JSONArray) o, stats.getDayHistogram()));
323-
}
324-
if ((o = input.get(STATISTIC_MONTH_HISTOGRAM)) != null) {
325-
stats.setMonthHistogram(convertJSONArrayToArray((JSONArray) o, stats.getMonthHistogram()));
326-
}
318+
public static Statistics fromJson(String jsonString) throws IOException {
319+
ObjectMapper mapper = new ObjectMapper();
320+
Statistics stats = mapper.readValue(jsonString, Statistics.class);
327321
stats.setTimeStart(System.currentTimeMillis());
322+
328323
return stats;
329324
}
330325

331326
/**
332-
* Convert statistics object into JSONObject.
327+
* Convert statistics object into JSON.
333328
*
334329
* @param stats the statistics object
335-
* @return the json object or empty json object if there was no request
336-
*/
337-
@SuppressWarnings("unchecked")
338-
public static JSONObject toJson(Statistics stats) {
339-
JSONObject output = new JSONObject();
340-
if (stats.getRequests() == 0) {
341-
return output;
342-
}
343-
output.put(STATISTIC_REQUEST_CATEGORIES, new JSONObject(stats.getRequestCategories()));
344-
output.put(STATISTIC_TIMING, new JSONObject(stats.getTiming()));
345-
output.put(STATISTIC_TIMING_MIN, new JSONObject(stats.getTimingMin()));
346-
output.put(STATISTIC_TIMING_MAX, new JSONObject(stats.getTimingMax()));
347-
output.put(STATISTIC_TIMING_AVG, new JSONObject(stats.getTimingAvg()));
348-
output.put(STATISTIC_MINUTES, stats.getMinutes());
349-
output.put(STATISTIC_REQUESTS, stats.getRequests());
350-
output.put(STATISTIC_REQUESTS_PER_MINUTE, stats.getRequestsPerMinute());
351-
output.put(STATISTIC_REQUESTS_PER_MINUTE_MIN, stats.getRequestsPerMinuteMin());
352-
output.put(STATISTIC_REQUESTS_PER_MINUTE_MAX, stats.getRequestsPerMinuteMax());
353-
output.put(STATISTIC_REQUESTS_PER_MINUTE_AVG, stats.getRequestsPerMinuteAvg());
354-
output.put(STATISTIC_DAY_HISTOGRAM, convertArrayToJSONArray(stats.getDayHistogram()));
355-
output.put(STATISTIC_MONTH_HISTOGRAM, convertArrayToJSONArray(stats.getMonthHistogram()));
356-
return output;
357-
}
358-
359-
/**
360-
* Converts an array into json array.
361-
*
362-
* @param array the input array
363-
* @return the output json array
330+
* @return String with JSON
364331
*/
365332
@SuppressWarnings("unchecked")
366-
private static JSONArray convertArrayToJSONArray(long[] array) {
367-
JSONArray ret = new JSONArray();
368-
for (long o : array) {
369-
ret.add(o);
370-
}
371-
return ret;
372-
}
333+
public static String toJson(Statistics stats) throws JsonProcessingException {
334+
ObjectMapper mapper = new ObjectMapper();
335+
String jsonStr = mapper.writeValueAsString(stats);
373336

374-
/**
375-
* Converts an json array into an array.
376-
*
377-
* @param dest the input json array
378-
* @param target the output array
379-
* @return target
380-
*/
381-
private static long[] convertJSONArrayToArray(JSONArray dest, long[] target) {
382-
for (int i = 0; i < target.length && i < dest.size(); i++) {
383-
target[i] = (long) dest.get(i);
384-
}
385-
return target;
337+
return jsonStr;
386338
}
387339

388340
@Override
@@ -400,6 +352,5 @@ public String toString() {
400352
+ "\nrequestsPerMinuteAvg = " + getRequestsPerMinuteAvg()
401353
+ "\ndayHistogram = " + LongStream.of(getDayHistogram()).mapToObj(a -> Long.toString(a)).map(a -> a.toString()).collect(Collectors.joining(", "))
402354
+ "\nmonthHistogram = " + LongStream.of(getMonthHistogram()).mapToObj(a -> Long.toString(a)).map(a -> a.toString()).collect(Collectors.joining(", "));
403-
404355
}
405356
}

opengrok-indexer/src/main/java/org/opengrok/indexer/web/Util.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,26 +1461,6 @@ public static JSONArray messagesToJson(Group group) {
14611461
return messagesToJson(group, new String[0]);
14621462
}
14631463

1464-
/**
1465-
* Convert statistics object into JSONObject.
1466-
*
1467-
* @param stats object containing statistics
1468-
* @return the json object
1469-
*/
1470-
public static JSONObject statisticToJson(Statistics stats) {
1471-
return stats.toJson();
1472-
}
1473-
1474-
/**
1475-
* Convert JSONObject object into statistics.
1476-
*
1477-
* @param input object containing statistics
1478-
* @return the statistics object
1479-
*/
1480-
public static Statistics jsonToStatistics(JSONObject input) {
1481-
return Statistics.from(input);
1482-
}
1483-
14841464
/**
14851465
* Print a row in an HTML table.
14861466
*

0 commit comments

Comments
 (0)