public int appendUnfragmentedMessage( final long defaultVersionFlagsType, final long defaultSessionId, final DirectBuffer srcBuffer, final int srcOffset, final int length) { final int frameLength = length + HEADER_LENGTH; final int alignedLength = align(frameLength, FRAME_ALIGNMENT); final int termOffset = metaDataBuffer.getAndAddInt(TERM_TAIL_COUNTER_OFFSET, alignedLength); final UnsafeBuffer termBuffer = this.termBuffer; final int capacity = termBuffer.capacity(); int resultingOffset = termOffset + alignedLength; if (resultingOffset > (capacity - HEADER_LENGTH)) { resultingOffset = handleEndOfLogCondition( termBuffer, termOffset, defaultVersionFlagsType, defaultSessionId, capacity); } else { applyDefaultHeader( termBuffer, termOffset, frameLength, defaultVersionFlagsType, defaultSessionId); termBuffer.putBytes(termOffset + HEADER_LENGTH, srcBuffer, srcOffset, length); frameLengthOrdered(termBuffer, termOffset, frameLength); } return resultingOffset; }
@Test public void shouldClaimRegionForZeroCopyEncoding() { final int headerLength = DEFAULT_HEADER.capacity(); final int msgLength = 20; final int frameLength = msgLength + headerLength; final int alignedFrameLength = align(frameLength, FRAME_ALIGNMENT); final int tail = 0; final BufferClaim bufferClaim = new BufferClaim(); when(metaDataBuffer.getAndAddInt(TERM_TAIL_COUNTER_OFFSET, alignedFrameLength)).thenReturn(0); assertThat(termAppender.claim(msgLength, bufferClaim), is(alignedFrameLength)); assertThat(bufferClaim.offset(), is(tail + headerLength)); assertThat(bufferClaim.length(), is(msgLength)); // Map flyweight or encode to buffer directly then call commit() when done bufferClaim.commit(); final InOrder inOrder = inOrder(termBuffer, metaDataBuffer); inOrder .verify(metaDataBuffer, times(1)) .getAndAddInt(TERM_TAIL_COUNTER_OFFSET, alignedFrameLength); verifyDefaultHeader(inOrder, termBuffer, tail, frameLength); inOrder.verify(termBuffer, times(1)).putInt(termOffsetOffset(tail), tail, LITTLE_ENDIAN); }
@Test public void shouldPadLogAndTripWhenAppendingWithInsufficientRemainingCapacityIncludingHeader() { final int headerLength = DEFAULT_HEADER.capacity(); final int msgLength = 120; final int requiredFrameSize = align(headerLength + msgLength, FRAME_ALIGNMENT); final int tailValue = termAppender.termBuffer().capacity() - (requiredFrameSize + (headerLength - FRAME_ALIGNMENT)); final UnsafeBuffer buffer = new UnsafeBuffer(new byte[128]); final int frameLength = TERM_BUFFER_LENGTH - tailValue; when(metaDataBuffer.getAndAddInt(TERM_TAIL_COUNTER_OFFSET, requiredFrameSize)) .thenReturn(tailValue); assertThat(termAppender.append(buffer, 0, msgLength), is(TermAppender.TRIPPED)); final InOrder inOrder = inOrder(termBuffer, metaDataBuffer); inOrder .verify(metaDataBuffer, times(1)) .getAndAddInt(TERM_TAIL_COUNTER_OFFSET, requiredFrameSize); verifyDefaultHeader(inOrder, termBuffer, tailValue, frameLength); inOrder .verify(termBuffer, times(1)) .putShort(typeOffset(tailValue), (short) PADDING_FRAME_TYPE, LITTLE_ENDIAN); inOrder .verify(termBuffer, times(1)) .putInt(termOffsetOffset(tailValue), tailValue, LITTLE_ENDIAN); inOrder.verify(termBuffer, times(1)).putIntOrdered(tailValue, frameLength); }
@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; when(metaDataBuffer.getAndAddInt(TERM_TAIL_COUNTER_OFFSET, alignedFrameLength)) .thenReturn(0) .thenReturn(alignedFrameLength); assertThat(termAppender.append(buffer, 0, msgLength), is(alignedFrameLength)); assertThat(termAppender.append(buffer, 0, msgLength), is(alignedFrameLength * 2)); final InOrder inOrder = inOrder(termBuffer, metaDataBuffer); inOrder .verify(metaDataBuffer, times(1)) .getAndAddInt(TERM_TAIL_COUNTER_OFFSET, alignedFrameLength); verifyDefaultHeader(inOrder, termBuffer, tail, frameLength); inOrder.verify(termBuffer, times(1)).putBytes(headerLength, buffer, 0, msgLength); inOrder.verify(termBuffer, times(1)).putInt(termOffsetOffset(tail), tail, LITTLE_ENDIAN); inOrder.verify(termBuffer, times(1)).putIntOrdered(tail, frameLength); tail = alignedFrameLength; inOrder .verify(metaDataBuffer, times(1)) .getAndAddInt(TERM_TAIL_COUNTER_OFFSET, alignedFrameLength); verifyDefaultHeader(inOrder, termBuffer, tail, frameLength); inOrder.verify(termBuffer, times(1)).putBytes(tail + headerLength, buffer, 0, msgLength); inOrder.verify(termBuffer, times(1)).putInt(termOffsetOffset(tail), tail, LITTLE_ENDIAN); inOrder.verify(termBuffer, times(1)).putIntOrdered(tail, frameLength); }
public int appendFragmentedMessage( final long defaultVersionFlagsType, final long defaultSessionId, final DirectBuffer srcBuffer, final int srcOffset, final int length, final int maxPayloadLength) { final int numMaxPayloads = length / maxPayloadLength; final int remainingPayload = length % maxPayloadLength; final int lastFrameLength = (remainingPayload > 0) ? align(remainingPayload + HEADER_LENGTH, FRAME_ALIGNMENT) : 0; final int requiredLength = (numMaxPayloads * (maxPayloadLength + HEADER_LENGTH)) + lastFrameLength; int termOffset = metaDataBuffer.getAndAddInt(TERM_TAIL_COUNTER_OFFSET, requiredLength); final UnsafeBuffer termBuffer = this.termBuffer; final int capacity = termBuffer.capacity(); int resultingOffset = termOffset + requiredLength; if (resultingOffset > (capacity - HEADER_LENGTH)) { resultingOffset = handleEndOfLogCondition( termBuffer, termOffset, defaultVersionFlagsType, defaultSessionId, capacity); } else { byte flags = BEGIN_FRAG_FLAG; int remaining = length; do { final int bytesToWrite = Math.min(remaining, maxPayloadLength); final int frameLength = bytesToWrite + HEADER_LENGTH; final int alignedLength = align(frameLength, FRAME_ALIGNMENT); applyDefaultHeader( termBuffer, termOffset, frameLength, defaultVersionFlagsType, defaultSessionId); termBuffer.putBytes( termOffset + HEADER_LENGTH, srcBuffer, srcOffset + (length - remaining), bytesToWrite); if (remaining <= maxPayloadLength) { flags |= END_FRAG_FLAG; } frameFlags(termBuffer, termOffset, flags); frameLengthOrdered(termBuffer, termOffset, frameLength); flags = 0; termOffset += alignedLength; remaining -= bytesToWrite; } while (remaining > 0); } return resultingOffset; }
public int claim( final long defaultVersionFlagsType, final long defaultSessionId, final int length, final BufferClaim bufferClaim) { final int frameLength = length + HEADER_LENGTH; final int alignedLength = align(frameLength, FRAME_ALIGNMENT); final int termOffset = metaDataBuffer.getAndAddInt(TERM_TAIL_COUNTER_OFFSET, alignedLength); final UnsafeBuffer termBuffer = this.termBuffer; final int capacity = termBuffer.capacity(); int resultingOffset = termOffset + alignedLength; if (resultingOffset > (capacity - HEADER_LENGTH)) { resultingOffset = handleEndOfLogCondition( termBuffer, termOffset, defaultVersionFlagsType, defaultSessionId, capacity); } else { applyDefaultHeader( termBuffer, termOffset, frameLength, defaultVersionFlagsType, defaultSessionId); bufferClaim.wrap(termBuffer, termOffset, frameLength); } return resultingOffset; }
@Test public void shouldFragmentMessageOverTwoFrames() { final int msgLength = termAppender.maxPayloadLength() + 1; final int headerLength = DEFAULT_HEADER.capacity(); final int frameLength = headerLength + 1; final int requiredCapacity = align(headerLength + 1, FRAME_ALIGNMENT) + termAppender.maxFrameLength(); final UnsafeBuffer buffer = new UnsafeBuffer(new byte[msgLength]); when(metaDataBuffer.getAndAddInt(TERM_TAIL_COUNTER_OFFSET, requiredCapacity)).thenReturn(0); assertThat(termAppender.append(buffer, 0, msgLength), is(requiredCapacity)); int tail = 0; final InOrder inOrder = inOrder(termBuffer, metaDataBuffer); inOrder .verify(metaDataBuffer, times(1)) .getAndAddInt(TERM_TAIL_COUNTER_OFFSET, requiredCapacity); verifyDefaultHeader(inOrder, termBuffer, tail, termAppender.maxFrameLength()); inOrder .verify(termBuffer, times(1)) .putBytes(tail + headerLength, buffer, 0, termAppender.maxPayloadLength()); inOrder.verify(termBuffer, times(1)).putByte(flagsOffset(tail), BEGIN_FRAG); inOrder.verify(termBuffer, times(1)).putInt(termOffsetOffset(tail), tail, LITTLE_ENDIAN); inOrder.verify(termBuffer, times(1)).putIntOrdered(tail, termAppender.maxFrameLength()); tail = termAppender.maxFrameLength(); verifyDefaultHeader(inOrder, termBuffer, tail, frameLength); inOrder .verify(termBuffer, times(1)) .putBytes(tail + headerLength, buffer, termAppender.maxPayloadLength(), 1); inOrder.verify(termBuffer, times(1)).putByte(flagsOffset(tail), END_FRAG); inOrder.verify(termBuffer, times(1)).putInt(termOffsetOffset(tail), tail, LITTLE_ENDIAN); inOrder.verify(termBuffer, times(1)).putIntOrdered(tail, frameLength); }