package com.neocoretechs.bigsack.io.cluster;
import java.io.File;
import java.io.ObjectInputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;
import mpi.MPI;
import mpi.MPIException;
import com.neocoretechs.bigsack.io.IOWorker;
import com.neocoretechs.bigsack.io.ThreadPoolManager;
import com.neocoretechs.bigsack.io.cluster.mpi.MPIWorker;
/**
* Get an address down, at the master we coordinate the assignment of addresses
* for each tablespace and node. It comes to this known address via TCP packet of serialized
* command. Also sent down are the tablespace and database to operate on
* for the worker we are spinning. We may spin a local worker, a UDP worker,a TCP worker or an MPI worker depending
* on passed packet at spin up time.
* @author jg
*
*/
public final class WorkBoot extends TCPServer {
private static boolean DEBUG = true;
private static boolean mpiIsInit = false;
private static int mpiThreadProvided;
private static String[] mpiArgs = new String[0];
public static int port = 8000;
private ConcurrentHashMap<String, IOWorker> dbToWorker = new ConcurrentHashMap<String, IOWorker>();
/**
* Spin the worker, get the tablespace from the cmdl param
* @param args
* @throws Exception
*/
public static void main(String args[]) throws Exception {
if( args.length > 0 ) {
port = Integer.valueOf(args[0]);
}
WorkBoot wb = new WorkBoot();
wb.startServer(port);
System.out.println("WorkBoot started on "+port+" of "+InetAddress.getLocalHost().getHostName());
}
private void MpiInit() throws MPIException {
mpiThreadProvided = MPI.InitThread(mpiArgs, MPI.THREAD_FUNNELED);
mpiIsInit = true;
}
public void run() {
while(!shouldStop) {
try {
Socket datasocket = server.accept();
// disable Nagles algoritm; do not combine small packets into larger ones
datasocket.setTcpNoDelay(true);
// wait 1 second before close; close blocks for 1 sec. and data can be sent
datasocket.setSoLinger(true, 1);
//
ObjectInputStream ois = new ObjectInputStream(datasocket.getInputStream());
CommandPacketInterface o = (CommandPacketInterface) ois.readObject();
if( DEBUG )
System.out.println("WorkBoot command received:"+o);
//datasocket.close();
// Create a new UDPWorker with database and tablespace
// Use mmap mode 0
// replace any marker of $ with tablespace number
String db = o.getDatabase();
if( db.indexOf('$') != -1) {
db = db.replace('$', String.valueOf(o.getTablespace()).charAt(0));
}
db = (new File(db)).toPath().getParent().toString() + File.separator +
"tablespace"+String.valueOf(o.getTablespace()) + File.separator +
(new File(o.getDatabase()).getName());
// determine if this worker has started, if so, cancel thread and start a new one.
IOWorker uworker = null;
if( (uworker = dbToWorker.get(db)) != null && o.getTransport().equals("TCP")) {
((TCPWorker)uworker).stopWorker();
} else {
if( (uworker = dbToWorker.get(db)) != null && o.getTransport().equals("MPI")) {
((MPIWorker)uworker).stopWorker();
}
}
// bring up TCP or UDP or MPI worker
if(o.getTransport().equals("UDP")) {
uworker = new UDPWorker(db, o.getTablespace(), o.getMasterPort(), o.getSlavePort(), 0);
} else {
if( o.getTransport().equals("MPI")) {
if( !mpiIsInit ) MpiInit();
uworker = new MPIWorker(db, o.getTablespace(), o.getMasterPort(), o.getSlavePort(), 0);
} else {
uworker = new TCPWorker(db, o.getTablespace(), o.getRemoteMaster(), Integer.valueOf(o.getMasterPort()), Integer.valueOf(o.getSlavePort()), 0);
}
}
dbToWorker.put(db, uworker);
ThreadPoolManager.getInstance().spin(uworker);
if( DEBUG ) {
System.out.println("WorkBoot starting new worker "+db+" tablespace "+o.getTablespace()+" master port:"+o.getMasterPort()+" slave port:"+o.getSlavePort());
}
} catch(Exception e) {
System.out.println("BigSack backchannel node configuration server socket accept exception "+e);
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
}