private void applyDefaultHeader( final UnsafeBuffer buffer, final int termOffset, final int frameLength, final long defaultVersionFlagsType, final long defaultSessionId) { long lengthVersionFlagsType; long termOffsetAndSessionId; if (ByteOrder.nativeOrder() == LITTLE_ENDIAN) { lengthVersionFlagsType = defaultVersionFlagsType | ((-frameLength) & 0xFFFF_FFFFL); termOffsetAndSessionId = defaultSessionId | termOffset; } else { lengthVersionFlagsType = (((reverseBytes(-frameLength)) & 0xFFFF_FFFFL) << 32) | defaultVersionFlagsType; termOffsetAndSessionId = (((reverseBytes(termOffset)) & 0xFFFF_FFFFL) << 32) | defaultSessionId; } buffer.putLongOrdered(termOffset + FRAME_LENGTH_FIELD_OFFSET, lengthVersionFlagsType); UnsafeAccess.UNSAFE.storeFence(); buffer.putLong(termOffset + TERM_OFFSET_FIELD_OFFSET, termOffsetAndSessionId); // read the stream(int) and term(int), this is the mutable part of the default header final long streamAndTermIds = defaultHeader.getLong(STREAM_ID_FIELD_OFFSET); buffer.putLong(termOffset + STREAM_ID_FIELD_OFFSET, streamAndTermIds); }
@Test public void shouldApplyPaddingWhenInsufficientSpaceAtEndOfBuffer() { long tail = CAPACITY - RECORD_ALIGNMENT; int recordOffset = (int) tail; final int length = RECORD_ALIGNMENT + 8; final int recordLength = length + HEADER_LENGTH; final int recordLengthAligned = align(recordLength, RECORD_ALIGNMENT); final int toEndOfBuffer = CAPACITY - recordOffset; when(buffer.getLong(TAIL_COUNTER_INDEX)).thenReturn(tail); final UnsafeBuffer srcBuffer = new UnsafeBuffer(new byte[1024]); final int srcIndex = 0; broadcastTransmitter.transmit(MSG_TYPE_ID, srcBuffer, srcIndex, length); final InOrder inOrder = inOrder(buffer); inOrder.verify(buffer).getLong(TAIL_COUNTER_INDEX); inOrder .verify(buffer) .putLong(TAIL_INTENT_COUNTER_OFFSET, tail + recordLengthAligned + toEndOfBuffer); inOrder.verify(buffer).putInt(lengthOffset(recordOffset), toEndOfBuffer); inOrder.verify(buffer).putInt(typeOffset(recordOffset), PADDING_MSG_TYPE_ID); tail += toEndOfBuffer; recordOffset = 0; inOrder.verify(buffer).putInt(lengthOffset(recordOffset), recordLength); inOrder.verify(buffer).putInt(typeOffset(recordOffset), MSG_TYPE_ID); inOrder.verify(buffer).putBytes(msgOffset(recordOffset), srcBuffer, srcIndex, length); inOrder.verify(buffer).putLong(LATEST_COUNTER_INDEX, tail); inOrder.verify(buffer).putLongOrdered(TAIL_COUNTER_INDEX, tail + recordLengthAligned); }
@Test public void shouldLateJoinTransmission() { final int length = 8; final int recordLength = length + HEADER_LENGTH; final int recordLengthAligned = align(recordLength, RECORD_ALIGNMENT); final long tail = (CAPACITY * 3L) + HEADER_LENGTH + recordLengthAligned; final long latestRecord = tail - recordLengthAligned; final int recordOffset = (int) latestRecord & (CAPACITY - 1); when(buffer.getLongVolatile(TAIL_INTENT_COUNTER_OFFSET)).thenReturn(tail); when(buffer.getLongVolatile(TAIL_COUNTER_INDEX)).thenReturn(tail); when(buffer.getLong(LATEST_COUNTER_INDEX)).thenReturn(latestRecord); when(buffer.getInt(lengthOffset(recordOffset))).thenReturn(recordLength); when(buffer.getInt(typeOffset(recordOffset))).thenReturn(MSG_TYPE_ID); assertTrue(broadcastReceiver.receiveNext()); assertThat(broadcastReceiver.typeId(), is(MSG_TYPE_ID)); assertThat(broadcastReceiver.buffer(), is(buffer)); assertThat(broadcastReceiver.offset(), is(msgOffset(recordOffset))); assertThat(broadcastReceiver.length(), is(length)); assertTrue(broadcastReceiver.validate()); assertThat(broadcastReceiver.lappedCount(), is(greaterThan(0L))); }
@Test public void shouldTransmitIntoUsedBuffer() { final long tail = RECORD_ALIGNMENT * 3; final int recordOffset = (int) tail; final int length = 8; final int recordLength = length + HEADER_LENGTH; final int recordLengthAligned = align(recordLength, RECORD_ALIGNMENT); when(buffer.getLong(TAIL_COUNTER_INDEX)).thenReturn(tail); final UnsafeBuffer srcBuffer = new UnsafeBuffer(new byte[1024]); final int srcIndex = 0; broadcastTransmitter.transmit(MSG_TYPE_ID, srcBuffer, srcIndex, length); final InOrder inOrder = inOrder(buffer); inOrder.verify(buffer).getLong(TAIL_COUNTER_INDEX); inOrder.verify(buffer).putLong(TAIL_INTENT_COUNTER_OFFSET, tail + recordLengthAligned); inOrder.verify(buffer).putInt(lengthOffset(recordOffset), recordLength); inOrder.verify(buffer).putInt(typeOffset(recordOffset), MSG_TYPE_ID); inOrder.verify(buffer).putBytes(msgOffset(recordOffset), srcBuffer, srcIndex, length); inOrder.verify(buffer).putLong(LATEST_COUNTER_INDEX, tail); inOrder.verify(buffer).putLongOrdered(TAIL_COUNTER_INDEX, tail + recordLengthAligned); }
@Test public void shouldCopeWithPaddingRecordAndWrapOfBufferForNextRecord() { final int length = 120; final int recordLength = length + HEADER_LENGTH; final int recordLengthAligned = align(recordLength, RECORD_ALIGNMENT); final long catchupTail = (CAPACITY * 2L) - HEADER_LENGTH; final long postPaddingTail = catchupTail + HEADER_LENGTH + recordLengthAligned; final long latestRecord = catchupTail - recordLengthAligned; final int catchupOffset = (int) latestRecord & (CAPACITY - 1); when(buffer.getLongVolatile(TAIL_INTENT_COUNTER_OFFSET)) .thenReturn(catchupTail) .thenReturn(postPaddingTail); when(buffer.getLongVolatile(TAIL_COUNTER_INDEX)) .thenReturn(catchupTail) .thenReturn(postPaddingTail); when(buffer.getLong(LATEST_COUNTER_INDEX)).thenReturn(latestRecord); when(buffer.getInt(lengthOffset(catchupOffset))).thenReturn(recordLength); when(buffer.getInt(typeOffset(catchupOffset))).thenReturn(MSG_TYPE_ID); final int paddingOffset = (int) catchupTail & (CAPACITY - 1); final int recordOffset = (int) (postPaddingTail - recordLengthAligned) & (CAPACITY - 1); when(buffer.getInt(typeOffset(paddingOffset))).thenReturn(PADDING_MSG_TYPE_ID); when(buffer.getInt(lengthOffset(recordOffset))).thenReturn(recordLength); when(buffer.getInt(typeOffset(recordOffset))).thenReturn(MSG_TYPE_ID); assertTrue(broadcastReceiver.receiveNext()); // To catch up to record before padding. assertTrue(broadcastReceiver.receiveNext()); // no skip over the padding and read next record. assertThat(broadcastReceiver.typeId(), is(MSG_TYPE_ID)); assertThat(broadcastReceiver.buffer(), is(buffer)); assertThat(broadcastReceiver.offset(), is(msgOffset(recordOffset))); assertThat(broadcastReceiver.length(), is(length)); assertTrue(broadcastReceiver.validate()); }