/* $Id$ */
package ibis.ipl.impl.nio;
import ibis.ipl.impl.ReceivePortIdentifier;
import ibis.ipl.impl.SendPortConnectionInfo;
import java.io.IOException;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.SelectionKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class NioAccumulatorConnection extends SendPortConnectionInfo {
static final int MAX_SEND_BUFFERS = 32;
private static Logger logger
= LoggerFactory.getLogger(NioAccumulatorConnection.class);
GatheringByteChannel channel;
SendBuffer[] pendingBuffers;
int bufferPosition = 0;
int bufferLimit = 0;
// placeholder for the accumulator to put a selection key in
SelectionKey key;
NioAccumulatorConnection(NioSendPort port, GatheringByteChannel channel,
ReceivePortIdentifier peer) {
super(port, peer);
pendingBuffers = new SendBuffer[MAX_SEND_BUFFERS];
this.channel = channel;
}
boolean full() {
return ((bufferLimit + 1) % MAX_SEND_BUFFERS) == bufferPosition;
}
boolean empty() {
return bufferLimit == bufferPosition;
}
/**
* Adds given buffer to list of buffer which will be send out.
*
* @return true if the add was succesfull, false if all the buffers are full
*/
boolean addToSendList(SendBuffer buffer) {
if (full()) {
return false;
}
pendingBuffers[bufferLimit] = buffer;
if (logger.isDebugEnabled()) {
logger.debug("adding new buffer to send list" + " at position "
+ bufferLimit);
}
bufferLimit = (bufferLimit + 1) % MAX_SEND_BUFFERS;
return true;
}
/**
* Send out data while it is possible to send without blocking. Assumes
* non-blocking channel, recycles empty buffers.
*
* @return true if are we done sending, or false if there is more data in
* the buffer.
*/
boolean send() throws IOException {
long count;
if (logger.isDebugEnabled()) {
logger.debug("sending");
}
while (!empty()) {
count = channel.write(pendingBuffers[bufferPosition].byteBuffers);
if (logger.isDebugEnabled()) {
logger.debug("send " + count + " bytes");
}
if (pendingBuffers[bufferPosition].hasRemaining()) {
if (logger.isDebugEnabled()) {
logger.debug("buffer has some bytes" + " remaining");
}
return false;
}
SendBuffer.recycle(pendingBuffers[bufferPosition]);
bufferPosition = (bufferPosition + 1) % MAX_SEND_BUFFERS;
if (logger.isDebugEnabled()) {
logger.debug("completely send buffer,"
+ " trying next one too");
}
}
if (logger.isDebugEnabled()) {
logger.debug("done sending");
}
return true;
}
public void closeConnection() {
try {
channel.close();
} catch(Throwable e) {
// ignored
}
}
}