package ch.usi.da.paxos.ring;
/*
* Copyright (c) 2013 Università della Svizzera italiana (USI)
*
* This file is part of URingPaxos.
*
* URingPaxos is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* URingPaxos is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with URingPaxos. If not, see <http://www.gnu.org/licenses/>.
*/
import java.nio.ByteBuffer;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import org.apache.log4j.Logger;
import ch.usi.da.paxos.message.Message;
/**
* Name: SessionHandler<br>
* Description: <br>
*
* Creation date: Apr 02, 2013<br>
* $Id$
*
* @author Samuel Benz benz@geoid.ch
*/
public class SessionHandler {
private static final Logger logger = Logger.getLogger(SessionHandler.class);
private final NetworkManager manager;
private final ByteBuffer readBuffer;;
private final ByteBuffer writeBuffer;
private boolean preamble = true;
private int msize;
public SessionHandler(NetworkManager manager) {
this.manager = manager;
readBuffer = ByteBuffer.allocate(2097152);
writeBuffer = ByteBuffer.allocate(2097152);
}
protected synchronized void handleReadable(SelectionKey key) {
try {
SocketChannel ch = (SocketChannel) key.channel();
if (readBuffer.hasRemaining()) {
int count = ch.read(readBuffer);
readBuffer.flip();
if(count < 0) {
// client has close inputStream
key.interestOps(key.interestOps() & ~SelectionKey.OP_READ);
ch.socket().shutdownInput();
}else if (count > 0) {
outerloop:
while(readBuffer.hasRemaining()){
if(preamble){
if(readBuffer.limit()-readBuffer.position() >= 8){
while(readBuffer.getInt() != NetworkManager.MAGIC_NUMBER){
readBuffer.position(readBuffer.position()-3);
if(readBuffer.limit()-readBuffer.position() < 4){
break outerloop;
}
}
msize = readBuffer.getInt();
if(manager.crc_32) msize += 8;
preamble = false;
}else{
break;
}
}
if(!preamble){
if(readBuffer.limit()-readBuffer.position() >= msize){
try{
Message msg = Message.fromBuffer(readBuffer);
if(manager.crc_32 && readBuffer.getLong() == Message.getCRC32(msg)){
manager.recv_count++;
manager.recv_bytes = manager.recv_bytes + Message.length(msg);
manager.receive(msg);
}else if(!manager.crc_32){
manager.recv_count++;
manager.recv_bytes = manager.recv_bytes + Message.length(msg);
manager.receive(msg);
}else{
logger.error("Error in SessionHandler: Message CRC fail!");
}
}catch(Exception e){
logger.error("Error in SessionHandler during de-serializing!",e);
}
preamble = true;
}else{
break;
}
}
}
readBuffer.compact();
}
}
} catch (ClosedChannelException e) {
// an other thread closed this channel
} catch (CancelledKeyException e) {
// an other thread closed this channel
} catch (Exception e) {
logger.error("Error in SessionHandler during reading!",e);
}
}
protected synchronized void handleWritable(SelectionKey key) {
try {
SocketChannel ch = (SocketChannel) key.channel();
if (writeBuffer.capacity() - writeBuffer.remaining() > 0) {
writeBuffer.flip();
ch.write(writeBuffer);
writeBuffer.compact();
}
} catch (ClosedChannelException e) {
// an other thread closed this channel
} catch (CancelledKeyException e) {
// an other thread closed this channel
} catch (Exception e) {
logger.error("Exception in SessionHandler during writing!",e);
}
}
}