com.findwise.hydra.Main Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hydra-core Show documentation
Show all versions of hydra-core Show documentation
Hydra Core - The main runnable artifact of Hydra
package com.findwise.hydra;
import java.io.IOException;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.TimeUnit;
import org.apache.commons.configuration.ConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.net.SimpleSocketServer;
import com.findwise.hydra.mongodb.MongoConnector;
import com.findwise.hydra.mongodb.MongoType;
import com.findwise.hydra.net.HttpRESTHandler;
import com.findwise.hydra.net.RESTServer;
public final class Main implements ShutdownHandler {
private static final long KILL_DELAY = TimeUnit.SECONDS.toMillis(30);
private final CoreConfiguration coreConfiguration;
public Main(CoreConfiguration coreConfiguration) {
this.coreConfiguration = coreConfiguration;
}
private static Logger logger = LoggerFactory.getLogger(Main.class);
private SimpleSocketServer simpleSocketServer = null;
private RESTServer server = null;
private volatile boolean shuttingDown = false;
private static Main main;
public static void main(String[] args) {
if (args.length > 1) {
logger.error("Some parameters on command line were ignored.");
}
CoreConfiguration conf;
if (args.length > 0) {
conf = getConfiguration(args[0]);
} else {
conf = getConfiguration(null);
}
main = new Main(conf);
main.startup();
}
/**
* This method should be used by service wrappers to properly shutdown Hydra.
*/
public static void stop(@SuppressWarnings("unused") String[] args) {
if (main != null) { // No need to shut things down if main never was
main.shutdown();
}
}
public void startup() {
ShuttingDownOnUncaughtException uncaughtExceptionHandler = new ShuttingDownOnUncaughtException(this);
Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
simpleSocketServer = new SimpleSocketServer((LoggerContext) LoggerFactory.getILoggerFactory(), coreConfiguration.getLoggingPort());
simpleSocketServer.start();
logger.info("Hydra Core creating connector, {}='{}', {}='{}'",
DatabaseConfiguration.DATABASE_URL_PARAM, coreConfiguration.getDatabaseUrl(),
DatabaseConfiguration.DATABASE_NAMESPACE, coreConfiguration.getNamespace());
DatabaseConnector backing = new MongoConnector(coreConfiguration);
try {
backing.connect();
} catch (IOException e) {
logger.error("Unable to start", e);
return;
}
Cache cache;
if (coreConfiguration.isCacheEnabled()) {
cache = new MemoryCache();
} else {
cache = new NoopCache();
}
CachingDocumentNIO caching = new CachingDocumentNIO(
backing,
cache,
coreConfiguration.isCacheEnabled(),
coreConfiguration.getCacheTimeout());
NodeMaster nm = new NodeMaster(
coreConfiguration,
caching,
new Pipeline(),
this);
server = new RESTServer(coreConfiguration,
new HttpRESTHandler(
nm.getDocumentIO(),
backing.getPipelineReader(),
null,
coreConfiguration.isPerformanceLogging()));
if (!server.blockingStart()) {
if (server.hasError()) {
logger.error("Failed to start REST server: ", server.getError());
} else {
logger.error("Failed to start REST server");
}
shutdown();
}
try {
nm.blockingStart();
} catch (IOException e) {
logger.error("Unable to start "+nm.getClass().getSimpleName()+"... Shutting down.");
shutdown();
}
}
public void shutdown() {
logger.info("Got shutdown request...");
shuttingDown = true;
killUnlessShutdownWithin(KILL_DELAY);
if (simpleSocketServer != null) {
try {
simpleSocketServer.close();
} catch (Exception e) {
logger.debug("Caught exception while shutting down "+simpleSocketServer.getClass().getSimpleName()+". Was it not started?", e);
}
} else {
logger.trace(simpleSocketServer.getClass().getSimpleName()+" was null");
}
if (server != null) {
try {
server.shutdown();
return;
} catch (Exception e) {
logger.debug("Caught exception while shutting down the server. Was it not started?", e);
System.exit(1);
}
} else {
logger.trace("server was null");
}
}
public boolean isShuttingDown() {
return shuttingDown;
}
private void killUnlessShutdownWithin(long killDelay) {
if (killDelay < 0) {
return;
}
HydraKiller killerThread = new HydraKiller(killDelay);
killerThread.setDaemon(true);
killerThread.start();
}
protected static CoreConfiguration getConfiguration(String fileName) {
try {
if (fileName != null) {
return new FileConfiguration(fileName);
} else {
return new FileConfiguration();
}
} catch (ConfigurationException e) {
logger.error("Unable to read configuration", e);
return null;
}
}
private class ShuttingDownOnUncaughtException implements UncaughtExceptionHandler {
private final ShutdownHandler shutdownHandler;
public ShuttingDownOnUncaughtException(ShutdownHandler shutdownHandler) {
this.shutdownHandler = shutdownHandler;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
if (!shutdownHandler.isShuttingDown()) {
logger.error("Got an uncaught exception. Shutting down Hydra", e);
shutdownHandler.shutdown();
} else {
logger.error("Got exception while shutting down", e);
}
}
}
private class HydraKiller extends Thread {
Logger logger = LoggerFactory.getLogger(HydraKiller.class);
private final long killDelay;
public HydraKiller(long killDelay) {
this.killDelay = killDelay;
}
@Override
public void run() {
currentThread().setName(getClass().getSimpleName());
try {
logger.debug("Hydra will be killed in " + killDelay + "ms unless it is shut down gracefully before then");
Thread.sleep(killDelay);
logger.info("Failed to shutdown hydra gracefully within configured shutdown timeout. Killing Hydra now");
System.exit(1);
} catch (Throwable e) {
logger.error("Caught exception in HydraKiller thread. Killing Hydra right away!", e);
System.exit(1);
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy