package dgm.driver;
import com.beust.jcommander.JCommander;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import dgm.driver.handler.HandlerModule;
import dgm.driver.server.Server;
import dgm.driver.server.ServerModule;
import dgm.fixtures.FixturesModule;
import dgm.fixtures.FixturesRunner;
import dgm.jmx.GraphBuilder;
import dgm.modules.BlueprintsSubgraphManagerModule;
import dgm.modules.DegraphmalizerModule;
import dgm.modules.ServiceRunner;
import dgm.modules.ThreadpoolModule;
import dgm.modules.elasticsearch.CommonElasticSearchModule;
import dgm.modules.elasticsearch.nodes.LocalES;
import dgm.modules.elasticsearch.nodes.NodeES;
import dgm.modules.fsmon.DynamicConfiguration;
import dgm.modules.fsmon.StaticConfiguration;
import dgm.modules.neo4j.CommonNeo4j;
import dgm.modules.neo4j.EmbeddedNeo4J;
import org.nnsoft.guice.sli4j.core.InjectLogger;
import org.nnsoft.guice.sli4j.slf4j.Slf4jLoggingModule;
import org.slf4j.Logger;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;
public final class Main
{
private static final String LOGBACK_CFG = "logback.configurationFile";
@InjectLogger
Logger log;
private Main(String[] args)
{
final Options opt = new Options();
// parse CLI options
final JCommander jcommander = new JCommander(opt, args);
// print help and exit
if (opt.help)
{
jcommander.usage();
System.exit(1);
}
// find logback settings file
if (System.getProperty(LOGBACK_CFG) == null)
System.setProperty(LOGBACK_CFG, opt.logbackConf);
// check if script directory exists
if (!new File(opt.config).isDirectory())
exit("Cannot find configuration directory " + opt.config + " Exiting.");
System.out.println("Automatic configuration reloading: " + (opt.reloading ? "enabled" : "disabled"));
// depending on properties / CLI, load proper modules
final List<Module> modules = new ArrayList<Module>();
// some defaults
modules.add(new BlueprintsSubgraphManagerModule());
modules.add(new Slf4jLoggingModule());
modules.add(new DegraphmalizerModule());
modules.add(new ThreadpoolModule());
// netty part
modules.add(new ServerModule(opt.bindhost, opt.port));
modules.add(new HandlerModule());
// we always run an embedded local graph database
modules.add(new CommonNeo4j());
modules.add(new EmbeddedNeo4J(opt.graphdb));
// elasticsearch setup
setupElasticsearch(opt, modules);
// configuration reloading etc
setupConfiguration(opt, modules);
// the injector
final Injector injector = Guice.createInjector(modules);
// logger
injector.injectMembers(this);
// start JMX?
if (opt.jmx)
{
// setup our JMX bean
try
{
log.info("Starting JMX");
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
final ObjectName name = new ObjectName("graph.mbeans:type=RandomizedGraphBuilder");
final GraphBuilder gb = injector.getInstance(GraphBuilder.class);
mbs.registerMBean(gb, name);
log.info("JMX bean {} started", name);
} catch (Exception e)
{
// TODO log errors
e.printStackTrace();
}
}
final Server server = injector.getInstance(Server.class);
final ServiceRunner runner = injector.getInstance(ServiceRunner.class);
// so we can shutdown cleanly
Runtime.getRuntime().addShutdownHook(new Thread()
{
@Override
public void run()
{
log.info("JVM Shutdown received (e.g., Ctrl-c pressed)");
server.stopAndWait();
runner.stopServices();
}
});
// start services and then the main netty server
runner.startServices();
// start fixtures
if (opt.fixtures)
{
FixturesRunner fl = injector.getInstance(FixturesRunner.class);
try
{
fl.runFixtures();
} catch (Exception e)
{
log.error("Could not load fixtures. reason: {}", e.getMessage());
}
}
log.info("Starting server on port {}", opt.port);
server.startAndWait();
}
private void setupElasticsearch(Options opt, List<Module> modules)
{
modules.add(new CommonElasticSearchModule());
// setup local node
if (opt.development)
{
modules.add(new LocalES());
return;
}
// setup node that connects to remote host
if (opt.transport.size() != 3)
exit("You need to specify either the local or transport ES config. Exiting.");
final String cluster = opt.transport.get(2);
final String host = opt.transport.get(0);
final int port = Integer.parseInt(opt.transport.get(1));
final String bindhost = opt.bindhost;
modules.add(new NodeES(cluster, bindhost, host, port));
}
private void setupConfiguration(Options opt, List<Module> modules)
{
// automatic reloading
if (opt.reloading)
modules.add(new DynamicConfiguration(opt.config, opt.libraries()));
else
modules.add(new StaticConfiguration(opt.config, opt.libraries()));
// fixtures
if (opt.fixtures)
modules.add(new FixturesModule(createRunMode(opt)));
}
public static void main(String[] args)
{
new Main(args);
}
private static void exit(String message)
{
System.err.println(message);
System.exit(1);
}
private static RunMode createRunMode(Options options)
{
if (options.development && options.reloading && options.fixtures)
{
return RunMode.DEVELOPMENT;
} else if (options.reloading && options.fixtures)
{
return RunMode.TEST;
}
return RunMode.PRODUCTION;
}
}