/*******************************************************************************
* Copyright (c) 2014 EURA NOVA.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* Aldemar Reynaga - initial API and implementation
* Salim Jouili - initial API and implementation
******************************************************************************/
package com.steffi.networking;
import org.zeromq.ZMQ;
import com.steffi.common.Configuration;
import com.steffi.common.ImgLogger;
import com.steffi.model.SteffiGraph;
import com.steffi.networking.messages.Message;
import com.steffi.networking.messages.MessageType;
import com.steffi.networking.messages.SearchEndMsg;
import com.steffi.networking.messages.SearchReqMsg;
import com.steffi.storage.CacheContainer;
/**
* @author Aldemar Reynaga
* The process representing an Imgraph data server
*/
public class NodeServer implements Runnable{
static { naughtmq.Loader.load(); }
private SearchWorkerManager searchWorkerManagerV5;
private LoadWorkerManager loadWorkerManager;
private CommandWorkerManager commandWorkerManager;
private ZMQ.Context context;
private long searchMsgCounter;
public NodeServer() {
loadWorkerManager = new LoadWorkerManager();
commandWorkerManager = new CommandWorkerManager();
searchWorkerManagerV5 = new SearchWorkerManager();
searchMsgCounter = 0;
context = SteffiGraph.getInstance().getZMQContext();
}
public long getSearchMsgCounter() {
return searchMsgCounter;
}
@Override
public void run() {
Message message = null;
boolean stop = false;
byte id[], msg [];
ZMQ.Socket frontend = null;
int numLoaders = Integer.parseInt(Configuration.getProperty(Configuration.Key.NUM_LOADERS));
frontend = context.socket(ZMQ.ROUTER);
frontend.bind("tcp://*:" + Configuration.getProperty(Configuration.Key.NODE_PORT));
ZMQ.Poller poller = context.poller(3 + numLoaders);
poller.register(frontend, ZMQ.Poller.POLLIN);
commandWorkerManager.init(context, poller); //Registers two backends
loadWorkerManager.init(context, poller, numLoaders);
searchWorkerManagerV5.init(context);
System.out.println("ZMQ Server started....");
try {
do {
poller.poll();
if (poller.pollin(0)) {
boolean msgFromReq = false;
id = frontend.recv(0);
msg = frontend.recv(0);
//In case we got a message from a REQ socket
if (frontend.hasReceiveMore()) {
msg = frontend.recv(0);
msgFromReq = true;
}
message = Message.readFromBytes(msg);
switch (message.getType()) {
case CONFIG_CLUSTER_REQ:
Message configResponse = new Message(MessageType.CONFIG_CLUSTER_REP);
try {
SteffiGraph.getInstance().initializeMemberIndexes();
searchWorkerManagerV5.initializeClientThreads();
configResponse.setBody("OK");
} catch (Exception x) {
configResponse.setBody("ERROR: " + x.getMessage());
ImgLogger.logError(x, x.getMessage());
}
frontend.send(id, ZMQ.SNDMORE);
frontend.send(Message.convertMessageToBytes(configResponse), 0);
break;
case CLEAR:
break;
case LOAD_REQ:
loadWorkerManager.sendToLoader(id, msg);
break;
case SEARCH_REQ:
searchMsgCounter++;
searchWorkerManagerV5.sendToSearchWorker((SearchReqMsg) message);
break;
case STOP:
loadWorkerManager.stop();
commandWorkerManager.stop();
searchWorkerManagerV5.stop();
SteffiGraph.getInstance().closeGraphClients();
stop = true;
break;
case END_SEARCH:
searchWorkerManagerV5.endSearch(((SearchEndMsg)message).getSearchId());
break;
default:
commandWorkerManager.sendToCommandWorker(id, msg, msgFromReq);
break;
}
}
if (poller.pollin(1)) {
commandWorkerManager.sentToFrontend(frontend, true);
}
if (poller.pollin(2)) {
commandWorkerManager.sentToFrontend(frontend, false);
}
for (int i=0; i<numLoaders; i++) {
if (poller.pollin(i+3)) {
loadWorkerManager.sendToFrontend(i, frontend);
}
}
} while (!stop);
} catch (Exception x) {
ImgLogger.logError(x, "Error on node server");
} finally {
frontend.close();
context.term();
CacheContainer.getCellCache().stop();
CacheContainer.getCacheContainer().stop();
}
System.out.println("Main node server closed...");
System.out.println(CacheContainer.getCacheContainer().getStatus());
}
public void resetCounters() {
searchMsgCounter = 0;
}
}