// Copyright 2016 Twitter. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.twitter.heron.common.config; import java.io.File; import java.time.Duration; import java.util.HashMap; import java.util.Map; import com.twitter.heron.common.basics.ByteAmount; import com.twitter.heron.common.basics.TypeUtils; /** * SystemConfig are a set of configuration parameters that are set by the system * All the config associated with time is in the unit of milli-seconds, unless otherwise specified. * All the config associated with data is in the unit of bytes, unless otherwise specified. */ public final class SystemConfig { /** * Bean name for SingletonRegistry */ public static final String HERON_SYSTEM_CONFIG = SystemConfig.class.getName(); private Map<String, Object> config = new HashMap<>(); private SystemConfig(Builder build) { this.config = new HashMap<>(build.keyValues); } public static Builder newBuilder(boolean loadDefaults) { return Builder.create(loadDefaults); } public int getInstanceInternalMetricsWriteQueueCapacity() { return getInteger(SystemConfigKey.INSTANCE_INTERNAL_METRICS_WRITE_QUEUE_CAPACITY); } public int getInstanceTuningExpectedMetricsWriteQueueSize() { return getInteger(SystemConfigKey.INSTANCE_TUNING_EXPECTED_METRICS_WRITE_QUEUE_SIZE); } public int getInstanceSetDataTupleCapacity() { return getInteger(SystemConfigKey.INSTANCE_SET_DATA_TUPLE_CAPACITY); } public ByteAmount getInstanceSetDataTupleSize() { return getByteAmount(SystemConfigKey.INSTANCE_SET_DATA_TUPLE_SIZE); } public int getInstanceSetControlTupleCapacity() { return getInteger(SystemConfigKey.INSTANCE_SET_CONTROL_TUPLE_CAPACITY); } public Duration getInstanceForceExitTimeout() { return getDuration(SystemConfigKey.INSTANCE_FORCE_EXIT_TIMEOUT); } public Duration getInstanceStateCheckInterval() { return getDuration(SystemConfigKey.INSTANCE_STATE_CHECK_INTERVAL); } public int getInstanceInternalBoltReadQueueCapacity() { return getInteger(SystemConfigKey.INSTANCE_INTERNAL_BOLT_READ_QUEUE_CAPACITY); } public int getInstanceInternalBoltWriteQueueCapacity() { return getInteger(SystemConfigKey.INSTANCE_INTERNAL_BOLT_WRITE_QUEUE_CAPACITY); } public int getInstanceInternalSpoutReadQueueCapacity() { return getInteger(SystemConfigKey.INSTANCE_INTERNAL_SPOUT_READ_QUEUE_CAPACITY); } public int getInstanceInternalSpoutWriteQueueCapacity() { return getInteger(SystemConfigKey.INSTANCE_INTERNAL_SPOUT_WRITE_QUEUE_CAPACITY); } public Duration getInstanceAckBatchTime() { return getDuration(SystemConfigKey.INSTANCE_ACK_BATCH_TIME); } public int getInstanceTuningExpectedBoltReadQueueSize() { return getInteger(SystemConfigKey.INSTANCE_TUNING_EXPECTED_BOLT_READ_QUEUE_SIZE); } public int getInstanceTuningExpectedBoltWriteQueueSize() { return getInteger(SystemConfigKey.INSTANCE_TUNING_EXPECTED_BOLT_WRITE_QUEUE_SIZE); } public int getInstanceTuningExpectedSpoutReadQueueSize() { return getInteger(SystemConfigKey.INSTANCE_TUNING_EXPECTED_SPOUT_READ_QUEUE_SIZE); } public int getInstanceTuningExpectedSpoutWriteQueueSize() { return getInteger(SystemConfigKey.INSTANCE_TUNING_EXPECTED_SPOUT_WRITE_QUEUE_SIZE); } public String getHeronLoggingDirectory() { return getString(SystemConfigKey.HERON_LOGGING_DIRECTORY); } public ByteAmount getHeronLoggingMaximumSize() { return ByteAmount.fromMegabytes(getInteger(SystemConfigKey.HERON_LOGGING_MAXIMUM_SIZE_MB)); } public int getHeronLoggingMaximumFiles() { return getInteger(SystemConfigKey.HERON_LOGGING_MAXIMUM_FILES); } public Duration getHeronMetricsExportInterval() { return getDuration(SystemConfigKey.HERON_METRICS_EXPORT_INTERVAL); } public Duration getInstanceNetworkReadBatchTime() { return getDuration(SystemConfigKey.INSTANCE_NETWORK_READ_BATCH_TIME); } public ByteAmount getInstanceNetworkReadBatchSize() { return getByteAmount(SystemConfigKey.INSTANCE_NETWORK_READ_BATCH_SIZE); } public Duration getInstanceNetworkWriteBatchTime() { return getDuration(SystemConfigKey.INSTANCE_NETWORK_WRITE_BATCH_TIME); } public ByteAmount getInstanceNetworkWriteBatchSize() { return getByteAmount(SystemConfigKey.INSTANCE_NETWORK_WRITE_BATCH_SIZE); } public ByteAmount getInstanceNetworkOptionsSocketReceivedBufferSize() { return getByteAmount(SystemConfigKey.INSTANCE_NETWORK_OPTIONS_SOCKET_RECEIVED_BUFFER_SIZE); } public ByteAmount getInstanceNetworkOptionsSocketSendBufferSize() { return getByteAmount(SystemConfigKey.INSTANCE_NETWORK_OPTIONS_SOCKET_SEND_BUFFER_SIZE); } public Duration getInstanceEmitBatchTime() { return getDuration(SystemConfigKey.INSTANCE_EMIT_BATCH_TIME); } public ByteAmount getInstanceEmitBatchSize() { return getByteAmount(SystemConfigKey.INSTANCE_EMIT_BATCH_SIZE); } public Duration getInstanceExecuteBatchTime() { return getDuration(SystemConfigKey.INSTANCE_EXECUTE_BATCH_TIME); } public ByteAmount getInstanceExecuteBatchSize() { return getByteAmount(SystemConfigKey.INSTANCE_EXECUTE_BATCH_SIZE); } public Duration getInstanceReconnectStreammgrInterval() { return getDuration(SystemConfigKey.INSTANCE_RECONNECT_STREAMMGR_INTERVAL); } public Duration getInstanceReconnectMetricsmgrInterval() { return getDuration(SystemConfigKey.INSTANCE_RECONNECT_METRICSMGR_INTERVAL); } public Duration getInstanceMetricsSystemSampleInterval() { return getDuration(SystemConfigKey.INSTANCE_METRICS_SYSTEM_SAMPLE_INTERVAL); } public int getInstanceAcknowledgementNbuckets() { return getInteger(SystemConfigKey.INSTANCE_ACKNOWLEDGEMENT_NBUCKETS); } public Duration getInstanceSlaveFetchPplanInterval() { return getDuration(SystemConfigKey.INSTANCE_SLAVE_FETCH_PPLAN_INTERVAL); } public Duration getInstanceTuningInterval() { return getDuration(SystemConfigKey.INSTANCE_TUNING_INTERVAL); } public double getInstanceTuningCurrentSampleWeight() { return getDouble(SystemConfigKey.INSTANCE_TUNING_CURRENT_SAMPLE_WEIGHT); } public Duration getMetricsMgrNetworkReadBatchTime() { return getDuration(SystemConfigKey.METRICSMGR_NETWORK_READ_BATCH_TIME); } public ByteAmount getMetricsMgrNetworkReadBatchSize() { return getByteAmount(SystemConfigKey.METRICSMGR_NETWORK_READ_BATCH_SIZE); } public Duration getMetricsMgrNetworkWriteBatchTime() { return getDuration(SystemConfigKey.METRICSMGR_NETWORK_WRITE_BATCH_TIME); } public ByteAmount getMetricsMgrNetworkWriteBatchSize() { return getByteAmount(SystemConfigKey.METRICSMGR_NETWORK_WRITE_BATCH_SIZE); } public ByteAmount getMetricsMgrNetworkOptionsSocketReceivedBufferSize() { return getByteAmount(SystemConfigKey.METRICSMGR_NETWORK_OPTIONS_SOCKET_RECEIVED_BUFFER_SIZE); } public ByteAmount getMetricsMgrNetworkOptionsSocketSendBufferSize() { return getByteAmount(SystemConfigKey.METRICSMGR_NETWORK_OPTIONS_SOCKET_SEND_BUFFER_SIZE); } public int getHeronMetricsMaxExceptionsPerMessageCount() { return getInteger(SystemConfigKey.HERON_METRICS_MAX_EXCEPTIONS_PER_MESSAGE_COUNT); } public long getTmasterMetricsCollectorMaximumException() { try { return getLong(SystemConfigKey.TMASTER_METRICS_COLLECTOR_MAXIMUM_EXCEPTION); } catch (IllegalArgumentException e) { return 256; // default value if not found in config } } public Duration getTmasterMetricsCollectorMaximumInterval() { return getDuration(SystemConfigKey.TMASTER_METRICS_COLLECTOR_MAXIMUM_INTERVAL); } public Duration getTmasterMetricsCollectorPurgeInterval() { return getDuration(SystemConfigKey.TMASTER_METRICS_COLLECTOR_PURGE_INTERVAL); } private String getString(SystemConfigKey key) { assertType(key, SystemConfigKey.Type.STRING); return (String) get(key); } private Integer getInteger(SystemConfigKey key) { assertType(key, SystemConfigKey.Type.INTEGER); return TypeUtils.getInteger(get(key)); } private Long getLong(SystemConfigKey key) { assertType(key, SystemConfigKey.Type.LONG); return TypeUtils.getLong(get(key)); } private Double getDouble(SystemConfigKey key) { assertType(key, SystemConfigKey.Type.DOUBLE); return TypeUtils.getDouble(get(key)); } private Duration getDuration(SystemConfigKey key) { assertType(key, SystemConfigKey.Type.DURATION); return TypeUtils.getDuration(get(key), key.getTemporalUnit()); } private ByteAmount getByteAmount(SystemConfigKey key) { assertType(key, SystemConfigKey.Type.BYTE_AMOUNT); return TypeUtils.getByteAmount(get(key)); } private Object get(SystemConfigKey key) { return config.get(key.value()); } private void assertType(SystemConfigKey key, SystemConfigKey.Type type) { if (key.getType() != type) { throw new IllegalArgumentException(String.format( "config key %s is of type %s instead of expected type %s", key, key.getType(), type)); } } public static class Builder { private final Map<String, Object> keyValues = new HashMap<>(); private static SystemConfig.Builder create(boolean loadDefaults) { SystemConfig.Builder cb = new Builder(); if (loadDefaults) { loadDefaults(cb, SystemConfigKey.values()); } return cb; } private static void loadDefaults(SystemConfig.Builder cb, SystemConfigKey... keys) { for (SystemConfigKey key : keys) { if (key.getDefault() != null) { cb.put(key, key.getDefault()); } } } public Builder put(SystemConfigKey key, Object value) { convertAndAdd(this.keyValues, key, value); return this; } public Builder putAll(String fileName, boolean mustExist) { File file = new File(fileName); if (!file.exists() && mustExist) { throw new IllegalArgumentException( String.format("Config file %s does not exist", fileName)); } // convert to the correct type upon load eagerly verify type correctness Map<String, Object> configValues = ConfigReader.loadFile(fileName); for (String keyValue : configValues.keySet()) { SystemConfigKey key = SystemConfigKey.toSystemConfigKey(keyValue); if (key != null) { // sometimes config have non-java configs without an enum SystemConfigKey convertAndAdd(configValues, key, configValues.get(keyValue)); } } keyValues.putAll(configValues); return this; } private static void convertAndAdd(Map<String, Object> config, SystemConfigKey key, Object value) { if (key != null) { // sometimes config have non-java configs without an enum SystemConfigKey switch(key.getType()) { case BOOLEAN: config.put(key.value(), TypeUtils.getBoolean(value)); break; case BYTE_AMOUNT: config.put(key.value(), TypeUtils.getByteAmount(value)); break; case DOUBLE: config.put(key.value(), TypeUtils.getDouble(value)); break; case DURATION: config.put(key.value(), TypeUtils.getDuration(value, key.getTemporalUnit())); break; case INTEGER: config.put(key.value(), TypeUtils.getInteger(value)); break; case LONG: config.put(key.value(), TypeUtils.getLong(value)); break; case STRING: break; default: throw new IllegalArgumentException(String.format( "config key %s is of type %s which is not yet supported", key, key.getType())); } } } public SystemConfig build() { return new SystemConfig(this); } } }