package edu.washington.escience.myria.daemon;
import java.util.concurrent.CountDownLatch;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import org.apache.reef.tang.annotations.Parameter;
import org.apache.reef.task.Task;
import org.apache.reef.task.events.CloseEvent;
import org.apache.reef.wake.EventHandler;
import edu.washington.escience.myria.api.MasterApiServer;
import edu.washington.escience.myria.parallel.Server;
import edu.washington.escience.myria.tools.MyriaGlobalConfigurationModule;
/**
* This is the class for the main daemon for Myria. It manages all the various services, including
* the API server and the Myria server.
*
*
*/
public final class MasterDaemon implements Task, EventHandler<CloseEvent> {
/** The logger for this class. */
private static final org.slf4j.Logger LOGGER =
org.slf4j.LoggerFactory.getLogger(MasterDaemon.class);
private final CountDownLatch terminated = new CountDownLatch(1);
/**
* @param memento the memento object passed down by the driver.
* @return the user defined return value
* @throws Exception whenever the Task encounters an unsolved issue. This Exception will be thrown
* at the Driver's event handler.
*/
@Override
public byte[] call(@SuppressWarnings("unused") final byte[] memento) throws Exception {
try {
start();
terminated.await();
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
stop();
}
return null;
}
/**
* Shut down this worker.
*/
@Override
public void onNext(final CloseEvent closeEvent) {
LOGGER.info("CloseEvent received, shutting down...");
terminated.countDown();
}
/** The Myria server. */
private final Server server;
/** The Master API server. */
private final MasterApiServer apiServer;
/**
* Instantiates a MasterDaemon object. Includes the API server and the Myria server.
*
* @param configFilePath the dir where the config file resides.
* @param apiPort api server port.
* @throws Exception if there are issues loading the Catalog or instantiating the servers.
*/
@Inject
public MasterDaemon(
final Server server,
final MasterApiServer apiServer,
final @Parameter(MyriaGlobalConfigurationModule.RestApiPort.class) int apiPort,
final @Parameter(MyriaGlobalConfigurationModule.UseSsl.class) boolean useSsl,
final @Parameter(MyriaGlobalConfigurationModule.SslKeystorePath.class) String keystorePath,
final @Parameter(MyriaGlobalConfigurationModule.SslKeystorePassword.class) String
keystorePassword,
final @Parameter(MyriaGlobalConfigurationModule.ApiAdminPassword.class) String adminPassword)
throws Exception {
this.server = server;
this.apiServer = apiServer;
try {
final int portMin = 1;
final int portMax = 65535;
if ((apiPort < portMin) || (apiPort > portMax)) {
throw new IllegalArgumentException("port must be between " + portMin + " and " + portMax);
}
} catch (NumberFormatException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Start the Daemon. Namely, start the API server and the Myria Server.
*
* @throws Exception if there is an issue starting either server.
*/
public void start() throws Exception {
Logger.getLogger("com.almworks.sqlite4java").setLevel(Level.SEVERE);
Logger.getLogger("com.almworks.sqlite4java.Internal").setLevel(Level.SEVERE);
server.start();
apiServer.start();
}
/**
* Stop the Daemon. Namely, stop the API server and the Myria Server.
*
* @throws Exception if there is an issue stopping either server.
*/
public void stop() throws Exception {
apiServer.stop();
server.shutdown();
}
/**
* @return the cluster master
* */
public Server getClusterMaster() {
return server;
}
}