public void ShouldPassThroughUnfragmentedMessage() { A.CallTo(() => header.Flags).Returns(FrameDescriptor.UNFRAGMENTED); var srcBuffer = new UnsafeBuffer(new byte[128]); const int offset = 8; const int length = 32; adapter.OnFragment(srcBuffer, offset, length, header); A.CallTo(() => delegateFragmentHandler.OnFragment(srcBuffer, offset, length, header)) .MustHaveHappened(Repeated.Exactly.Once); }
/// <summary> /// The implementation of <seealso cref="FragmentHandler"/> that reassembles and forwards whole messages. /// </summary> /// <param name="buffer"> containing the data. </param> /// <param name="offset"> at which the data begins. </param> /// <param name="length"> of the data in bytes. </param> /// <param name="header"> representing the meta data for the data. </param> public void OnFragment(IDirectBuffer buffer, int offset, int length, Header header) { byte flags = header.Flags; if ((flags & FrameDescriptor.UNFRAGMENTED) == FrameDescriptor.UNFRAGMENTED) { _delegate.OnFragment(buffer, offset, length, header); } else { HandleFragment(buffer, offset, length, header, flags); } }
public static long Read(UnsafeBuffer termBuffer, int offset, IFragmentHandler handler, int fragmentsLimit, Header header, ErrorHandler errorHandler) { int fragmentsRead = 0; int capacity = termBuffer.Capacity; try { do { int frameLength = FrameDescriptor.FrameLengthVolatile(termBuffer, offset); if (frameLength <= 0) { break; } int termOffset = offset; offset += BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT); if (!FrameDescriptor.IsPaddingFrame(termBuffer, termOffset)) { header.SetBuffer(termBuffer, termOffset); handler.OnFragment(termBuffer, termOffset + DataHeaderFlyweight.HEADER_LENGTH, frameLength - DataHeaderFlyweight.HEADER_LENGTH, header); ++fragmentsRead; } } while (fragmentsRead < fragmentsLimit && offset < capacity); } catch (Exception t) { errorHandler(t); } return(Pack(offset, fragmentsRead)); }
/// <summary> /// Poll for new messages in a stream. If new messages are found beyond the last consumed position then they /// will be delivered to the <seealso cref="FragmentHandler"/> up to a limited number of fragments as specified or /// the maximum position specified. /// <para> /// Use a <seealso cref="FragmentAssembler"/> to assemble messages which span multiple fragments. /// /// </para> /// </summary> /// <param name="handler"> to which message fragments are delivered. </param> /// <param name="limitPosition"> to consume messages up to. </param> /// <param name="fragmentLimit"> for the number of fragments to be consumed during one polling operation. </param> /// <returns> the number of fragments that have been consumed. </returns> /// <seealso cref="FragmentAssembler" /> /// <seealso cref="ImageFragmentAssembler" /> public int BoundedPoll(IFragmentHandler handler, long limitPosition, int fragmentLimit) { if (_isClosed) { return(0); } int fragmentsRead = 0; long initialPosition = _subscriberPosition.Get(); int initialOffset = (int)initialPosition & _termLengthMask; int offset = initialOffset; UnsafeBuffer termBuffer = ActiveTermBuffer(initialPosition); int limitOffset = (int)Math.Min(termBuffer.Capacity, (limitPosition - initialPosition) + offset); Header header = _header; header.Buffer = termBuffer; try { while (fragmentsRead < fragmentLimit && offset < limitOffset) { int length = FrameDescriptor.FrameLengthVolatile(termBuffer, offset); if (length <= 0) { break; } int frameOffset = offset; int alignedLength = BitUtil.Align(length, FrameDescriptor.FRAME_ALIGNMENT); offset += alignedLength; if (FrameDescriptor.IsPaddingFrame(termBuffer, frameOffset)) { continue; } header.Offset = frameOffset; handler.OnFragment(termBuffer, frameOffset + DataHeaderFlyweight.HEADER_LENGTH, length - DataHeaderFlyweight.HEADER_LENGTH, header); ++fragmentsRead; } } catch (Exception t) { _errorHandler(t); } finally { long resultingPosition = initialPosition + (offset - initialOffset); if (resultingPosition > initialPosition) { _subscriberPosition.SetOrdered(resultingPosition); } } return(fragmentsRead); }
public static int Read( UnsafeBuffer termBuffer, int termOffset, IFragmentHandler handler, int fragmentsLimit, Header header, ErrorHandler errorHandler, long currentPosition, IPosition subscriberPosition) { int fragmentsRead = 0; int offset = termOffset; int capacity = termBuffer.Capacity; header.Buffer = termBuffer; try { while (fragmentsRead < fragmentsLimit && offset < capacity) { int frameLength = FrameDescriptor.FrameLengthVolatile(termBuffer, offset); if (frameLength <= 0) { break; } int frameOffset = offset; offset += BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT); if (!FrameDescriptor.IsPaddingFrame(termBuffer, frameOffset)) { header.Offset = frameOffset; handler.OnFragment(termBuffer, frameOffset + DataHeaderFlyweight.HEADER_LENGTH, frameLength - DataHeaderFlyweight.HEADER_LENGTH, header); ++fragmentsRead; } } } catch (Exception t) { errorHandler(t); } finally { long newPosition = currentPosition + (offset - termOffset); if (newPosition > currentPosition) { subscriberPosition.SetOrdered(newPosition); } } return(fragmentsRead); }
public void ShouldReadData() { Subscription.AddImage(ImageOneMock); A.CallTo(() => ImageOneMock.Poll(A <IFragmentHandler> ._, A <int> ._)).ReturnsLazily(o => { var handler = (IFragmentHandler)o.Arguments[0]; handler.OnFragment(AtomicReadBuffer, HEADER_LENGTH, READ_BUFFER_CAPACITY - HEADER_LENGTH, Header); return(1); }); Assert.AreEqual(1, Subscription.Poll(FragmentHandler, FRAGMENT_COUNT_LIMIT)); A.CallTo(() => FragmentHandler.OnFragment(AtomicReadBuffer, HEADER_LENGTH, READ_BUFFER_CAPACITY - HEADER_LENGTH, A <Header> ._)).MustHaveHappened(); }
public void ShouldReportCorrectPositionOnReception() { var initialPosition = LogBufferDescriptor.ComputePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); Position.SetOrdered(initialPosition); var image = CreateImage(); InsertDataFrame(INITIAL_TERM_ID, OffsetForFrame(0)); var messages = image.Poll(MockFragmentHandler, int.MaxValue); Assert.AreEqual(1, messages); A.CallTo(() => MockFragmentHandler.OnFragment(A <UnsafeBuffer> ._, DataHeaderFlyweight.HEADER_LENGTH, DATA.Length, A <Header> ._)).MustHaveHappened(); A.CallTo(() => Position.SetOrdered(initialPosition)).MustHaveHappened().Then( A.CallTo(() => Position.SetOrdered(initialPosition + ALIGNED_FRAME_LENGTH)).MustHaveHappened() ); }
public void ShouldReadFirstMessage() { const int msgLength = 1; int frameLength = HEADER_LENGTH + msgLength; int alignedFrameLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT); const int termOffset = 0; A.CallTo(() => termBuffer.GetIntVolatile(0)) .Returns(frameLength); A.CallTo(() => termBuffer.GetShort(FrameDescriptor.TypeOffset(0))) .Returns((short)HeaderFlyweight.HDR_TYPE_DATA); int readOutcome = TermReader.Read(termBuffer, termOffset, handler, int.MaxValue, header, errorHandler, 0, subscriberPosition); Assert.That(TermReader.FragmentsRead(readOutcome), Is.EqualTo(1)); A.CallTo(() => termBuffer.GetIntVolatile(0)).MustHaveHappened() .Then(A.CallTo(() => handler.OnFragment(termBuffer, HEADER_LENGTH, msgLength, A <Header> ._)).MustHaveHappened()) .Then(A.CallTo(() => subscriberPosition.SetOrdered(alignedFrameLength)).MustHaveHappened()); }