@Override
    public synchronized void addRecord(Slice record, boolean force)
            throws IOException
    {
        checkState(!closed.get(), "Log has been closed");

        SliceInput sliceInput = record.input();

        // used to track first, middle and last blocks
        boolean begin = true;

        // Fragment the record int chunks as necessary and write it.  Note that if record
        // is empty, we still want to iterate once to write a single
        // zero-length chunk.
        do {
            int bytesRemainingInBlock = BLOCK_SIZE - blockOffset;
            checkState(bytesRemainingInBlock >= 0);

            // Switch to a new block if necessary
            if (bytesRemainingInBlock < HEADER_SIZE) {
                if (bytesRemainingInBlock > 0) {
                    // Fill the rest of the block with zeros
                    // todo lame... need a better way to write zeros
                    fileChannel.write(ByteBuffer.allocate(bytesRemainingInBlock));
                }
                blockOffset = 0;
                bytesRemainingInBlock = BLOCK_SIZE - blockOffset;
            }

            // Invariant: we never leave less than HEADER_SIZE bytes available in a block
            int bytesAvailableInBlock = bytesRemainingInBlock - HEADER_SIZE;
            checkState(bytesAvailableInBlock >= 0);

            // if there are more bytes in the record then there are available in the block,
            // fragment the record; otherwise write to the end of the record
            boolean end;
            int fragmentLength;
            if (sliceInput.available() > bytesAvailableInBlock) {
                end = false;
                fragmentLength = bytesAvailableInBlock;
            }
            else {
                end = true;
                fragmentLength = sliceInput.available();
            }

            // determine block type
            LogChunkType type;
            if (begin && end) {
                type = LogChunkType.FULL;
            }
            else if (begin) {
                type = LogChunkType.FIRST;
            }
            else if (end) {
                type = LogChunkType.LAST;
            }
            else {
                type = LogChunkType.MIDDLE;
            }

            // write the chunk
            writeChunk(type, sliceInput.readSlice(fragmentLength));

            // we are no longer on the first chunk
            begin = false;
        } while (sliceInput.isReadable());

        if (force) {
            fileChannel.force(false);
        }
    }
@ Override public synchronized void addRecord ( Slice record , boolean force ) throws IOException { checkState ( ! closed . get ( ) , "Log has been closed" ) ; SliceInput sliceInput = record . input ( ) ; boolean begin = true ; do { int bytesRemainingInBlock = BLOCK_SIZE - blockOffset ; checkState ( bytesRemainingInBlock >= 0 ) ; if ( bytesRemainingInBlock < HEADER_SIZE ) { if ( bytesRemainingInBlock > 0 ) { fileChannel . write ( ByteBuffer . allocate ( bytesRemainingInBlock ) ) ; } blockOffset = 0 ; bytesRemainingInBlock = BLOCK_SIZE - blockOffset ; } int bytesAvailableInBlock = bytesRemainingInBlock - HEADER_SIZE ; checkState ( bytesAvailableInBlock >= 0 ) ; boolean end ; int fragmentLength ; if ( sliceInput . available ( ) > bytesAvailableInBlock ) { end = false ; fragmentLength = bytesAvailableInBlock ; } else { end = true ; fragmentLength = sliceInput . available ( ) ; } LogChunkType type ; if ( begin && end ) { type = LogChunkType . FULL ; } else if ( begin ) { type = LogChunkType . FIRST ; } else if ( end ) { type = LogChunkType . LAST ; } else { type = LogChunkType . MIDDLE ; } writeChunk ( type , sliceInput . readSlice ( fragmentLength ) ) ; begin = false ; } while ( sliceInput . isReadable ( ) ) ; if ( force ) { fileChannel . force ( false ) ; } }
Writes a stream of chunks such that no chunk is split across a block boundary