package uk.ac.imperial.lsds.seepworker;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import joptsimple.OptionParser;
import uk.ac.imperial.lsds.seep.comm.Comm;
import uk.ac.imperial.lsds.seep.comm.Connection;
import uk.ac.imperial.lsds.seep.comm.IOComm;
import uk.ac.imperial.lsds.seep.comm.serialization.JavaSerializer;
import uk.ac.imperial.lsds.seep.config.CommandLineArgs;
import uk.ac.imperial.lsds.seep.config.ConfigKey;
import uk.ac.imperial.lsds.seep.infrastructure.ControlEndPoint;
import uk.ac.imperial.lsds.seep.metrics.SeepMetrics;
import uk.ac.imperial.lsds.seep.util.RuntimeClassLoader;
import uk.ac.imperial.lsds.seep.util.Utils;
import uk.ac.imperial.lsds.seepworker.comm.ControlAPIImplementation;
import uk.ac.imperial.lsds.seepworker.comm.ControlCommManager;
import uk.ac.imperial.lsds.seepworker.core.Conductor;
import uk.ac.imperial.lsds.seepworker.core.DataReferenceManager;
public class Main {
final private static Logger LOG = LoggerFactory.getLogger(Main.class);
private void executeWorker(WorkerConfig wc) {
int masterPort = wc.getInt(WorkerConfig.MASTER_PORT);
String masterIpStr = wc.getString(WorkerConfig.MASTER_IP);
InetAddress masterIp = null;
try {
masterIp = InetAddress.getByName(masterIpStr);
}
catch (UnknownHostException e) {
e.printStackTrace();
}
// Get connection to master node
int masterId = Utils.computeIdFromIpAndPort(masterIp, masterPort);
ControlEndPoint masterEndPoint = new ControlEndPoint(masterId, masterIpStr, masterPort);
Connection masterConnection = new Connection(masterEndPoint);
// Read configs with info about IP and port to bind to
String myIpStr = wc.getString(WorkerConfig.WORKER_IP);
InetAddress myIp = Utils.getIpFromStringRepresentation(myIpStr);//InetAddress.getByName(myIpStr);
int controlPort = wc.getInt(WorkerConfig.CONTROL_PORT);
int dataPort = wc.getInt(WorkerConfig.DATA_PORT);
// If no IP is given, then find some local address
if(myIp == null) {
myIp = Utils.getLocalIp();
}
// Create comm object
Comm comm = new IOComm(new JavaSerializer(), Executors.newCachedThreadPool());
// Create master-worker API handler (to send commands to master)
ControlAPIImplementation api = new ControlAPIImplementation(comm, wc);
// Create DataReferenceManager
DataReferenceManager drm = DataReferenceManager.makeDataReferenceManager(wc);
// Create conductor
Conductor c = new Conductor(myIp, api, masterConnection, wc, comm, drm);
// Create and start master-worker communication manager (to receive commands from master)
RuntimeClassLoader rcl = new RuntimeClassLoader(new URL[0], this.getClass().getClassLoader());
ControlCommManager wmcm = new ControlCommManager(myIp, controlPort, wc, rcl, c);
wmcm.start();
// Bootstrap
myIpStr = Utils.getStringRepresentationOfIp(myIp);
api.bootstrap(masterConnection, myIpStr, controlPort, dataPort);
// Configure metrics serving
this.configureMetricsReporting(wc);
// Register JVM shutdown hook
registerShutdownHook(Utils.computeIdFromIpAndPort(myIp, controlPort), c, masterConnection, api);
}
private void configureMetricsReporting(WorkerConfig wc){
int reportConsole = wc.getInt(WorkerConfig.REPORT_METRICS_CONSOLE_PERIOD);
int reportJMX = wc.getInt(WorkerConfig.REPORT_METRICS_JMX);
if(reportJMX == 1){
SeepMetrics.startJMXReporter();
}
if(reportConsole > 0){
SeepMetrics.startConsoleReporter(reportConsole);
}
}
public static void main(String args[]){
// Get properties from command line
List<ConfigKey> configKeys = WorkerConfig.getAllConfigKey();
OptionParser parser = new OptionParser();
CommandLineArgs cla = new CommandLineArgs(args, parser, configKeys);
Properties commandLineProperties = cla.getProperties();
// Get properties from file, if any
Properties fileProperties = Utils.readPropertiesFromFile(cla.getProperties().getProperty(WorkerConfig.PROPERTIES_FILE), WorkerConfig.PROPERTIES_RESOURCE_FILE);
Properties validatedProperties = Utils.overwriteSecondPropertiesWithFirst(commandLineProperties, fileProperties, configKeys);
boolean validates = validateProperties(validatedProperties);
if(!validates){
printHelp(parser);
System.exit(0);
}
WorkerConfig wc = new WorkerConfig(validatedProperties);
Main instance = new Main();
instance.executeWorker(wc);
}
private static boolean validateProperties(Properties validatedProperties){
if((!validatedProperties.containsKey(WorkerConfig.MASTER_IP)) ||
validatedProperties.getProperty(WorkerConfig.MASTER_IP) == null ||
validatedProperties.getProperty(WorkerConfig.MASTER_IP).equals("")){
LOG.error("Missing required parameter: {}", WorkerConfig.MASTER_IP);
return false;
}
return true;
}
private static void printHelp(OptionParser parser){
try {
parser.printHelpOn(System.out);
}
catch (IOException e) {
e.printStackTrace();
}
}
private static void registerShutdownHook(int workerId, Conductor c, Connection masterConn,
ControlAPIImplementation api){
Thread hook = new Thread(new WorkerShutdownHookWorker(workerId, c, masterConn, api));
Runtime.getRuntime().addShutdownHook(hook);
}
}