// Copyright 2017 JanusGraph Authors // // Licensed 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.janusgraph; import static org.janusgraph.diskstorage.cassandra.AbstractCassandraStoreManager.CASSANDRA_KEYSPACE; import java.io.File; import java.io.IOException; import java.time.Duration; import org.janusgraph.diskstorage.cassandra.AbstractCassandraStoreManager; import org.janusgraph.diskstorage.cassandra.utils.CassandraDaemonWrapper; import org.janusgraph.diskstorage.configuration.ModifiableConfiguration; import org.janusgraph.diskstorage.configuration.WriteConfiguration; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.*; public class CassandraStorageSetup { public static final String CONFDIR_SYSPROP = "test.cassandra.confdir"; public static final String DATADIR_SYSPROP = "test.cassandra.datadir"; private static volatile Paths paths; private static final Logger log = LoggerFactory.getLogger(CassandraStorageSetup.class); private static synchronized Paths getPaths() { if (null == paths) { String yamlPath = "file://" + loadAbsoluteDirectoryPath("conf", CONFDIR_SYSPROP, true) + File.separator + "cassandra.yaml"; String dataPath = loadAbsoluteDirectoryPath("data", DATADIR_SYSPROP, false); paths = new Paths(yamlPath, dataPath); } return paths; } private static ModifiableConfiguration getGenericConfiguration(String ks, String backend) { ModifiableConfiguration config = buildGraphConfiguration(); config.set(CASSANDRA_KEYSPACE, cleanKeyspaceName(ks)); log.debug("Set keyspace name: {}", config.get(CASSANDRA_KEYSPACE)); config.set(PAGE_SIZE,500); config.set(CONNECTION_TIMEOUT, Duration.ofSeconds(60L)); config.set(STORAGE_BACKEND, backend); return config; } public static ModifiableConfiguration getEmbeddedConfiguration(String ks) { ModifiableConfiguration config = getGenericConfiguration(ks, "embeddedcassandra"); config.set(STORAGE_CONF_FILE, getPaths().yamlPath); return config; } public static ModifiableConfiguration getEmbeddedCassandraPartitionConfiguration(String ks) { ModifiableConfiguration config = getEmbeddedConfiguration(ks); config.set(IDS_FLUSH,false); return config; } public static WriteConfiguration getEmbeddedGraphConfiguration(String ks) { return getEmbeddedConfiguration(ks).getConfiguration(); } public static WriteConfiguration getEmbeddedCassandraPartitionGraphConfiguration(String ks) { return getEmbeddedConfiguration(ks).getConfiguration(); } public static ModifiableConfiguration getAstyanaxConfiguration(String ks) { return getGenericConfiguration(ks, "astyanax"); } public static ModifiableConfiguration getAstyanaxSSLConfiguration(String ks) { return enableSSL(getGenericConfiguration(ks, "astyanax")); } public static WriteConfiguration getAstyanaxGraphConfiguration(String ks) { return getAstyanaxConfiguration(ks).getConfiguration(); } public static ModifiableConfiguration getCassandraConfiguration(String ks) { return getGenericConfiguration(ks, "cassandra"); } public static WriteConfiguration getCassandraGraphConfiguration(String ks) { return getCassandraConfiguration(ks).getConfiguration(); } public static ModifiableConfiguration getCassandraThriftConfiguration(String ks) { return getGenericConfiguration(ks, "cassandrathrift"); } public static ModifiableConfiguration getCassandraThriftSSLConfiguration(String ks) { return enableSSL(getGenericConfiguration(ks, "cassandrathrift")); } public static WriteConfiguration getCassandraThriftGraphConfiguration(String ks) { return getCassandraThriftConfiguration(ks).getConfiguration(); } /** * Load cassandra.yaml and data paths from the environment or from default * values if nothing is set in the environment, then delete all existing * data, and finally start Cassandra. * <p> * This method is idempotent. Calls after the first have no effect aside * from logging statements. */ public static void startCleanEmbedded() { startCleanEmbedded(getPaths()); } /* * Cassandra only accepts keyspace names 48 characters long or shorter made * up of alphanumeric characters and underscores. */ public static String cleanKeyspaceName(String raw) { Preconditions.checkNotNull(raw); Preconditions.checkArgument(0 < raw.length()); if (48 < raw.length() || raw.matches("^.*[^a-zA-Z0-9_].*$")) { return "strhash" + String.valueOf(Math.abs(raw.hashCode())); } else { return raw; } } private static ModifiableConfiguration enableSSL(ModifiableConfiguration mc) { mc.set(AbstractCassandraStoreManager.SSL_ENABLED, true); mc.set(STORAGE_HOSTS, new String[]{ "localhost" }); mc.set(AbstractCassandraStoreManager.SSL_TRUSTSTORE_LOCATION, Joiner.on(File.separator).join("target", "cassandra", "conf", "localhost-murmur-ssl", "test.truststore")); mc.set(AbstractCassandraStoreManager.SSL_TRUSTSTORE_PASSWORD, "cassandra"); return mc; } private static void startCleanEmbedded(Paths p) { if (!CassandraDaemonWrapper.isStarted()) { try { FileUtils.deleteDirectory(new File(p.dataPath)); } catch (IOException e) { throw new RuntimeException(e); } } CassandraDaemonWrapper.start(p.yamlPath); } private static String loadAbsoluteDirectoryPath(String name, String prop, boolean mustExistAndBeAbsolute) { String s = System.getProperty(prop); if (null == s) { s = Joiner.on(File.separator).join(System.getProperty("user.dir"), "target", "cassandra", name, "localhost-bop"); log.info("Set default Cassandra {} directory path {}", name, s); } else { log.info("Loaded Cassandra {} directory path {} from system property {}", new Object[] { name, s, prop }); } if (mustExistAndBeAbsolute) { File dir = new File(s); Preconditions.checkArgument(dir.isDirectory(), "Path %s must be a directory", s); Preconditions.checkArgument(dir.isAbsolute(), "Path %s must be absolute", s); } return s; } private static class Paths { private final String yamlPath; private final String dataPath; public Paths(String yamlPath, String dataPath) { this.yamlPath = yamlPath; this.dataPath = dataPath; } } }