/*******************************************************************************
* 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 java.util.Map;
import java.util.Queue;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Context;
import org.zeromq.ZMQ.Socket;
import com.steffi.common.Configuration;
import com.steffi.loader.ResponseProcessor;
import com.steffi.model.SteffiGraph;
import com.steffi.networking.messages.Identifiable;
import com.steffi.networking.messages.IdentifiableMessage;
import com.steffi.networking.messages.Message;
/**
* @author Aldemar Reynaga
* A general purpose sender of asynchronous messages, the sender can relate a received response message with
* the sent message that triggered that response. It is possible to register a callback function that will be called
* upon the arrival of a response.
*/
public class ClientMultiThread implements Runnable {
private Context context;
private Socket socket;
private ZMQ.Poller poller;
private Queue<IdentifiableMessage> messageQueue;
private boolean alive;
private Map<UUID, ResponseProcessor> pendingResponses;
public ClientMultiThread(String ipAddress, String address) {
context = SteffiGraph.getInstance().getZMQContext();
socket = context.socket(ZMQ.DEALER);
String identity = UUID.randomUUID().toString();
socket.setIdentity(identity.getBytes());
socket.connect("tcp://" + ipAddress + ":" +
Configuration.getProperty(Configuration.Key.NODE_PORT));
poller = context.poller(1);
poller.register(socket, ZMQ.Poller.POLLIN);
messageQueue = new ConcurrentLinkedQueue<IdentifiableMessage>();
pendingResponses = new ConcurrentHashMap<UUID, ResponseProcessor>();
}
public void addMsgToQueue(IdentifiableMessage message, ResponseProcessor sender) {
pendingResponses.put(message.getId(), sender);
messageQueue.add(message);
}
public void stop() {
alive = false;
}
@Override
public void run() {
alive = true;
try {
while (alive) {
poller.poll(5);
if (poller.pollin(0)) {
byte [] msg = socket.recv(0);
IdentifiableMessage message = (IdentifiableMessage) Message.readFromBytes(msg);
ResponseProcessor responseProcessor = pendingResponses.remove(message.getId());
responseProcessor.processResponse(message);
}
//Send from queue
if (!messageQueue.isEmpty()) {
Identifiable mq = messageQueue.poll();
socket.send(Message.convertMessageToBytes((Message) mq), 0);
}
}
} catch (Exception x) {
if (alive)
throw new RuntimeException(x);
} finally {
this.socket.close();
}
}
}