package org.rzo.netty.ahessian.io;
import java.io.InputStream;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.rzo.netty.ahessian.Constants;
import org.rzo.netty.ahessian.stopable.StopableHandler;
public class PullInputStreamConsumer extends SimpleChannelUpstreamHandler implements StopableHandler
{
final InputStreamConsumer _consumer;
final Executor _executor;
final Lock _lock = new ReentrantLock();
final Condition _hasData = _lock.newCondition();
volatile boolean _stop = false;
volatile ChannelHandlerContext _ctx;
volatile InputStream _inputStream;
volatile boolean _waiting = false;
static AtomicInteger _threadCounter = new AtomicInteger(0);
private boolean _stopEnabled = true;
public PullInputStreamConsumer(InputStreamConsumer consumer, Executor executor)
{
_consumer = consumer;
_executor = executor;
_executor.execute(new Runnable()
{
public void run()
{
String tName = Thread.currentThread().getName();
Thread.currentThread().setName("ahessian-PullInputStreamConsumer-#"+_threadCounter.incrementAndGet());
try
{
waitForData();
while (!_stop)
{
_consumer.consume(_ctx, _inputStream);
waitForData();
}
}
finally
{
Thread.currentThread().setName(tName);
_threadCounter.decrementAndGet();
}
}
});
}
private void waitForData()
{
//System.out.println("wait for data");
while (! _stop &&( _consumer == null || _consumer.isBufferEmpty() || _ctx == null || !_ctx.getChannel().isConnected()))
{
_lock.lock();
try
{
_waiting = true;
_hasData.await(500, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e)
{
Constants.ahessianLogger.warn("", e);
}
finally
{
_waiting = false;
_lock.unlock();
}
}
//System.out.println("got data");
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent evnt) throws Exception
{
if (_ctx != ctx)
_ctx = ctx;
if (_inputStream != evnt.getMessage())
{
_inputStream = (InputStream) evnt.getMessage();
((InputStreamBuffer)_inputStream).setReadTimeout(-1);
}
if (_waiting)
{
_lock.lock();
_hasData.signal();
_lock.unlock();
}
}
public void channelConnected(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception
{
_lock.lock();
_consumer.setContext(ctx);
_ctx = ctx;
_lock.unlock();
ctx.sendUpstream(e);
}
public boolean isStopEnabled()
{
return _stopEnabled ;
}
public void setStopEnabled(boolean stopEnabled)
{
_stopEnabled = stopEnabled;
}
public void stop()
{
_stop = true;
}
}