/** * Set the value of the current active term count for the producer using memory ordered semantics. * * @param metadataBuffer containing the meta data. * @param termCount value of the active term count used by the producer of this log. */ public static void activeTermCountOrdered(final UnsafeBuffer metadataBuffer, final int termCount) { metadataBuffer.putIntOrdered(LOG_ACTIVE_TERM_COUNT_OFFSET, termCount); }
/** * Set whether the log is considered connected or not by the driver. * * @param metadataBuffer containing the meta data. * @param isConnected or not */ public static void isConnected(final UnsafeBuffer metadataBuffer, final boolean isConnected) { metadataBuffer.putIntOrdered(LOG_IS_CONNECTED_OFFSET, isConnected ? 1 : 0); }
public void signalReady(final int version) { buffer.putIntOrdered(versionFieldOffset, version); }
/** * Write the length header for a frame in a memory ordered fashion. * * @param buffer containing the frame. * @param termOffset at which a frame begins. * @param frameLength field to be set for the frame. */ public static void frameLengthOrdered(final UnsafeBuffer buffer, final int termOffset, final int frameLength) { int length = frameLength; if (ByteOrder.nativeOrder() != LITTLE_ENDIAN) { length = Integer.reverseBytes(frameLength); } buffer.putIntOrdered(termOffset, length); }
/** * Commit the message to the log buffer so that is it available to subscribers. */ public final void commit() { int frameLength = buffer.capacity(); if (ByteOrder.nativeOrder() != LITTLE_ENDIAN) { frameLength = Integer.reverseBytes(frameLength); } buffer.putIntOrdered(FRAME_LENGTH_FIELD_OFFSET, frameLength); }
/** * Abort a claim of the message space to the log buffer so that the log can progress by ignoring this claim. */ public final void abort() { int frameLength = buffer.capacity(); if (ByteOrder.nativeOrder() != LITTLE_ENDIAN) { frameLength = Integer.reverseBytes(frameLength); } buffer.putShort(TYPE_FIELD_OFFSET, (short)HDR_TYPE_PAD, LITTLE_ENDIAN); buffer.putIntOrdered(FRAME_LENGTH_FIELD_OFFSET, frameLength); } }
@Test public void shouldPatchToEndOfPartition() { final int messageLength = HEADER_LENGTH * 4; final int termOffset = TERM_BUFFER_CAPACITY - messageLength; final int tailOffset = TERM_BUFFER_CAPACITY; when(mockTermBuffer.getIntVolatile(termOffset)).thenReturn(0); assertThat(TermUnblocker.unblock( mockLogMetaDataBuffer, mockTermBuffer, termOffset, tailOffset, TERM_ID), is(UNBLOCKED_TO_END)); final InOrder inOrder = inOrder(mockTermBuffer); inOrder.verify(mockTermBuffer).putShort(typeOffset(termOffset), (short)HDR_TYPE_PAD, LITTLE_ENDIAN); inOrder.verify(mockTermBuffer).putInt(termOffsetOffset(termOffset), termOffset, LITTLE_ENDIAN); inOrder.verify(mockTermBuffer).putIntOrdered(termOffset, messageLength); }
@Test public void shouldScanForwardForNextCompleteMessage() { final int messageLength = HEADER_LENGTH * 4; final int termOffset = 0; final int tailOffset = messageLength * 2; when(mockTermBuffer.getIntVolatile(messageLength)).thenReturn(messageLength); assertThat(TermUnblocker.unblock( mockLogMetaDataBuffer, mockTermBuffer, termOffset, tailOffset, TERM_ID), is(UNBLOCKED)); final InOrder inOrder = inOrder(mockTermBuffer); inOrder.verify(mockTermBuffer).putShort(typeOffset(termOffset), (short)HDR_TYPE_PAD, LITTLE_ENDIAN); inOrder.verify(mockTermBuffer).putInt(termOffsetOffset(termOffset), termOffset, LITTLE_ENDIAN); inOrder.verify(mockTermBuffer).putIntOrdered(termOffset, messageLength); }
@Test public void shouldScanForwardForNextNonCommittedMessage() { final int messageLength = HEADER_LENGTH * 4; final int termOffset = 0; final int tailOffset = messageLength * 2; when(mockTermBuffer.getIntVolatile(messageLength)).thenReturn(-messageLength); assertThat(TermUnblocker.unblock( mockLogMetaDataBuffer, mockTermBuffer, termOffset, tailOffset, TERM_ID), is(UNBLOCKED)); final InOrder inOrder = inOrder(mockTermBuffer); inOrder.verify(mockTermBuffer).putShort(typeOffset(termOffset), (short)HDR_TYPE_PAD, LITTLE_ENDIAN); inOrder.verify(mockTermBuffer).putInt(termOffsetOffset(termOffset), termOffset, LITTLE_ENDIAN); inOrder.verify(mockTermBuffer).putIntOrdered(termOffset, messageLength); }
@Test public void shouldPatchNonCommittedMessage() { final int termOffset = 0; final int messageLength = HEADER_LENGTH * 4; final int tailOffset = messageLength; when(mockTermBuffer.getIntVolatile(termOffset)).thenReturn(-messageLength); assertThat(TermUnblocker.unblock( mockLogMetaDataBuffer, mockTermBuffer, termOffset, tailOffset, TERM_ID), is(UNBLOCKED)); final InOrder inOrder = inOrder(mockTermBuffer); inOrder.verify(mockTermBuffer).putShort(typeOffset(termOffset), (short)HDR_TYPE_PAD, LITTLE_ENDIAN); inOrder.verify(mockTermBuffer).putInt(termOffsetOffset(termOffset), termOffset, LITTLE_ENDIAN); inOrder.verify(mockTermBuffer).putIntOrdered(termOffset, messageLength); }
@Test public void shouldRejectWriteWhenBufferFull() { final int length = 8; final long head = 0L; final long tail = head + CAPACITY; when(buffer.getLongVolatile(HEAD_COUNTER_INDEX)).thenReturn(head); when(buffer.getLongVolatile(TAIL_COUNTER_INDEX)).thenReturn(tail); final UnsafeBuffer srcBuffer = new UnsafeBuffer(new byte[1024]); final int srcIndex = 0; assertFalse(ringBuffer.write(MSG_TYPE_ID, srcBuffer, srcIndex, length)); verify(buffer, never()).putInt(anyInt(), anyInt()); verify(buffer, never()).compareAndSetLong(anyInt(), anyLong(), anyLong()); verify(buffer, never()).putIntOrdered(anyInt(), anyInt()); }
@Test public void shouldRejectWriteWhenInsufficientSpace() { final int length = 200; final long head = 0L; final long tail = head + (CAPACITY - align(length - ALIGNMENT, ALIGNMENT)); when(buffer.getLongVolatile(HEAD_COUNTER_INDEX)).thenReturn(head); when(buffer.getLongVolatile(TAIL_COUNTER_INDEX)).thenReturn(tail); final UnsafeBuffer srcBuffer = new UnsafeBuffer(new byte[1024]); final int srcIndex = 0; assertFalse(ringBuffer.write(MSG_TYPE_ID, srcBuffer, srcIndex, length)); verify(buffer, never()).putInt(anyInt(), anyInt()); verify(buffer, never()).compareAndSetLong(anyInt(), anyLong(), anyLong()); verify(buffer, never()).putBytes(anyInt(), eq(srcBuffer), anyInt(), anyInt()); verify(buffer, never()).putIntOrdered(anyInt(), anyInt()); }
@Test public void shouldUnblockMessageWithHeader() { final int messageLength = ALIGNMENT * 4; when(buffer.getLongVolatile(HEAD_COUNTER_INDEX)).thenReturn((long)messageLength); when(buffer.getLongVolatile(TAIL_COUNTER_INDEX)).thenReturn((long)messageLength * 2); when(buffer.getIntVolatile(messageLength)).thenReturn(-messageLength); assertTrue(ringBuffer.unblock()); final InOrder inOrder = inOrder(buffer); inOrder.verify(buffer).putInt(typeOffset(messageLength), PADDING_MSG_TYPE_ID); inOrder.verify(buffer).putIntOrdered(lengthOffset(messageLength), messageLength); }
@Test public void shouldUnblockWhenFullWithoutHeader() { final int messageLength = ALIGNMENT * 4; when(buffer.getLongVolatile(HEAD_COUNTER_INDEX)).thenReturn((long)messageLength); when(buffer.getLongVolatile(TAIL_COUNTER_INDEX)).thenReturn((long)messageLength + CAPACITY); when(buffer.getIntVolatile(messageLength * 2)).thenReturn(messageLength); assertTrue(ringBuffer.unblock()); final InOrder inOrder = inOrder(buffer); inOrder.verify(buffer).putInt(typeOffset(messageLength), PADDING_MSG_TYPE_ID); inOrder.verify(buffer).putIntOrdered(lengthOffset(messageLength), messageLength); }
@Test public void shouldUnblockWhenFullWithHeader() { final int messageLength = ALIGNMENT * 4; when(buffer.getLongVolatile(HEAD_COUNTER_INDEX)).thenReturn((long)messageLength); when(buffer.getLongVolatile(TAIL_COUNTER_INDEX)).thenReturn((long)messageLength + CAPACITY); when(buffer.getIntVolatile(messageLength)).thenReturn(-messageLength); assertTrue(ringBuffer.unblock()); final InOrder inOrder = inOrder(buffer); inOrder.verify(buffer).putInt(typeOffset(messageLength), PADDING_MSG_TYPE_ID); inOrder.verify(buffer).putIntOrdered(lengthOffset(messageLength), messageLength); }
@Test public void shouldUnblockGapWithZeros() { final int messageLength = ALIGNMENT * 4; when(buffer.getLongVolatile(HEAD_COUNTER_INDEX)).thenReturn((long)messageLength); when(buffer.getLongVolatile(TAIL_COUNTER_INDEX)).thenReturn((long)messageLength * 3); when(buffer.getIntVolatile(messageLength * 2)).thenReturn(messageLength); assertTrue(ringBuffer.unblock()); final InOrder inOrder = inOrder(buffer); inOrder.verify(buffer).putInt(typeOffset(messageLength), PADDING_MSG_TYPE_ID); inOrder.verify(buffer).putIntOrdered(lengthOffset(messageLength), messageLength); }
@Test public void shouldAppendFrameTwiceToLog() { final int headerLength = DEFAULT_HEADER.capacity(); final UnsafeBuffer buffer = new UnsafeBuffer(new byte[128]); final int msgLength = 20; final int frameLength = msgLength + headerLength; final int alignedFrameLength = align(frameLength, FRAME_ALIGNMENT); int tail = 0; logMetaDataBuffer.putLong(TERM_TAIL_COUNTER_OFFSET, packTail(TERM_ID, tail)); assertThat(termAppender.appendUnfragmentedMessage( headerWriter, buffer, 0, msgLength, RVS, TERM_ID), is(alignedFrameLength)); assertThat(termAppender.appendUnfragmentedMessage( headerWriter, buffer, 0, msgLength, RVS, TERM_ID), is(alignedFrameLength * 2)); assertThat(rawTailVolatile(logMetaDataBuffer, PARTITION_INDEX), is(packTail(TERM_ID, tail + (alignedFrameLength * 2)))); final InOrder inOrder = inOrder(termBuffer, headerWriter); inOrder.verify(headerWriter, times(1)).write(termBuffer, tail, frameLength, TERM_ID); inOrder.verify(termBuffer, times(1)).putBytes(headerLength, buffer, 0, msgLength); inOrder.verify(termBuffer, times(1)).putLong(tail + RESERVED_VALUE_OFFSET, RV, LITTLE_ENDIAN); inOrder.verify(termBuffer, times(1)).putIntOrdered(tail, frameLength); tail = alignedFrameLength; inOrder.verify(headerWriter, times(1)).write(termBuffer, tail, frameLength, TERM_ID); inOrder.verify(termBuffer, times(1)) .putBytes(tail + headerLength, buffer, 0, msgLength); inOrder.verify(termBuffer, times(1)).putLong(tail + RESERVED_VALUE_OFFSET, RV, LITTLE_ENDIAN); inOrder.verify(termBuffer, times(1)).putIntOrdered(tail, frameLength); }
@Test public void shouldFragmentMessageOverTwoFrames() { final int msgLength = MAX_PAYLOAD_LENGTH + 1; final int headerLength = DEFAULT_HEADER.capacity(); final int frameLength = headerLength + 1; final int requiredCapacity = align(headerLength + 1, FRAME_ALIGNMENT) + MAX_FRAME_LENGTH; final UnsafeBuffer buffer = new UnsafeBuffer(new byte[msgLength]); int tail = 0; logMetaDataBuffer.putLong(TERM_TAIL_COUNTER_OFFSET, packTail(TERM_ID, tail)); assertThat(termAppender.appendFragmentedMessage( headerWriter, buffer, 0, msgLength, MAX_PAYLOAD_LENGTH, RVS, TERM_ID), is(requiredCapacity)); assertThat(rawTailVolatile(logMetaDataBuffer, PARTITION_INDEX), is(packTail(TERM_ID, tail + requiredCapacity))); final InOrder inOrder = inOrder(termBuffer, headerWriter); inOrder.verify(headerWriter, times(1)).write(termBuffer, tail, MAX_FRAME_LENGTH, TERM_ID); inOrder.verify(termBuffer, times(1)).putBytes(tail + headerLength, buffer, 0, MAX_PAYLOAD_LENGTH); inOrder.verify(termBuffer, times(1)).putByte(flagsOffset(tail), BEGIN_FRAG_FLAG); inOrder.verify(termBuffer, times(1)).putLong(tail + RESERVED_VALUE_OFFSET, RV, LITTLE_ENDIAN); inOrder.verify(termBuffer, times(1)).putIntOrdered(tail, MAX_FRAME_LENGTH); tail = MAX_FRAME_LENGTH; inOrder.verify(headerWriter, times(1)).write(termBuffer, tail, frameLength, TERM_ID); inOrder.verify(termBuffer, times(1)).putBytes(tail + headerLength, buffer, MAX_PAYLOAD_LENGTH, 1); inOrder.verify(termBuffer, times(1)).putByte(flagsOffset(tail), END_FRAG_FLAG); inOrder.verify(termBuffer, times(1)).putLong(tail + RESERVED_VALUE_OFFSET, RV, LITTLE_ENDIAN); inOrder.verify(termBuffer, times(1)).putIntOrdered(tail, frameLength); }
@Test public void shouldAppendFrameToEmptyLog() { final int headerLength = DEFAULT_HEADER.capacity(); final UnsafeBuffer buffer = new UnsafeBuffer(new byte[128]); final int msgLength = 20; final int frameLength = msgLength + headerLength; final int alignedFrameLength = align(frameLength, FRAME_ALIGNMENT); final int tail = 0; logMetaDataBuffer.putLong(TERM_TAIL_COUNTER_OFFSET, packTail(TERM_ID, tail)); assertThat(termAppender.appendUnfragmentedMessage(headerWriter, buffer, 0, msgLength, RVS, TERM_ID), is(alignedFrameLength)); assertThat(rawTailVolatile(logMetaDataBuffer, PARTITION_INDEX), is(packTail(TERM_ID, tail + alignedFrameLength))); final InOrder inOrder = inOrder(termBuffer, headerWriter); inOrder.verify(headerWriter, times(1)).write(termBuffer, tail, frameLength, TERM_ID); inOrder.verify(termBuffer, times(1)).putBytes(headerLength, buffer, 0, msgLength); inOrder.verify(termBuffer, times(1)).putLong(tail + RESERVED_VALUE_OFFSET, RV, LITTLE_ENDIAN); inOrder.verify(termBuffer, times(1)).putIntOrdered(tail, frameLength); }
@Test public void shouldPadLogWhenAppendingWithInsufficientRemainingCapacity() { final int msgLength = 120; final int headerLength = DEFAULT_HEADER.capacity(); final int requiredFrameSize = align(headerLength + msgLength, FRAME_ALIGNMENT); final int tailValue = TERM_BUFFER_LENGTH - align(msgLength, FRAME_ALIGNMENT); final UnsafeBuffer buffer = new UnsafeBuffer(new byte[128]); final int frameLength = TERM_BUFFER_LENGTH - tailValue; logMetaDataBuffer.putLong(TERM_TAIL_COUNTER_OFFSET, packTail(TERM_ID, tailValue)); assertThat(termAppender.appendUnfragmentedMessage(headerWriter, buffer, 0, msgLength, RVS, TERM_ID), is(FAILED)); assertThat(rawTailVolatile(logMetaDataBuffer, PARTITION_INDEX), is(packTail(TERM_ID, tailValue + requiredFrameSize))); final InOrder inOrder = inOrder(termBuffer, headerWriter); inOrder.verify(headerWriter, times(1)).write(termBuffer, tailValue, frameLength, TERM_ID); inOrder.verify(termBuffer, times(1)).putShort(typeOffset(tailValue), (short)PADDING_FRAME_TYPE, LITTLE_ENDIAN); inOrder.verify(termBuffer, times(1)).putIntOrdered(tailValue, frameLength); }