| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.drill.exec.server.options; |
| |
| import java.io.IOException; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.concurrent.ConcurrentMap; |
| |
| import org.apache.commons.collections.IteratorUtils; |
| import org.apache.drill.common.config.DrillConfig; |
| import org.apache.drill.exec.ExecConstants; |
| import org.apache.drill.exec.compile.ClassTransformer; |
| import org.apache.drill.exec.compile.QueryClassLoader; |
| import org.apache.drill.exec.planner.physical.PlannerSettings; |
| import org.apache.drill.exec.server.options.OptionValue.OptionType; |
| import org.apache.drill.exec.server.options.TypeValidators.BooleanValidator; |
| import org.apache.drill.exec.server.options.TypeValidators.DoubleValidator; |
| import org.apache.drill.exec.server.options.TypeValidators.LongValidator; |
| import org.apache.drill.exec.server.options.TypeValidators.StringValidator; |
| import org.apache.drill.exec.store.sys.PStore; |
| import org.apache.drill.exec.store.sys.PStoreConfig; |
| import org.apache.drill.exec.store.sys.PStoreProvider; |
| import org.apache.calcite.sql.SqlLiteral; |
| |
| import com.google.common.collect.Maps; |
| |
| public class SystemOptionManager extends BaseOptionManager { |
| private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(SystemOptionManager.class); |
| |
| private static final OptionValidator[] VALIDATORS = { |
| PlannerSettings.CONSTANT_FOLDING, |
| PlannerSettings.EXCHANGE, |
| PlannerSettings.HASHAGG, |
| PlannerSettings.STREAMAGG, |
| PlannerSettings.HASHJOIN, |
| PlannerSettings.MERGEJOIN, |
| PlannerSettings.NESTEDLOOPJOIN, |
| PlannerSettings.MULTIPHASE, |
| PlannerSettings.BROADCAST, |
| PlannerSettings.BROADCAST_THRESHOLD, |
| PlannerSettings.BROADCAST_FACTOR, |
| PlannerSettings.NESTEDLOOPJOIN_FACTOR, |
| PlannerSettings.NLJOIN_FOR_SCALAR, |
| PlannerSettings.JOIN_ROW_COUNT_ESTIMATE_FACTOR, |
| PlannerSettings.MUX_EXCHANGE, |
| PlannerSettings.DEMUX_EXCHANGE, |
| PlannerSettings.PRODUCER_CONSUMER, |
| PlannerSettings.PRODUCER_CONSUMER_QUEUE_SIZE, |
| PlannerSettings.HASH_SINGLE_KEY, |
| PlannerSettings.IDENTIFIER_MAX_LENGTH, |
| PlannerSettings.HASH_JOIN_SWAP, |
| PlannerSettings.HASH_JOIN_SWAP_MARGIN_FACTOR, |
| PlannerSettings.PARTITION_SENDER_THREADS_FACTOR, |
| PlannerSettings.PARTITION_SENDER_MAX_THREADS, |
| PlannerSettings.PARTITION_SENDER_SET_THREADS, |
| ExecConstants.CAST_TO_NULLABLE_NUMERIC_OPTION, |
| ExecConstants.OUTPUT_FORMAT_VALIDATOR, |
| ExecConstants.PARQUET_BLOCK_SIZE_VALIDATOR, |
| ExecConstants.PARQUET_WRITER_COMPRESSION_TYPE_VALIDATOR, |
| ExecConstants.PARQUET_WRITER_ENABLE_DICTIONARY_ENCODING_VALIDATOR, |
| ExecConstants.PARQUET_VECTOR_FILL_THRESHOLD_VALIDATOR, |
| ExecConstants.PARQUET_VECTOR_FILL_CHECK_THRESHOLD_VALIDATOR, |
| ExecConstants.PARQUET_RECORD_READER_IMPLEMENTATION_VALIDATOR, |
| ExecConstants.JSON_READER_ALL_TEXT_MODE_VALIDATOR, |
| ExecConstants.JSON_EXTENDED_TYPES, |
| ExecConstants.FILESYSTEM_PARTITION_COLUMN_LABEL_VALIDATOR, |
| ExecConstants.MONGO_READER_ALL_TEXT_MODE_VALIDATOR, |
| ExecConstants.SLICE_TARGET_OPTION, |
| ExecConstants.AFFINITY_FACTOR, |
| ExecConstants.MAX_WIDTH_GLOBAL, |
| ExecConstants.MAX_WIDTH_PER_NODE, |
| ExecConstants.ENABLE_QUEUE, |
| ExecConstants.LARGE_QUEUE_SIZE, |
| ExecConstants.QUEUE_THRESHOLD_SIZE, |
| ExecConstants.QUEUE_TIMEOUT, |
| ExecConstants.SMALL_QUEUE_SIZE, |
| ExecConstants.MIN_HASH_TABLE_SIZE, |
| ExecConstants.MAX_HASH_TABLE_SIZE, |
| ExecConstants.ENABLE_MEMORY_ESTIMATION, |
| ExecConstants.MAX_QUERY_MEMORY_PER_NODE, |
| ExecConstants.NON_BLOCKING_OPERATORS_MEMORY, |
| ExecConstants.HASH_JOIN_TABLE_FACTOR, |
| ExecConstants.HASH_AGG_TABLE_FACTOR, |
| ExecConstants.AVERAGE_FIELD_WIDTH, |
| ExecConstants.NEW_VIEW_DEFAULT_PERMS_VALIDATOR, |
| ExecConstants.USE_OLD_ASSIGNMENT_CREATOR_VALIDATOR, |
| QueryClassLoader.JAVA_COMPILER_VALIDATOR, |
| QueryClassLoader.JAVA_COMPILER_JANINO_MAXSIZE, |
| QueryClassLoader.JAVA_COMPILER_DEBUG, |
| ExecConstants.ENABLE_VERBOSE_ERRORS, |
| ExecConstants.ENABLE_WINDOW_FUNCTIONS_VALIDATOR, |
| ExecConstants.DRILLBIT_CONTROLS_VALIDATOR, |
| ClassTransformer.SCALAR_REPLACEMENT_VALIDATOR, |
| }; |
| |
| private final PStoreConfig<OptionValue> config; |
| private PStore<OptionValue> options; |
| private SystemOptionAdmin admin; |
| private final ConcurrentMap<String, OptionValidator> knownOptions = Maps.newConcurrentMap(); |
| private final PStoreProvider provider; |
| |
| public SystemOptionManager(final DrillConfig config, final PStoreProvider provider) { |
| this.provider = provider; |
| this.config = PStoreConfig.newJacksonBuilder(config.getMapper(), OptionValue.class) |
| .name("sys.options") |
| .build(); |
| } |
| |
| public SystemOptionManager init() throws IOException { |
| options = provider.getStore(config); |
| admin = new SystemOptionAdmin(); |
| return this; |
| } |
| |
| @Override |
| public Iterator<OptionValue> iterator() { |
| final Map<String, OptionValue> buildList = Maps.newHashMap(); |
| for(OptionValidator v : knownOptions.values()){ |
| buildList.put(v.getOptionName(), v.getDefault()); |
| } |
| for(Map.Entry<String, OptionValue> v : options){ |
| final OptionValue value = v.getValue(); |
| buildList.put(value.name, value); |
| } |
| return buildList.values().iterator(); |
| } |
| |
| @Override |
| public OptionValue getOption(final String name) { |
| // check local space |
| final OptionValue v = options.get(name); |
| if(v != null){ |
| return v; |
| } |
| |
| // otherwise, return default. |
| OptionValidator validator = knownOptions.get(name); |
| if(validator == null) { |
| return null; |
| } else { |
| return validator.getDefault(); |
| } |
| } |
| |
| @Override |
| public void setOption(final OptionValue value) { |
| assert value.type == OptionType.SYSTEM; |
| admin.validate(value); |
| setOptionInternal(value); |
| } |
| |
| private void setOptionInternal(final OptionValue value) { |
| if (!value.equals(knownOptions.get(value.name))) { |
| options.put(value.name, value); |
| } |
| } |
| |
| |
| @Override |
| public void setOption(final String name, final SqlLiteral literal, final OptionType type) { |
| assert type == OptionValue.OptionType.SYSTEM || type == OptionValue.OptionType.SESSION; |
| final OptionValue v = admin.validate(name, literal, type); |
| setOptionInternal(v); |
| } |
| |
| @Override |
| public OptionList getOptionList() { |
| return (OptionList) IteratorUtils.toList(iterator()); |
| } |
| |
| @Override |
| public OptionManager getSystemManager() { |
| return this; |
| } |
| |
| @Override |
| public OptionAdmin getAdmin() { |
| return admin; |
| } |
| |
| private class SystemOptionAdmin implements OptionAdmin { |
| public SystemOptionAdmin() { |
| for(OptionValidator v : VALIDATORS) { |
| knownOptions.put(v.getOptionName(), v); |
| } |
| |
| for(Entry<String, OptionValue> v : options) { |
| final OptionValue value = v.getValue(); |
| final OptionValidator defaultValidator = knownOptions.get(v.getKey()); |
| if (defaultValidator == null) { |
| // deprecated option, delete. |
| options.delete(value.name); |
| logger.warn("Deleting deprecated option `{}`.", value.name); |
| } |
| } |
| } |
| |
| @Override |
| public void registerOptionType(final OptionValidator validator) { |
| if (null != knownOptions.putIfAbsent(validator.getOptionName(), validator)) { |
| throw new IllegalArgumentException("Only one option is allowed to be registered with name: " |
| + validator.getOptionName()); |
| } |
| } |
| |
| @Override |
| public OptionValidator getValidator(final String name) { |
| return knownOptions.get(name); |
| } |
| |
| @Override |
| public void validate(final OptionValue v) throws SetOptionException { |
| final OptionValidator validator = knownOptions.get(v.name); |
| if (validator == null) { |
| throw new SetOptionException("Unknown option " + v.name); |
| } |
| validator.validate(v); |
| } |
| |
| @Override |
| public OptionValue validate(final String name, final SqlLiteral value, final OptionType optionType) |
| throws SetOptionException { |
| final OptionValidator validator = knownOptions.get(name); |
| if (validator == null) { |
| throw new SetOptionException("Unknown option: " + name); |
| } |
| return validator.validate(value, optionType); |
| } |
| } |
| } |