/*
* Method invoked when the read event is selected for this channel.
*/
public void onRead(IOEvent<Context> ioEvent) {
Context ctx = ioEvent.attachment();
ByteBuffer byteBuffer = null;
WorkerThread workerThread = (WorkerThread) Thread.currentThread();
byteBuffer = workerThread.getByteBuffer();
SelectionKey febeSelectionKey = ctx.getSelectionKey();
if (!readFromFeBeChannel(ctx)) {
return;
}
/*
* Paranoid check to fail early.
*/
if (byteBuffer.position() == 0 || responseHandler == null
|| clientKey == null ) {
ctx.getSelectorHandler().register(febeSelectionKey,
SelectionKey.OP_READ);
return;
}
/* Parsed is an instance variable whose value has to be preserved
* until the lifecycle of the callback handler.
*/
if (!parsed) {
while (!responseHandler.parse(byteBuffer)) {
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE,
"clb.proxy.callback_algorithm_parse_false");
}
if (!readFromFeBeChannel(ctx)) {
return;
}
}
parsed = true;
} else {
byteBuffer.flip();
}
SocketChannel clientChannel = null;
if (clientKey != null){
clientChannel = (SocketChannel)clientKey.channel();
}
if (_logger.isLoggable(Level.FINEST)) {
_logger.log(Level.FINEST, "clb.proxy.callback.algorithm_finished",
clientChannel.socket().getRemoteSocketAddress());
_logger.log(Level.FINEST, "clb.proxy.callback_clientkey",
clientKey.channel());
_logger.log(Level.FINEST, "clb.proxy.callback.server_channel",
ctx.getSelectionKey().channel());
_logger.log(Level.FINEST, "Byte Buffer " + byteBuffer);
try {
dumpBuffer(byteBuffer);
} catch (Exception e) {
//ignore
}
}
long byteswritten = 0;
int iPos = byteBuffer.position();
int iLimit = byteBuffer.limit();
int bytesToBeWritten = byteBuffer.remaining();
boolean writeSuccess = true;
/*
* If we have the bytes ready write it to the client
*/
if ((clientChannel != null) && (clientChannel.isConnected())) {
try {
if (isSecure) {
if (_logger.isLoggable(Level.FINEST)) {
_logger.log(Level.FINEST,
"clb.proxy.callback.ssl_writer",
clientChannel + " " + byteBuffer + " " +
outputBB + " " + sslEngine);
}
byteswritten = SSLOutputWriter.flushChannel(clientChannel,
byteBuffer, outputBB, sslEngine);
} else {
byteswritten = OutputWriter.flushChannel(clientChannel,
byteBuffer);
}
} catch (Exception ioe) {
/*
* If write fails then close client and update the response
* handler. We have to drop the response because we cannot send
* it through another channel.
*/
writeSuccess = false;
responseHandler.updateBytesWritten(bytesToBeWritten);
byteBuffer.position(iPos);
byteBuffer.limit(iLimit);
}
if (responseHandler.isTransferEncoding()) {
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "Transfer encoding Byte buffer " +
byteBuffer);
}
/**
* It is quite inefficient to search for termination in the whole
* bytebuffer, Needs to be modified
*/
responseHandler.updateEnd((ByteBuffer) byteBuffer.flip());
} else {
responseHandler.updateBytesWritten(byteswritten);
}
} else {
_logger.log(Level.SEVERE,
"clb.proxy.callback_client_channel_closed");
writeSuccess = false;
}
if (byteBuffer != null) {
byteBuffer.clear();
}
boolean register = false;
if (outputBB != null) {
outputBB.clear();
}
if (responseHandler.hasRemaining()) {
/*
* If write to client failed and there is still more data
* to be read from the backend we cannot re-use the febe channel
* anymore.
*/
if (!writeSuccess) {
cleanFeBeHandler(ctx.getSelectorHandler(),
febeSelectionKey);
connectionManager.removeClientEndpoint(clientKey);
connectionManager.cancelClientKey(clientKey);
} else {
register = true;
}
if (_logger.isLoggable(Level.FINEST)) {
_logger.log(Level.FINEST,
"clb.proxy.callback.algorithm_more_data",
clientChannel.socket().getRemoteSocketAddress());
}
} else {
/* keep the key registered because it can be closed by the
* peer when in the cache, when this happens the read will
* will be invoked and we can close the channel. We dont have to
* keep it registered when keep alive is disabled because we
* can be sure that the channel will not be closed.
*/
register = true;
// refactor
if (!writeSuccess){
/*
* Close only the client because we can re-use febe channel
*/
connectionManager.removeClientEndpoint(clientKey);
connectionManager.cancelClientKey(clientKey);
}
if (!keepAlive) {
if (_logger.isLoggable(Level.FINEST)) {
_logger.log(Level.FINEST,
"clb.proxy.callback.algorithm_cancelled_key",
clientChannel.socket().getRemoteSocketAddress());
}
connectionManager.cancelClientKey(clientKey);
} else {
if (_logger.isLoggable(Level.FINEST)) {
_logger.log(Level.FINEST,
"clb.proxy.callback.algorithm_registered_key",
clientChannel.socket().getRemoteSocketAddress());
}
connectionManager.registerClientKey(clientKey);
}
release();
}
if (register) {
ctx.getSelectorHandler().register(febeSelectionKey,
SelectionKey.OP_READ);
}
}