com.eucalyptus.cassandra.CassandraKeyspaces.java Source code

Java tutorial

Introduction

Here is the source code for com.eucalyptus.cassandra.CassandraKeyspaces.java

Source

/*************************************************************************
 * (c) Copyright 2017 Hewlett Packard Enterprise Development Company LP
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/.
 ************************************************************************/
package com.eucalyptus.cassandra;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import com.eucalyptus.cassandra.common.CassandraPersistence;
import com.eucalyptus.cassandra.common.CassandraReplicas;
import com.eucalyptus.cassandra.common.util.CqlUtil;
import com.eucalyptus.util.Either;
import com.eucalyptus.util.Exceptions;
import com.eucalyptus.util.FUtils;
import com.eucalyptus.util.Parameters;
import com.eucalyptus.util.ThrowingFunction;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Resources;
import javaslang.Function3;
import javaslang.Tuple2;

/**
 *
 */
public class CassandraKeyspaces {
    private static final ConcurrentMap<String, KeyspaceSpec> keyspaceMap = Maps.newConcurrentMap();
    private static final String KEYSPACE_CQL = "CREATE KEYSPACE IF NOT EXISTS %1$s WITH REPLICATION = {'class': 'NetworkTopologyStrategy', '%2$s': %3$d};";
    private static final String KEYSPACE_RESOURCE_TEMPLATE = "classpath*:*-*-*-%s-*.cql";

    /**
     * Process all keyspaces, returning any failures.
     */
    public static List<Tuple2<String, Optional<Throwable>>> all(final String dc, final int dcNodes) {
        return keyspaceMap.values().stream().map(KeyspaceSpec::name).sorted(String.CASE_INSENSITIVE_ORDER)
                .map(FUtils.tuple(FUtils
                        .eitherThrowable(Function3.of(CassandraKeyspaces::keyspace).reversed().apply(dcNodes, dc))
                        .andThen(Either.leftOption())))
                .collect(Collectors.toList());
    }

    /**
     * Process the specified keyspace
     */
    public static boolean keyspace(final String name, final String dc, final int dcNodes) {
        final KeyspaceSpec keyspaceSpec = keyspaceMap.get(name);
        if (keyspaceSpec == null) {
            throw new IllegalArgumentException("Unknown keyspace: " + name);
        }
        return CassandraPersistence.doWithSession(CassandraPersistence.SessionUsage.Admin, name, session -> {
            session.execute(String.format(KEYSPACE_CQL, keyspaceSpec.name(), dc,
                    keyspaceSpec.replicas().replicas(dcNodes)));
            scripts(name).flatMap(ThrowingFunction.undeclared(CqlUtil::splitCql).andThen(Collection::stream))
                    .forEach(session::execute);
            return true;
        });
    }

    static void register(@Nonnull final String keyspace, @Nonnull final CassandraReplicas replicas) {
        Parameters.checkParamNotNull("keyspace", keyspace);
        keyspaceMap.putIfAbsent(keyspace, new KeyspaceSpec(keyspace, replicas));
    }

    private static Stream<String> scripts(final String keyspace) {
        // discover and sort cql scriptFilenames
        final List<String> scripts = Lists.newArrayList();
        final PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(
                CassandraKeyspaces.class.getClassLoader());
        try {
            final String pattern = String.format(KEYSPACE_RESOURCE_TEMPLATE, scriptName(keyspace));
            final Resource[] resources = resolver.getResources(pattern);
            final List<String> scriptFilenames = Lists.newArrayList();
            for (final Resource resource : resources) {
                scriptFilenames.add(resource.getFilename());
            }
            Collections.sort(scriptFilenames);
            for (final String resourceName : scriptFilenames) {
                scripts.add(Resources.toString(Resources.getResource(resourceName), StandardCharsets.UTF_8));
            }
        } catch (IOException e) {
            throw Exceptions.toUndeclared(e);
        }

        return scripts.stream();
    }

    private static String scriptName(final String keyspace) {
        return keyspace.replace('_', '-').toLowerCase();
    }

    private static final class KeyspaceSpec {
        private final String name;
        private final CassandraReplicas replicas;

        private KeyspaceSpec(final String name, final CassandraReplicas replicas) {
            this.name = Parameters.checkParamNotNullOrEmpty("name", name);
            this.replicas = Parameters.checkParamNotNull("replicas", replicas);
        }

        public String name() {
            return name;
        }

        public CassandraReplicas replicas() {
            return replicas;
        }
    }
}