/*******************************************************************************
* Copyright (c) 2013 Imperial College London.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Raul Castro Fernandez - initial design and implementation
******************************************************************************/
package uk.ac.imperial.lsds.seep.infrastructure.master;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import uk.ac.imperial.lsds.seep.GLOBALS;
import uk.ac.imperial.lsds.seep.api.QueryPlan;
import uk.ac.imperial.lsds.seep.elastic.ElasticInfrastructureUtils;
import uk.ac.imperial.lsds.seep.elastic.NodePoolEmptyException;
import uk.ac.imperial.lsds.seep.infrastructure.OperatorDeploymentException;
public class MasterController {
final private Logger LOG = LoggerFactory.getLogger(MasterController.class.getName());
//MasterController must be a singleton
private static final MasterController instance = new MasterController();
private URLClassLoader ucl = null;
private MasterController() {}
public static MasterController getInstance() {
return instance;
}
private Infrastructure inf;
ElasticInfrastructureUtils eiu;
public void init(){
LOG.debug("-> Initializing Master Controller...");
inf = new Infrastructure(Integer.parseInt(GLOBALS.valueFor("mainPort")));
eiu = new ElasticInfrastructureUtils(inf);
inf.setEiu(eiu);
inf.startInfrastructure();
LOG.debug("-> Initializing Master Controller...DONE");
}
public void submitQuery(QueryPlan qp){
LOG.info("-> Submitting query to the system...");
inf.loadQuery(qp);
LOG.info("-> Submitting query to the system...DONE");
}
public void start() throws OperatorDeploymentException{
LOG.info("-> Console, waiting for commands: ");
try {
boolean alive = true;
/// \todo{make this robust}
while(alive){
consoleOutputMessage();
try{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String option = br.readLine();
int opt = Integer.parseInt(option);
switch(opt){
//Map operators to nodes
case 0:
System.out.println("Not implemented yet");
//Submit Query to the system
break;
case 1:
deployQueryToNodes();
break;
//start system
case 2:
startSystemOption(inf);
break;
//configure source rate
// case 3:
// configureSourceRateOption(inf);
// break;
//parallelize operator manually
case 4:
parallelizeOpManualOption(inf, eiu);
break;
//silent the console
case 5:
alive = false;
inf.stopWorkers();
System.out.println("ENDING console...");
break;
//Exit the system
case 6:
System.out.println("BYE");
System.exit(0);
break;
case 10:
System.out.println("Parsing txt file...");
inf.parseFileForNetflix();
break;
default:
System.out.println("Wrong option. Try again...");
}
}
catch(IOException io){
System.out.println("While reading from terminal: "+io.getMessage());
io.printStackTrace();
}
}
System.out.println("BYE");
}
catch(ESFTRuntimeException ere){
System.out.println(ere.getMessage());
}
catch(Exception g){
System.out.println(g.getMessage());
}
}
public QueryPlan executeComposeFromQuery(String pathToJar, String definitionClass){
Class<?> baseI = null;
Object baseInstance = null;
Method compose = null;
QueryPlan qp = null;
inf.setPathToQueryDefinition(pathToJar);
File urlPathToQueryDefinition = new File(pathToJar);
LOG.debug("-> Set path to query definition: {}", urlPathToQueryDefinition.getAbsolutePath());
URL[] urls = new URL[1];
try {
urls[0] = urlPathToQueryDefinition.toURI().toURL();
}
catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// First time it is created we pass the urls
ucl = new URLClassLoader(urls);
eiu.setClassLoader(ucl);
try {
baseI = ucl.loadClass(definitionClass);
baseInstance = baseI.newInstance();
compose = baseI.getDeclaredMethod("compose", (Class<?>[])null);
qp = (QueryPlan) compose.invoke(baseInstance, (Object[])null);
}
catch (SecurityException e) {
e.printStackTrace();
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
catch (IllegalArgumentException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
catch (InstantiationException e) {
e.printStackTrace();
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
//Finally we return the queryPlan
return qp;
}
private void deployQueryToNodes(){
LOG.info("-> Configuring and deploying query...");
//First configure statically (local) the connections between operators
inf.localMapPhysicalOperatorsToNodes();
// Create initial starTopology
inf.createInitialStarTopology();
//Finally deploy the new submitted query (instantiation, etc)
try {
// The code is previously sent to the nodes (when these attached to the master)
//Send code to nodes (query code)
inf.deployCodeToAllOperators();
inf.deployQuery();
}
catch (CodeDeploymentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (OperatorDeploymentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
LOG.info("-> Configuring and deploying query...DONE");
}
private String getUserInput(String msg) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println(msg);
String option = br.readLine();
return option;
}
public void startSystemOption(Infrastructure inf) throws IOException, ESFTRuntimeException{
getUserInput("Press a button to start the source");
//Start the source, and thus the stream processing system
inf.start();
}
public void configureSourceRateOption(Infrastructure inf) throws IOException{
// String option = getUserInput("Introduce number of events: ");
// int numberEvents = Integer.parseInt(option);
// option = getUserInput("Introduce time (ms): ");
// int time = Integer.parseInt(option);
// inf.configureSourceRate(numberEvents, time);
}
public void parallelizeOpManualOption(Infrastructure inf, ElasticInfrastructureUtils eiu) throws IOException{
String option = getUserInput("Enter operator ID (old): ");
int opId = Integer.parseInt(option);
option = getUserInput("Enter operator ID (new): ");
int newOpId = Integer.parseInt(option);
System.out.println("1= get node automatically");
System.out.println("2= get node manually, put new data");
option = getUserInput("");
int opt = Integer.parseInt(option);
Node newNode = null;
switch (opt){
case 1:
try {
newNode = inf.getNodeFromPool();
}
catch (NodePoolEmptyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
case 2:
option = getUserInput("Introduce IP: ");
InetAddress ip = InetAddress.getByName(option);
option = getUserInput("Introduce port: ");
int newPort = Integer.parseInt(option);
newNode = new Node(ip, newPort);
inf.addNode(newNode);
break;
default:
}
if(newNode == null){
System.out.println("NO NODES AVAILABLE. IMPOSSIBLE TO PARALLELIZE");
return;
}
eiu.scaleOutOperator(opId, newOpId, newNode);
}
public void consoleOutputMessage(){
System.out.println("#############");
System.out.println("USER Console, choose an option");
System.out.println();
System.out.println("0- Submit query to the System");
System.out.println("1- Deploy query to Nodes");
System.out.println("2- Start system");
// System.out.println("3- Configure source rate");
System.out.println("4- Parallelize Operator Manually");
System.out.println("5- Stop system console (EXP)");
System.out.println("6- Exit");
System.out.println("10- Parse txt file to binary kryo");
}
}