public void logReplicationEnded(
        final int memberId,
        final String purpose,
        final String channel,
        final long srcRecordingId,
        final long dstRecordingId,
        final long position,
        final boolean hasSynced)
    {
        final int length = ClusterEventEncoder.replicationEndedLength(purpose, channel);
        final int captureLength = captureLength(length);
        final int encodedLength = encodedLength(captureLength);
        final ManyToOneRingBuffer ringBuffer = this.ringBuffer;
        final int index = ringBuffer.tryClaim(REPLICATION_ENDED.toEventCodeId(), encodedLength);

        if (index > 0)
        {
            try
            {
                ClusterEventEncoder.encodeReplicationEnded(
                    (UnsafeBuffer)ringBuffer.buffer(),
                    index,
                    captureLength,
                    length,
                    memberId,
                    purpose,
                    channel,
                    srcRecordingId,
                    dstRecordingId,
                    position,
                    hasSynced);
            }
            finally
            {
                ringBuffer.commit(index);
            }
        }
    }
@Test
    void logReplicationEnded()
    {
        final int memberId = 222;
        final String purpose = "STANDBY_SNAPSHOT";
        final String channel = "aeron:udp?endpoint=localhost:9090";
        final long srcRecordingId = 234;
        final long dstRecordingId = 8435;
        final long position = 982342;
        final boolean hasSynced = true;
        final int offset = 64;

        logBuffer.putLong(CAPACITY + TAIL_POSITION_OFFSET, offset);
        logger.logReplicationEnded(
            memberId, purpose, channel, srcRecordingId, dstRecordingId, position, hasSynced);

        verifyLogHeader(
            logBuffer,
            offset,
            REPLICATION_ENDED.toEventCodeId(),
            replicationEndedLength(purpose, channel),
            replicationEndedLength(purpose, channel));

        final int index = encodedMsgOffset(offset) + LOG_HEADER_LENGTH;
        assertEquals(srcRecordingId, logBuffer.getLong(index, LITTLE_ENDIAN));
        assertEquals(dstRecordingId, logBuffer.getLong(index + SIZE_OF_LONG, LITTLE_ENDIAN));
        assertEquals(position, logBuffer.getLong(index + (2 * SIZE_OF_LONG), LITTLE_ENDIAN));
        assertEquals(memberId, logBuffer.getInt(index + (3 * SIZE_OF_LONG), LITTLE_ENDIAN));
        assertEquals(1, logBuffer.getByte(index + (3 * SIZE_OF_LONG) + (SIZE_OF_INT)));
        final int purposeIndex = index + (3 * SIZE_OF_LONG) + (SIZE_OF_INT) + (SIZE_OF_BYTE);
        assertEquals(purpose, logBuffer.getStringAscii(purposeIndex));
        final int channelIndex = purposeIndex + SIZE_OF_INT + purpose.length();
        assertEquals(channel, logBuffer.getStringAscii(channelIndex, LITTLE_ENDIAN));

        final StringBuilder sb = new StringBuilder();
        ClusterEventDissector.dissectReplicationEnded(
            REPLICATION_ENDED, logBuffer, encodedMsgOffset(offset), sb);

        final String expectedMessagePattern =
            "\\[[0-9]+\\.[0-9]+] CLUSTER: REPLICATION_ENDED \\[86/86]: memberId=222 " +
            "purpose=STANDBY_SNAPSHOT channel=aeron:udp\\?endpoint=localhost:9090 srcRecordingId=234 " +
            "dstRecordingId=8435 position=982342 hasSynced=true";

        assertThat(sb.toString(), Matchers.matchesPattern(expectedMessagePattern));
    }