| /* |
| * 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.cassandra.cql3.statements.schema; |
| |
| import java.util.Map; |
| import java.util.Set; |
| |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.collect.Sets; |
| |
| import org.apache.cassandra.cql3.statements.PropertyDefinitions; |
| import org.apache.cassandra.exceptions.ConfigurationException; |
| import org.apache.cassandra.schema.CachingParams; |
| import org.apache.cassandra.schema.CompactionParams; |
| import org.apache.cassandra.schema.CompressionParams; |
| import org.apache.cassandra.schema.MemtableParams; |
| import org.apache.cassandra.schema.TableId; |
| import org.apache.cassandra.schema.TableParams; |
| import org.apache.cassandra.schema.TableParams.Option; |
| import org.apache.cassandra.service.reads.SpeculativeRetryPolicy; |
| import org.apache.cassandra.service.reads.repair.ReadRepairStrategy; |
| |
| import static java.lang.String.format; |
| import static org.apache.cassandra.schema.TableParams.Option.*; |
| |
| public final class TableAttributes extends PropertyDefinitions |
| { |
| public static final String ID = "id"; |
| private static final Set<String> validKeywords; |
| private static final Set<String> obsoleteKeywords; |
| |
| static |
| { |
| ImmutableSet.Builder<String> validBuilder = ImmutableSet.builder(); |
| for (Option option : Option.values()) |
| validBuilder.add(option.toString()); |
| validBuilder.add(ID); |
| validKeywords = validBuilder.build(); |
| obsoleteKeywords = ImmutableSet.of(); |
| } |
| |
| public void validate() |
| { |
| validate(validKeywords, obsoleteKeywords); |
| build(TableParams.builder()).validate(); |
| } |
| |
| TableParams asNewTableParams() |
| { |
| return build(TableParams.builder()); |
| } |
| |
| TableParams asAlteredTableParams(TableParams previous) |
| { |
| if (getId() != null) |
| throw new ConfigurationException("Cannot alter table id."); |
| return build(previous.unbuild()); |
| } |
| |
| public TableId getId() throws ConfigurationException |
| { |
| String id = getString(ID); |
| try |
| { |
| return id != null ? TableId.fromString(id) : null; |
| } |
| catch (IllegalArgumentException e) |
| { |
| throw new ConfigurationException("Invalid table id", e); |
| } |
| } |
| |
| public static Set<String> validKeywords() |
| { |
| return ImmutableSet.copyOf(validKeywords); |
| } |
| |
| public static Set<String> allKeywords() |
| { |
| return Sets.union(validKeywords, obsoleteKeywords); |
| } |
| |
| private TableParams build(TableParams.Builder builder) |
| { |
| if (hasOption(Option.ALLOW_AUTO_SNAPSHOT)) |
| builder.allowAutoSnapshot(getBoolean(Option.ALLOW_AUTO_SNAPSHOT.toString(), true)); |
| |
| if (hasOption(BLOOM_FILTER_FP_CHANCE)) |
| builder.bloomFilterFpChance(getDouble(BLOOM_FILTER_FP_CHANCE)); |
| |
| if (hasOption(CACHING)) |
| builder.caching(CachingParams.fromMap(getMap(CACHING))); |
| |
| if (hasOption(COMMENT)) |
| builder.comment(getString(COMMENT)); |
| |
| if (hasOption(COMPACTION)) |
| builder.compaction(CompactionParams.fromMap(getMap(COMPACTION))); |
| |
| if (hasOption(COMPRESSION)) |
| { |
| //crc_check_chance was "promoted" from a compression property to a top-level-property after #9839, |
| //so we temporarily accept it to be defined as a compression option, to maintain backwards compatibility |
| Map<String, String> compressionOpts = getMap(COMPRESSION); |
| if (compressionOpts.containsKey(CRC_CHECK_CHANCE.toString().toLowerCase())) |
| { |
| double crcCheckChance = getDeprecatedCrcCheckChance(compressionOpts); |
| builder.crcCheckChance(crcCheckChance); |
| } |
| builder.compression(CompressionParams.fromMap(getMap(COMPRESSION))); |
| } |
| |
| if (hasOption(Option.MEMTABLE)) |
| builder.memtable(MemtableParams.get(getString(Option.MEMTABLE))); |
| |
| if (hasOption(DEFAULT_TIME_TO_LIVE)) |
| builder.defaultTimeToLive(getInt(DEFAULT_TIME_TO_LIVE)); |
| |
| if (hasOption(GC_GRACE_SECONDS)) |
| builder.gcGraceSeconds(getInt(GC_GRACE_SECONDS)); |
| |
| if (hasOption(INCREMENTAL_BACKUPS)) |
| builder.incrementalBackups(getBoolean(INCREMENTAL_BACKUPS.toString(), true)); |
| |
| if (hasOption(MAX_INDEX_INTERVAL)) |
| builder.maxIndexInterval(getInt(MAX_INDEX_INTERVAL)); |
| |
| if (hasOption(MEMTABLE_FLUSH_PERIOD_IN_MS)) |
| builder.memtableFlushPeriodInMs(getInt(MEMTABLE_FLUSH_PERIOD_IN_MS)); |
| |
| if (hasOption(MIN_INDEX_INTERVAL)) |
| builder.minIndexInterval(getInt(MIN_INDEX_INTERVAL)); |
| |
| if (hasOption(SPECULATIVE_RETRY)) |
| builder.speculativeRetry(SpeculativeRetryPolicy.fromString(getString(SPECULATIVE_RETRY))); |
| |
| if (hasOption(ADDITIONAL_WRITE_POLICY)) |
| builder.additionalWritePolicy(SpeculativeRetryPolicy.fromString(getString(ADDITIONAL_WRITE_POLICY))); |
| |
| if (hasOption(CRC_CHECK_CHANCE)) |
| builder.crcCheckChance(getDouble(CRC_CHECK_CHANCE)); |
| |
| if (hasOption(CDC)) |
| builder.cdc(getBoolean(CDC)); |
| |
| if (hasOption(READ_REPAIR)) |
| builder.readRepair(ReadRepairStrategy.fromString(getString(READ_REPAIR))); |
| |
| return builder.build(); |
| } |
| |
| public boolean hasOption(Option option) |
| { |
| return hasProperty(option.toString()); |
| } |
| |
| private String getString(Option option) |
| { |
| String value = getString(option.toString()); |
| if (value == null) |
| throw new IllegalStateException(format("Option '%s' is absent", option)); |
| return value; |
| } |
| |
| private Map<String, String> getMap(Option option) |
| { |
| Map<String, String> value = getMap(option.toString()); |
| if (value == null) |
| throw new IllegalStateException(format("Option '%s' is absent", option)); |
| return value; |
| } |
| |
| private boolean getBoolean(Option option) |
| { |
| return parseBoolean(option.toString(), getString(option)); |
| } |
| |
| private int getInt(Option option) |
| { |
| return parseInt(option.toString(), getString(option)); |
| } |
| |
| private double getDouble(Option option) |
| { |
| return parseDouble(option.toString(), getString(option)); |
| } |
| |
| private double getDeprecatedCrcCheckChance(Map<String, String> compressionOpts) |
| { |
| String value = compressionOpts.get(CRC_CHECK_CHANCE.toString().toLowerCase()); |
| return parseDouble(CRC_CHECK_CHANCE.toString(), value); |
| } |
| } |