@SuppressWarnings("NonAtomicOperationOnVolatileField")
    public int write(final long logIndex, final byte[] data, final WriteContext ctx) {
        int pos = -1;
        MappedByteBuffer buf = null;
        this.writeLock.lock();
        try {
            assert (this.wrotePos == this.buffer.position());
            buf = this.buffer;
            pos = this.wrotePos;
            this.wrotePos += RECORD_MAGIC_BYTES_SIZE + RECORD_DATA_LENGTH_SIZE + data.length;
            this.buffer.position(this.wrotePos);
            // Update log index.
            if (isBlank() || pos == HEADER_SIZE) {
                this.header.firstLogIndex = logIndex;
                // we don't need to call fsync header here, the new header will be flushed with this wrote.
                saveHeader(false);
            }
            this.lastLogIndex = logIndex;
            return pos;
        } finally {
            this.writeLock.unlock();
            final int wroteIndex = pos;
            final MappedByteBuffer buffer = buf;
            this.writeExecutor.execute(() -> {
                try {
                    put(buffer, wroteIndex, RECORD_MAGIC_BYTES);
                    putInt(buffer, wroteIndex + RECORD_MAGIC_BYTES_SIZE, data.length);
                    put(buffer, wroteIndex + RECORD_MAGIC_BYTES_SIZE + RECORD_DATA_LENGTH_SIZE, data);
                } catch (final Exception e) {
                    ctx.setError(e);
                } finally {
                    ctx.finishJob();
                }
            });
        }
    }
Write the data and return it's wrote position.

@param logIndex the log index
@param data     data to write
@return the wrote position
jraft-core/src/main/java/com/alipay/sofa/jraft/storage/log/SegmentFile.java