package io.mycat.net; import io.mycat.util.ByteBufferUtil; import java.nio.ByteBuffer; import java.util.Collections; import java.util.LinkedList; import java.util.List; /** * used for large data write ,composed by buffer array, when a large MySQL * package write ,shoud use this object to write data * * @author wuzhih * */ public class BufferArray { private final BufferPool bufferPool; private ByteBuffer curWritingBlock; private List<ByteBuffer> writedBlockLst = Collections.emptyList(); public BufferArray(BufferPool bufferPool) { super(); this.bufferPool = bufferPool; curWritingBlock = bufferPool.allocate(); } public ByteBuffer checkWriteBuffer(int capacity) { if (capacity > curWritingBlock.remaining()) { addtoBlock(curWritingBlock); curWritingBlock = bufferPool.allocate(capacity); return curWritingBlock; } else { return curWritingBlock; } } public int getBlockCount() { return writedBlockLst.size()+1; } private void addtoBlock(ByteBuffer buffer) { if (writedBlockLst.isEmpty()) { writedBlockLst = new LinkedList<ByteBuffer>(); } writedBlockLst.add(buffer); } public ByteBuffer getCurWritingBlock() { return curWritingBlock; } public List<ByteBuffer> getWritedBlockLst() { return writedBlockLst; } public void clear() { curWritingBlock = null; writedBlockLst.clear(); writedBlockLst = null; } public ByteBuffer write(byte[] src) { int offset = 0; int remains = src.length; while (remains > 0) { int writeable = curWritingBlock.remaining(); if (writeable >= remains) { // can write whole srce curWritingBlock.put(src, offset, remains); break; } else { // can write partly curWritingBlock.put(src, offset, writeable); offset += writeable; remains -= writeable; addtoBlock(curWritingBlock); curWritingBlock = bufferPool.allocate(); continue; } } return curWritingBlock; } public byte[] writeToByteArrayAndRecycle() { BufferArray bufferArray=this; try { int size=0; List<ByteBuffer> blockes = bufferArray.getWritedBlockLst(); if (!bufferArray.getWritedBlockLst().isEmpty()) { for (ByteBuffer curBuf : blockes) { curBuf.flip(); size+=curBuf.remaining(); } } ByteBuffer curBuf = bufferArray.getCurWritingBlock(); curBuf.flip(); if(curBuf.hasRemaining()) { size += curBuf.remaining(); } if(size>0) { int offset=0; byte[] all=new byte[size]; if (!bufferArray.getWritedBlockLst().isEmpty()) { for (ByteBuffer tBuf : blockes) { ByteBufferUtil.arrayCopy(tBuf,0,all,offset,tBuf.remaining()); offset+=tBuf.remaining(); NetSystem.getInstance().getBufferPool().recycle(tBuf); } } ByteBuffer tBuf = bufferArray.getCurWritingBlock(); if(tBuf.hasRemaining()) { ByteBufferUtil.arrayCopy(tBuf,0,all,offset,tBuf.remaining()); NetSystem.getInstance().getBufferPool().recycle(tBuf); // offset += curBuf.remaining(); } return all; } } finally { bufferArray.clear(); } return EMPTY; } private static byte[] EMPTY=new byte[0]; }