package uk.ac.imperial.lsds.seepmaster.comm;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import uk.ac.imperial.lsds.seep.comm.protocol.BootstrapCommand;
import uk.ac.imperial.lsds.seep.comm.protocol.Command;
import uk.ac.imperial.lsds.seep.comm.protocol.CommandFamilyType;
import uk.ac.imperial.lsds.seep.comm.protocol.DeadWorkerCommand;
import uk.ac.imperial.lsds.seep.comm.protocol.MasterWorkerCommand;
import uk.ac.imperial.lsds.seep.comm.protocol.MasterWorkerProtocolAPI;
import uk.ac.imperial.lsds.seep.comm.protocol.StageStatusCommand;
import uk.ac.imperial.lsds.seep.comm.serialization.KryoFactory;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
public class MasterWorkerCommManager {
final private Logger LOG = LoggerFactory.getLogger(MasterWorkerCommManager.class.getName());
private ServerSocket serverSocket;
private Kryo k;
private Thread listener;
private boolean working = false;
private MasterWorkerAPIImplementation api;
public MasterWorkerCommManager(int port, MasterWorkerAPIImplementation api){
this.api = api;
this.k = KryoFactory.buildKryoForProtocolCommands(this.getClass().getClassLoader());
try {
serverSocket = new ServerSocket(port);
LOG.info(" Listening on {}:{}", InetAddress.getLocalHost(), port);
}
catch (IOException e) {
e.printStackTrace();
}
listener = new Thread(new CommMasterWorker());
listener.setName(CommMasterWorker.class.getSimpleName());
// TODO: set uncaughtexceptionhandler
}
public void start(){
this.working = true;
LOG.info("Start MasterWorkerCommManager");
this.listener.start();
}
public void stop(){
//TODO: do some other cleaning work here
this.working = false;
}
class CommMasterWorker implements Runnable{
@Override
public void run() {
while(working){
Input i = null;
Socket incomingSocket = null;
try{
// Blocking call
incomingSocket = serverSocket.accept();
InputStream is = incomingSocket.getInputStream();
i = new Input(is);
Command c = k.readObject(i, Command.class);
if(c.familyType() != CommandFamilyType.MASTERCOMMAND.ofType()) {
LOG.error("Received an unrecognized (non-Master Command) here");
}
MasterWorkerCommand command = (MasterWorkerCommand) c.getCommand();
short type = command.type();
// BOOTSTRAP command
if(type == MasterWorkerProtocolAPI.BOOTSTRAP.type()){
LOG.info("RX-> Bootstrap command");
BootstrapCommand bc = command.getBootstrapCommand();
api.bootstrapCommand(bc);
}
// STAGE_STATUS command
else if(type == MasterWorkerProtocolAPI.STAGE_STATUS.type()) {
LOG.info("RX-> Stage Status update command");
StageStatusCommand ssc = command.getStageStatusCommand();
api.stageStatusCommand(ssc);
}
// CRASH command
else if(type == MasterWorkerProtocolAPI.CRASH.type()){
LOG.info("RX-> Crash command");
}
// DEADWORKER command
else if(type == MasterWorkerProtocolAPI.DEADWORKER.type()){
LOG.info("RX-> DeadWorker command");
DeadWorkerCommand dwc = command.getDeadWorkerCommand();
api.handleDeadWorker(dwc);
}
}
catch(IOException io){
io.printStackTrace();
}
finally {
if (incomingSocket != null){
try {
i.close();
incomingSocket.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
}