merge documentation (that needs to be rewritten) with TLP graduation changes
diff --git a/README.md b/README.md
index 0691d30..855df60 100644
--- a/README.md
+++ b/README.md
@@ -9,3 +9,235 @@
The repository is still in a very early state and lacks both unit tests and
robust documentation.
+
+## Interaction
+
+Configuration and interaction with the server are done via JSON. We will
+demonstrate the main features of the server by creating a simple configuration
+and using that for some example requests and responses.
+
+Aside from configuration, all inputs may be sent as individual JSON objects or as
+a JSON Array. Also, the server does not implement a transactional database. In the event
+of an error partway through an array the server will return an error, but the
+effects of any requests processed up to that point will be retained.
+
+JSON input may be passed in via either POST or GET.
+
+
+### Sketch Families
+
+The server supports a variety of sketches suitable for different types of data analysis. For
+full details of the sketches, see the main Apache DataSketches website documentation. The
+key concepts used in the server are the sketch `family`, which determines the type of sketch, and
+in some cases a value `type`, which is used to interpret the input values.
+
+The known sketch families, the short name used in the server, and a description of the uses is
+summarized in the following table:
+
+| Short Name | Sketch Type | Description |
+| ---------- | ---------------- | ----------- |
+| theta | Theta Sketch | Distinct counting with set operations |
+| hll | HyperLogLog | Distinct counting, no set operations |
+| cpc | CPC | Most compact distinct counting, no set operations |
+| kll | KLL | Absolute error quantiles sketch of floating point values |
+| frequency | Frequent Items | Heavy Hitters, items as strings |
+| reservoir | Reservoir Sample | Uniform, unweighted random sample, items as strings |
+| varopt | VarOpt Sample | Weighted random sample for subset sum queries, items as strings |
+
+The three distinct counting sketches also require the specification of a value type so that items
+are presented to the sketch in a consistent way. The supported types are:
+
+| Type Name | Description |
+| --------- | ----------- |
+| int | 32-bit signed integer |
+| long | 64-bit signed integer |
+| float | 32-bit floating-point value |
+| double | 64-bit floating-point value |
+| string | Java String |
+
+
+### Configuration
+
+The configuration file is passed in at server creation time. Aside from the port, the configuration file defines the
+sketches held by the server. All sketches are instantiated at initialization, which keeps memory usage (mostly)
+constrained during operation. Keep in mind that quantiles sketches do grow indefinitely, although very slowly as the
+number of samples increases.
+
+Examples are taken from [conf.json][example/conf.json].
+
+There are two mechanisms for defining sketches. The first is an array of
+fully-described entries. The key for such an array must have a prefix `sketches`:
+```json
+{
+ "sketches_A": [
+ { "name": "cpc_int",
+ "k": 12,
+ "type": "int",
+ "family": "cpc"
+ },
+ { "name": "cpc_string",
+ "k": 12,
+ "type": "string",
+ "family": "cpc"
+ }
+ ]
+}
+ ```
+The above code creates two CPC sketches, `cpc_int` and `cpc_string`,
+holding `int` and `string` data, respectively, both configured with a log2(k) size
+parameter of 12.
+
+In order to create multiple sketches with different names but otherwise
+configured identically, the key name must start with the prefix `set`:
+```json
+{
+ "set1": {
+ "k": 10,
+ "family": "hll",
+ "type": "double",
+ "names": [
+ "hll1",
+ "hll2",
+ "hll3"
+ ]
+ }
+}
+```
+or
+```json
+{
+ "set2": {
+ "k": 12,
+ "family": "theta",
+ "type": "float",
+ "names": [
+ "theta0",
+ "theta1",
+ "theta2",
+ "theta3",
+ "theta4"
+ ]
+ }
+}
+```
+The above examples create one set of 3 HLL sketches and one set of 5 theta sketches, respectively.
+
+### Supported Operations
+
+The available calls are:
+* `/update`
+* `/merge`
+* `/query`
+* `/serialize`
+* `/status`
+
+Each is described below, along with examples of input and output. As noted above, all calls accepting input may
+be invoked with either a single JSON object or a JSON Array of such objects.
+
+### Update
+
+Adding data is perhaps the key operation of a sketch. Each update key is the target sketch's name, and the value is
+either a single item or an array of items to be added to the sketch.
+
+For sketches that accept weighted values, specifically Frequent Items and VarOpt Sampling, passing in an item without a
+weight will be treated as having a weight of 1.0. To include a weight, the input must be a JSON object with both `item`
+and `weight`. An array of values to update may include a mix of plain, unweighted values and weighted input objects.
+
+An input to update may look like:
+```json
+{
+ "cpc_int": [1, 2, 2, 3, 4, 5],
+ "cpc_string": "single-item",
+ "fi": ["abc",
+ { "item": "def", "weight": 3 },
+ { "item": "ghi", "weight": 2 },
+ "def"
+ ],
+ "theta0": [1, 2, 3, 4, 5, 6],
+ "theta1": [5, 6, 7, 8, 9, 10]
+}
+```
+This example demonstrates the variety of inputs types, including repeated values, that are accepted by the server.
+
+There is no result returned from a successful call to update aside from the standard status code 200.
+
+```json
+{
+ "giveName": ["Alice", "Bob", "Cindy"],
+ "heightInches": [62, 70, 64],
+ "postalCode": [12345, 11111, 94030]
+}
+```
+
+### Merge
+
+
+
+
+### Query
+
+### Serialize
+
+### Status
+
+A query to the `/status` page returns a list of the configured sketches. There is no input to this query.
+
+Using `example/conf.json` to launch the server, a call to status returns:
+```json
+{
+ "count": 11,
+ "sketches": [
+ {
+ "name": "hll_3",
+ "type": "double",
+ "family": "hll"
+ },
+ {
+ "name": "hll_4",
+ "type": "double",
+ "family": "hll"
+ },
+ {
+ "name": "rs",
+ "family": "reservoir"
+ },
+ {
+ "name": "fi",
+ "family": "frequency"
+ },
+ {
+ "name": "hll_1",
+ "type": "double",
+ "family": "hll"
+ },
+ {
+ "name": "hll_2",
+ "type": "double",
+ "family": "hll"
+ },
+ {
+ "name": "cpc",
+ "type": "string",
+ "family": "cpc"
+ },
+ {
+ "name": "theta_string",
+ "type": "string",
+ "family": "theta"
+ },
+ {
+ "name": "theta_int",
+ "type": "int",
+ "family": "theta"
+ },
+ {
+ "name": "vo",
+ "family": "varopt"
+ },
+ {
+ "name": "kll",
+ "family": "kll"
+ }
+ ]
+}
+```
diff --git a/src/main/java/org/apache/datasketches/server/BaseSketchesQueryHandler.java b/src/main/java/org/apache/datasketches/server/BaseSketchesQueryHandler.java
index bad4af0..a3b1b8e 100644
--- a/src/main/java/org/apache/datasketches/server/BaseSketchesQueryHandler.java
+++ b/src/main/java/org/apache/datasketches/server/BaseSketchesQueryHandler.java
@@ -23,12 +23,14 @@
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
+import java.io.Reader;
import java.net.URLDecoder;
import org.apache.datasketches.Family;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
+import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -41,7 +43,7 @@
* <ul>
* <li>Extracts JSON query from querystring or POST body, as appropriate, to allow multiple input types.</li>
* <li>Sketches are stateful, and even reading can be disrupted by writes on another thread. A real
- * database would have a more sophisticated locking system, but this class lets us syncrhonize across
+ * database would have a more sophisticated locking system, but this class lets us synchronize across
* query types.</li>
* <li>Handles both JSON arrays or single JSON objects as inputs, letting the query handlers avoid
* code duplication.
@@ -57,7 +59,7 @@
* Basic query handler. Assumes calls must include a JSON query.
* @param sketches The sketches database to use
*/
- BaseSketchesQueryHandler(SketchStorage sketches) {
+ BaseSketchesQueryHandler(final SketchStorage sketches) {
this(sketches, false);
}
@@ -66,7 +68,7 @@
* @param sketches The sketches database to use
* @param queryExempt <tt>true</tt> if a query is not required, otherwise <tt>false</tt>
*/
- BaseSketchesQueryHandler(SketchStorage sketches, boolean queryExempt) {
+ BaseSketchesQueryHandler(final SketchStorage sketches, final boolean queryExempt) {
if (sketches == null) {
throw new IllegalArgumentException("Cannot initialize handler with SketchStorage == null");
}
@@ -74,13 +76,15 @@
this.queryExempt = queryExempt;
}
- JsonElement checkMethodAndReadJson(Request baseRequest,
- HttpServletRequest request,
- HttpServletResponse response) throws IOException {
+ static JsonElement checkMethodAndReadJson(final Request baseRequest,
+ final HttpServletRequest request,
+ final HttpServletResponse response) throws IOException {
JsonElement query = null;
if (request.getMethod().equals("POST")) {
response.setContentType("application/json");
- query = JsonParser.parseReader(request.getReader());
+ try (final Reader reader = request.getReader()) {
+ query = JsonParser.parseReader(reader);
+ }
} else if (request.getMethod().equals("GET")) {
response.setContentType("text/html");
query = JsonParser.parseString(URLDecoder.decode(request.getQueryString(), "utf-8"));
@@ -104,15 +108,15 @@
* @param query A JSON query to process
* @return A JSON response
*/
- final synchronized JsonObject callProcessQuery(JsonObject query) {
+ final synchronized JsonObject callProcessQuery(final JsonObject query) {
return processQuery(query);
}
@Override
- public void handle(String target,
- Request baseRequest,
- HttpServletRequest request,
- HttpServletResponse response) throws IOException {
+ public void handle(final String target,
+ final Request baseRequest,
+ final HttpServletRequest request,
+ final HttpServletResponse response) throws IOException {
JsonElement query = null;
if (!queryExempt && ((query = checkMethodAndReadJson(baseRequest, request, response)) == null)) {
return;
@@ -128,8 +132,8 @@
if (query == null) {
result = callProcessQuery(null);
} else if (query.isJsonArray()) {
- for (JsonElement subQuery : query.getAsJsonArray()) {
- JsonObject subResult = callProcessQuery(subQuery.getAsJsonObject());
+ for (final JsonElement subQuery : query.getAsJsonArray()) {
+ final JsonObject subResult = callProcessQuery(subQuery.getAsJsonObject());
if (subResult != null) {
// lazy initialization to avoid possibly empty array
if (result == null) {
@@ -143,14 +147,14 @@
}
if (result != null) {
- response.getWriter().print(result.toString());
- //response.getWriter().print(new GsonBuilder().setPrettyPrinting().create().toJson(result));
+ //response.getWriter().print(result.toString());
+ response.getWriter().print(new GsonBuilder().setPrettyPrinting().create().toJson(result));
}
// we're ok if we reach here without an exception
response.setStatus(HttpServletResponse.SC_OK);
- } catch (Exception e) {
- JsonObject error = new JsonObject();
+ } catch (final Exception e) {
+ final JsonObject error = new JsonObject();
error.addProperty(ERROR_KEY, e.getMessage());
response.setStatus(UNPROCESSABLE_ENTITY);
}
@@ -158,7 +162,7 @@
baseRequest.setHandled(true);
}
- static Family familyFromString(String type) throws IllegalArgumentException {
+ static Family familyFromString(final String type) throws IllegalArgumentException {
switch (type.toLowerCase()) {
case SKETCH_FAMILY_THETA:
return Family.QUICKSELECT;
diff --git a/src/main/java/org/apache/datasketches/server/DataQueryHandler.java b/src/main/java/org/apache/datasketches/server/DataQueryHandler.java
index 68255e4..c328eee 100644
--- a/src/main/java/org/apache/datasketches/server/DataQueryHandler.java
+++ b/src/main/java/org/apache/datasketches/server/DataQueryHandler.java
@@ -44,23 +44,23 @@
* Full description to be added later.
*/
public class DataQueryHandler extends BaseSketchesQueryHandler {
- public DataQueryHandler(SketchStorage sketches) {
+ public DataQueryHandler(final SketchStorage sketches) {
super(sketches, false);
}
@Override
- protected JsonObject processQuery(JsonObject query) {
+ protected JsonObject processQuery(final JsonObject query) {
if (!query.has(QUERY_NAME_FIELD)) {
throw new IllegalArgumentException("Query missing sketch name field");
}
- String key = query.get(QUERY_NAME_FIELD).getAsString();
+ final String key = query.get(QUERY_NAME_FIELD).getAsString();
if (!sketches.contains(key)) {
throw new IllegalArgumentException("Invalid sketch name: " + key);
}
- SketchStorage.SketchEntry se = sketches.getSketch(key);
- JsonObject result;
+ final SketchStorage.SketchEntry se = sketches.getSketch(key);
+ final JsonObject result;
switch (se.family) {
case UNION:
@@ -89,7 +89,7 @@
return result;
}
- private boolean checkSummaryFlag(JsonObject query) {
+ private static boolean checkSummaryFlag(final JsonObject query) {
boolean addSummary = false;
if (query != null && query.has(QUERY_SUMMARY_FIELD)) {
addSummary = query.get(QUERY_SUMMARY_FIELD).getAsBoolean();
@@ -97,27 +97,27 @@
return addSummary;
}
- private JsonObject processDistinctQuery(JsonObject query, Family type, Object sketch) {
+ private static JsonObject processDistinctQuery(final JsonObject query, final Family type, final Object sketch) {
if (query == null || type == null || sketch == null) {
return null;
}
// check if we need a summary
- boolean addSummary = checkSummaryFlag(query);
+ final boolean addSummary = checkSummaryFlag(query);
String summary = null;
- double estimate;
- boolean isEstimationMode;
- double p1StdDev;
- double p2StdDev;
- double p3StdDev;
- double m1StdDev;
- double m2StdDev;
- double m3StdDev;
+ final double estimate;
+ final boolean isEstimationMode;
+ final double p1StdDev;
+ final double p2StdDev;
+ final double p3StdDev;
+ final double m1StdDev;
+ final double m2StdDev;
+ final double m3StdDev;
switch (type) {
case UNION:
- CompactSketch thetaSketch = ((Union) sketch).getResult();
+ final CompactSketch thetaSketch = ((Union) sketch).getResult();
isEstimationMode = thetaSketch.isEstimationMode();
estimate = thetaSketch.getEstimate();
p1StdDev = thetaSketch.getUpperBound(1);
@@ -130,7 +130,7 @@
break;
case CPC:
- CpcSketch cpcSketch = (CpcSketch) sketch;
+ final CpcSketch cpcSketch = (CpcSketch) sketch;
isEstimationMode = true; // no exact mode
estimate = cpcSketch.getEstimate();
p1StdDev = cpcSketch.getUpperBound(1);
@@ -143,7 +143,7 @@
break;
case HLL:
- HllSketch hllSketch = (HllSketch) sketch;
+ final HllSketch hllSketch = (HllSketch) sketch;
isEstimationMode = hllSketch.isEstimationMode();
estimate = hllSketch.getEstimate();
p1StdDev = hllSketch.getUpperBound(1);
@@ -159,7 +159,7 @@
throw new IllegalArgumentException("Unknown distinct counting sketch type: " + type.toString());
}
- JsonObject result = new JsonObject();
+ final JsonObject result = new JsonObject();
result.addProperty(RESPONSE_ESTIMATE_FIELD, estimate);
result.addProperty(RESPONSE_ESTIMATION_MODE_FIELD, isEstimationMode);
result.addProperty(RESPONSE_P1STDEV_FIELD, p1StdDev);
@@ -174,31 +174,31 @@
return result;
}
- private JsonObject processQuantilesQuery(JsonObject query, Family type, Object sketch) {
+ private static JsonObject processQuantilesQuery(final JsonObject query, final Family type, final Object sketch) {
if (query == null || type == null || sketch == null) {
return null;
}
// check if we need a summary
- boolean addSummary = checkSummaryFlag(query);
+ final boolean addSummary = checkSummaryFlag(query);
String summary = null;
- boolean isEstimationMode;
- float maxValue;
- float minValue;
- long streamLength;
+ final boolean isEstimationMode;
+ final float maxValue;
+ final float minValue;
+ final long streamLength;
- double[] fractions = getFractionsArray(query);
+ final double[] fractions = getFractionsArray(query);
float[] quantiles = null;
- float[] values = getValuesArray(query);
- String resultType = getResultType(query);
+ final float[] values = getValuesArray(query);
+ final String resultType = getResultType(query);
double[] ranks = null;
// since we know REQ is coming
switch (type) {
case KLL:
- KllFloatsSketch kll = (KllFloatsSketch) sketch;
+ final KllFloatsSketch kll = (KllFloatsSketch) sketch;
isEstimationMode = kll.isEstimationMode();
maxValue = kll.getMaxValue();
minValue = kll.getMinValue();
@@ -220,7 +220,7 @@
throw new SketchesException("processQuantilesQuery() received a non-quantiles sketch: " + type.toString());
}
- JsonObject result = new JsonObject();
+ final JsonObject result = new JsonObject();
result.addProperty(RESPONSE_STREAM_LENGTH, streamLength);
result.addProperty(RESPONSE_ESTIMATION_MODE_FIELD, isEstimationMode);
result.addProperty(RESPONSE_MIN_VALUE, minValue);
@@ -228,9 +228,9 @@
if (ranks != null) {
final String label = resultType.equals(QUERY_RESULT_TYPE_PMF) ? RESPONSE_RESULT_MASS : RESPONSE_RESULT_RANK;
- JsonArray rankArray = new JsonArray();
+ final JsonArray rankArray = new JsonArray();
for (int i = 0; i < ranks.length; ++i) {
- JsonObject rankPair = new JsonObject();
+ final JsonObject rankPair = new JsonObject();
if (i == values.length) {
rankPair.addProperty(RESPONSE_RESULT_VALUE, maxValue);
} else {
@@ -247,9 +247,9 @@
}
if (quantiles != null) {
- JsonArray quantileArray = new JsonArray();
+ final JsonArray quantileArray = new JsonArray();
for (int i = 0; i < quantiles.length; ++i) {
- JsonObject quantilePair = new JsonObject();
+ final JsonObject quantilePair = new JsonObject();
quantilePair.addProperty(RESPONSE_RESULT_RANK, fractions[i]);
quantilePair.addProperty(RESPONSE_RESULT_QUANTILE, quantiles[i]);
quantileArray.add(quantilePair);
@@ -266,23 +266,23 @@
// only one sketch type here so could use ItemsSketch<String> instead of Object, but
// we'll eep the signatures generic here
@SuppressWarnings("unchecked")
- private JsonObject processFrequencyQuery(JsonObject query, Family type, Object sketch) {
+ private static JsonObject processFrequencyQuery(final JsonObject query, final Family type, final Object sketch) {
if (query == null || type != Family.FREQUENCY || sketch == null) {
return null;
}
- ItemsSketch<String> sk = (ItemsSketch<String>) sketch;
+ final ItemsSketch<String> sk = (ItemsSketch<String>) sketch;
// check if we need a summary
- boolean addSummary = checkSummaryFlag(query);
+ final boolean addSummary = checkSummaryFlag(query);
if (!query.has(QUERY_ERRORTYPE_FIELD)) {
throw new SketchesException("Must specify a value for " + QUERY_ERRORTYPE_FIELD
+ " for Frequent Items queries");
}
- ErrorType errorType;
- String errorTypeString = query.get(QUERY_ERRORTYPE_FIELD).getAsString();
+ final ErrorType errorType;
+ final String errorTypeString = query.get(QUERY_ERRORTYPE_FIELD).getAsString();
if (errorTypeString.equals(QUERY_ERRORTYPE_NO_FP)) {
errorType = ErrorType.NO_FALSE_POSITIVES;
} else if (errorTypeString.equals(QUERY_ERRORTYPE_NO_FN)) {
@@ -291,11 +291,11 @@
throw new SketchesException("Unknown Frequent Items ErrorType: " + errorTypeString);
}
- ItemsSketch.Row<String>[] items = sk.getFrequentItems(errorType);
+ final ItemsSketch.Row<String>[] items = sk.getFrequentItems(errorType);
- JsonArray itemArray = new JsonArray();
- for (ItemsSketch.Row<String> item : items) {
- JsonObject row = new JsonObject();
+ final JsonArray itemArray = new JsonArray();
+ for (final ItemsSketch.Row<String> item : items) {
+ final JsonObject row = new JsonObject();
row.addProperty(RESPONSE_ITEM_VALUE, item.getItem());
row.addProperty(RESPONSE_ITEM_ESTIMATE, item.getEstimate());
row.addProperty(RESPONSE_ITEM_UPPER_BOUND, item.getUpperBound());
@@ -303,7 +303,7 @@
itemArray.add(row);
}
- JsonObject result = new JsonObject();
+ final JsonObject result = new JsonObject();
result.add(RESPONSE_ITEMS_ARRAY, itemArray);
if (addSummary)
result.addProperty(RESPONSE_SUMMARY_FIELD, sk.toString());
@@ -312,23 +312,23 @@
}
@SuppressWarnings("unchecked")
- private JsonObject processSamplingQuery(JsonObject query, Family type, Object sketch) {
+ private static JsonObject processSamplingQuery(final JsonObject query, final Family type, final Object sketch) {
if (query == null || type == null || sketch == null) {
return null;
}
// check if we need a summary
- boolean addSummary = checkSummaryFlag(query);
+ final boolean addSummary = checkSummaryFlag(query);
String summary = null;
- long streamWeight;
- int k;
- JsonArray itemArray = new JsonArray();
+ final long streamWeight;
+ final int k;
+ final JsonArray itemArray = new JsonArray();
switch (type) {
case RESERVOIR:
- ReservoirItemsSketch<String> ris = (ReservoirItemsSketch<String>) sketch;
- for (String item : ris.getSamples()) {
+ final ReservoirItemsSketch<String> ris = (ReservoirItemsSketch<String>) sketch;
+ for (final String item : ris.getSamples()) {
itemArray.add(item);
}
streamWeight = ris.getN();
@@ -338,9 +338,9 @@
break;
case VAROPT:
- VarOptItemsSketch<String> vis = (VarOptItemsSketch<String>) sketch;
- for (VarOptItemsSamples<String>.WeightedSample ws : vis.getSketchSamples()) {
- JsonObject item = new JsonObject();
+ final VarOptItemsSketch<String> vis = (VarOptItemsSketch<String>) sketch;
+ for (final VarOptItemsSamples<String>.WeightedSample ws : vis.getSketchSamples()) {
+ final JsonObject item = new JsonObject();
item.addProperty(RESPONSE_ITEM_VALUE, ws.getItem());
item.addProperty(RESPONSE_ITEM_WEIGHT, ws.getWeight());
itemArray.add(item);
@@ -355,7 +355,7 @@
throw new SketchesException("processSamplingQuery() received a non-sampling sketch: " + type.toString());
}
- JsonObject result = new JsonObject();
+ final JsonObject result = new JsonObject();
result.addProperty(RESPONSE_SKETCH_K, k);
result.addProperty(RESPONSE_STREAM_WEIGHT, streamWeight);
result.add(RESPONSE_ITEMS_ARRAY, itemArray);
@@ -366,13 +366,13 @@
}
// returns an array of rank points, or null if none in query
- private float[] getValuesArray(JsonObject query) {
+ private static float[] getValuesArray(final JsonObject query) {
if (query == null || !query.has(QUERY_VALUES_FIELD_NAME)) {
return null;
}
- JsonArray valuesArray = query.get(QUERY_VALUES_FIELD_NAME).getAsJsonArray();
- float[] values = new float[valuesArray.size()];
+ final JsonArray valuesArray = query.get(QUERY_VALUES_FIELD_NAME).getAsJsonArray();
+ final float[] values = new float[valuesArray.size()];
for (int i = 0; i < values.length; ++i) {
if (!valuesArray.get(i).isJsonPrimitive()) {
@@ -386,16 +386,16 @@
// returns QUERY_RESULT_TYPE_PMF if specified in QUERY_RESULT_TYPE_NAME_FIELD, otherwise returns default of
// QUERY_RESULT_TYPE_CDF
- private String getResultType(JsonObject query) {
+ private static String getResultType(final JsonObject query) {
if (query == null || !query.has(QUERY_RESULT_TYPE_NAME_FIELD)) {
return QUERY_RESULT_TYPE_CDF;
}
- JsonElement resultTypeElement = query.get(QUERY_RESULT_TYPE_NAME_FIELD);
+ final JsonElement resultTypeElement = query.get(QUERY_RESULT_TYPE_NAME_FIELD);
if (!resultTypeElement.isJsonPrimitive())
return QUERY_RESULT_TYPE_CDF;
- String resultType = resultTypeElement.getAsString().toLowerCase();
+ final String resultType = resultTypeElement.getAsString().toLowerCase();
if (resultType.equals(QUERY_RESULT_TYPE_PMF))
return QUERY_RESULT_TYPE_PMF;
else
@@ -403,13 +403,13 @@
}
// returns an array of provided split points, or null if none in query
- private double[] getFractionsArray(JsonObject query) {
+ private static double[] getFractionsArray(final JsonObject query) {
if (query == null || !query.has(QUERY_FRACTIONS_NAME_FIELD)) {
return null;
}
- JsonArray fractionsArray = query.get(QUERY_FRACTIONS_NAME_FIELD).getAsJsonArray();
- double[] fractions = new double[fractionsArray.size()];
+ final JsonArray fractionsArray = query.get(QUERY_FRACTIONS_NAME_FIELD).getAsJsonArray();
+ final double[] fractions = new double[fractionsArray.size()];
for (int i = 0; i < fractions.length; ++i) {
if (!fractionsArray.get(i).isJsonPrimitive()) {
diff --git a/src/main/java/org/apache/datasketches/server/MergeHandler.java b/src/main/java/org/apache/datasketches/server/MergeHandler.java
index ecc07e1..3966cf2 100644
--- a/src/main/java/org/apache/datasketches/server/MergeHandler.java
+++ b/src/main/java/org/apache/datasketches/server/MergeHandler.java
@@ -59,24 +59,24 @@
* is not guaranteed.
*/
public class MergeHandler extends BaseSketchesQueryHandler {
- MergeHandler(SketchStorage sketches) {
+ MergeHandler(final SketchStorage sketches) {
super(sketches);
}
@Override
- protected JsonObject processQuery(JsonObject query) {
+ protected JsonObject processQuery(final JsonObject query) {
// optional targets:
// If no QUERY_MERGE_TGT_FIELD serialize the result, but then need specify QUERY_MERGE_K_FIELD.
// If a valid target is present, any value of QUERY_MERGE_K_FIELD is ignored
- JsonElement dstElement = query.get(SketchConstants.QUERY_MERGE_TGT_FIELD);
- String dst = dstElement != null ? dstElement.getAsString() : null;
+ final JsonElement dstElement = query.get(SketchConstants.QUERY_MERGE_TGT_FIELD);
+ final String dst = dstElement != null ? dstElement.getAsString() : null;
if (dst != null && !sketches.contains(dst)) {
throw new IllegalArgumentException("Specified target sketch does not exist: " + dst);
}
int k = 0;
if (dst == null) {
- JsonElement kElement = query.get(SketchConstants.QUERY_MERGE_K_FIELD);
+ final JsonElement kElement = query.get(SketchConstants.QUERY_MERGE_K_FIELD);
if (kElement == null) {
throw new IllegalArgumentException("Must specify either \"" + SketchConstants.QUERY_MERGE_TGT_FIELD
+ "\" or \"" + SketchConstants.QUERY_MERGE_K_FIELD + "\". Neither found.");
@@ -84,11 +84,11 @@
k = kElement.getAsInt();
}
- JsonElement srcElement = query.get(SketchConstants.QUERY_MERGE_SRC_FIELD);
+ final JsonElement srcElement = query.get(SketchConstants.QUERY_MERGE_SRC_FIELD);
if (srcElement == null || !srcElement.isJsonArray()) {
throw new IllegalArgumentException("Merge source data must be a JSON Array");
}
- JsonArray srcList = srcElement.getAsJsonArray();
+ final JsonArray srcList = srcElement.getAsJsonArray();
SketchStorage.SketchEntry se = null;
Family dstFamily = null;
@@ -99,14 +99,14 @@
// we'll process (and dedup) any stored sketches before we handle encoded inputs
// but we'll run through all of them before doing anything
- ArrayList<Object> srcSketches = new ArrayList<>(srcList.size());
+ final ArrayList<Object> srcSketches = new ArrayList<>(srcList.size());
dstFamily = prepareSketches(srcList, dstFamily, dst, srcSketches);
- byte[] skBytes = mergeSketches(dstFamily, k, se, srcSketches);
+ final byte[] skBytes = mergeSketches(dstFamily, k, se, srcSketches);
// skBytes == null if merging into another sketch; only non-null if returning a serialized image
if (skBytes != null) {
- JsonObject result = new JsonObject();
+ final JsonObject result = new JsonObject();
result.addProperty(SketchConstants.QUERY_ENCODING_FIELD, SketchConstants.ENCODING_TYPE);
result.addProperty(SketchConstants.QUERY_SKETCH_FIELD, Base64.getEncoder().encodeToString(skBytes));
return result;
@@ -115,8 +115,8 @@
}
}
- private Family prepareSketches(JsonArray sources, Family family, String dst, ArrayList<Object> sketchList) {
- HashSet<String> namedSet = new HashSet<>();
+ private Family prepareSketches(final JsonArray sources, Family family, final String dst, final ArrayList<Object> sketchList) {
+ final HashSet<String> namedSet = new HashSet<>();
// TODO: Check for sketch value types with distinct counting?
// Less obvious how to handle serialized sketch input in that case
@@ -126,11 +126,11 @@
namedSet.add(dst);
}
- for (JsonElement elmt : sources) {
+ for (final JsonElement elmt : sources) {
if (elmt.isJsonPrimitive()) {
// check family
- String key = elmt.getAsString();
- SketchStorage.SketchEntry entry = sketches.getSketch(key);
+ final String key = elmt.getAsString();
+ final SketchStorage.SketchEntry entry = sketches.getSketch(key);
if (entry == null || (family != null && family != entry.family)) {
throw new SketchesException("Input sketches must exist and be of the same family as the target");
}
@@ -151,21 +151,21 @@
}
} else { // is JsonObject
// need special handling for theta as we store Unions?
- JsonObject sourceObj = elmt.getAsJsonObject();
+ final JsonObject sourceObj = elmt.getAsJsonObject();
if (!sourceObj.has(SketchConstants.QUERY_FAMILY_FIELD)
|| !sourceObj.has(SketchConstants.QUERY_DATA_FIELD)) {
throw new SketchesException("Base64 sketch used as merge input must specify both \""
+ SketchConstants.QUERY_FAMILY_FIELD + "\" and \"" + SketchConstants.QUERY_DATA_FIELD + "\"");
}
- Family skFamily = familyFromString(sourceObj.get(SketchConstants.QUERY_FAMILY_FIELD).getAsString());
- String skString = sourceObj.get(SketchConstants.QUERY_DATA_FIELD).getAsString();
+ final Family skFamily = familyFromString(sourceObj.get(SketchConstants.QUERY_FAMILY_FIELD).getAsString());
+ final String skString = sourceObj.get(SketchConstants.QUERY_DATA_FIELD).getAsString();
if (skString == null || (family != null && family != skFamily)) {
throw new SketchesException("Input sketches must exist and be of the same family as the target");
}
// add to list, save family if we didn't have one yet
- Object sketch = deserializeSketch(skFamily, skString);
+ final Object sketch = deserializeSketch(skFamily, skString);
sketchList.add(sketch);
if (family == null) {
family = skFamily;
@@ -176,12 +176,12 @@
return family;
}
- private Object deserializeSketch(Family family, String b64String) {
+ private static Object deserializeSketch(final Family family, final String b64String) {
if (family == null || b64String == null) {
return null;
}
- Memory skBytes = Memory.wrap(Base64.getDecoder().decode(b64String));
+ final Memory skBytes = Memory.wrap(Base64.getDecoder().decode(b64String));
switch (family) {
case QUICKSELECT:
@@ -211,7 +211,8 @@
}
@SuppressWarnings("unchecked")
- private byte[] mergeSketches(Family family, int k, SketchStorage.SketchEntry dstEntry, ArrayList<Object> sketchList) {
+ private static byte[] mergeSketches(final Family family, final int k,
+ final SketchStorage.SketchEntry dstEntry, final ArrayList<Object> sketchList) {
if (family == null || sketchList.size() == 0) {
return null;
}
@@ -220,9 +221,9 @@
case UNION:
case QUICKSELECT: {
// for HLL, the destination is already a union so no need to add explicitly
- Union dst = dstEntry == null ? new SetOperationBuilder().setNominalEntries(1 << k).buildUnion()
+ final Union dst = dstEntry == null ? new SetOperationBuilder().setNominalEntries(1 << k).buildUnion()
: (Union) dstEntry.sketch;
- for (Object obj : sketchList) {
+ for (final Object obj : sketchList) {
dst.update((CompactSketch) obj);
}
@@ -235,11 +236,11 @@
}
case HLL: {
- org.apache.datasketches.hll.Union union = new org.apache.datasketches.hll.Union(k);
+ final org.apache.datasketches.hll.Union union = new org.apache.datasketches.hll.Union(k);
if (dstEntry != null) {
union.update((HllSketch) dstEntry.sketch);
}
- for (Object obj : sketchList) {
+ for (final Object obj : sketchList) {
union.update((HllSketch) obj);
}
@@ -252,11 +253,11 @@
}
case CPC: {
- CpcUnion union = new CpcUnion(k);
+ final CpcUnion union = new CpcUnion(k);
if (dstEntry != null) {
union.update((CpcSketch) dstEntry.sketch);
}
- for (Object obj : sketchList) {
+ for (final Object obj : sketchList) {
union.update((CpcSketch) obj);
}
@@ -270,9 +271,9 @@
case KLL: {
// Only merge(), no separate union. Slightly abusing terminology to call it union
- KllFloatsSketch union = dstEntry == null ? new KllFloatsSketch(k) : (KllFloatsSketch) dstEntry.sketch;
+ final KllFloatsSketch union = dstEntry == null ? new KllFloatsSketch(k) : (KllFloatsSketch) dstEntry.sketch;
- for (Object obj : sketchList) {
+ for (final Object obj : sketchList) {
union.merge((KllFloatsSketch) obj);
}
@@ -286,9 +287,9 @@
case FREQUENCY: {
// Only merge(), no separate union. Slightly abusing terminology to call it union
- ItemsSketch<String> union = dstEntry == null ? new ItemsSketch<>(k) : (ItemsSketch<String>) dstEntry.sketch;
+ final ItemsSketch<String> union = dstEntry == null ? new ItemsSketch<>(k) : (ItemsSketch<String>) dstEntry.sketch;
- for (Object obj : sketchList) {
+ for (final Object obj : sketchList) {
union.merge((ItemsSketch<String>) obj);
}
@@ -301,12 +302,12 @@
}
case RESERVOIR: {
- ReservoirItemsUnion<String> union = ReservoirItemsUnion.newInstance(k);
+ final ReservoirItemsUnion<String> union = ReservoirItemsUnion.newInstance(k);
if (dstEntry != null) {
union.update((ReservoirItemsSketch<String>) dstEntry.sketch);
}
- for (Object obj : sketchList) {
+ for (final Object obj : sketchList) {
union.update((ReservoirItemsSketch<String>) obj);
}
@@ -319,12 +320,12 @@
}
case VAROPT: {
- VarOptItemsUnion<String> union = VarOptItemsUnion.newInstance(k);
+ final VarOptItemsUnion<String> union = VarOptItemsUnion.newInstance(k);
if (dstEntry != null) {
union.update((VarOptItemsSketch<String>) dstEntry.sketch);
}
- for (Object obj : sketchList) {
+ for (final Object obj : sketchList) {
union.update((VarOptItemsSketch<String>) obj);
}
diff --git a/src/main/java/org/apache/datasketches/server/SerializationHandler.java b/src/main/java/org/apache/datasketches/server/SerializationHandler.java
index be78b4c..ce44ba6 100644
--- a/src/main/java/org/apache/datasketches/server/SerializationHandler.java
+++ b/src/main/java/org/apache/datasketches/server/SerializationHandler.java
@@ -44,25 +44,25 @@
* </pre>
*/
public class SerializationHandler extends BaseSketchesQueryHandler {
- public SerializationHandler(SketchStorage sketches) {
+ public SerializationHandler(final SketchStorage sketches) {
super(sketches, false);
}
@Override
@SuppressWarnings("unchecked")
- protected JsonObject processQuery(JsonObject query) {
+ protected JsonObject processQuery(final JsonObject query) {
if (!query.has(QUERY_NAME_FIELD)) {
throw new IllegalArgumentException("Query missing sketch name field");
}
- String name = query.get(QUERY_NAME_FIELD).getAsString();
+ final String name = query.get(QUERY_NAME_FIELD).getAsString();
if (!sketches.contains(name)) {
throw new IllegalArgumentException("Invalid sketch name: " + name);
}
- SketchStorage.SketchEntry se = sketches.getSketch(name);
+ final SketchStorage.SketchEntry se = sketches.getSketch(name);
- byte[] bytes;
+ final byte[] bytes;
switch (se.family) {
case UNION:
bytes = ((Union) se.sketch).getResult().toByteArray();
@@ -89,9 +89,9 @@
throw new IllegalStateException("Unexpected value: " + se.family);
}
- String b64Sketch = Base64.getEncoder().encodeToString(bytes);
+ final String b64Sketch = Base64.getEncoder().encodeToString(bytes);
- JsonObject result = new JsonObject();
+ final JsonObject result = new JsonObject();
result.addProperty(QUERY_NAME_FIELD, name);
result.addProperty(CONFIG_FAMILY_FIELD, se.family.getFamilyName());
if (se.type != null)
diff --git a/src/main/java/org/apache/datasketches/server/SketchServer.java b/src/main/java/org/apache/datasketches/server/SketchServer.java
index eed38c4..6e4edce 100644
--- a/src/main/java/org/apache/datasketches/server/SketchServer.java
+++ b/src/main/java/org/apache/datasketches/server/SketchServer.java
@@ -27,6 +27,8 @@
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.ErrorHandler;
+import static org.apache.datasketches.server.SketchConstants.*;
+
/**
* Creates a very basic sketch server running embedded Jetty. Configuration options are specified in a config
* file; for details @see SketchServerConfig.
@@ -39,7 +41,7 @@
/**
* Creates a server with the provided configuration
* @param configFile Path to a configuration file following the <tt>SketchServerConfig</tt> format
- * @throws IOException
+ * @throws IOException on parse errors
*/
public SketchServer(final String configFile) throws IOException {
config = new SketchServerConfig(configFile);
@@ -50,26 +52,26 @@
server = new Server(config.getPort());
// Error page unless you have a correct URL
- ContextHandler contextRoot = new ContextHandler("/");
+ final ContextHandler contextRoot = new ContextHandler("/");
contextRoot.setContextPath("/");
contextRoot.setHandler(new ErrorHandler());
- ContextHandler contextStatus = new ContextHandler(SketchConstants.STATUS_PATH);
+ final ContextHandler contextStatus = new ContextHandler(STATUS_PATH);
contextStatus.setHandler(new StatusHandler(sketches));
- ContextHandler contextSerialize = new ContextHandler(SketchConstants.SERIALIZE_PATH);
+ final ContextHandler contextSerialize = new ContextHandler(SERIALIZE_PATH);
contextSerialize.setHandler(new SerializationHandler(sketches));
- ContextHandler contextUpdate = new ContextHandler(SketchConstants.UPDATE_PATH);
+ final ContextHandler contextUpdate = new ContextHandler(UPDATE_PATH);
contextUpdate.setHandler(new UpdateHandler(sketches));
- ContextHandler contextMerge = new ContextHandler(SketchConstants.MERGE_PATH);
+ final ContextHandler contextMerge = new ContextHandler(MERGE_PATH);
contextMerge.setHandler(new MergeHandler(sketches));
- ContextHandler contextQuery = new ContextHandler(SketchConstants.QUERY_PATH);
+ final ContextHandler contextQuery = new ContextHandler(QUERY_PATH);
contextQuery.setHandler(new DataQueryHandler(sketches));
- ContextHandlerCollection contexts =
+ final ContextHandlerCollection contexts =
new ContextHandlerCollection(contextRoot,
contextStatus,
contextSerialize,
@@ -81,7 +83,7 @@
/**
* Initializes the sketches, configures query handlers, and Starts the server.
- * @throws Exception
+ * @throws Exception Relays exceptions from parsing config or running the server
*/
public void start() throws Exception {
sketches = new SketchStorage(config.getSketchList());
@@ -110,11 +112,11 @@
return -1;
}
- public static void main(String[] args) throws Exception {
+ public static void main(final String[] args) throws Exception {
//String confFile = args[0];
- String confFile = "conf3.json";
+ final String confFile = "example/conf.json";
- SketchServer sketchServer = new SketchServer(confFile);
+ final SketchServer sketchServer = new SketchServer(confFile);
sketchServer.start();
}
}
diff --git a/src/main/java/org/apache/datasketches/server/SketchServerConfig.java b/src/main/java/org/apache/datasketches/server/SketchServerConfig.java
index 8a1a4c5..31a2daf 100644
--- a/src/main/java/org/apache/datasketches/server/SketchServerConfig.java
+++ b/src/main/java/org/apache/datasketches/server/SketchServerConfig.java
@@ -48,31 +48,28 @@
public String family;
public String type;
- SketchInfo(String name, int k, String family, String type) {
+ SketchInfo(final String name, final int k, final String family, final String type) {
this.name = name;
this.k = k;
this.family = family;
this.type = type;
}
- SketchInfo(String name, int k, String family) {
- this.name = name;
- this.k = k;
- this.family = family;
- this.type = null;
+ SketchInfo(final String name, final int k, final String family) {
+ this(name, k, family, null);
}
}
- private int port = SketchConstants.DEFAULT_PORT;
+ private int port = DEFAULT_PORT;
private ArrayList<SketchInfo> sketchList;
- SketchServerConfig(String configFile) throws IOException {
- JsonElement config = readJsonFromFile(configFile);
+ SketchServerConfig(final String configFile) throws IOException {
+ final JsonElement config = readJsonFromFile(configFile);
parseConfig(config);
}
- SketchServerConfig(JsonElement config) throws IOException {
+ SketchServerConfig(final JsonElement config) throws IOException {
parseConfig(config);
}
@@ -86,22 +83,20 @@
// output should have a list with full info per sketch, even if input allows a
// more condensed format
- private JsonElement readJsonFromFile(String configFile) {
+ private static JsonElement readJsonFromFile(final String configFile) {
JsonElement config = null;
- try {
- Reader reader = Files.newBufferedReader(Paths.get(configFile));
+ try (final Reader reader = Files.newBufferedReader(Paths.get(configFile))) {
config = JsonParser.parseReader(reader);
- reader.close();
- } catch (IOException e) {
+ } catch (final IOException e) {
e.printStackTrace();
}
return config;
}
- private void parseConfig(JsonElement config) throws IOException {
- Gson gson = new Gson();
+ private void parseConfig(final JsonElement config) throws IOException {
+ final Gson gson = new Gson();
sketchList = new ArrayList<>();
@@ -109,9 +104,9 @@
// must be a list of fully-described sketches
sketchList.addAll(Arrays.asList(gson.fromJson(config.getAsJsonArray(), SketchInfo[].class)));
} else if (config.isJsonObject()) {
- JsonObject confEntry = config.getAsJsonObject();
- for (String name : confEntry.keySet()) {
- if (name.toLowerCase().equals(CONFIG_PORT_FIELD)) {
+ final JsonObject confEntry = config.getAsJsonObject();
+ for (final String name : confEntry.keySet()) {
+ if (name.equalsIgnoreCase(CONFIG_PORT_FIELD)) {
// port the server should use
port = confEntry.get(name).getAsInt();
}
@@ -120,16 +115,16 @@
sketchList.addAll(Arrays.asList(gson.fromJson(confEntry.get(name).getAsJsonArray(), SketchInfo[].class)));
} else if (name.toLowerCase().startsWith(CONFIG_SET_PREFIX)) {
// set* has a common name and type with an array of name names
- JsonObject sketchSetInfo = confEntry.get(name).getAsJsonObject();
- int k = sketchSetInfo.get(CONFIG_K_FIELD).getAsInt();
- String family = sketchSetInfo.get(CONFIG_FAMILY_FIELD).getAsString();
+ final JsonObject sketchSetInfo = confEntry.get(name).getAsJsonObject();
+ final int k = sketchSetInfo.get(CONFIG_K_FIELD).getAsInt();
+ final String family = sketchSetInfo.get(CONFIG_FAMILY_FIELD).getAsString();
String type = null;
if (isDistinctCounting(BaseSketchesQueryHandler.familyFromString(family))) {
type = sketchSetInfo.get(CONFIG_TYPE_FIELD).getAsString();
}
- String[] nameList = gson.fromJson(sketchSetInfo.get(CONFIG_SET_NAMES_FIELD).getAsJsonArray(), String[].class);
+ final String[] nameList = gson.fromJson(sketchSetInfo.get(CONFIG_SET_NAMES_FIELD).getAsJsonArray(), String[].class);
- for (String n : nameList)
+ for (final String n : nameList)
sketchList.add(new SketchInfo(n, k, family, type));
}
}
diff --git a/src/main/java/org/apache/datasketches/server/SketchStorage.java b/src/main/java/org/apache/datasketches/server/SketchStorage.java
index dd4b1ed..5c21de8 100644
--- a/src/main/java/org/apache/datasketches/server/SketchStorage.java
+++ b/src/main/java/org/apache/datasketches/server/SketchStorage.java
@@ -59,7 +59,7 @@
public final ValueType type;
public Object sketch;
- SketchEntry(Family family, ValueType type, Object sketch) throws IllegalArgumentException {
+ SketchEntry(final Family family, final ValueType type, final Object sketch) throws IllegalArgumentException {
if (isDistinctCounting(family) && type == null)
throw new IllegalArgumentException("Must specify a value type for distinct counting sketches");
@@ -68,7 +68,7 @@
this.sketch = sketch;
}
- SketchEntry(Family family, Object sketch) throws IllegalArgumentException {
+ SketchEntry(final Family family, final Object sketch) throws IllegalArgumentException {
if (isDistinctCounting(family))
throw new IllegalArgumentException("Must specify a value type for distinct counting sketches");
@@ -80,18 +80,18 @@
HashMap<String, SketchEntry> sketchMap;
- SketchStorage(List<SketchServerConfig.SketchInfo> sketchList) {
+ SketchStorage(final List<SketchServerConfig.SketchInfo> sketchList) {
if (sketchList != null) {
createSketches(sketchList);
}
}
JsonObject listSketches() {
- JsonObject summary = new JsonObject();
+ final JsonObject summary = new JsonObject();
- JsonArray sketchList = new JsonArray(sketchMap.size());
- for (Map.Entry<String, SketchEntry> e : sketchMap.entrySet()) {
- JsonObject item = new JsonObject();
+ final JsonArray sketchList = new JsonArray(sketchMap.size());
+ for (final Map.Entry<String, SketchEntry> e : sketchMap.entrySet()) {
+ final JsonObject item = new JsonObject();
item.addProperty(CONFIG_SKETCH_NAME_FIELD, e.getKey());
switch (e.getValue().family) {
case UNION:
@@ -128,25 +128,25 @@
return summary;
}
- boolean contains(String key) {
+ boolean contains(final String key) {
return sketchMap.containsKey(key);
}
- SketchEntry getSketch(String key) {
+ SketchEntry getSketch(final String key) {
return sketchMap.get(key);
}
// instantiate the actual sketches, throwing if there's a duplicate key
- private void createSketches(List<SketchServerConfig.SketchInfo> list) throws IllegalArgumentException {
+ private void createSketches(final List<SketchServerConfig.SketchInfo> list) throws IllegalArgumentException {
sketchMap = new HashMap<>(list.size());
- for (SketchServerConfig.SketchInfo info : list) {
+ for (final SketchServerConfig.SketchInfo info : list) {
if (sketchMap.containsKey(info.name)) {
throw new IllegalArgumentException("Duplicate sketch key: " + info.name);
}
SketchEntry sketchEntry = null;
- Family family = BaseSketchesQueryHandler.familyFromString(info.family);
+ final Family family = BaseSketchesQueryHandler.familyFromString(info.family);
switch (family) {
case QUICKSELECT:
diff --git a/src/main/java/org/apache/datasketches/server/StatusHandler.java b/src/main/java/org/apache/datasketches/server/StatusHandler.java
index d782a12..0f44f15 100644
--- a/src/main/java/org/apache/datasketches/server/StatusHandler.java
+++ b/src/main/java/org/apache/datasketches/server/StatusHandler.java
@@ -26,12 +26,12 @@
*/
public class StatusHandler extends BaseSketchesQueryHandler {
- public StatusHandler(SketchStorage sketches) {
+ public StatusHandler(final SketchStorage sketches) {
super(sketches, true);
}
@Override
- protected JsonObject processQuery(JsonObject query) {
+ protected JsonObject processQuery(final JsonObject query) {
return sketches.listSketches();
}
}
diff --git a/src/main/java/org/apache/datasketches/server/UpdateHandler.java b/src/main/java/org/apache/datasketches/server/UpdateHandler.java
index 2cc362f..eb8c97a 100644
--- a/src/main/java/org/apache/datasketches/server/UpdateHandler.java
+++ b/src/main/java/org/apache/datasketches/server/UpdateHandler.java
@@ -52,7 +52,7 @@
* Each <em>value</em> may be a stand-alone item or, for sketches accepting weighted inputs, may be a JSON
* object: <tt>{ "item": <value>, "weight": <weight> }</tt>. Attempting to use a weight with a
* sketch that does not support weighted inputs will result in an error. The multi-value update format
- * may contain a mux of weighted and unweighted items, as lonig s the sketch accepts weighted values.
+ * may contain a mux of weighted and unweighted items, as long s the sketch accepts weighted values.
* </p>
* <p>
* The JSON parsing library does not allow duplicate key names; to send multiple values into the same sketch
@@ -65,16 +65,16 @@
* </p>
*/
public class UpdateHandler extends BaseSketchesQueryHandler {
- public UpdateHandler(SketchStorage sketches) {
+ public UpdateHandler(final SketchStorage sketches) {
super(sketches);
}
@Override
- protected JsonObject processQuery(JsonObject query) {
- for (Map.Entry<String, JsonElement> entry : query.entrySet()) {
- String name = entry.getKey();
- SketchStorage.SketchEntry se = sketches.getSketch(name);
- JsonElement data = entry.getValue();
+ protected JsonObject processQuery(final JsonObject query) {
+ for (final Map.Entry<String, JsonElement> entry : query.entrySet()) {
+ final String name = entry.getKey();
+ final SketchStorage.SketchEntry se = sketches.getSketch(name);
+ final JsonElement data = entry.getValue();
if (name == null || se == null || data == null) {
throw new IllegalArgumentException("Attempt to call update with missing name or sketch not found");
@@ -92,20 +92,20 @@
}
@SuppressWarnings("unchecked")
- private void processBatchUpdate(SketchStorage.SketchEntry entry,
- JsonArray data) {
+ private static void processBatchUpdate(final SketchStorage.SketchEntry entry,
+ final JsonArray data) {
switch (entry.family) {
case UNION: // theta
assert(entry.type != null);
switch (entry.type) {
case FLOAT: case DOUBLE:
- for (JsonElement e : data) { ((Union) entry.sketch).update(e.getAsDouble()); }
+ for (final JsonElement e : data) { ((Union) entry.sketch).update(e.getAsDouble()); }
break;
case INT: case LONG:
- for (JsonElement e : data) { ((Union) entry.sketch).update(e.getAsLong()); }
+ for (final JsonElement e : data) { ((Union) entry.sketch).update(e.getAsLong()); }
break;
case STRING: default:
- for (JsonElement e : data) { ((Union) entry.sketch).update(e.getAsString()); }
+ for (final JsonElement e : data) { ((Union) entry.sketch).update(e.getAsString()); }
break;
}
break;
@@ -114,13 +114,13 @@
assert(entry.type != null);
switch (entry.type) {
case FLOAT: case DOUBLE:
- for (JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsDouble()); }
+ for (final JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsDouble()); }
break;
case INT: case LONG:
- for (JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsLong()); }
+ for (final JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsLong()); }
break;
case STRING: default:
- for (JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsString()); }
+ for (final JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsString()); }
break;
}
break;
@@ -129,31 +129,31 @@
assert(entry.type != null);
switch (entry.type) {
case FLOAT: case DOUBLE:
- for (JsonElement e : data) { ((HllSketch) entry.sketch).update(e.getAsDouble()); }
+ for (final JsonElement e : data) { ((HllSketch) entry.sketch).update(e.getAsDouble()); }
break;
case INT: case LONG:
- for (JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsLong()); }
+ for (final JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsLong()); }
break;
case STRING: default:
- for (JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsString()); }
+ for (final JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsString()); }
break;
}
break;
case KLL:
- for (JsonElement e : data) { ((KllFloatsSketch) entry.sketch).update(e.getAsFloat()); }
+ for (final JsonElement e : data) { ((KllFloatsSketch) entry.sketch).update(e.getAsFloat()); }
break;
case FREQUENCY:
- for (JsonElement e : data) {
+ for (final JsonElement e : data) {
if (e.isJsonObject()) {
- JsonObject inputPair = e.getAsJsonObject();
+ final JsonObject inputPair = e.getAsJsonObject();
if (!inputPair.has(QUERY_PAIR_ITEM_FIELD) || !inputPair.has(QUERY_PAIR_WEIGHT_FIELD)) {
throw new IllegalArgumentException("Frequent Items input pairs must include both "
+ QUERY_PAIR_ITEM_FIELD + " and " + QUERY_PAIR_WEIGHT_FIELD + " values");
}
- String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
- int weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsInt();
+ final String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
+ final int weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsInt();
((ItemsSketch<String>) entry.sketch).update(item, weight);
} else {
((ItemsSketch<String>) entry.sketch).update(e.getAsString());
@@ -162,19 +162,19 @@
break;
case RESERVOIR:
- for (JsonElement e : data) { ((ReservoirItemsSketch<String>) entry.sketch).update(e.getAsString()); }
+ for (final JsonElement e : data) { ((ReservoirItemsSketch<String>) entry.sketch).update(e.getAsString()); }
break;
case VAROPT:
- for (JsonElement e : data) {
+ for (final JsonElement e : data) {
if (e.isJsonObject()) {
- JsonObject inputPair = e.getAsJsonObject();
+ final JsonObject inputPair = e.getAsJsonObject();
if (!inputPair.has(QUERY_PAIR_ITEM_FIELD) || !inputPair.has(QUERY_PAIR_WEIGHT_FIELD)) {
throw new IllegalArgumentException("VarOpt input pairs must include both "
+ QUERY_PAIR_ITEM_FIELD + " and " + QUERY_PAIR_WEIGHT_FIELD + " values");
}
- String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
- double weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsDouble();
+ final String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
+ final double weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsDouble();
((VarOptItemsSketch<String>) entry.sketch).update(item, weight);
} else {
((VarOptItemsSketch<String>) entry.sketch).update(e.getAsString(), 1.0);
@@ -188,8 +188,8 @@
}
@SuppressWarnings("unchecked")
- private void processSingleUpdate(SketchStorage.SketchEntry entry,
- JsonElement data) {
+ private static void processSingleUpdate(final SketchStorage.SketchEntry entry,
+ final JsonElement data) {
switch (entry.family) {
case UNION:
assert(entry.type != null);
@@ -242,13 +242,13 @@
case FREQUENCY:
if (data.isJsonObject()) {
- JsonObject inputPair = data.getAsJsonObject();
+ final JsonObject inputPair = data.getAsJsonObject();
if (!inputPair.has(QUERY_PAIR_ITEM_FIELD) || !inputPair.has(QUERY_PAIR_WEIGHT_FIELD)) {
throw new IllegalArgumentException("Frequent Items input pairs must include both "
+ QUERY_PAIR_ITEM_FIELD + " and " + QUERY_PAIR_WEIGHT_FIELD + " values");
}
- String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
- int weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsInt();
+ final String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
+ final int weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsInt();
((ItemsSketch<String>) entry.sketch).update(item, weight);
} else {
((ItemsSketch<String>) entry.sketch).update(data.getAsString());
@@ -261,13 +261,13 @@
case VAROPT:
if (data.isJsonObject()) {
- JsonObject inputPair = data.getAsJsonObject();
+ final JsonObject inputPair = data.getAsJsonObject();
if (!inputPair.has(QUERY_PAIR_ITEM_FIELD) || !inputPair.has(QUERY_PAIR_WEIGHT_FIELD)) {
throw new IllegalArgumentException("VarOpt input pairs must include both "
+ QUERY_PAIR_ITEM_FIELD + " and " + QUERY_PAIR_WEIGHT_FIELD + " values");
}
- String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
- double weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsDouble();
+ final String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
+ final double weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsDouble();
((VarOptItemsSketch<String>) entry.sketch).update(item, weight);
} else {
((VarOptItemsSketch<String>) entry.sketch).update(data.getAsString(), 1.0);
diff --git a/src/main/java/org/apache/datasketches/server/ValueType.java b/src/main/java/org/apache/datasketches/server/ValueType.java
index 0ec1ff9..6bde33e 100644
--- a/src/main/java/org/apache/datasketches/server/ValueType.java
+++ b/src/main/java/org/apache/datasketches/server/ValueType.java
@@ -56,7 +56,7 @@
private final String typeName_;
static {
- for (ValueType t : values()) {
+ for (final ValueType t : values()) {
lookupTypeName.put(t.getTypeName().toLowerCase(), t);
}
}