This is an automated email from the ASF dual-hosted git repository. mblow pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/asterixdb.git
commit 6eb42a0ebf010b69c8f4e763d90f89cfbe46ea1a Author: Michael Blow <mb...@apache.org> AuthorDate: Wed Dec 9 10:11:00 2020 -0500 [NO ISSUE][CONFIG] Avoid integer overflow on option parse - Do not use Integer.parseUnsignedInt() for nonnegative integer option parsing, as this will result in negative numbers for values > 0x7fffffff - Renamed (OptionTypes.)UNSIGNED_INTEGER to NONNEGATIVE_INTEGER for clarity - Add POSITIVE_INTEGER_BYTE_UNIT & POSITIVE_LONG_BYTE_UNIT option types (includes cherry-pick of commit 7a99fcefe3) Change-Id: I03bc9e92c2b6ce48977e93966f6cb9160c4df893 Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/10003 Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Reviewed-by: Michael Blow <mb...@apache.org> Reviewed-by: Murtadha Hubail <mhub...@apache.org> --- .../asterix/common/config/CompilerProperties.java | 7 +- .../asterix/common/config/ExternalProperties.java | 17 +- .../asterix/common/config/MetadataProperties.java | 6 +- .../common/config/ReplicationProperties.java | 4 +- .../asterix/common/config/StorageProperties.java | 6 +- .../common/config/TransactionProperties.java | 6 +- .../hyracks/control/common/config/OptionTypes.java | 271 ++++++++++++--------- .../control/common/controllers/CCConfig.java | 20 +- .../control/common/controllers/NCConfig.java | 26 +- 9 files changed, 202 insertions(+), 161 deletions(-) diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/CompilerProperties.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/CompilerProperties.java index 9428e6f..8860495 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/CompilerProperties.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/CompilerProperties.java @@ -23,7 +23,6 @@ import static org.apache.hyracks.control.common.config.OptionTypes.INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.INTEGER_BYTE_UNIT; import static org.apache.hyracks.control.common.config.OptionTypes.LONG_BYTE_UNIT; import static org.apache.hyracks.control.common.config.OptionTypes.POSITIVE_INTEGER; -import static org.apache.hyracks.control.common.config.OptionTypes.UNSIGNED_INTEGER; import static org.apache.hyracks.util.StorageUtil.StorageUnit.KILOBYTE; import static org.apache.hyracks.util.StorageUtil.StorageUnit.MEGABYTE; @@ -31,6 +30,7 @@ import org.apache.hyracks.algebricks.core.config.AlgebricksConfig; import org.apache.hyracks.api.config.IOption; import org.apache.hyracks.api.config.IOptionType; import org.apache.hyracks.api.config.Section; +import org.apache.hyracks.control.common.config.OptionTypes; import org.apache.hyracks.util.StorageUtil; public class CompilerProperties extends AbstractProperties { @@ -68,7 +68,10 @@ public class CompilerProperties extends AbstractProperties { + "other integer values dictate the number of query execution parallel partitions. The system will " + "fall back to use the number of all available CPU cores in the cluster as the degree of parallelism " + "if the number set by a user is too large or too small"), - COMPILER_STRINGOFFSET(UNSIGNED_INTEGER, 0, "Position of a first character in a String/Binary (0 or 1)"), + COMPILER_STRINGOFFSET( + OptionTypes.getRangedIntegerType(0, 1), + 0, + "Position of a first character in a String/Binary (0 or 1)"), COMPILER_SORT_PARALLEL(BOOLEAN, AlgebricksConfig.SORT_PARALLEL, "Enabling/Disabling full parallel sort"), COMPILER_SORT_SAMPLES( POSITIVE_INTEGER, diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/ExternalProperties.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/ExternalProperties.java index 1533c9f..642cbd6 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/ExternalProperties.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/ExternalProperties.java @@ -19,9 +19,10 @@ package org.apache.asterix.common.config; import static org.apache.hyracks.control.common.config.OptionTypes.LEVEL; +import static org.apache.hyracks.control.common.config.OptionTypes.NONNEGATIVE_INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.POSITIVE_INTEGER; +import static org.apache.hyracks.control.common.config.OptionTypes.POSITIVE_INTEGER_BYTE_UNIT; import static org.apache.hyracks.control.common.config.OptionTypes.STRING; -import static org.apache.hyracks.control.common.config.OptionTypes.UNSIGNED_INTEGER; import org.apache.hyracks.api.config.IOption; import org.apache.hyracks.api.config.IOptionType; @@ -32,11 +33,11 @@ import org.apache.logging.log4j.Level; public class ExternalProperties extends AbstractProperties { public enum Option implements IOption { - WEB_PORT(UNSIGNED_INTEGER, 19001, "The listen port of the legacy query interface"), - WEB_QUERYINTERFACE_PORT(UNSIGNED_INTEGER, 19006, "The listen port of the query web interface"), - API_PORT(UNSIGNED_INTEGER, 19002, "The listen port of the API server"), - ACTIVE_PORT(UNSIGNED_INTEGER, 19003, "The listen port of the active server"), - NC_API_PORT(UNSIGNED_INTEGER, 19004, "The listen port of the node controller API server"), + WEB_PORT(NONNEGATIVE_INTEGER, 19001, "The listen port of the legacy query interface"), + WEB_QUERYINTERFACE_PORT(NONNEGATIVE_INTEGER, 19006, "The listen port of the query web interface"), + API_PORT(NONNEGATIVE_INTEGER, 19002, "The listen port of the API server"), + ACTIVE_PORT(NONNEGATIVE_INTEGER, 19003, "The listen port of the active server"), + NC_API_PORT(NONNEGATIVE_INTEGER, 19004, "The listen port of the node controller API server"), LOG_LEVEL(LEVEL, Level.WARN, "The logging level for master and slave processes"), MAX_WAIT_ACTIVE_CLUSTER( POSITIVE_INTEGER, @@ -46,10 +47,10 @@ public class ExternalProperties extends AbstractProperties { CC_JAVA_OPTS(STRING, "-Xmx1024m", "The JVM options passed to the cluster controller process by managix"), NC_JAVA_OPTS(STRING, "-Xmx1024m", "The JVM options passed to the node controller process(es) by managix"), MAX_WEB_REQUEST_SIZE( - UNSIGNED_INTEGER, + POSITIVE_INTEGER_BYTE_UNIT, StorageUtil.getIntSizeInBytes(50, StorageUtil.StorageUnit.MEGABYTE), "The maximum accepted web request size in bytes"), - REQUESTS_ARCHIVE_SIZE(UNSIGNED_INTEGER, 50, "The maximum number of archived requests to maintain"); + REQUESTS_ARCHIVE_SIZE(NONNEGATIVE_INTEGER, 50, "The maximum number of archived requests to maintain"); private final IOptionType type; private final Object defaultValue; diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/MetadataProperties.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/MetadataProperties.java index 7a3e707..7d5ec42 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/MetadataProperties.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/MetadataProperties.java @@ -18,9 +18,9 @@ */ package org.apache.asterix.common.config; +import static org.apache.hyracks.control.common.config.OptionTypes.NONNEGATIVE_INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.POSITIVE_INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.STRING; -import static org.apache.hyracks.control.common.config.OptionTypes.UNSIGNED_INTEGER; import java.util.List; import java.util.Map; @@ -37,8 +37,8 @@ public class MetadataProperties extends AbstractProperties { public enum Option implements IOption { METADATA_NODE(STRING, null), METADATA_REGISTRATION_TIMEOUT_SECS(POSITIVE_INTEGER, 60), - METADATA_LISTEN_PORT(UNSIGNED_INTEGER, 0), - METADATA_CALLBACK_PORT(UNSIGNED_INTEGER, 0); + METADATA_LISTEN_PORT(NONNEGATIVE_INTEGER, 0), + METADATA_CALLBACK_PORT(NONNEGATIVE_INTEGER, 0); private final IOptionType type; private final Object defaultValue; diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/ReplicationProperties.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/ReplicationProperties.java index 6082f30..dd42936 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/ReplicationProperties.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/ReplicationProperties.java @@ -21,9 +21,9 @@ package org.apache.asterix.common.config; import static org.apache.hyracks.control.common.config.OptionTypes.BOOLEAN; import static org.apache.hyracks.control.common.config.OptionTypes.INTEGER_BYTE_UNIT; import static org.apache.hyracks.control.common.config.OptionTypes.LONG; +import static org.apache.hyracks.control.common.config.OptionTypes.NONNEGATIVE_INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.POSITIVE_INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.STRING; -import static org.apache.hyracks.control.common.config.OptionTypes.UNSIGNED_INTEGER; import java.util.concurrent.TimeUnit; @@ -51,7 +51,7 @@ public class ReplicationProperties extends AbstractProperties { TimeUnit.SECONDS.toSeconds(30), "The time in seconds to timeout waiting for master or replica to ack"), REPLICATION_ENABLED(BOOLEAN, false, "Whether or not data replication is enabled"), - REPLICATION_FACTOR(UNSIGNED_INTEGER, 2, "Number of replicas (backups) to maintain per master replica"), + REPLICATION_FACTOR(NONNEGATIVE_INTEGER, 2, "Number of replicas (backups) to maintain per master replica"), REPLICATION_STRATEGY(STRING, "none", "Replication strategy to choose"); private final IOptionType type; diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/StorageProperties.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/StorageProperties.java index 58bc828..0bea099 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/StorageProperties.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/StorageProperties.java @@ -21,9 +21,9 @@ package org.apache.asterix.common.config; import static org.apache.hyracks.control.common.config.OptionTypes.DOUBLE; import static org.apache.hyracks.control.common.config.OptionTypes.INTEGER_BYTE_UNIT; import static org.apache.hyracks.control.common.config.OptionTypes.LONG_BYTE_UNIT; +import static org.apache.hyracks.control.common.config.OptionTypes.NONNEGATIVE_INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.POSITIVE_INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.STRING; -import static org.apache.hyracks.control.common.config.OptionTypes.UNSIGNED_INTEGER; import static org.apache.hyracks.util.StorageUtil.StorageUnit.KILOBYTE; import static org.apache.hyracks.util.StorageUtil.StorageUnit.MEGABYTE; @@ -43,13 +43,13 @@ public class StorageProperties extends AbstractProperties { STORAGE_BUFFERCACHE_PAGESIZE(INTEGER_BYTE_UNIT, StorageUtil.getIntSizeInBytes(128, KILOBYTE)), // By default, uses 1/4 of the maximum heap size for read cache, i.e., disk buffer cache. STORAGE_BUFFERCACHE_SIZE(LONG_BYTE_UNIT, Runtime.getRuntime().maxMemory() / 4), - STORAGE_BUFFERCACHE_MAXOPENFILES(UNSIGNED_INTEGER, Integer.MAX_VALUE), + STORAGE_BUFFERCACHE_MAXOPENFILES(NONNEGATIVE_INTEGER, Integer.MAX_VALUE), STORAGE_MEMORYCOMPONENT_GLOBALBUDGET(LONG_BYTE_UNIT, Runtime.getRuntime().maxMemory() / 4), STORAGE_MEMORYCOMPONENT_PAGESIZE(INTEGER_BYTE_UNIT, StorageUtil.getIntSizeInBytes(128, KILOBYTE)), STORAGE_MEMORYCOMPONENT_NUMCOMPONENTS(POSITIVE_INTEGER, 2), STORAGE_METADATA_MEMORYCOMPONENT_NUMPAGES(POSITIVE_INTEGER, 8), STORAGE_LSM_BLOOMFILTER_FALSEPOSITIVERATE(DOUBLE, 0.01d), - STORAGE_MAX_ACTIVE_WRITABLE_DATASETS(UNSIGNED_INTEGER, 8), + STORAGE_MAX_ACTIVE_WRITABLE_DATASETS(POSITIVE_INTEGER, 8), STORAGE_COMPRESSION_BLOCK(STRING, "snappy"), STORAGE_DISK_FORCE_BYTES(LONG_BYTE_UNIT, StorageUtil.getLongSizeInBytes(16, MEGABYTE)), STORAGE_IO_SCHEDULER(STRING, "greedy"); diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/TransactionProperties.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/TransactionProperties.java index 5ed069c..f813ac3 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/TransactionProperties.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/TransactionProperties.java @@ -21,8 +21,8 @@ package org.apache.asterix.common.config; import static org.apache.hyracks.control.common.config.OptionTypes.BOOLEAN; import static org.apache.hyracks.control.common.config.OptionTypes.INTEGER_BYTE_UNIT; import static org.apache.hyracks.control.common.config.OptionTypes.LONG_BYTE_UNIT; +import static org.apache.hyracks.control.common.config.OptionTypes.NONNEGATIVE_INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.POSITIVE_INTEGER; -import static org.apache.hyracks.control.common.config.OptionTypes.UNSIGNED_INTEGER; import static org.apache.hyracks.util.StorageUtil.StorageUnit.MEGABYTE; import java.util.Map; @@ -59,9 +59,9 @@ public class TransactionProperties extends AbstractProperties { 120, "The frequency (in seconds) the checkpoint thread should check to see if a checkpoint should be " + "written"), - TXN_LOG_CHECKPOINT_HISTORY(UNSIGNED_INTEGER, 2, "The number of checkpoints to keep in the transaction log"), + TXN_LOG_CHECKPOINT_HISTORY(NONNEGATIVE_INTEGER, 2, "The number of checkpoints to keep in the transaction log"), TXN_LOCK_ESCALATIONTHRESHOLD( - UNSIGNED_INTEGER, + NONNEGATIVE_INTEGER, 1000, "The maximum number of entity locks to obtain before upgrading to a dataset lock"), TXN_LOCK_SHRINKTIMER( diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/OptionTypes.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/OptionTypes.java index 7088e08..332d65b 100644 --- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/OptionTypes.java +++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/OptionTypes.java @@ -33,66 +33,11 @@ import com.fasterxml.jackson.databind.node.ObjectNode; public class OptionTypes { - public static final IOptionType<Integer> INTEGER_BYTE_UNIT = new IOptionType<Integer>() { - @Override - public Integer parse(String s) { - if (s == null) { - return null; - } - long result1 = StorageUtil.getByteValue(s); - if (result1 > Integer.MAX_VALUE || result1 < Integer.MIN_VALUE) { - throw new IllegalArgumentException("The given value: " + result1 + " is not within the int range."); - } - return (int) result1; - } - - @Override - public Integer parse(JsonNode node) { - return node.isNull() ? null : parse(node.asText()); - } - - @Override - public Class<Integer> targetType() { - return Integer.class; - } - - @Override - public String serializeToHumanReadable(Object value) { - return value + " (" + StorageUtil.toHumanReadableSize((int) value) + ")"; - } - - @Override - public void serializeJSONField(String fieldName, Object value, ObjectNode node) { - node.put(fieldName, (int) value); - } - }; - - public static final IOptionType<Long> LONG_BYTE_UNIT = new IOptionType<Long>() { - @Override - public Long parse(String s) { - return s == null ? null : StorageUtil.getByteValue(s); - } - - @Override - public Long parse(JsonNode node) { - return node.isNull() ? null : parse(node.asText()); - } - - @Override - public Class<Long> targetType() { - return Long.class; - } - - @Override - public String serializeToHumanReadable(Object value) { - return value + " (" + StorageUtil.toHumanReadableSize((long) value) + ")"; - } + public static final IOptionType<Integer> INTEGER_BYTE_UNIT = new IntegerByteUnit(); + public static final IOptionType<Integer> POSITIVE_INTEGER_BYTE_UNIT = new IntegerByteUnit(1, Integer.MAX_VALUE); - @Override - public void serializeJSONField(String fieldName, Object value, ObjectNode node) { - node.put(fieldName, (long) value); - } - }; + public static final IOptionType<Long> LONG_BYTE_UNIT = new LongByteUnit(); + public static final IOptionType<Long> POSITIVE_LONG_BYTE_UNIT = new LongByteUnit(1, Long.MAX_VALUE); public static final IOptionType<Short> SHORT = new IOptionType<Short>() { @Override @@ -124,27 +69,7 @@ public class OptionTypes { } }; - public static final IOptionType<Integer> INTEGER = new IOptionType<Integer>() { - @Override - public Integer parse(String s) { - return Integer.parseInt(s); - } - - @Override - public Integer parse(JsonNode node) { - return node.isNull() ? null : node.asInt(); - } - - @Override - public Class<Integer> targetType() { - return Integer.class; - } - - @Override - public void serializeJSONField(String fieldName, Object value, ObjectNode node) { - node.put(fieldName, (int) value); - } - }; + public static final IOptionType<Integer> INTEGER = new IntegerOptionType(); public static final IOptionType<Double> DOUBLE = new IOptionType<Double>() { @Override @@ -190,27 +115,7 @@ public class OptionTypes { } }; - public static final IOptionType<Long> LONG = new IOptionType<Long>() { - @Override - public Long parse(String s) { - return Long.parseLong(s); - } - - @Override - public Long parse(JsonNode node) { - return node.isNull() ? null : node.asLong(); - } - - @Override - public Class<Long> targetType() { - return Long.class; - } - - @Override - public void serializeJSONField(String fieldName, Object value, ObjectNode node) { - node.put(fieldName, (long) value); - } - }; + public static final IOptionType<Long> LONG = new LongOptionType(); public static final IOptionType<Boolean> BOOLEAN = new IOptionType<Boolean>() { @Override @@ -287,7 +192,7 @@ public class OptionTypes { List<String> strings = new ArrayList<>(); if (node instanceof ArrayNode) { node.elements().forEachRemaining(n -> strings.add(n.asText())); - return strings.toArray(new String[strings.size()]); + return strings.toArray(new String[0]); } else { return parse(node.asText()); } @@ -340,15 +245,26 @@ public class OptionTypes { } }; - public static final IOptionType<Integer> UNSIGNED_INTEGER = new IOptionType<Integer>() { + public static final IOptionType<Integer> NONNEGATIVE_INTEGER = getRangedIntegerType(0, Integer.MAX_VALUE); + + public static final IOptionType<Integer> POSITIVE_INTEGER = getRangedIntegerType(1, Integer.MAX_VALUE); + + private OptionTypes() { + } + + public static IOptionType<Integer> getRangedIntegerType(final int minValueInclusive, final int maxValueInclusive) { + return new RangedIntegerOptionType(minValueInclusive, maxValueInclusive); + } + + public static class IntegerOptionType implements IOptionType<Integer> { @Override public Integer parse(String s) { - return Integer.parseUnsignedInt(s); + return Integer.parseInt(s); } @Override public Integer parse(JsonNode node) { - return node.isNull() ? null : parse(node.asText()); + return node.isNull() ? null : node.asInt(); } @Override @@ -360,34 +276,155 @@ public class OptionTypes { public void serializeJSONField(String fieldName, Object value, ObjectNode node) { node.put(fieldName, (int) value); } - }; + } + + private static class RangedIntegerOptionType extends IntegerOptionType { + private final int minValue; + private final int maxValue; + + RangedIntegerOptionType(int minValue, int maxValue) { + this.minValue = minValue; + this.maxValue = maxValue; + } + + @Override + public Integer parse(String value) { + int intValue = super.parse(value); + rangeCheck(intValue); + return intValue; + } + + void rangeCheck(long intValue) { + if (intValue < minValue || intValue > maxValue) { + if (maxValue == Integer.MAX_VALUE) { + if (minValue == 0) { + throw new IllegalArgumentException("integer value must not be negative, but was " + intValue); + } else if (minValue == 1) { + throw new IllegalArgumentException( + "integer value must be greater than zero, but was " + intValue); + } + } + throw new IllegalArgumentException( + "integer value must be between " + minValue + "-" + maxValue + " (inclusive)"); + } + } + } + + private static class IntegerByteUnit extends RangedIntegerOptionType { + + IntegerByteUnit() { + this(Integer.MIN_VALUE, Integer.MAX_VALUE); + } + + IntegerByteUnit(int minValue, int maxValue) { + super(minValue, maxValue); + } - public static final IOptionType<Integer> POSITIVE_INTEGER = new IOptionType<Integer>() { @Override public Integer parse(String s) { - final int value = Integer.parseUnsignedInt(s); - if (value == 0) { - throw new IllegalArgumentException("Value must be greater than zero"); + if (s == null) { + return null; } - return value; + long result = StorageUtil.getByteValue(s); + rangeCheck(result); + return (int) result; } @Override public Integer parse(JsonNode node) { + // TODO: we accept human readable sizes from json- why not emit human readable sizes? return node.isNull() ? null : parse(node.asText()); } @Override - public Class<Integer> targetType() { - return Integer.class; + public String serializeToHumanReadable(Object value) { + return value + " (" + StorageUtil.toHumanReadableSize((int) value) + ")"; + } + } + + private static class RangedLongOptionType extends LongOptionType { + private final long minValue; + private final long maxValue; + + RangedLongOptionType(long minValue, long maxValue) { + this.minValue = minValue; + this.maxValue = maxValue; } @Override - public void serializeJSONField(String fieldName, Object value, ObjectNode node) { - node.put(fieldName, (int) value); + public Long parse(String value) { + long longValue = super.parse(value); + rangeCheck(longValue); + return longValue; } - }; - private OptionTypes() { + void rangeCheck(long longValue) { + if (longValue < minValue || longValue > maxValue) { + if (maxValue == Long.MAX_VALUE) { + if (minValue == 0) { + throw new IllegalArgumentException("long value must not be negative, but was " + longValue); + } else if (minValue == 1) { + throw new IllegalArgumentException( + "long value must be greater than zero, but was " + longValue); + } + } + throw new IllegalArgumentException( + "long value must be between " + minValue + "-" + maxValue + " (inclusive)"); + } + } + } + + private static class LongByteUnit extends RangedLongOptionType { + + LongByteUnit() { + this(Long.MIN_VALUE, Long.MAX_VALUE); + } + + LongByteUnit(long minValue, long maxValue) { + super(minValue, maxValue); + } + + @Override + public Long parse(String s) { + if (s == null) { + return null; + } + long result = StorageUtil.getByteValue(s); + rangeCheck(result); + return result; + } + + @Override + public Long parse(JsonNode node) { + // TODO: we accept human readable sizes from json- why not emit human readable sizes? + return node.isNull() ? null : parse(node.asText()); + } + + @Override + public String serializeToHumanReadable(Object value) { + return value + " (" + StorageUtil.toHumanReadableSize((long) value) + ")"; + } + } + + private static class LongOptionType implements IOptionType<Long> { + @Override + public Long parse(String s) { + return Long.parseLong(s); + } + + @Override + public Long parse(JsonNode node) { + return node.isNull() ? null : node.asLong(); + } + + @Override + public Class<Long> targetType() { + return Long.class; + } + + @Override + public void serializeJSONField(String fieldName, Object value, ObjectNode node) { + node.put(fieldName, (long) value); + } } } diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/CCConfig.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/CCConfig.java index 0de75d9..17be02e 100644 --- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/CCConfig.java +++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/CCConfig.java @@ -20,10 +20,10 @@ package org.apache.hyracks.control.common.controllers; import static org.apache.hyracks.control.common.config.OptionTypes.BOOLEAN; import static org.apache.hyracks.control.common.config.OptionTypes.LONG; +import static org.apache.hyracks.control.common.config.OptionTypes.NONNEGATIVE_INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.POSITIVE_INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.SHORT; import static org.apache.hyracks.control.common.config.OptionTypes.STRING; -import static org.apache.hyracks.control.common.config.OptionTypes.UNSIGNED_INTEGER; import java.io.File; import java.net.InetAddress; @@ -49,22 +49,22 @@ public class CCConfig extends ControllerConfig { ADDRESS(STRING, InetAddress.getLoopbackAddress().getHostAddress()), PUBLIC_ADDRESS(STRING, ADDRESS), CLUSTER_LISTEN_ADDRESS(STRING, ADDRESS), - CLUSTER_LISTEN_PORT(UNSIGNED_INTEGER, 1099), + CLUSTER_LISTEN_PORT(NONNEGATIVE_INTEGER, 1099), CLUSTER_PUBLIC_ADDRESS(STRING, PUBLIC_ADDRESS), - CLUSTER_PUBLIC_PORT(UNSIGNED_INTEGER, CLUSTER_LISTEN_PORT), + CLUSTER_PUBLIC_PORT(NONNEGATIVE_INTEGER, CLUSTER_LISTEN_PORT), CLIENT_LISTEN_ADDRESS(STRING, ADDRESS), - CLIENT_LISTEN_PORT(UNSIGNED_INTEGER, 1098), + CLIENT_LISTEN_PORT(NONNEGATIVE_INTEGER, 1098), CLIENT_PUBLIC_ADDRESS(STRING, PUBLIC_ADDRESS), - CLIENT_PUBLIC_PORT(UNSIGNED_INTEGER, CLIENT_LISTEN_PORT), + CLIENT_PUBLIC_PORT(NONNEGATIVE_INTEGER, CLIENT_LISTEN_PORT), CONSOLE_LISTEN_ADDRESS(STRING, ADDRESS), - CONSOLE_LISTEN_PORT(UNSIGNED_INTEGER, 16001), + CONSOLE_LISTEN_PORT(NONNEGATIVE_INTEGER, 16001), CONSOLE_PUBLIC_ADDRESS(STRING, PUBLIC_ADDRESS), - CONSOLE_PUBLIC_PORT(UNSIGNED_INTEGER, CONSOLE_LISTEN_PORT), + CONSOLE_PUBLIC_PORT(NONNEGATIVE_INTEGER, CONSOLE_LISTEN_PORT), HEARTBEAT_PERIOD(LONG, 10000L), // TODO (mblow): add time unit - HEARTBEAT_MAX_MISSES(UNSIGNED_INTEGER, 5), + HEARTBEAT_MAX_MISSES(NONNEGATIVE_INTEGER, 5), DEAD_NODE_SWEEP_THRESHOLD(LONG, HEARTBEAT_PERIOD), - PROFILE_DUMP_PERIOD(UNSIGNED_INTEGER, 0), - JOB_HISTORY_SIZE(UNSIGNED_INTEGER, 10), + PROFILE_DUMP_PERIOD(NONNEGATIVE_INTEGER, 0), + JOB_HISTORY_SIZE(NONNEGATIVE_INTEGER, 10), RESULT_TTL(LONG, 86400000L), // TODO(mblow): add time unit RESULT_SWEEP_THRESHOLD(LONG, 60000L), // TODO(mblow): add time unit @SuppressWarnings("RedundantCast") // not redundant- false positive from IDEA diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NCConfig.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NCConfig.java index e947d7a..ef244c5 100644 --- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NCConfig.java +++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NCConfig.java @@ -21,10 +21,10 @@ package org.apache.hyracks.control.common.controllers; import static org.apache.hyracks.control.common.config.OptionTypes.INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.INTEGER_BYTE_UNIT; import static org.apache.hyracks.control.common.config.OptionTypes.LONG; +import static org.apache.hyracks.control.common.config.OptionTypes.NONNEGATIVE_INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.POSITIVE_INTEGER; import static org.apache.hyracks.control.common.config.OptionTypes.STRING; import static org.apache.hyracks.control.common.config.OptionTypes.STRING_ARRAY; -import static org.apache.hyracks.control.common.config.OptionTypes.UNSIGNED_INTEGER; import java.net.InetAddress; import java.util.ArrayList; @@ -45,31 +45,31 @@ public class NCConfig extends ControllerConfig { ADDRESS(STRING, InetAddress.getLoopbackAddress().getHostAddress()), PUBLIC_ADDRESS(STRING, ADDRESS), CLUSTER_LISTEN_ADDRESS(STRING, ADDRESS), - CLUSTER_LISTEN_PORT(UNSIGNED_INTEGER, 0), + CLUSTER_LISTEN_PORT(NONNEGATIVE_INTEGER, 0), NCSERVICE_ADDRESS(STRING, PUBLIC_ADDRESS), NCSERVICE_PORT(INTEGER, 9090), CLUSTER_ADDRESS(STRING, (String) null), - CLUSTER_PORT(UNSIGNED_INTEGER, 1099), + CLUSTER_PORT(NONNEGATIVE_INTEGER, 1099), CLUSTER_PUBLIC_ADDRESS(STRING, PUBLIC_ADDRESS), - CLUSTER_PUBLIC_PORT(UNSIGNED_INTEGER, CLUSTER_LISTEN_PORT), + CLUSTER_PUBLIC_PORT(NONNEGATIVE_INTEGER, CLUSTER_LISTEN_PORT), NODE_ID(STRING, (String) null), DATA_LISTEN_ADDRESS(STRING, ADDRESS), - DATA_LISTEN_PORT(UNSIGNED_INTEGER, 0), + DATA_LISTEN_PORT(NONNEGATIVE_INTEGER, 0), DATA_PUBLIC_ADDRESS(STRING, PUBLIC_ADDRESS), - DATA_PUBLIC_PORT(UNSIGNED_INTEGER, DATA_LISTEN_PORT), + DATA_PUBLIC_PORT(NONNEGATIVE_INTEGER, DATA_LISTEN_PORT), RESULT_LISTEN_ADDRESS(STRING, ADDRESS), - RESULT_LISTEN_PORT(UNSIGNED_INTEGER, 0), + RESULT_LISTEN_PORT(NONNEGATIVE_INTEGER, 0), RESULT_PUBLIC_ADDRESS(STRING, PUBLIC_ADDRESS), - RESULT_PUBLIC_PORT(UNSIGNED_INTEGER, RESULT_LISTEN_PORT), + RESULT_PUBLIC_PORT(NONNEGATIVE_INTEGER, RESULT_LISTEN_PORT), MESSAGING_LISTEN_ADDRESS(STRING, ADDRESS), - MESSAGING_LISTEN_PORT(UNSIGNED_INTEGER, 0), + MESSAGING_LISTEN_PORT(NONNEGATIVE_INTEGER, 0), MESSAGING_PUBLIC_ADDRESS(STRING, PUBLIC_ADDRESS), - MESSAGING_PUBLIC_PORT(UNSIGNED_INTEGER, MESSAGING_LISTEN_PORT), + MESSAGING_PUBLIC_PORT(NONNEGATIVE_INTEGER, MESSAGING_LISTEN_PORT), REPLICATION_LISTEN_ADDRESS(STRING, ADDRESS), - REPLICATION_LISTEN_PORT(UNSIGNED_INTEGER, 2000), + REPLICATION_LISTEN_PORT(NONNEGATIVE_INTEGER, 2000), REPLICATION_PUBLIC_ADDRESS(STRING, PUBLIC_ADDRESS), - REPLICATION_PUBLIC_PORT(UNSIGNED_INTEGER, REPLICATION_LISTEN_PORT), - CLUSTER_CONNECT_RETRIES(UNSIGNED_INTEGER, 5), + REPLICATION_PUBLIC_PORT(NONNEGATIVE_INTEGER, REPLICATION_LISTEN_PORT), + CLUSTER_CONNECT_RETRIES(NONNEGATIVE_INTEGER, 5), IODEVICES( STRING_ARRAY, appConfig -> new String[] {