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

com.lordofthejars.nosqlunit.cassandra.EmbeddedCassandraServerHelper Maven / Gradle / Ivy

package com.lordofthejars.nosqlunit.cassandra;


import static java.util.concurrent.TimeUnit.SECONDS;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import me.prettyprint.cassandra.service.CassandraHostConfigurator;
import me.prettyprint.hector.api.Cluster;
import me.prettyprint.hector.api.ddl.KeyspaceDefinition;
import me.prettyprint.hector.api.factory.HFactory;

import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.commitlog.CommitLog;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.io.util.FileUtils;
import org.apache.cassandra.service.CassandraDaemon;
import org.apache.commons.lang.StringUtils;
import org.apache.thrift.transport.TTransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class EmbeddedCassandraServerHelper {
	
	private static Logger log = LoggerFactory.getLogger(EmbeddedCassandraServerHelper.class);

	public static final String DEFAULT_TMP_DIR = "target/embeddedCassandra";
	public static final String DEFAULT_CASSANDRA_YML_FILE = "cu-cassandra.yaml";
	private static final String INTERNAL_CASSANDRA_KEYSPACE = "system";

	private static CassandraDaemon cassandraDaemon = null;
	static ExecutorService executor = Executors.newSingleThreadExecutor();

	public EmbeddedCassandraServerHelper() {
		super();
	}
	
	public void startEmbeddedCassandra() throws TTransportException, IOException, InterruptedException,
			ConfigurationException {
		startEmbeddedCassandra(DEFAULT_CASSANDRA_YML_FILE);
	}
	
	public void startEmbeddedCassandra(String yamlFile) throws TTransportException, IOException, ConfigurationException {
		startEmbeddedCassandra(yamlFile, DEFAULT_TMP_DIR);
	}

	/**
	 * Set embedded cassandra up and spawn it in a new thread.
	 * 
	 * @throws TTransportException
	 * @throws IOException
	 * @throws InterruptedException
	 */
	public void startEmbeddedCassandra(String yamlFile, String tmpDir) throws TTransportException, IOException, ConfigurationException {

		if (!StringUtils.startsWith(yamlFile, "/")) {
			yamlFile = "/" + yamlFile;
		}

		if (cassandraDaemon == null) {
			log.debug("Starting cassandra...");
			log.debug("Initialization needed");
			rmdir(tmpDir);
			copy("/log4j-embedded-cassandra.properties", tmpDir);
			copy(yamlFile, tmpDir);

			System.setProperty("cassandra.config", "file:" + tmpDir + yamlFile);
			System.setProperty("log4j.configuration", "file:" + tmpDir + "/log4j-embedded-cassandra.properties");
			System.setProperty("cassandra-foreground", "true");

			cleanupAndLeaveDirs();
			final CountDownLatch startupLatch = new CountDownLatch(1);
			executor.execute(new Runnable() {
				@Override
				public void run() {
					cassandraDaemon = new CassandraDaemon();
					cassandraDaemon.activate();
					startupLatch.countDown();
				}
			});
			try {
				startupLatch.await(10, SECONDS);
			} catch (InterruptedException e) {
				log.error("Interrupted waiting for Cassandra daemon to start:", e);
				throw new AssertionError(e);
			}
		} else {
			/* nothing to do Cassandra is already started */
		}
	}

	/**
	 * stop the embedded cassandra
	 */
	public void stopEmbeddedCassandra() {
        if (cassandraDaemon != null) {
            cassandraDaemon.stop();
        }
		executor.shutdown();
		executor.shutdownNow();
		log.debug("Cassandra is stopped");
	}

	/**
	 * drop all keyspaces (expect system)
	 */
	public static void cleanEmbeddedCassandra() {
		dropKeyspaces();
	}

	private static void dropKeyspaces() {
		String host = DatabaseDescriptor.getRpcAddress().getHostName();
		int port = DatabaseDescriptor.getRpcPort();
		log.debug("Cleaning cassandra keyspaces on " + host + ":" + port);
		Cluster cluster = HFactory.getOrCreateCluster("TestCluster", new CassandraHostConfigurator(host + ":" + port));
		/* get all keyspace */
		List keyspaces = cluster.describeKeyspaces();

		/* drop all keyspace except internal cassandra keyspace */
		for (KeyspaceDefinition keyspaceDefinition : keyspaces) {
			String keyspaceName = keyspaceDefinition.getName();

			if (!INTERNAL_CASSANDRA_KEYSPACE.equals(keyspaceName)) {
				cluster.dropKeyspace(keyspaceName);
			}
		}
	}

	private static void rmdir(String dir) throws IOException {
		File dirFile = new File(dir);
		if (dirFile.exists()) {
			FileUtils.deleteRecursive(new File(dir));
		}
	}

	/**
	 * Copies a resource from within the jar to a directory.
	 * 
	 * @param resource
	 * @param directory
	 * @throws IOException
	 */
	private static void copy(String resource, String directory) throws IOException {
		mkdir(directory);
		InputStream is = EmbeddedCassandraServerHelper.class.getResourceAsStream(resource);
		String fileName = resource.substring(resource.lastIndexOf("/") + 1);
		File file = new File(directory + System.getProperty("file.separator") + fileName);
		OutputStream out = new FileOutputStream(file);
		byte buf[] = new byte[1024];
		int len;
		while ((len = is.read(buf)) > 0) {
			out.write(buf, 0, len);
		}
		out.close();
		is.close();
	}

	/**
	 * Creates a directory
	 * 
	 * @param dir
	 * @throws IOException
	 */
	private static void mkdir(String dir) throws IOException {
		FileUtils.createDirectory(dir);
	}

	private static void cleanupAndLeaveDirs() throws IOException {
		mkdirs();
		cleanup();
		mkdirs();
		CommitLog.instance.resetUnsafe(); // cleanup screws w/ CommitLog, this
											// brings it back to safe state
	}

	private static void cleanup() throws IOException {
		// clean up commitlog
		String[] directoryNames = { DatabaseDescriptor.getCommitLogLocation(), };
		for (String dirName : directoryNames) {
			File dir = new File(dirName);
			if (!dir.exists())
				throw new RuntimeException("No such directory: " + dir.getAbsolutePath());
			FileUtils.deleteRecursive(dir);
		}

		// clean up data directory which are stored as data directory/table/data
		// files
		for (String dirName : DatabaseDescriptor.getAllDataFileLocations()) {
			File dir = new File(dirName);
			if (!dir.exists())
				throw new RuntimeException("No such directory: " + dir.getAbsolutePath());
			FileUtils.deleteRecursive(dir);
		}
	}

	public static void mkdirs() {
        DatabaseDescriptor.createAllDirectories();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy