/// <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="IControlledFragmentHandler"/> up to a limited number of fragments as specified or /// the maximum position specified. /// <para> /// Use a <seealso cref="IControlledFragmentHandler"/> 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="ControlledFragmentAssembler"/> /// <seealso cref="ImageControlledFragmentAssembler"/> public int BoundedControlledPoll(ControlledFragmentHandler handler, long limitPosition, int fragmentLimit) { var fragmentHandler = HandlerHelper.ToControlledFragmentHandler(handler); return(BoundedControlledPoll(fragmentHandler, limitPosition, fragmentLimit)); }
public void SetUp() { RcvBuffer = new UnsafeBuffer(new byte[ALIGNED_FRAME_LENGTH]); DataHeader = new DataHeaderFlyweight(); MockFragmentHandler = A.Fake <FragmentHandler>(); MockControlledFragmentHandler = A.Fake <ControlledFragmentHandler>(); Position = A.Fake <IPosition>(options => options.Wrapping(new AtomicLongPosition())); LogBuffers = A.Fake <LogBuffers>(); ErrorHandler = A.Fake <ErrorHandler>(); Subscription = A.Fake <Subscription>(); TermBuffers = new UnsafeBuffer[LogBufferDescriptor.PARTITION_COUNT]; DataHeader.Wrap(RcvBuffer); for (var i = 0; i < LogBufferDescriptor.PARTITION_COUNT; i++) { TermBuffers[i] = new UnsafeBuffer(new byte[TERM_BUFFER_LENGTH]); } var logMetaDataBuffer = new UnsafeBuffer(new byte[LogBufferDescriptor.LOG_META_DATA_LENGTH]); A.CallTo(() => LogBuffers.TermBuffers()).Returns(TermBuffers); A.CallTo(() => LogBuffers.TermLength()).Returns(TERM_BUFFER_LENGTH); A.CallTo(() => LogBuffers.MetaDataBuffer()).Returns(logMetaDataBuffer); }
/// <summary> /// Poll in a controlled manner the <seealso cref="Image"/>s under the subscription for available message fragments. /// Control is applied to fragments in the stream. If more fragments can be read on another stream /// they will even if BREAK or ABORT is returned from the fragment handler. /// <para> /// Each fragment read will be a whole message if it is under MTU length. If larger than MTU then it will come /// as a series of fragments ordered within a session. /// </para> /// <para> /// To assemble messages that span multiple fragments then use <seealso cref="ControlledFragmentAssembler"/>. /// /// </para> /// </summary> /// <param name="fragmentHandler"> callback for handling each message fragment as it is read. </param> /// <param name="fragmentLimit"> number of message fragments to limit for the poll operation across multiple <seealso cref="Image"/>s. </param> /// <returns> the number of fragments received </returns> /// <seealso cref="ControlledFragmentHandler" /> public int ControlledPoll(ControlledFragmentHandler fragmentHandler, int fragmentLimit) { var images = _fields.images; var length = images.Length; var fragmentsRead = 0; var startingIndex = _fields.roundRobinIndex++; if (startingIndex >= length) { _fields.roundRobinIndex = startingIndex = 0; } for (var i = startingIndex; i < length && fragmentsRead < fragmentLimit; i++) { fragmentsRead += images[i].ControlledPoll(fragmentHandler, fragmentLimit - fragmentsRead); } for (var i = 0; i < startingIndex && fragmentsRead < fragmentLimit; i++) { fragmentsRead += images[i].ControlledPoll(fragmentHandler, fragmentLimit - fragmentsRead); } return(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="IControlledFragmentHandler"/> up to a limited number of fragments as specified or /// the maximum position specified. /// <para> /// Use a <seealso cref="IControlledFragmentHandler"/> to assemble messages which span multiple fragments. /// /// </para> /// </summary> /// <param name="fragmentHandler"> to which message fragments are delivered. </param> /// <param name="maxPosition"> 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="ControlledFragmentAssembler"/> /// <seealso cref="ImageControlledFragmentAssembler"/> public virtual int BoundedControlledPoll(ControlledFragmentHandler fragmentHandler, long maxPosition, int fragmentLimit) { var handler = HandlerHelper.ToControlledFragmentHandler(fragmentHandler); return(BoundedControlledPoll(handler, maxPosition, fragmentLimit)); }
public long ControlledPeek(long initialPosition, ControlledFragmentHandler handler, long limitPosition) { var fragmentHandler = HandlerHelper.ToControlledFragmentHandler(handler); return(ControlledPeek(initialPosition, fragmentHandler, limitPosition)); }
/// <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="ControlledFragmentHandler"/> up to a limited number of fragments as specified. /// /// Use a <see cref="ControlledFragmentAssembler"/>. to assemble messages which span multiple fragments. /// /// </summary> /// <param name="handler"> to which message fragments are delivered. </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="ControlledFragmentAssembler" /> /// <seealso cref="ImageControlledFragmentAssembler" /> public int ControlledPoll(ControlledFragmentHandler handler, int fragmentLimit) { var fragmentHandler = HandlerHelper.ToControlledFragmentHandler(handler); return(ControlledPoll(fragmentHandler, fragmentLimit)); }
/// <summary> /// Peek for new messages in a stream by scanning forward from an initial position. If new messages are found then /// they will be delivered to the <seealso cref="IControlledFragmentHandler"/> up to a limited position. /// /// Use a <seealso cref="ControlledFragmentAssembler"/> to assemble messages which span multiple fragments. Scans must also /// start at the beginning of a message so that the assembler is reset. /// /// </summary> /// <param name="initialPosition"> from which to peek forward. </param> /// <param name="fragmentHandler"> to which message fragments are delivered. </param> /// <param name="limitPosition"> up to which can be scanned. </param> /// <returns> the resulting position after the scan terminates which is a complete message. </returns> /// <seealso cref="ControlledFragmentAssembler"/> /// <seealso cref="ImageControlledFragmentAssembler"/> public virtual long ControlledPeek(long initialPosition, ControlledFragmentHandler fragmentHandler, long limitPosition) { if (_isClosed) { return(0); } ValidatePosition(initialPosition); int initialOffset = (int)initialPosition & _termLengthMask; int offset = initialOffset; long position = initialPosition; UnsafeBuffer termBuffer = ActiveTermBuffer(initialPosition); int capacity = termBuffer.Capacity; _header.Buffer = termBuffer; long resultingPosition = initialPosition; try { do { int length = FrameDescriptor.FrameLengthVolatile(termBuffer, offset); if (length <= 0) { break; } int frameOffset = offset; var alignedLength = BitUtil.Align(length, FrameDescriptor.FRAME_ALIGNMENT); offset += alignedLength; if (FrameDescriptor.IsPaddingFrame(termBuffer, frameOffset)) { continue; } _header.Offset = frameOffset; var action = fragmentHandler( termBuffer, frameOffset + DataHeaderFlyweight.HEADER_LENGTH, length - DataHeaderFlyweight.HEADER_LENGTH, _header); if (action == ControlledFragmentHandlerAction.ABORT) { break; } position += (offset - initialOffset); initialOffset = offset; if ((_header.Flags & FrameDescriptor.END_FRAG_FLAG) == FrameDescriptor.END_FRAG_FLAG) { resultingPosition = position; } if (action == ControlledFragmentHandlerAction.BREAK) { break; } } while (position < limitPosition && offset < capacity); } catch (Exception t) { _errorHandler(t); } return(resultingPosition); }
/// <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="IControlledFragmentHandler"/> up to a limited number of fragments as specified. /// /// Use a <see cref="ControlledFragmentAssembler"/>. to assemble messages which span multiple fragments. /// /// </summary> /// <param name="fragmentHandler"> to which message fragments are delivered. </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="ControlledFragmentAssembler" /> /// <seealso cref="ImageControlledFragmentAssembler" /> public int ControlledPoll(ControlledFragmentHandler fragmentHandler, int fragmentLimit) { if (_isClosed) { return(0); } var fragmentsRead = 0; var initialPosition = _subscriberPosition.Get(); var initialOffset = (int)initialPosition & _termLengthMask; var resultingOffset = initialOffset; var termBuffer = ActiveTermBuffer(initialPosition); int capacity = termBuffer.Capacity; _header.Buffer = termBuffer; try { do { var length = FrameDescriptor.FrameLengthVolatile(termBuffer, resultingOffset); if (length <= 0) { break; } var frameOffset = resultingOffset; var alignedLength = BitUtil.Align(length, FrameDescriptor.FRAME_ALIGNMENT); resultingOffset += alignedLength; if (FrameDescriptor.IsPaddingFrame(termBuffer, frameOffset)) { continue; } _header.Offset = frameOffset; var action = fragmentHandler( termBuffer, frameOffset + DataHeaderFlyweight.HEADER_LENGTH, length - DataHeaderFlyweight.HEADER_LENGTH, _header); if (action == ControlledFragmentHandlerAction.ABORT) { resultingOffset -= alignedLength; break; } ++fragmentsRead; if (action == ControlledFragmentHandlerAction.BREAK) { break; } else if (action == ControlledFragmentHandlerAction.COMMIT) { initialPosition += (resultingOffset - initialOffset); initialOffset = resultingOffset; _subscriberPosition.SetOrdered(initialPosition); } } while (fragmentsRead < fragmentLimit && resultingOffset < capacity); } catch (Exception t) { _errorHandler(t); } finally { long resultingPosition = initialPosition + (resultingOffset - initialOffset); if (resultingPosition > initialPosition) { _subscriberPosition.SetOrdered(resultingPosition); } } return(fragmentsRead); }
public static IControlledFragmentHandler ToControlledFragmentHandler(ControlledFragmentHandler @delegate) { return(new ControlledFragmentHandlerWrapper(@delegate)); }
public ControlledFragmentHandlerWrapper(ControlledFragmentHandler @delegate) { _delegate = @delegate; }
/// <summary> /// Construct an adapter to reassembly message fragments and delegate on only whole messages. /// </summary> /// <param name="delegate"> onto which whole messages are forwarded. </param> /// <param name="initialBufferLength"> to be used for each session. </param> public ImageControlledFragmentAssembler(ControlledFragmentHandler @delegate, int initialBufferLength = BufferBuilder.MIN_ALLOCATED_CAPACITY) { _delegate = @delegate; _builder = new BufferBuilder(initialBufferLength); }
/** * Poll for new messages in a stream. If new messages are found beyond the last consumed position then they * will be delivered to the {@link ControlledFragmentHandler} up to a limited number of fragments as specified. * * To assemble messages that span multiple fragments then use {@link ControlledFragmentAssembler}. * * @param fragmentHandler to which message fragments are delivered. * @param fragmentLimit for the number of fragments to be consumed during one polling operation. * @return the number of fragments that have been consumed. * @see ControlledFragmentAssembler */ public int controlledPoll(ControlledFragmentHandler fragmentHandler, int fragmentLimit) { if (isClosed) { return(0); } long position = subscriberPosition.get(); int termOffset = (int)position & termLengthMask; int offset = termOffset; int fragmentsRead = 0; DirectBuffer termBuffer = activeTermBuffer(position); try { int capacity = termBuffer.capacity(); do { int length = frameLengthVolatile(termBuffer, offset); if (length <= 0) { break; } int frameOffset = offset; int alignedLength = BitUtil.align(length, FRAME_ALIGNMENT); offset += alignedLength; if (!isPaddingFrame(termBuffer, frameOffset)) { header.buffer(termBuffer); header.offset(frameOffset); Action action = fragmentHandler.onFragment( termBuffer, frameOffset + HEADER_LENGTH, length - HEADER_LENGTH, header); ++fragmentsRead; if (action == BREAK) { break; } else if (action == ABORT) { --fragmentsRead; offset = frameOffset; break; } else if (action == COMMIT) { position += alignedLength; termOffset = offset; subscriberPosition.setOrdered(position); } } }while (fragmentsRead < fragmentLimit && offset < capacity); } catch (Throwable t) { errorHandler.onError(t); } updatePosition(position, termOffset, offset); return(fragmentsRead); }
/// <summary> /// Construct an adapter to reassembly message fragments and delegate on only whole messages. /// </summary> /// <param name="delegate"> onto which whole messages are forwarded. </param> /// <param name="initialBufferLength"> to be used for each session. </param> public ControlledFragmentAssembler(ControlledFragmentHandler @delegate, int initialBufferLength = BufferBuilder.MIN_ALLOCATED_CAPACITY) { _initialBufferLength = initialBufferLength; _delegate = @delegate; }