Beispiel #1
0
        public virtual void SetUp()
        {
            RcvBuffer = new UnsafeBuffer(new byte[ALIGNED_FRAME_LENGTH]);
            DataHeader = new DataHeaderFlyweight();
            MockFragmentHandler = A.Fake<FragmentHandler>();
            MockControlledFragmentHandler = A.Fake<IControlledFragmentHandler>();
            Position = A.Fake<IPosition>(options => options.Wrapping(new AtomicLongPosition()));
            LogBuffers = A.Fake<LogBuffers>();
            ErrorHandler = A.Fake<ErrorHandler>();
            Subscription = A.Fake<Subscription>();

            AtomicBuffers = new UnsafeBuffer[(LogBufferDescriptor.PARTITION_COUNT * 2) + 1];
            TermBuffers = new UnsafeBuffer[LogBufferDescriptor.PARTITION_COUNT];

            DataHeader.Wrap(RcvBuffer);

            for (var i = 0; i < LogBufferDescriptor.PARTITION_COUNT; i++)
            {
                AtomicBuffers[i] = new UnsafeBuffer(new byte[TERM_BUFFER_LENGTH]);
                TermBuffers[i] = AtomicBuffers[i];

                AtomicBuffers[i + LogBufferDescriptor.PARTITION_COUNT] = new UnsafeBuffer(new byte[LogBufferDescriptor.TERM_META_DATA_LENGTH]);
            }

            AtomicBuffers[LogBufferDescriptor.LOG_META_DATA_SECTION_INDEX] = new UnsafeBuffer(new byte[LogBufferDescriptor.LOG_META_DATA_LENGTH]);

            A.CallTo(() => LogBuffers.AtomicBuffers()).Returns(AtomicBuffers);
            A.CallTo(() => LogBuffers.TermLength()).Returns(TERM_BUFFER_LENGTH);
        }
Beispiel #2
0
        public void SetUp()
        {
            RcvBuffer                     = new UnsafeBuffer(new byte[ALIGNED_FRAME_LENGTH]);
            DataHeader                    = new DataHeaderFlyweight();
            MockFragmentHandler           = A.Fake <FragmentHandler>();
            MockControlledFragmentHandler = A.Fake <IControlledFragmentHandler>();
            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]);
            }

            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);
        }
Beispiel #3
0
        /// <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(IControlledFragmentHandler 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);
        }
Beispiel #4
0
        /// <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(IControlledFragmentHandler 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.OnFragment(
                        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);
        }
 /// <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(IControlledFragmentHandler @delegate, int initialBufferLength = 0)
 {
     _delegate = @delegate;
     _builder  = new BufferBuilder(initialBufferLength);
 }
 /// <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(IControlledFragmentHandler @delegate, int initialBufferLength = 0)
 {
     _initialBufferLength = initialBufferLength;
     _delegate            = @delegate;
 }
Beispiel #7
0
 /// <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(IControlledFragmentHandler @delegate, int initialBufferLength)
 {
     _delegate = @delegate;
     _builderFunc = (ignore) => new BufferBuilder(initialBufferLength);
 }
Beispiel #8
0
 /// <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(IControlledFragmentHandler @delegate, int initialBufferLength = BufferBuilder.MIN_ALLOCATED_CAPACITY, bool isDirect = false)
 {
     _delegate = @delegate;
     _builder  = new BufferBuilder(initialBufferLength);
 }
Beispiel #9
0
        /// <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.
        ///
        /// To assemble messages that span multiple fragments then use <seealso cref="ControlledFragmentAssembler"/>.
        /// </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" />
        public int ControlledPoll(IControlledFragmentHandler fragmentHandler, int fragmentLimit)
        {
            if (_isClosed)
            {
                return(0);
            }

            var position      = _subscriberPosition.Get();
            var termOffset    = (int)position & _termLengthMask;
            var offset        = termOffset;
            var fragmentsRead = 0;
            var termBuffer    = ActiveTermBuffer(position);

            try
            {
                var capacity = termBuffer.Capacity;
                do
                {
                    var length = FrameDescriptor.FrameLengthVolatile(termBuffer, offset);
                    if (length <= 0)
                    {
                        break;
                    }

                    var frameOffset   = offset;
                    var alignedLength = BitUtil.Align(length, FrameDescriptor.FRAME_ALIGNMENT);
                    offset += alignedLength;

                    if (!FrameDescriptor.IsPaddingFrame(termBuffer, frameOffset))
                    {
                        _header.SetBuffer(termBuffer, frameOffset);

                        var action = fragmentHandler.OnFragment(termBuffer, frameOffset + DataHeaderFlyweight.HEADER_LENGTH, length - DataHeaderFlyweight.HEADER_LENGTH, _header);

                        ++fragmentsRead;

                        if (action == ControlledFragmentHandlerAction.BREAK)
                        {
                            break;
                        }
                        if (action == ControlledFragmentHandlerAction.ABORT)
                        {
                            --fragmentsRead;
                            offset = frameOffset;
                            break;
                        }
                        if (action == ControlledFragmentHandlerAction.COMMIT)
                        {
                            position  += alignedLength;
                            termOffset = offset;
                            _subscriberPosition.SetOrdered(position);
                        }
                    }
                } while (fragmentsRead < fragmentLimit && offset < capacity);
            }
            catch (Exception t)
            {
                _errorHandler(t);
            }

            UpdatePosition(position, termOffset, offset);

            return(fragmentsRead);
        }
Beispiel #10
0
 /// <summary>
 /// Construct an adapter to reassemble message fragments and delegate on only whole messages.
 /// </summary>
 /// <param name="delegate"> onto which whole messages are forwarded. </param>
 public ControlledFragmentAssembler(IControlledFragmentHandler @delegate) : this(@delegate, BufferBuilder.INITIAL_CAPACITY)
 {
 }
 /// <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(IControlledFragmentHandler @delegate, int initialBufferLength)
 {
     _delegate    = @delegate;
     _builderFunc = (ignore) => new BufferBuilder(initialBufferLength);
 }
 /// <summary>
 /// Construct an adapter to reassemble message fragments and delegate on only whole messages.
 /// </summary>
 /// <param name="delegate"> onto which whole messages are forwarded. </param>
 public ControlledFragmentAssembler(IControlledFragmentHandler @delegate) : this(@delegate, BufferBuilder.INITIAL_CAPACITY)
 {
 }
Beispiel #13
0
        /// <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.
        ///     
        /// To assemble messages that span multiple fragments then use <seealso cref="ControlledFragmentAssembler"/>.
        /// </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" />
        public int ControlledPoll(IControlledFragmentHandler fragmentHandler, int fragmentLimit)
        {
            if (_isClosed)
            {
                return 0;
            }

            var position = _subscriberPosition.Get();
            var termOffset = (int) position & _termLengthMask;
            var offset = termOffset;
            var fragmentsRead = 0;
            var termBuffer = ActiveTermBuffer(position);

            try
            {
                var capacity = termBuffer.Capacity;
                do
                {
                    var length = FrameDescriptor.FrameLengthVolatile(termBuffer, offset);
                    if (length <= 0)
                    {
                        break;
                    }

                    var frameOffset = offset;
                    var alignedLength = BitUtil.Align(length, FrameDescriptor.FRAME_ALIGNMENT);
                    offset += alignedLength;

                    if (!FrameDescriptor.IsPaddingFrame(termBuffer, frameOffset))
                    {
                        _header.SetBuffer(termBuffer, frameOffset);

                        var action = fragmentHandler.OnFragment(termBuffer, frameOffset + DataHeaderFlyweight.HEADER_LENGTH, length - DataHeaderFlyweight.HEADER_LENGTH, _header);

                        ++fragmentsRead;

                        if (action == ControlledFragmentHandlerAction.BREAK)
                        {
                            break;
                        }
                        if (action == ControlledFragmentHandlerAction.ABORT)
                        {
                            --fragmentsRead;
                            offset = frameOffset;
                            break;
                        }
                        if (action == ControlledFragmentHandlerAction.COMMIT)
                        {
                            position += alignedLength;
                            termOffset = offset;
                            _subscriberPosition.SetOrdered(position);
                        }
                    }
                } while (fragmentsRead < fragmentLimit && offset < capacity);
            }
            catch (Exception t)
            {
                _errorHandler(t);
            }

            UpdatePosition(position, termOffset, offset);

            return fragmentsRead;
        }
Beispiel #14
0
        /// <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(IControlledFragmentHandler handler, long limitPosition,
                                         int fragmentLimit)
        {
            if (_isClosed)
            {
                return(0);
            }

            var fragmentsRead   = 0;
            var initialPosition = _subscriberPosition.Get();
            var initialOffset   = (int)initialPosition & _termLengthMask;
            var offset          = initialOffset;
            var termBuffer      = ActiveTermBuffer(initialPosition);
            var limitOffset     = (int)Math.Min(termBuffer.Capacity, (limitPosition - initialPosition + initialOffset));
            var 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;

                    var action = handler.OnFragment(termBuffer,
                                                    frameOffset + DataHeaderFlyweight.HEADER_LENGTH,
                                                    length - DataHeaderFlyweight.HEADER_LENGTH, header);

                    if (action == ControlledFragmentHandlerAction.ABORT)
                    {
                        offset -= alignedLength;
                        break;
                    }

                    ++fragmentsRead;

                    if (action == ControlledFragmentHandlerAction.BREAK)
                    {
                        break;
                    }
                    else if (action == ControlledFragmentHandlerAction.COMMIT)
                    {
                        initialPosition += (offset - initialOffset);
                        initialOffset    = offset;
                        _subscriberPosition.SetOrdered(initialPosition);
                    }
                }
            }
            catch (Exception t)
            {
                _errorHandler(t);
            }
            finally
            {
                long resultingPosition = initialPosition + (offset - initialOffset);
                if (resultingPosition > initialPosition)
                {
                    _subscriberPosition.SetOrdered(resultingPosition);
                }
            }

            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(IControlledFragmentHandler @delegate, int initialBufferLength = BufferBuilder.MIN_ALLOCATED_CAPACITY)
 {
     _initialBufferLength = initialBufferLength;
     _delegate            = @delegate;
 }
Beispiel #16
0
        /// <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="handler"> 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 long ControlledPeek(long initialPosition, IControlledFragmentHandler handler, long limitPosition)
        {
            if (_isClosed)
            {
                return(initialPosition);
            }

            ValidatePosition(initialPosition);
            if (initialPosition >= limitPosition)
            {
                return(initialPosition);
            }

            int          initialOffset = (int)initialPosition & _termLengthMask;
            int          offset        = initialOffset;
            long         position      = initialPosition;
            UnsafeBuffer termBuffer    = ActiveTermBuffer(initialPosition);
            var          header        = _header;
            int          limitOffset   = (int)Math.Min(termBuffer.Capacity, (limitPosition - initialPosition) + offset);

            _header.Buffer = termBuffer;
            long resultingPosition = initialPosition;

            try
            {
                while (offset < limitOffset)
                {
                    int length = FrameDescriptor.FrameLengthVolatile(termBuffer, offset);
                    if (length <= 0)
                    {
                        break;
                    }

                    int frameOffset = offset;
                    offset += BitUtil.Align(length, FrameDescriptor.FRAME_ALIGNMENT);

                    if (FrameDescriptor.IsPaddingFrame(termBuffer, frameOffset))
                    {
                        position         += (offset - initialOffset);
                        initialOffset     = offset;
                        resultingPosition = position;

                        continue;
                    }

                    _header.Offset = frameOffset;


                    var action = handler.OnFragment(
                        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;
                    }
                }
            }
            catch (Exception t)
            {
                _errorHandler(t);
            }

            return(resultingPosition);
        }
Beispiel #17
0
        /// <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="IControlledFragmentHandler" />
        public int ControlledPoll(IControlledFragmentHandler fragmentHandler, int fragmentLimit)
        {
            var images = _images;
            var length = images.Length;
            var fragmentsRead = 0;

            var startingIndex = _roundRobinIndex++;
            if (startingIndex >= length)
            {
                _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;
        }