package com.techq.available.connector.impl;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.apache.jute.BinaryInputArchive;
import org.apache.jute.BinaryOutputArchive;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.techq.available.AvailableConfig;
import com.techq.available.data.BasicPacket;
import com.techq.available.quorum.handler.Leader;
import com.techq.available.quorum.handler.LearnerHandler;
/**
*
* @author CHQ
* 2012-2-3
*/
public class DataCnxManager {
private static final Logger LOG = LoggerFactory.getLogger(DataCnxManager.class);
class LearnerCnxAcceptor extends Thread {
private volatile boolean stop = false;
Leader leader;
ServerSocket ss;
long id;
public LearnerCnxAcceptor(Leader handler, int port, long id) throws IOException {
super("LearnerCnxAcceptor[myid=" + id + "]");
this.id = id;
ss = new ServerSocket(port);
leader = handler;
}
@Override
public void run() {
try {
while (!stop) {
try {
Socket s = ss.accept();
s.setSoTimeout(AvailableConfig.tickTime * AvailableConfig.syncTick);
s.setTcpNoDelay(true);
LearnerHandler fh = new LearnerHandler(s, leader, id);
fh.start();
} catch (SocketException e) {
if (stop) {
LOG.info("exception while shutting down acceptor: " + e);
// When Leader.shutdown() calls ss.close(),
// the call to accept throws an exception.
// We catch and set stop to true.
stop = true;
} else {
throw e;
}
}
}
} catch (Exception e) {
LOG.warn("Exception while accepting follower", e);
}
}
public void halt() {
stop = true;
LOG.debug("halt LearnerCnxAcceptor");
}
}
public static class MessageReceiver extends Thread {
volatile boolean running = true;
Socket sock;
LinkedBlockingQueue<BasicPacket> recvqueue;
public MessageReceiver(Socket sock, LinkedBlockingQueue<BasicPacket> re, long id) {
super("MessageReceiver[myid=" + id + "]");
this.sock = sock;
recvqueue = re;
}
@Override
public void run() {
BinaryInputArchive ia = null;
try {
ia = BinaryInputArchive.getArchive(sock.getInputStream());
} catch (IOException e1) {
e1.printStackTrace();
this.running = false;
return;
}
while(running) {
try {
// byte requestBytes[];
// if (DebugConfig.debug)
// requestBytes = new byte[Message.DEBUG_DEFAULT_SIZE];
// else
// requestBytes = new byte[Message.DEFAULT_SIZE];
BasicPacket packet = new BasicPacket();
ia.readRecord(packet, "BasicPacket");
// in.read(requestBytes);
// ByteBuffer requestBuffer = ByteBuffer.wrap(requestBytes);
// Notification n = new Notification();
// int type = requestBuffer.getInt();
// int state = requestBuffer.getInt();
// long leader = requestBuffer.getLong();
// long zxid = requestBuffer.getLong();
// long clock = requestBuffer.getLong();
// long from = requestBuffer.getLong();
// int seq = requestBuffer.getInt();
// n.setType(Notification.getTypeByInt(type));
// n.setState(Notification.getStateByInt(state));
// n.setLeader(leader);
// n.setZxid(zxid);
// n.setLogicalClock(clock);
// n.setFrom(from);
//// n.setSid(-1);
// if (DebugConfig.debug)
// n.setSeq(seq);
recvqueue.offer(packet);
} catch (IOException e) {
LOG.error("read time", e);
running = false;
}
}
}
public void halt() {
if (!running)
return;
running = false;
LOG.debug("halt MessageReceiver");
this.interrupt();
}
}
public static class MessageSender extends Thread {
volatile boolean running = true;
Socket sock;
LinkedBlockingQueue<BasicPacket> sendqueue;
public MessageSender(Socket sock, LinkedBlockingQueue<BasicPacket> se, long id) {
super("MessageSender[myid=" + id + "]");
this.sock = sock;
sendqueue = se;
}
@Override
public void run() {
BinaryOutputArchive oa = null;
try {
oa = BinaryOutputArchive.getArchive(sock.getOutputStream());
} catch (IOException e1) {
e1.printStackTrace(System.out);
this.running = false;
return;
}
while(running) {
try {
BasicPacket p = sendqueue.poll(200, TimeUnit.MILLISECONDS);
if (p == null) {
p = sendqueue.take();
}
LOG.trace("send:" + p);
// byte requestBytes[];
// if (DebugConfig.debug)
// requestBytes = new byte[Message.DEBUG_DEFAULT_SIZE];
// else
// requestBytes = new byte[Message.DEFAULT_SIZE];
// ByteBuffer requestBuffer = ByteBuffer.wrap(requestBytes);
// requestBuffer.clear();
// requestBuffer.putInt(m.getType().ordinal());
// requestBuffer.putInt(m.getState().ordinal());
// requestBuffer.putLong(m.getLeader());
// requestBuffer.putLong(m.getZxid());
// requestBuffer.putLong(m.getLogicalClock());
// requestBuffer.putLong(m.getFrom());//from which peer
//// requestBuffer.putLong(m.getSid());//from which peer
// if (DebugConfig.debug)
// requestBuffer.putInt(m.getSeq());
oa.writeRecord(p, "BasicPacket");
// try {
// dos.write(requestBytes);
// } catch (IOException e) {
// LOG.error("write exception", e);
// this.halt();
// }
} catch (InterruptedException e) {
running = false;
LOG.error("InterruptedException", e);
} catch (IOException e) {
running = false;
LOG.error("InterruptedException", e);
}
}
}
public void halt() {
if (!running)
return;
running = false;
LOG.debug("halt MessageSender");
this.interrupt();
}
}
}