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

info.archinnov.achilles.embedded.CQLEmbeddedServer Maven / Gradle / Ivy

/**
 *
 * Copyright (C) 2012-2013 DuyHai DOAN
 *
 * 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 info.archinnov.achilles.embedded;

import static com.datastax.driver.core.ProtocolOptions.Compression.SNAPPY;
import static info.archinnov.achilles.configuration.CQLConfigurationParameters.*;
import static info.archinnov.achilles.configuration.ConfigurationParameters.*;
import static info.archinnov.achilles.context.CQLDaoContext.ACHILLES_DML_STATEMENT;
import static info.archinnov.achilles.embedded.CassandraEmbeddedConfigParameters.*;
import info.archinnov.achilles.entity.manager.CQLPersistenceManager;
import info.archinnov.achilles.entity.manager.CQLPersistenceManagerFactory;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.SimpleStatement;
import com.datastax.driver.core.policies.Policies;

public class CQLEmbeddedServer extends AchillesEmbeddedServer {
	private static final Map KEYSPACE_BOOTSTRAP_MAP = new HashMap();

	private static final Map SESSIONS_MAP = new HashMap();

	private static final Map FACTORIES_MAP = new HashMap();

	private static final Map MANAGERS_MAP = new HashMap();

	private static final Logger LOGGER = LoggerFactory.getLogger(CQLEmbeddedServer.class);

	private static final Logger DML_LOGGER = LoggerFactory.getLogger(ACHILLES_DML_STATEMENT);

	private static String entityPackages;

	public CQLEmbeddedServer(Map originalParameters) {
		Map parameters = CassandraEmbeddedConfigParameters
				.mergeWithDefaultParameters(originalParameters);

		String keyspaceName = (String) parameters.get(KEYSPACE_NAME);
		String cassandraHost = System.getProperty(CASSANDRA_HOST);

		// No external Cassandra server, start an embedded instance
		if (StringUtils.isBlank(cassandraHost)) {
			synchronized (SEMAPHORE) {
				if (!embeddedServerStarted) {
					startServer(parameters);
				} else {
					Integer cqlPort = (Integer) parameters.get(CASSANDRA_CQL_PORT);
					Integer thriftPort = (Integer) parameters.get(CASSANDRA_THRIFT_PORT);
					if (cqlPort != null && AchillesEmbeddedServer.cqlPort != cqlPort.intValue()) {
						throw new IllegalArgumentException(
								String.format(
										"An embedded Cassandra server is already listening to CQL port '%s', the specified CQL port '%s' does not match",
										AchillesEmbeddedServer.cqlPort, cqlPort));
					} else {
						parameters.put(CASSANDRA_CQL_PORT, AchillesEmbeddedServer.cqlPort);
					}

					if (thriftPort != null && AchillesEmbeddedServer.thriftPort != thriftPort.intValue()) {
						throw new IllegalArgumentException(
								String.format(
										"An embedded Cassandra server is already listening to Thrift port '%s', the specified Thrift port '%s' does not match",
										AchillesEmbeddedServer.thriftPort, thriftPort));
					} else {
						parameters.put(CASSANDRA_THRIFT_PORT, AchillesEmbeddedServer.thriftPort);
					}

				}
			}
		}

		synchronized (KEYSPACE_BOOTSTRAP_MAP) {
			if (!KEYSPACE_BOOTSTRAP_MAP.containsKey(keyspaceName)) {
				CQLEmbeddedServer.entityPackages = (String) parameters.get(ENTITY_PACKAGES);
				initialize(parameters);
				KEYSPACE_BOOTSTRAP_MAP.put(keyspaceName, true);
			}
		}
	}

	private void initialize(Map parameters) {

		Map achillesConfigMap = new HashMap();

		String keyspaceName = extractAndValidateKeyspaceName(parameters);
		Boolean keyspaceDurableWrite = (Boolean) parameters.get(KEYSPACE_DURABLE_WRITE);
		Boolean nativeSessionOnly = (Boolean) parameters.get(BUILD_NATIVE_SESSION_ONLY);

		String hostname;
		int cqlPort;

		String cassandraHost = System.getProperty(CASSANDRA_HOST);
		if (StringUtils.isNotBlank(cassandraHost) && cassandraHost.contains(":")) {
			String[] split = cassandraHost.split(":");
			hostname = split[0];
			cqlPort = Integer.parseInt(split[1]);
		} else {
			hostname = DEFAULT_CASSANDRA_HOST;
			cqlPort = (Integer) parameters.get(CASSANDRA_CQL_PORT);
		}

		Cluster cluster = createCluster(hostname, cqlPort);
		createKeyspaceIfNeeded(cluster, keyspaceName, keyspaceDurableWrite);

		if (nativeSessionOnly) {
			SESSIONS_MAP.put(keyspaceName, cluster.connect(keyspaceName));
		} else {
			achillesConfigMap.put(CLUSTER_PARAM, cluster);
			achillesConfigMap.put(NATIVE_SESSION_PARAM, cluster.connect(keyspaceName));
			achillesConfigMap.put(ENTITY_PACKAGES_PARAM, entityPackages);
			achillesConfigMap.put(KEYSPACE_NAME_PARAM, keyspaceName);
			achillesConfigMap.put(FORCE_CF_CREATION_PARAM, true);

			CQLPersistenceManagerFactory factory = new CQLPersistenceManagerFactory(achillesConfigMap);
			CQLPersistenceManager manager = factory.createPersistenceManager();

			FACTORIES_MAP.put(keyspaceName, factory);
			MANAGERS_MAP.put(keyspaceName, manager);
			SESSIONS_MAP.put(keyspaceName, manager.getNativeSession());
		}
	}

	public CQLPersistenceManagerFactory getPersistenceManagerFactory(String keyspaceName) {
		if (!FACTORIES_MAP.containsKey(keyspaceName)) {
			throw new IllegalStateException(String.format("Cannot find CQLPersistenceManagerFactory for keyspace '%s'",
					keyspaceName));
		}
		return FACTORIES_MAP.get(keyspaceName);
	}

	public CQLPersistenceManager getPersistenceManager(String keyspaceName) {
		if (!MANAGERS_MAP.containsKey(keyspaceName)) {
			throw new IllegalStateException(String.format("Cannot find CQLPersistenceManager for keyspace '%s'",
					keyspaceName));
		}
		return MANAGERS_MAP.get(keyspaceName);
	}

	public Session getNativeSession(String keyspaceName) {
		if (!SESSIONS_MAP.containsKey(keyspaceName)) {
			throw new IllegalStateException(String.format("Cannot find Session for keyspace '%s'", keyspaceName));
		}
		return SESSIONS_MAP.get(keyspaceName);
	}

	private Cluster createCluster(String host, int cqlPort) {
		return Cluster.builder().addContactPoint(host).withPort(cqlPort).withCompression(SNAPPY)
				.withLoadBalancingPolicy(Policies.defaultLoadBalancingPolicy())
				.withRetryPolicy(Policies.defaultRetryPolicy())
				.withReconnectionPolicy(Policies.defaultReconnectionPolicy()).build();
	}

	private void createKeyspaceIfNeeded(Cluster cluster, String keyspaceName, Boolean keyspaceDurableWrite) {
		final Session session = cluster.connect("system");
		final Row row = session.execute(
				"SELECT count(1) FROM schema_keyspaces WHERE keyspace_name='" + keyspaceName + "'").one();
		if (row.getLong(0) != 1) {
			StringBuilder createKeyspaceStatement = new StringBuilder("CREATE keyspace ");
			createKeyspaceStatement.append(keyspaceName);
			createKeyspaceStatement.append(" WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':1}");
			if (!keyspaceDurableWrite) {
				createKeyspaceStatement.append(" AND DURABLE_WRITES=false");
			}
			session.execute(createKeyspaceStatement.toString());
		}
		session.shutdown();
	}

	public void truncateTable(String keyspaceName, String tableName) {
		String query = "TRUNCATE " + tableName;
		Session session = SESSIONS_MAP.get(keyspaceName);
		session.execute(new SimpleStatement(query).setConsistencyLevel(com.datastax.driver.core.ConsistencyLevel.ALL));
		DML_LOGGER.debug("{} : [{}] with CONSISTENCY LEVEL [{}]", "  Simple query", query, "ALL");
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy