package com.koushikdutta.async; import com.koushikdutta.async.callback.CompletedCallback; import com.koushikdutta.async.callback.WritableCallback; import java.nio.ByteBuffer; public class BufferedDataSink implements DataSink { DataSink mDataSink; public BufferedDataSink(DataSink datasink) { setDataSink(datasink); } public boolean isBuffering() { return mPendingWrites.hasRemaining() || forceBuffering; } public DataSink getDataSink() { return mDataSink; } boolean forceBuffering; public void forceBuffering(boolean forceBuffering) { this.forceBuffering = forceBuffering; if (!forceBuffering) writePending(); } public void setDataSink(DataSink datasink) { mDataSink = datasink; mDataSink.setWriteableCallback(new WritableCallback() { @Override public void onWriteable() { writePending(); } }); } private void writePending() { if (forceBuffering) return; // Log.i("NIO", "Writing to buffer..."); if (mPendingWrites.hasRemaining()) { mDataSink.write(mPendingWrites); if (mPendingWrites.remaining() == 0) { if (endPending) mDataSink.end(); } } if (!mPendingWrites.hasRemaining() && mWritable != null) mWritable.onWriteable(); } ByteBufferList mPendingWrites = new ByteBufferList(); @Override public void write(ByteBufferList bb) { write(bb, false); } protected void write(final ByteBufferList bb, final boolean ignoreBuffer) { if (getServer().getAffinity() != Thread.currentThread()) { getServer().run(new Runnable() { @Override public void run() { write(bb, ignoreBuffer); } }); return; } if (!isBuffering()) mDataSink.write(bb); if (bb.remaining() > 0) { int toRead = Math.min(bb.remaining(), mMaxBuffer); if (ignoreBuffer) toRead = bb.remaining(); if (toRead > 0) { bb.get(mPendingWrites, toRead); } } } WritableCallback mWritable; @Override public void setWriteableCallback(WritableCallback handler) { mWritable = handler; } @Override public WritableCallback getWriteableCallback() { return mWritable; } public int remaining() { return mPendingWrites.remaining(); } int mMaxBuffer = Integer.MAX_VALUE; public int getMaxBuffer() { return mMaxBuffer; } public void setMaxBuffer(int maxBuffer) { assert maxBuffer >= 0; mMaxBuffer = maxBuffer; } @Override public boolean isOpen() { return mDataSink.isOpen(); } boolean endPending; @Override public void end() { if (getServer().getAffinity() != Thread.currentThread()) { getServer().run(new Runnable() { @Override public void run() { end(); } }); return; } if (mPendingWrites.hasRemaining()) { endPending = true; return; } mDataSink.end(); } @Override public void setClosedCallback(CompletedCallback handler) { mDataSink.setClosedCallback(handler); } @Override public CompletedCallback getClosedCallback() { return mDataSink.getClosedCallback(); } @Override public AsyncServer getServer() { return mDataSink.getServer(); } }