All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cassandra.cql3.statements.CFPropDefs Maven / Gradle / Ivy

There is a newer version: 2.2.18-2.2.18-1.170.1-rc1
Show newest version
/*
 * 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;

import java.util.*;

import org.apache.cassandra.cache.CachingOptions;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.CFMetaData.SpeculativeRetry;
import org.apache.cassandra.db.ExpiringCell;
import org.apache.cassandra.db.compaction.AbstractCompactionStrategy;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.io.compress.CompressionParameters;
import org.apache.cassandra.utils.BloomCalculations;

public class CFPropDefs extends PropertyDefinitions
{
    public static final String KW_COMMENT = "comment";
    public static final String KW_READREPAIRCHANCE = "read_repair_chance";
    public static final String KW_DCLOCALREADREPAIRCHANCE = "dclocal_read_repair_chance";
    public static final String KW_GCGRACESECONDS = "gc_grace_seconds";
    public static final String KW_MINCOMPACTIONTHRESHOLD = "min_threshold";
    public static final String KW_MAXCOMPACTIONTHRESHOLD = "max_threshold";
    public static final String KW_CACHING = "caching";
    public static final String KW_DEFAULT_TIME_TO_LIVE = "default_time_to_live";
    public static final String KW_MIN_INDEX_INTERVAL = "min_index_interval";
    public static final String KW_MAX_INDEX_INTERVAL = "max_index_interval";
    public static final String KW_SPECULATIVE_RETRY = "speculative_retry";
    public static final String KW_BF_FP_CHANCE = "bloom_filter_fp_chance";
    public static final String KW_MEMTABLE_FLUSH_PERIOD = "memtable_flush_period_in_ms";

    public static final String KW_COMPACTION = "compaction";
    public static final String KW_COMPRESSION = "compression";

    public static final String KW_ID = "id";

    public static final String COMPACTION_STRATEGY_CLASS_KEY = "class";

    public static final Set keywords = new HashSet<>();
    public static final Set obsoleteKeywords = new HashSet<>();

    static
    {
        keywords.add(KW_COMMENT);
        keywords.add(KW_READREPAIRCHANCE);
        keywords.add(KW_DCLOCALREADREPAIRCHANCE);
        keywords.add(KW_GCGRACESECONDS);
        keywords.add(KW_CACHING);
        keywords.add(KW_DEFAULT_TIME_TO_LIVE);
        keywords.add(KW_MIN_INDEX_INTERVAL);
        keywords.add(KW_MAX_INDEX_INTERVAL);
        keywords.add(KW_SPECULATIVE_RETRY);
        keywords.add(KW_BF_FP_CHANCE);
        keywords.add(KW_COMPACTION);
        keywords.add(KW_COMPRESSION);
        keywords.add(KW_MEMTABLE_FLUSH_PERIOD);
        keywords.add(KW_ID);

        obsoleteKeywords.add("index_interval");
        obsoleteKeywords.add("replicate_on_write");
        obsoleteKeywords.add("populate_io_cache_on_flush");
    }

    private Class compactionStrategyClass = null;

    public void validate() throws ConfigurationException, SyntaxException
    {
        // Skip validation if the comapction strategy class is already set as it means we've alreayd
        // prepared (and redoing it would set strategyClass back to null, which we don't want)
        if (compactionStrategyClass != null)
            return;

        validate(keywords, obsoleteKeywords);

        try
        {
            getId();
        }
        catch (IllegalArgumentException e)
        {
            throw new ConfigurationException("Invalid table id", e);
        }

        Map compactionOptions = getCompactionOptions();
        if (!compactionOptions.isEmpty())
        {
            String strategy = compactionOptions.get(COMPACTION_STRATEGY_CLASS_KEY);
            if (strategy == null)
                throw new ConfigurationException("Missing sub-option '" + COMPACTION_STRATEGY_CLASS_KEY + "' for the '" + KW_COMPACTION + "' option.");

            compactionStrategyClass = CFMetaData.createCompactionStrategy(strategy);
            compactionOptions.remove(COMPACTION_STRATEGY_CLASS_KEY);

            CFMetaData.validateCompactionOptions(compactionStrategyClass, compactionOptions);
        }

        Map compressionOptions = getCompressionOptions();
        if (!compressionOptions.isEmpty())
        {
            String sstableCompressionClass = compressionOptions.get(CompressionParameters.SSTABLE_COMPRESSION);
            if (sstableCompressionClass == null)
                throw new ConfigurationException("Missing sub-option '" + CompressionParameters.SSTABLE_COMPRESSION + "' for the '" + KW_COMPRESSION + "' option.");

            Integer chunkLength = CompressionParameters.DEFAULT_CHUNK_LENGTH;
            if (compressionOptions.containsKey(CompressionParameters.CHUNK_LENGTH_KB))
                chunkLength = CompressionParameters.parseChunkLength(compressionOptions.get(CompressionParameters.CHUNK_LENGTH_KB));

            Map remainingOptions = new HashMap<>(compressionOptions);
            remainingOptions.remove(CompressionParameters.SSTABLE_COMPRESSION);
            remainingOptions.remove(CompressionParameters.CHUNK_LENGTH_KB);
            CompressionParameters cp = new CompressionParameters(sstableCompressionClass, chunkLength, remainingOptions);
            cp.validate();
        }

        validateMinimumInt(KW_DEFAULT_TIME_TO_LIVE, 0, CFMetaData.DEFAULT_DEFAULT_TIME_TO_LIVE);
        Integer defaultTimeToLive = getInt(KW_DEFAULT_TIME_TO_LIVE, 0);
        if (defaultTimeToLive > ExpiringCell.MAX_TTL)
            throw new ConfigurationException(String.format("%s must be less than or equal to %d (got %s)",
                                                           KW_DEFAULT_TIME_TO_LIVE,
                                                           ExpiringCell.MAX_TTL,
                                                           defaultTimeToLive));

        Integer minIndexInterval = getInt(KW_MIN_INDEX_INTERVAL, null);
        Integer maxIndexInterval = getInt(KW_MAX_INDEX_INTERVAL, null);
        if (minIndexInterval != null && minIndexInterval < 1)
            throw new ConfigurationException(KW_MIN_INDEX_INTERVAL + " must be greater than 0");
        if (maxIndexInterval != null && minIndexInterval != null && maxIndexInterval < minIndexInterval)
            throw new ConfigurationException(KW_MAX_INDEX_INTERVAL + " must be greater than " + KW_MIN_INDEX_INTERVAL);

        SpeculativeRetry.fromString(getString(KW_SPECULATIVE_RETRY, SpeculativeRetry.RetryType.NONE.name()));
    }

    public Class getCompactionStrategy()
    {
        return compactionStrategyClass;
    }

    public Map getCompactionOptions() throws SyntaxException
    {
        Map compactionOptions = getMap(KW_COMPACTION);
        if (compactionOptions == null)
            return Collections.emptyMap();
        return compactionOptions;
    }

    public Map getCompressionOptions() throws SyntaxException
    {
        Map compressionOptions = getMap(KW_COMPRESSION);
        if (compressionOptions == null)
            return Collections.emptyMap();
        return compressionOptions;
    }
    public CachingOptions getCachingOptions() throws SyntaxException, ConfigurationException
    {
        CachingOptions options = null;
        Object val = properties.get(KW_CACHING);
        if (val == null)
            return null;
        else if (val instanceof Map)
            options = CachingOptions.fromMap(getMap(KW_CACHING));
        else if (val instanceof String) // legacy syntax
        {
            options = CachingOptions.fromString(getSimple(KW_CACHING));
            logger.warn("Setting caching options with deprecated syntax.");
        }
        return options;
    }

    public Integer getDefaultTimeToLive() throws SyntaxException
    {
        return getInt(KW_DEFAULT_TIME_TO_LIVE, 0);
    }

    public UUID getId() throws SyntaxException
    {
        String id = getSimple(KW_ID);
        return id != null ? UUID.fromString(id) : null;
    }

    public void applyToCFMetadata(CFMetaData cfm) throws ConfigurationException, SyntaxException
    {
        if (hasProperty(KW_COMMENT))
            cfm.comment(getString(KW_COMMENT, ""));

        cfm.readRepairChance(getDouble(KW_READREPAIRCHANCE, cfm.getReadRepairChance()));
        cfm.dcLocalReadRepairChance(getDouble(KW_DCLOCALREADREPAIRCHANCE, cfm.getDcLocalReadRepairChance()));
        cfm.gcGraceSeconds(getInt(KW_GCGRACESECONDS, cfm.getGcGraceSeconds()));
        int minCompactionThreshold = toInt(KW_MINCOMPACTIONTHRESHOLD, getCompactionOptions().get(KW_MINCOMPACTIONTHRESHOLD), cfm.getMinCompactionThreshold());
        int maxCompactionThreshold = toInt(KW_MAXCOMPACTIONTHRESHOLD, getCompactionOptions().get(KW_MAXCOMPACTIONTHRESHOLD), cfm.getMaxCompactionThreshold());
        if (minCompactionThreshold <= 0 || maxCompactionThreshold <= 0)
            throw new ConfigurationException("Disabling compaction by setting compaction thresholds to 0 has been deprecated, set the compaction option 'enabled' to false instead.");
        cfm.minCompactionThreshold(minCompactionThreshold);
        cfm.maxCompactionThreshold(maxCompactionThreshold);
        cfm.defaultTimeToLive(getInt(KW_DEFAULT_TIME_TO_LIVE, cfm.getDefaultTimeToLive()));
        cfm.speculativeRetry(CFMetaData.SpeculativeRetry.fromString(getString(KW_SPECULATIVE_RETRY, cfm.getSpeculativeRetry().toString())));
        cfm.memtableFlushPeriod(getInt(KW_MEMTABLE_FLUSH_PERIOD, cfm.getMemtableFlushPeriod()));
        cfm.minIndexInterval(getInt(KW_MIN_INDEX_INTERVAL, cfm.getMinIndexInterval()));
        cfm.maxIndexInterval(getInt(KW_MAX_INDEX_INTERVAL, cfm.getMaxIndexInterval()));

        if (compactionStrategyClass != null)
        {
            cfm.compactionStrategyClass(compactionStrategyClass);
            cfm.compactionStrategyOptions(new HashMap<>(getCompactionOptions()));
        }

        double bloomFilterFpChance = getDouble(KW_BF_FP_CHANCE, cfm.getBloomFilterFpChance());
        double minBloomFilterFpChanceValue = BloomCalculations.minSupportedBloomFilterFpChance();
        if (bloomFilterFpChance <=  minBloomFilterFpChanceValue || bloomFilterFpChance > 1)
        {
            throw new ConfigurationException(String.format(
                    "%s must be larger than %s and less than or equal to 1.0 (got %s)",
                    KW_BF_FP_CHANCE,
                    minBloomFilterFpChanceValue,
                    bloomFilterFpChance));
        }
        cfm.bloomFilterFpChance(bloomFilterFpChance);

        if (!getCompressionOptions().isEmpty())
            cfm.compressionParameters(CompressionParameters.create(getCompressionOptions()));
        CachingOptions cachingOptions = getCachingOptions();
        if (cachingOptions != null)
            cfm.caching(cachingOptions);
    }

    @Override
    public String toString()
    {
        return String.format("CFPropDefs(%s)", properties.toString());
    }

    private void validateMinimumInt(String field, int minimumValue, int defaultValue) throws SyntaxException, ConfigurationException
    {
        Integer val = getInt(field, null);
        if (val != null && val < minimumValue)
            throw new ConfigurationException(String.format("%s cannot be smaller than %s, (default %s)",
                                                            field, minimumValue, defaultValue));

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy