protected void flushFromExternalBuffer(byte[] buffer, int offset, int length) throws IOException { assert (recordCount > 0); assert (recordSizeBufferPos > 0); BlockType blockType = BlockType.INVALID; int blockBodySize = 0; if (recordCount == 1) { blockType = BlockType.SINGLE; blockBodySize = length; } else if (recordSize >= 0) { blockType = BlockType.FIXED; blockBodySize = Varint.size(recordSize) + length; if (recordSize == 0) { blockBodySize += Varint.size(recordCount); } } else { blockType = BlockType.VARIABLE; blockBodySize = Varint.size(recordSizeBufferPos) + recordSizeBufferPos + length; } checksum = Constants.CRC32_INIT_VALUE; writeBytes(Constants.BLOCK_HEADER_MAGIC, 0, Constants.BLOCK_HEADER_MAGIC.length, true); writeByte(blockType.getValue(), true); writeVarint(blockBodySize, true); short headerChecksum = CRC32.toCRC16(checksum); writeShort(headerChecksum, false); switch (blockType) { case FIXED: writeVarint(recordSize, true); if (recordSize == 0) { writeVarint(recordCount, true); } break; case VARIABLE: writeVarint(recordSizeBufferPos, true); writeBytes(recordSizeBuffer, 0, recordSizeBufferPos, true); break; case SINGLE: break; default: break; } writeBytes(buffer, offset, length, true); writeInt(checksum, false); output.flush(); recordSize = RECORD_SIZE_INIT; recordCount = 0; recordSizeBufferPos = 0; recordBufferPos = 0; }
public boolean write(byte[] buffer, int offset, int length) throws IOException { if (length > Constants.MAX_RECORD_SIZE) { return false; } if (recordSizeBuffer == null) { recordSizeBuffer = new byte[Constants.RECORD_SIZE_BUFFER_SIZE]; } if (recordBuffer == null) { recordBuffer = new byte[Constants.RECORD_BUFFER_SIZE]; } if (recordCount > 0) { if ((recordBufferPos + length) >= Constants.RECORD_BUFFER_SIZE || recordSizeBufferPos + Varint.size(length) >= Constants.RECORD_SIZE_BUFFER_SIZE) { flush(); } else { if ((recordSize >= 0) && (recordSize != length)) { if (recordSizeBufferPos > (2 * (Constants.MAX_BLOCK_HEADER_SIZE + Constants.BLOCK_FOOTER_SIZE))) { flush(); } } } } recordSizeBufferPos += Varint.encode(length, recordSizeBuffer, recordSizeBufferPos); ++recordCount; if ((recordBufferPos + length) >= Constants.RECORD_BUFFER_SIZE) { flushFromExternalBuffer(buffer, offset, length); } else { System.arraycopy(buffer, offset, recordBuffer, recordBufferPos, length); recordBufferPos += length; if (recordSize == RECORD_SIZE_INIT) { recordSize = length; } else if (recordSize != length) { recordSize = RECORD_SIZE_DIFFERENT; } } return true; }