package lsr.paxos.network;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import lsr.common.PID;
import lsr.paxos.messages.Message;
import lsr.paxos.messages.MessageFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NioInputConnection extends NioConnection
{
private static final int BUFFER_SIZE = 8192;
private ByteBuffer readBuffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
private byte[] outputArray;
private int outputArrayRemainging = 0;
public NioInputConnection(NioNetwork network, PID replica, SocketChannel channel)
throws IOException
{
super(network, replica, channel);
channel.register(selector, SelectionKey.OP_READ);
}
@Override
public void run()
{
String name = "NioInputConnection_" + replicaId + "->" + Network.localId;
setName(name);
logger.trace("starting {}", name);
while (true)
{
try
{
selector.select();
Iterator<SelectionKey> selectedKeys = this.selector
.selectedKeys().iterator();
while (selectedKeys.hasNext())
{
SelectionKey key = (SelectionKey) selectedKeys.next();
selectedKeys.remove();
if (!key.isValid())
continue;
if (key.isReadable())
read(key);
}
} catch (Exception e)
{
logger.debug("input connection problem with: {}", replicaId);
// e.printStackTrace();
disposeConnection();
return;
}
}
}
// if (stop == true)
// {
// logger_.finest("quitting");
// break;
// }
private void read(SelectionKey key) throws IOException
{
logger.trace("socket read: {}", replicaId);
int numRead;
try
{
numRead = channel.read(readBuffer);
} catch (IOException e)
{
disposeConnection();
return;
}
if (numRead == -1)
{
disposeConnection();
return;
}
// Network.bytesRead.add(peerId, numRead);
// Network.numberOfReads.increment(peerId);
readBuffer.flip();
while (readBuffer.remaining() > 0)
{
if (outputArray == null)
{
if (readBuffer.remaining() < 4)
{
break;
}
outputArrayRemainging = readBuffer.getInt();
outputArray = new byte[outputArrayRemainging];
continue;
}
int bytesToCopy = Math.min(outputArrayRemainging, readBuffer.remaining());
readBuffer.get(outputArray, outputArray.length
- outputArrayRemainging, bytesToCopy);
outputArrayRemainging -= bytesToCopy;
if (outputArrayRemainging == 0)
{
// network.fireReceiveMessage(Message.create(outputArray,
// MessageType.A, false), peerId);
// TODO poprawic strumienie
DataInputStream input = new DataInputStream(new ByteArrayInputStream(outputArray));
Message message = MessageFactory.create(input);
logger.debug("Received [{}] {} size: {}", replicaId, message,
message.byteSize());
network.fireReceiveMessage(message, replicaId);
outputArray = null;
}
}
readBuffer.compact();
}
protected void disposeConnection()
{
for (SelectionKey key : selector.keys())
key.cancel();
logger.debug("input connection closed with: " + replicaId);
network.removeConnection(replicaId, Network.localId);
}
private final static Logger logger = LoggerFactory.getLogger(Network.class);
}