/** * {@inheritDoc} */ public boolean write(final int msgTypeId, final DirectBuffer srcBuffer, final int srcIndex, final int length) { checkTypeId(msgTypeId); checkMsgLength(length); boolean isSuccessful = false; final AtomicBuffer buffer = this.buffer; final int recordLength = length + HEADER_LENGTH; final int requiredCapacity = align(recordLength, ALIGNMENT); final int recordIndex = claimCapacity(buffer, requiredCapacity); if (INSUFFICIENT_CAPACITY != recordIndex) { buffer.putIntOrdered(lengthOffset(recordIndex), -recordLength); UnsafeAccess.UNSAFE.storeFence(); buffer.putInt(typeOffset(recordIndex), msgTypeId); buffer.putBytes(encodedMsgOffset(recordIndex), srcBuffer, srcIndex, length); buffer.putIntOrdered(lengthOffset(recordIndex), recordLength); isSuccessful = true; } return isSuccessful; }
if (length < 0) buffer.putInt(typeOffset(consumerIndex), PADDING_MSG_TYPE_ID); buffer.putIntOrdered(lengthOffset(consumerIndex), -length); unblocked = true; buffer.putInt(typeOffset(consumerIndex), PADDING_MSG_TYPE_ID); buffer.putIntOrdered(lengthOffset(consumerIndex), i - consumerIndex); unblocked = true;
@Test public void shouldInsertPaddingRecordPlusMessageOnBufferWrap() { final int length = 200; final int recordLength = length + HEADER_LENGTH; final int alignedRecordLength = align(recordLength, ALIGNMENT); final long tail = CAPACITY - HEADER_LENGTH; final long head = tail - (ALIGNMENT * 4); when(buffer.getLongVolatile(HEAD_COUNTER_INDEX)).thenReturn(head); when(buffer.getLongVolatile(TAIL_COUNTER_INDEX)).thenReturn(tail); when(buffer.compareAndSetLong(TAIL_COUNTER_INDEX, tail, tail + alignedRecordLength + ALIGNMENT)) .thenReturn(TRUE); final UnsafeBuffer srcBuffer = new UnsafeBuffer(new byte[1024]); final int srcIndex = 0; assertTrue(ringBuffer.write(MSG_TYPE_ID, srcBuffer, srcIndex, length)); final InOrder inOrder = inOrder(buffer); inOrder.verify(buffer).putIntOrdered(lengthOffset((int)tail), -HEADER_LENGTH); inOrder.verify(buffer).putInt(typeOffset((int)tail), PADDING_MSG_TYPE_ID); inOrder.verify(buffer).putIntOrdered(lengthOffset((int)tail), HEADER_LENGTH); inOrder.verify(buffer).putIntOrdered(lengthOffset(0), -recordLength); inOrder.verify(buffer).putInt(typeOffset(0), MSG_TYPE_ID); inOrder.verify(buffer).putBytes(encodedMsgOffset(0), srcBuffer, srcIndex, length); inOrder.verify(buffer).putIntOrdered(lengthOffset(0), recordLength); }
/** * {@inheritDoc} */ public boolean write(final int msgTypeId, final DirectBuffer srcBuffer, final int srcIndex, final int length) { checkTypeId(msgTypeId); checkMsgLength(length); boolean isSuccessful = false; final AtomicBuffer buffer = this.buffer; final int recordLength = length + HEADER_LENGTH; final int requiredCapacity = align(recordLength, ALIGNMENT); final int recordIndex = claimCapacity(buffer, requiredCapacity); if (INSUFFICIENT_CAPACITY != recordIndex) { buffer.putLongOrdered(recordIndex, makeHeader(-recordLength, msgTypeId)); UnsafeAccess.UNSAFE.storeFence(); buffer.putBytes(encodedMsgOffset(recordIndex), srcBuffer, srcIndex, length); buffer.putIntOrdered(lengthOffset(recordIndex), recordLength); isSuccessful = true; } return isSuccessful; }
checkTypeId(msgTypeId); checkMsgLength(length); buffer.putLongOrdered(recordIndex, makeHeader(padding, PADDING_MSG_TYPE_ID)); recordIndex = 0; buffer.putBytes(encodedMsgOffset(recordIndex), srcBuffer, srcIndex, length); buffer.putLong(recordIndex + alignedRecordLength, 0L); buffer.putLongOrdered(recordIndex, makeHeader(recordLength, msgTypeId)); buffer.putLongOrdered(tailPositionIndex, tail + alignedRecordLength + padding);
@Test public void shouldNotReadSingleMessagePartWayThroughWriting() { final long head = 0L; final int headIndex = (int)head; when(buffer.getLong(HEAD_COUNTER_INDEX)).thenReturn(head); when(buffer.getIntVolatile(lengthOffset(headIndex))).thenReturn(0); final int[] times = new int[1]; final MessageHandler handler = (msgTypeId, buffer, index, length) -> times[0]++; final int messagesRead = ringBuffer.read(handler); assertThat(messagesRead, is(0)); assertThat(times[0], is(0)); final InOrder inOrder = inOrder(buffer); inOrder.verify(buffer, times(1)).getIntVolatile(lengthOffset(headIndex)); inOrder.verify(buffer, times(0)).setMemory(headIndex, 0, (byte)0); inOrder.verify(buffer, times(0)).putLongOrdered(HEAD_COUNTER_INDEX, headIndex); }
@Test public void shouldNotUnblockGapWithMessageRaceOnSecondMessageIncreasingTailThenInterrupting() { 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(0).thenReturn(messageLength); assertFalse(ringBuffer.unblock()); verify(buffer, never()).putInt(typeOffset(messageLength), PADDING_MSG_TYPE_ID); }
final long header = buffer.getLongVolatile(recordIndex); final int recordLength = recordLength(header); if (recordLength <= 0) final int messageTypeId = messageTypeId(header); if (PADDING_MSG_TYPE_ID == messageTypeId)
if (length < 0) buffer.putLongOrdered(consumerIndex, makeHeader(-length, PADDING_MSG_TYPE_ID)); unblocked = true; buffer.putLongOrdered(consumerIndex, makeHeader(i - consumerIndex, PADDING_MSG_TYPE_ID)); unblocked = true;
@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 shouldInsertPaddingRecordPlusMessageOnBufferWrapWithHeadEqualToTail() { final int length = 200; final int recordLength = length + HEADER_LENGTH; final int alignedRecordLength = align(recordLength, ALIGNMENT); final long tail = CAPACITY - HEADER_LENGTH; final long head = tail; when(buffer.getLongVolatile(HEAD_COUNTER_INDEX)).thenReturn(head); when(buffer.getLongVolatile(TAIL_COUNTER_INDEX)).thenReturn(tail); when(buffer.compareAndSetLong(TAIL_COUNTER_INDEX, tail, tail + alignedRecordLength + ALIGNMENT)) .thenReturn(TRUE); final UnsafeBuffer srcBuffer = new UnsafeBuffer(new byte[1024]); final int srcIndex = 0; assertTrue(ringBuffer.write(MSG_TYPE_ID, srcBuffer, srcIndex, length)); final InOrder inOrder = inOrder(buffer); inOrder.verify(buffer).putIntOrdered(lengthOffset((int)tail), -HEADER_LENGTH); inOrder.verify(buffer).putInt(typeOffset((int)tail), PADDING_MSG_TYPE_ID); inOrder.verify(buffer).putIntOrdered(lengthOffset((int)tail), HEADER_LENGTH); inOrder.verify(buffer).putIntOrdered(lengthOffset(0), -recordLength); inOrder.verify(buffer).putInt(typeOffset(0), MSG_TYPE_ID); inOrder.verify(buffer).putBytes(encodedMsgOffset(0), srcBuffer, srcIndex, length); inOrder.verify(buffer).putIntOrdered(lengthOffset(0), recordLength); }
@Test public void shouldNotReadSingleMessagePartWayThroughWriting() { final long head = 0L; final int headIndex = (int)head; when(buffer.getLong(HEAD_COUNTER_INDEX)).thenReturn(head); when(buffer.getIntVolatile(lengthOffset(headIndex))).thenReturn(0); final int[] times = new int[1]; final MessageHandler handler = (msgTypeId, buffer, index, length) -> times[0]++; final int messagesRead = ringBuffer.read(handler); assertThat(messagesRead, is(0)); assertThat(times[0], is(0)); final InOrder inOrder = inOrder(buffer); inOrder.verify(buffer, times(1)).getIntVolatile(lengthOffset(headIndex)); inOrder.verify(buffer, times(0)).setMemory(anyInt(), anyInt(), anyByte()); inOrder.verify(buffer, times(0)).putLongOrdered(HEAD_COUNTER_INDEX, headIndex); }
@Test public void shouldNotUnblockGapWithMessageRaceWhenScanForwardTakesAnInterrupt() { 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(0).thenReturn(messageLength); when(buffer.getIntVolatile(messageLength * 2 + ALIGNMENT)).thenReturn(7); assertFalse(ringBuffer.unblock()); verify(buffer, never()).putInt(typeOffset(messageLength), PADDING_MSG_TYPE_ID); }
final long header = buffer.getLongVolatile(recordIndex); final int recordLength = recordLength(header); if (recordLength <= 0) final int messageTypeId = messageTypeId(header); if (PADDING_MSG_TYPE_ID == messageTypeId)
buffer.putLongOrdered(tailIndex, makeHeader(padding, PADDING_MSG_TYPE_ID)); tailIndex = 0;
@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); }
checkTypeId(msgTypeId); checkMsgLength(length); buffer.putInt(typeOffset(recordIndex), PADDING_MSG_TYPE_ID); buffer.putIntOrdered(lengthOffset(recordIndex), padding); recordIndex = 0; buffer.putBytes(encodedMsgOffset(recordIndex), srcBuffer, srcIndex, length); buffer.putLong(recordIndex + alignedRecordLength, 0L); buffer.putInt(typeOffset(recordIndex), msgTypeId); buffer.putIntOrdered(lengthOffset(recordIndex), recordLength); buffer.putLongOrdered(tailPositionIndex, tail + alignedRecordLength + padding);
@Test public void shouldWriteToEmptyBuffer() { final int length = 8; final int recordLength = length + HEADER_LENGTH; final int alignedRecordLength = align(recordLength, ALIGNMENT); final long tail = 0L; final long head = 0L; when(buffer.getLongVolatile(HEAD_COUNTER_INDEX)).thenReturn(head); when(buffer.getLongVolatile(TAIL_COUNTER_INDEX)).thenReturn(tail); when(buffer.compareAndSetLong(TAIL_COUNTER_INDEX, tail, tail + alignedRecordLength)) .thenReturn(TRUE); final UnsafeBuffer srcBuffer = new UnsafeBuffer(new byte[1024]); final int srcIndex = 0; assertTrue(ringBuffer.write(MSG_TYPE_ID, srcBuffer, srcIndex, length)); final InOrder inOrder = inOrder(buffer); inOrder.verify(buffer).putIntOrdered(lengthOffset((int)tail), -recordLength); inOrder.verify(buffer).putInt(typeOffset((int)tail), MSG_TYPE_ID); inOrder.verify(buffer).putBytes(encodedMsgOffset((int)tail), srcBuffer, srcIndex, length); inOrder.verify(buffer).putIntOrdered(lengthOffset((int)tail), recordLength); }
@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); }
/** * {@inheritDoc} */ public boolean write(final int msgTypeId, final DirectBuffer srcBuffer, final int srcIndex, final int length) { checkTypeId(msgTypeId); checkMsgLength(length); boolean isSuccessful = false; final AtomicBuffer buffer = this.buffer; final int recordLength = length + HEADER_LENGTH; final int requiredCapacity = align(recordLength, ALIGNMENT); final int recordIndex = claimCapacity(buffer, requiredCapacity); if (INSUFFICIENT_CAPACITY != recordIndex) { buffer.putIntOrdered(lengthOffset(recordIndex), -recordLength); UnsafeAccess.UNSAFE.storeFence(); buffer.putInt(typeOffset(recordIndex), msgTypeId); buffer.putBytes(encodedMsgOffset(recordIndex), srcBuffer, srcIndex, length); buffer.putIntOrdered(lengthOffset(recordIndex), recordLength); isSuccessful = true; } return isSuccessful; }