org.apache.cassandra.cache.CachingOptions.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.cassandra.cache.CachingOptions.java

Source

/*
 * 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.cache;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;

import org.apache.cassandra.exceptions.ConfigurationException;
import static org.apache.cassandra.utils.FBUtilities.fromJsonMap;

/*
CQL: { 'keys' : 'ALL|NONE', 'rows_per_partition': '200|NONE|ALL' }
 */
public class CachingOptions {
    public static final CachingOptions KEYS_ONLY = new CachingOptions(new KeyCache(KeyCache.Type.ALL),
            new RowCache(RowCache.Type.NONE));
    public static final CachingOptions ALL = new CachingOptions(new KeyCache(KeyCache.Type.ALL),
            new RowCache(RowCache.Type.ALL));
    public static final CachingOptions ROWS_ONLY = new CachingOptions(new KeyCache(KeyCache.Type.NONE),
            new RowCache(RowCache.Type.ALL));
    public static final CachingOptions NONE = new CachingOptions(new KeyCache(KeyCache.Type.NONE),
            new RowCache(RowCache.Type.NONE));

    public final KeyCache keyCache;
    public final RowCache rowCache;
    private static final Set<String> legacyOptions = new HashSet<>(
            Arrays.asList("ALL", "NONE", "KEYS_ONLY", "ROWS_ONLY"));

    public CachingOptions(KeyCache kc, RowCache rc) {
        this.keyCache = kc;
        this.rowCache = rc;
    }

    public static CachingOptions fromString(String cache) throws ConfigurationException {
        if (legacyOptions.contains(cache.toUpperCase()))
            return fromLegacyOption(cache.toUpperCase());
        return fromMap(fromJsonMap(cache));
    }

    public static CachingOptions fromMap(Map<String, String> cacheConfig) throws ConfigurationException {
        validateCacheConfig(cacheConfig);
        if (!cacheConfig.containsKey("keys") && !cacheConfig.containsKey("rows_per_partition"))
            return CachingOptions.NONE;
        if (!cacheConfig.containsKey("keys"))
            return new CachingOptions(new KeyCache(KeyCache.Type.NONE),
                    RowCache.fromString(cacheConfig.get("rows_per_partition")));
        if (!cacheConfig.containsKey("rows_per_partition"))
            return CachingOptions.KEYS_ONLY;

        return new CachingOptions(KeyCache.fromString(cacheConfig.get("keys")),
                RowCache.fromString(cacheConfig.get("rows_per_partition")));
    }

    private static void validateCacheConfig(Map<String, String> cacheConfig) throws ConfigurationException {
        for (Map.Entry<String, String> entry : cacheConfig.entrySet()) {
            String value = entry.getValue().toUpperCase();
            if (entry.getKey().equals("keys")) {
                if (!(value.equals("ALL") || value.equals("NONE"))) {
                    throw new ConfigurationException(
                            "'keys' can only have values 'ALL' or 'NONE', but was '" + value + "'");
                }
            } else if (entry.getKey().equals("rows_per_partition")) {
                if (!(value.equals("ALL") || value.equals("NONE") || StringUtils.isNumeric(value))) {
                    throw new ConfigurationException(
                            "'rows_per_partition' can only have values 'ALL', 'NONE' or be numeric, but was '"
                                    + value + "'.");
                }
            } else
                throw new ConfigurationException(
                        "Only supported CachingOptions parameters are 'keys' and 'rows_per_partition', but was '"
                                + entry.getKey() + "'");
        }
    }

    @Override
    public String toString() {
        return String.format("{\"keys\":\"%s\", \"rows_per_partition\":\"%s\"}", keyCache.toString(),
                rowCache.toString());
    }

    private static CachingOptions fromLegacyOption(String cache) {
        if (cache.equals("ALL"))
            return ALL;
        if (cache.equals("KEYS_ONLY"))
            return KEYS_ONLY;
        if (cache.equals("ROWS_ONLY"))
            return ROWS_ONLY;
        return NONE;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        CachingOptions o2 = (CachingOptions) o;

        if (!keyCache.equals(o2.keyCache))
            return false;
        if (!rowCache.equals(o2.rowCache))
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = keyCache.hashCode();
        result = 31 * result + rowCache.hashCode();
        return result;
    }

    // FIXME: move to ThriftConversion
    public static CachingOptions fromThrift(String caching, String cellsPerRow) throws ConfigurationException {

        RowCache rc = new RowCache(RowCache.Type.NONE);
        KeyCache kc = new KeyCache(KeyCache.Type.ALL);
        // if we get a caching string from thrift it is legacy, "ALL", "KEYS_ONLY" etc, fromString handles those
        if (caching != null) {
            CachingOptions givenOptions = CachingOptions.fromString(caching);
            rc = givenOptions.rowCache;
            kc = givenOptions.keyCache;
        }
        // if we get cells_per_row from thrift, it is either "ALL" or "<number of cells to cache>".
        if (cellsPerRow != null && rc.isEnabled())
            rc = RowCache.fromString(cellsPerRow);
        return new CachingOptions(kc, rc);
    }

    // FIXME: move to ThriftConversion
    public String toThriftCaching() {
        if (rowCache.isEnabled() && keyCache.isEnabled())
            return "ALL";
        if (rowCache.isEnabled())
            return "ROWS_ONLY";
        if (keyCache.isEnabled())
            return "KEYS_ONLY";
        return "NONE";
    }

    // FIXME: move to ThriftConversion
    public String toThriftCellsPerRow() {
        if (rowCache.cacheFullPartitions())
            return "ALL";
        return String.valueOf(rowCache.rowsToCache);
    }

    public static class KeyCache {
        public final Type type;

        public KeyCache(Type type) {
            this.type = type;
        }

        public enum Type {
            ALL, NONE
        }

        public static KeyCache fromString(String keyCache) {
            return new KeyCache(Type.valueOf(keyCache.toUpperCase()));
        }

        public boolean isEnabled() {
            return type == Type.ALL;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o)
                return true;
            if (o == null || getClass() != o.getClass())
                return false;

            KeyCache keyCache = (KeyCache) o;

            if (type != keyCache.type)
                return false;

            return true;
        }

        @Override
        public int hashCode() {
            return type.hashCode();
        }

        @Override
        public String toString() {
            return type.toString();
        }
    }

    public static class RowCache {
        public final Type type;
        public final int rowsToCache;

        public RowCache(Type type) {
            this(type, (type == Type.ALL) ? Integer.MAX_VALUE : 0);
        }

        public RowCache(Type type, int rowsToCache) {
            this.type = type;
            this.rowsToCache = rowsToCache;
        }

        public enum Type {
            ALL, NONE, HEAD
        }

        public static RowCache fromString(String rowCache) {
            if (rowCache == null || rowCache.equalsIgnoreCase("none"))
                return new RowCache(Type.NONE, 0);
            else if (rowCache.equalsIgnoreCase("all"))
                return new RowCache(Type.ALL, Integer.MAX_VALUE);
            return new RowCache(Type.HEAD, Integer.parseInt(rowCache));
        }

        public boolean isEnabled() {
            return (type == Type.ALL) || (type == Type.HEAD);
        }

        public boolean cacheFullPartitions() {
            return type == Type.ALL;
        }

        @Override
        public String toString() {
            if (type == Type.ALL)
                return "ALL";
            if (type == Type.NONE)
                return "NONE";
            return String.valueOf(rowsToCache);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o)
                return true;
            if (o == null || getClass() != o.getClass())
                return false;

            RowCache rowCache = (RowCache) o;

            if (rowsToCache != rowCache.rowsToCache)
                return false;
            if (type != rowCache.type)
                return false;

            return true;
        }

        @Override
        public int hashCode() {
            int result = type.hashCode();
            result = 31 * result + rowsToCache;
            return result;
        }
    }
}