first commit for new repo
[sdc/sdc-titan-cassandra.git] / src / main / java / com / thinkaurelius / titan / diskstorage / cassandra / utils / CassandraDaemonWrapper.java
1 package com.thinkaurelius.titan.diskstorage.cassandra.utils;
2
3 import java.lang.Thread.UncaughtExceptionHandler;
4
5 import org.apache.cassandra.config.Schema;
6 import org.apache.cassandra.db.commitlog.CommitLog;
7 import org.apache.cassandra.net.MessagingService;
8 import org.apache.cassandra.service.CassandraDaemon;
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11
12 /**
13  * This class starts a Thrift CassandraDaemon inside the current JVM. This class
14  * supports testing and shouldn't be used in production.
15  *
16  * This class starts Cassandra on the first invocation of
17  * {@link CassandraDaemonWrapper#start(String)} in the life of the JVM.
18  * Invocations after the first have no effect except that they may log a
19  * warning.
20  *
21  * When the thread that first called {@code #start(String)} dies, a daemon
22  * thread returns from {@link Thread#join()} and kills all embedded Cassandra
23  * threads in the JVM.
24  *
25  * This class once supported consecutive, idempotent calls to start(String) so
26  * long as the argument was the same in each invocation. It also once used
27  * refcounting to kill Cassandra's non-daemon threads once stop() was called as
28  * many times as start(). Some of Cassandra's background threads and statics
29  * can't be easily reset to allow a restart inside the same JVM, so this was
30  * intended as a one-use thing. However, this interacts poorly with the new
31  * KCVConfiguration system in titan-core. When KCVConfiguration is in use, core
32  * starts and stops each backend at least twice in the course of opening a
33  * single database instance. So the old refcounting and killing approach is out.
34  *
35  * @author Dan LaRocque <dalaro@hopcount.org>
36  */
37 public class CassandraDaemonWrapper {
38
39     private static final Logger log =
40             LoggerFactory.getLogger(CassandraDaemonWrapper.class);
41
42     private static String activeConfig;
43
44     private static boolean started;
45
46     public static synchronized void start(String config) {
47
48         if (started) {
49             if (null != config && !config.equals(activeConfig)) {
50                 log.warn("Can't start in-process Cassandra instance " +
51                          "with yaml path {} because an instance was " +
52                          "previously started with yaml path {}",
53                          config, activeConfig);
54             }
55
56             return;
57         }
58
59         started = true;
60
61         log.debug("Current working directory: {}", System.getProperty("user.dir"));
62
63         System.setProperty("cassandra.config", config);
64         // Prevent Cassandra from closing stdout/stderr streams
65         System.setProperty("cassandra-foreground", "yes");
66         // Prevent Cassandra from overwriting Log4J configuration
67         System.setProperty("log4j.defaultInitOverride", "false");
68
69         log.info("Starting cassandra with {}", config);
70
71         /*
72          * This main method doesn't block for any substantial length of time. It
73          * creates and starts threads and returns in relatively short order.
74          */
75         CassandraDaemon.main(new String[0]);
76
77         activeConfig = config;
78     }
79
80     public static synchronized boolean isStarted() {
81         return started;
82     }
83
84     public static void stop() {
85         // Do nothing
86     }
87 }