private void cleanBuffer(final long minConsumerPosition) { final long cleanPosition = this.cleanPosition; final UnsafeBuffer dirtyTerm = termBuffers[indexByPosition(cleanPosition, positionBitsToShift)]; final int bytesForCleaning = (int)(minConsumerPosition - cleanPosition); final int bufferCapacity = termBufferLength; final int termOffset = (int)cleanPosition & (bufferCapacity - 1); final int length = Math.min(bytesForCleaning, bufferCapacity - termOffset); if (length > 0) { dirtyTerm.setMemory(termOffset, length, (byte)0); this.cleanPosition = cleanPosition + length; } } }
private void cleanBuffer(final long publisherLimit) { final long cleanPosition = this.cleanPosition; final long dirtyRange = publisherLimit - cleanPosition; final int bufferCapacity = termBufferLength; final int reservedRange = bufferCapacity * 2; if (dirtyRange > reservedRange) { final UnsafeBuffer dirtyTerm = termBuffers[indexByPosition(cleanPosition, positionBitsToShift)]; final int termOffset = (int)cleanPosition & termLengthMask; final int bytesForCleaning = (int)(dirtyRange - reservedRange); final int length = Math.min(bytesForCleaning, bufferCapacity - termOffset); dirtyTerm.setMemory(termOffset, length, (byte)0); this.cleanPosition = cleanPosition + length; } }
private void cleanBufferTo(final long newCleanPosition) { final long cleanPosition = this.cleanPosition; final int bytesForCleaning = (int)(newCleanPosition - cleanPosition); final UnsafeBuffer dirtyTerm = termBuffers[indexByPosition(cleanPosition, positionBitsToShift)]; final int termOffset = (int)cleanPosition & termLengthMask; final int length = Math.min(bytesForCleaning, dirtyTerm.capacity() - termOffset); if (length > 0) { dirtyTerm.setMemory(termOffset, length, (byte)0); this.cleanPosition = cleanPosition + length; } }
@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 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 shouldAssembleTwoPartMessage() { when(header.flags()) .thenReturn(FrameDescriptor.BEGIN_FRAG_FLAG) .thenReturn(FrameDescriptor.END_FRAG_FLAG); final UnsafeBuffer srcBuffer = new UnsafeBuffer(new byte[1024]); final int offset = 0; final int length = srcBuffer.capacity() / 2; srcBuffer.setMemory(0, length, (byte)65); srcBuffer.setMemory(length, length, (byte)66); adapter.onFragment(srcBuffer, offset, length, header); adapter.onFragment(srcBuffer, length, length, header); final ArgumentCaptor<UnsafeBuffer> bufferArg = ArgumentCaptor.forClass(UnsafeBuffer.class); final ArgumentCaptor<Header> headerArg = ArgumentCaptor.forClass(Header.class); verify(delegateFragmentHandler, times(1)).onFragment( bufferArg.capture(), eq(offset), eq(length * 2), headerArg.capture()); final UnsafeBuffer capturedBuffer = bufferArg.getValue(); for (int i = 0; i < srcBuffer.capacity(); i++) { assertThat("same at i=" + i, capturedBuffer.getByte(i), is(srcBuffer.getByte(i))); } final Header capturedHeader = headerArg.getValue(); assertThat(capturedHeader.sessionId(), is(SESSION_ID)); assertThat(capturedHeader.flags(), is(FrameDescriptor.END_FRAG_FLAG)); }
private void publishDataToBeRecorded(final Publication publication) { startPosition = publication.position(); buffer.setMemory(0, 1024, (byte)'z'); for (int i = 0; i < MESSAGE_COUNT; i++) { final int messageLength = 64 + (rnd.nextInt((MAX_FRAGMENT_SIZE - 64) / 4) * 4); totalPayloadLength += messageLength; buffer.putInt(0, i, LITTLE_ENDIAN); buffer.putInt(messageLength - 4, i, LITTLE_ENDIAN); while (true) { final long result = publication.offer(buffer, 0, messageLength); if (result > 0) { break; } if (result == Publication.CLOSED || result == Publication.NOT_CONNECTED) { throw new IllegalStateException("publication unexpectedly not connected"); } Thread.yield(); } } expectedRecordingLength = publication.position() - startPosition; }
@Test public void shouldLimitReadOfMessages() { final int msgLength = 16; final int recordLength = HEADER_LENGTH + msgLength; final int alignedRecordLength = align(recordLength, ALIGNMENT); final long head = 0L; final int headIndex = (int)head; when(buffer.getLong(HEAD_COUNTER_INDEX)).thenReturn(head); when(buffer.getInt(typeOffset(headIndex))).thenReturn(MSG_TYPE_ID); when(buffer.getIntVolatile(lengthOffset(headIndex))).thenReturn(recordLength); final int[] times = new int[1]; final MessageHandler handler = (msgTypeId, buffer, index, length) -> times[0]++; final int limit = 1; final int messagesRead = ringBuffer.read(handler, limit); assertThat(messagesRead, is(1)); assertThat(times[0], is(1)); final InOrder inOrder = inOrder(buffer); inOrder.verify(buffer, times(1)).putLongOrdered(HEAD_COUNTER_INDEX, head + alignedRecordLength); inOrder.verify(buffer, times(0)).setMemory(anyInt(), anyInt(), anyByte()); }
@Test public void shouldLimitReadOfMessages() { final int msgLength = 16; final int recordLength = HEADER_LENGTH + msgLength; final int alignedRecordLength = align(recordLength, ALIGNMENT); final long head = 0L; final int headIndex = (int)head; when(buffer.getLong(HEAD_COUNTER_INDEX)).thenReturn(head); when(buffer.getInt(typeOffset(headIndex))).thenReturn(MSG_TYPE_ID); when(buffer.getIntVolatile(lengthOffset(headIndex))).thenReturn(recordLength); final int[] times = new int[1]; final MessageHandler handler = (msgTypeId, buffer, index, length) -> times[0]++; final int limit = 1; final int messagesRead = ringBuffer.read(handler, limit); assertThat(messagesRead, is(1)); assertThat(times[0], is(1)); final InOrder inOrder = inOrder(buffer); inOrder.verify(buffer, times(1)).setMemory(headIndex, alignedRecordLength, (byte)0); inOrder.verify(buffer, times(1)).putLongOrdered(HEAD_COUNTER_INDEX, head + alignedRecordLength); }
srcBuffer.setMemory(i * length, length, (byte)(65 + i));
final UnsafeBuffer bufferOne = new UnsafeBuffer(new byte[bufferOneLength]); final UnsafeBuffer bufferTwo = new UnsafeBuffer(new byte[bufferTwoTotalLength]); bufferOne.setMemory(0, bufferOne.capacity(), (byte)'1'); bufferTwo.setMemory(0, bufferTwo.capacity(), (byte)'2'); final int msgLength = bufferOneLength + bufferTwoLength; int tail = 0;
@Test public void shouldFreeSessionBuffer() { when(header.flags()) .thenReturn(FrameDescriptor.BEGIN_FRAG_FLAG) .thenReturn(FrameDescriptor.END_FRAG_FLAG); final UnsafeBuffer srcBuffer = new UnsafeBuffer(new byte[1024]); final int offset = 0; final int length = srcBuffer.capacity() / 2; srcBuffer.setMemory(0, length, (byte)65); srcBuffer.setMemory(length, length, (byte)66); assertFalse(adapter.freeSessionBuffer(SESSION_ID)); adapter.onFragment(srcBuffer, offset, length, header); adapter.onFragment(srcBuffer, length, length, header); assertTrue(adapter.freeSessionBuffer(SESSION_ID)); assertFalse(adapter.freeSessionBuffer(SESSION_ID)); }
private void publishDataToBeRecorded(final Publication publication, final int messageCount) { startPosition = publication.position(); buffer.setMemory(0, 1024, (byte)'z'); buffer.putStringAscii(32, "TEST"); for (int i = 0; i < messageCount; i++) { final int dataLength = messageLengths[i] - HEADER_LENGTH; buffer.putInt(0, i); while (true) { final long result = publication.offer(buffer, 0, dataLength); if (result > 0) { break; } if (result == Publication.CLOSED || result == Publication.NOT_CONNECTED) { throw new IllegalStateException("Publication not connected: result=" + result); } SystemTest.checkInterruptedStatus(); Thread.yield(); } } final long position = publication.position(); totalRecordingLength = position - startPosition; stopPosition = position; }
@Test public void shouldAppendUnfragmentedFromVectorsToEmptyLog() { final int headerLength = DEFAULT_HEADER.capacity(); final UnsafeBuffer bufferOne = new UnsafeBuffer(new byte[64]); final UnsafeBuffer bufferTwo = new UnsafeBuffer(new byte[256]); bufferOne.setMemory(0, bufferOne.capacity(), (byte)'1'); bufferTwo.setMemory(0, bufferTwo.capacity(), (byte)'2'); final int msgLength = bufferOne.capacity() + 200; 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)); final DirectBufferVector[] vectors = new DirectBufferVector[] { new DirectBufferVector(bufferOne, 0, bufferOne.capacity()), new DirectBufferVector(bufferTwo, 0, 200) }; assertThat(termAppender.appendUnfragmentedMessage(headerWriter, vectors, 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, bufferOne, 0, bufferOne.capacity()); inOrder.verify(termBuffer, times(1)).putBytes(headerLength + bufferOne.capacity(), bufferTwo, 0, 200); inOrder.verify(termBuffer, times(1)).putLong(tail + RESERVED_VALUE_OFFSET, RV, LITTLE_ENDIAN); inOrder.verify(termBuffer, times(1)).putIntOrdered(tail, frameLength); }
private void publishDataToBeRecorded(final ExclusivePublication publication) { buffer.setMemory(0, 1024, (byte)'z'); final int termLength = publication.termBufferLength(); final int positionBitsToShift = LogBufferDescriptor.positionBitsToShift(termLength); final int initialTermId = publication.initialTermId(); final long startPosition = publication.position(); final int startTermOffset = (int)startPosition & (termLength - 1); final int startTermId = computeTermIdFromPosition(startPosition, positionBitsToShift, initialTermId); for (int i = 0; i < MESSAGE_COUNT; i++) { final int dataLength = messageLengths[i] - DataHeaderFlyweight.HEADER_LENGTH; buffer.putInt(0, i); offer(publication, buffer, dataLength); } final long position = publication.position(); final int lastTermOffset = (int)position & (termLength - 1); final int lastTermId = computeTermIdFromPosition(position, positionBitsToShift, initialTermId); expectedRecordingLength = ((lastTermId - startTermId) * (long)termLength) + (lastTermOffset - startTermOffset); assertThat(position - startPosition, is(expectedRecordingLength)); }
srcBuffer.setMemory(i * PAYLOAD_LENGTH, PAYLOAD_LENGTH, (byte)(65 + i));
srcBuffer.setMemory(i * PAYLOAD_LENGTH, PAYLOAD_LENGTH, (byte)(65 + i));
private void recordFragment( final RecordingWriter recordingWriter, final UnsafeBuffer buffer, final DataHeaderFlyweight headerFlyweight, final Header header, final int message, final byte flags, final int type) { final int offset = INITIAL_TERM_OFFSET + message * FRAME_LENGTH; headerFlyweight.wrap(buffer, offset, HEADER_LENGTH); headerFlyweight .streamId(STREAM_ID) .sessionId(SESSION_ID) .termOffset(offset) .termId(INITIAL_TERM_ID) .reservedValue(message) .headerType(type) .flags(flags) .frameLength(FRAME_LENGTH); buffer.setMemory( offset + HEADER_LENGTH, FRAME_LENGTH - HEADER_LENGTH, (byte)message); header.offset(offset); recordingWriter.onBlock(buffer, offset, FRAME_LENGTH, SESSION_ID, INITIAL_TERM_ID); recordingPosition += FRAME_LENGTH; }
@Test(timeout = 10_000) public void shouldTransferUnfragmentedTwoPartMessage() { final UnsafeBuffer expectedBuffer = new UnsafeBuffer(new byte[256]); final UnsafeBuffer bufferOne = new UnsafeBuffer(expectedBuffer, 0, 32); final UnsafeBuffer bufferTwo = new UnsafeBuffer(expectedBuffer, 32, expectedBuffer.capacity() - 32); bufferOne.setMemory(0, bufferOne.capacity(), (byte)'a'); bufferTwo.setMemory(0, bufferTwo.capacity(), (byte)'b'); final String expectedMessage = expectedBuffer.getStringWithoutLengthAscii(0, expectedBuffer.capacity()); final MutableReference<String> receivedMessage = new MutableReference<>(); final FragmentHandler fragmentHandler = (buffer, offset, length, header) -> receivedMessage.set(buffer.getStringWithoutLengthAscii(offset, length)); try (Subscription subscription = aeron.addSubscription(CHANNEL, STREAM_ID)) { try (Publication publication = aeron.addPublication(CHANNEL, STREAM_ID)) { publishMessage(bufferOne, bufferTwo, publication); pollForMessage(subscription, receivedMessage, fragmentHandler); assertEquals(expectedMessage, receivedMessage.get()); } try (Publication publication = aeron.addExclusivePublication(CHANNEL, STREAM_ID)) { publishMessage(bufferOne, bufferTwo, publication); pollForMessage(subscription, receivedMessage, fragmentHandler); assertEquals(expectedMessage, receivedMessage.get()); } } }
@Test(timeout = 10_000) public void shouldTransferFragmentedTwoPartMessage() { final UnsafeBuffer expectedBuffer = new UnsafeBuffer(new byte[32 + driver.context().mtuLength()]); final UnsafeBuffer bufferOne = new UnsafeBuffer(expectedBuffer, 0, 32); final UnsafeBuffer bufferTwo = new UnsafeBuffer(expectedBuffer, 32, expectedBuffer.capacity() - 32); bufferOne.setMemory(0, bufferOne.capacity(), (byte)'a'); bufferTwo.setMemory(0, bufferTwo.capacity(), (byte)'b'); final String expectedMessage = expectedBuffer.getStringWithoutLengthAscii(0, expectedBuffer.capacity()); final MutableReference<String> receivedMessage = new MutableReference<>(); final FragmentHandler fragmentHandler = new FragmentAssembler((buffer, offset, length, header) -> receivedMessage.set(buffer.getStringWithoutLengthAscii(offset, length))); try (Subscription subscription = aeron.addSubscription(CHANNEL, STREAM_ID)) { try (Publication publication = aeron.addPublication(CHANNEL, STREAM_ID)) { publishMessage(bufferOne, bufferTwo, publication); pollForMessage(subscription, receivedMessage, fragmentHandler); assertEquals(expectedMessage, receivedMessage.get()); } try (Publication publication = aeron.addExclusivePublication(CHANNEL, STREAM_ID)) { publishMessage(bufferOne, bufferTwo, publication); pollForMessage(subscription, receivedMessage, fragmentHandler); assertEquals(expectedMessage, receivedMessage.get()); } } }