package org.apache.haox.transport.buffer; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import java.util.Iterator; import java.util.LinkedList; public class RecvBuffer { private LinkedList<ByteBuffer> bufferQueue; public RecvBuffer() { bufferQueue = new LinkedList<ByteBuffer>(); } public synchronized void write(ByteBuffer buffer) { bufferQueue.addLast(buffer); } /** * Put buffer as the first into the buffer queue */ public synchronized void writeFirst(ByteBuffer buffer) { bufferQueue.addFirst(buffer); } /** * Read and return the first buffer if available */ public synchronized ByteBuffer readFirst() { if (! bufferQueue.isEmpty()) { return bufferQueue.removeFirst(); } return null; } /** * Read most available bytes into the dst buffer */ public synchronized ByteBuffer readMostBytes() { int len = remaining(); return readBytes(len); } /** * Read len bytes into the dst buffer if available */ public synchronized ByteBuffer readBytes(int len) { if (remaining() < len) { // no enough data that's available throw new BufferOverflowException(); } ByteBuffer result = null; ByteBuffer takenBuffer; if (bufferQueue.size() == 1) { takenBuffer = bufferQueue.removeFirst(); if (takenBuffer.remaining() == len) { return takenBuffer; } result = BufferPool.allocate(len); for (int i = 0; i < len; i++) { result.put(takenBuffer.get()); } // Has left bytes so put it back for future reading if (takenBuffer.remaining() > 0) { bufferQueue.addFirst(takenBuffer); } } else { result = BufferPool.allocate(len); Iterator<ByteBuffer> iter = bufferQueue.iterator(); int alreadyGot = 0, toGet; while (iter.hasNext()) { takenBuffer = iter.next(); iter.remove(); toGet = takenBuffer.remaining() < len - alreadyGot ? takenBuffer.remaining() : len -alreadyGot; byte[] toGetBytes = new byte[toGet]; takenBuffer.get(toGetBytes); result.put(toGetBytes); if (takenBuffer.remaining() > 0) { bufferQueue.addFirst(takenBuffer); } alreadyGot += toGet; if (alreadyGot == len) { break; } } } result.flip(); return result; } public boolean isEmpty() { return bufferQueue.isEmpty(); } /** * Return count of remaining and left bytes that's available */ public int remaining() { if (bufferQueue.isEmpty()) { return 0; } else if (bufferQueue.size() == 1) { return bufferQueue.getFirst().remaining(); } int result = 0; Iterator<ByteBuffer> iter = bufferQueue.iterator(); while (iter.hasNext()) { result += iter.next().remaining(); } return result; } public synchronized void clear() { if (bufferQueue.isEmpty()) { return; } else if (bufferQueue.size() == 1) { BufferPool.release(bufferQueue.getFirst()); } Iterator<ByteBuffer> iter = bufferQueue.iterator(); while (iter.hasNext()) { BufferPool.release(iter.next()); } bufferQueue.clear(); } }