Пример #1
0
        public virtual void ShouldPollOneFragmentToControlledFragmentHandlerOnContinue()
        {
            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));

            A.CallTo(() => MockControlledFragmentHandler.OnFragment(A <IDirectBuffer> ._, A <int> ._, A <int> ._, A <Header> ._)).Returns(ControlledFragmentHandlerAction.CONTINUE);

            var fragmentsRead = image.ControlledPoll(MockControlledFragmentHandler, int.MaxValue);

            Assert.AreEqual(fragmentsRead, 1);

            A.CallTo(() => MockControlledFragmentHandler.OnFragment(A <UnsafeBuffer> ._, DataHeaderFlyweight.HEADER_LENGTH, DATA.Length, A <Header> ._)).MustHaveHappened().Then(
                A.CallTo(() => Position.SetOrdered(initialPosition + ALIGNED_FRAME_LENGTH)).MustHaveHappened());
        }
Пример #2
0
        public void ShouldNotPollOneFragmentToControlledFragmentHandlerOnAbort()
        {
            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));

            A.CallTo(() => MockControlledFragmentHandler.OnFragment(A <UnsafeBuffer> ._, A <int> ._, A <int> ._, A <Header> ._)).Returns(ControlledFragmentHandlerAction.ABORT);

            var fragmentsRead = image.ControlledPoll(MockControlledFragmentHandler, int.MaxValue);

            Assert.AreEqual(0, fragmentsRead);
            Assert.AreEqual(initialPosition, image.Position);

            A.CallTo(() => MockControlledFragmentHandler.OnFragment(A <UnsafeBuffer> ._, DataHeaderFlyweight.HEADER_LENGTH, DATA.Length, A <Header> ._)).MustHaveHappened();
        }
Пример #3
0
        /// <summary>
        /// Construct a new image over a log to represent a stream of messages from a <seealso cref="Publication"/>.
        /// </summary>
        /// <param name="subscription">       to which this <seealso cref="Image"/> belongs. </param>
        /// <param name="sessionId">          of the stream of messages. </param>
        /// <param name="subscriberPosition"> for indicating the position of the subscriber in the stream. </param>
        /// <param name="logBuffers">         containing the stream of messages. </param>
        /// <param name="errorHandler">       to be called if an error occurs when polling for messages. </param>
        /// <param name="sourceIdentity">     of the source sending the stream of messages. </param>
        /// <param name="correlationId">      of the request to the media driver. </param>
        public Image(Subscription subscription, int sessionId, IPosition subscriberPosition, LogBuffers logBuffers, ErrorHandler errorHandler, string sourceIdentity, long correlationId)
        {
            Subscription        = subscription;
            SessionId           = sessionId;
            _subscriberPosition = subscriberPosition;
            _logBuffers         = logBuffers;
            _errorHandler       = errorHandler;
            SourceIdentity      = sourceIdentity;
            CorrelationId       = correlationId;

            _termBuffers = logBuffers.TermBuffers();

            var termLength = logBuffers.TermLength();

            _termLengthMask      = termLength - 1;
            _positionBitsToShift = IntUtil.NumberOfTrailingZeros(termLength);
            _header = new Header(LogBufferDescriptor.InitialTermId(logBuffers.MetaDataBuffer()), _positionBitsToShift);
        }
Пример #4
0
        public long Offer(
            UnsafeBuffer buffer,
            int offset,
            int length,
            ReservedValueSupplier reservedValueSupplier = null)
        {
            var newPosition = CLOSED;

            if (!_isClosed)
            {
                var limit          = _positionLimit.Volatile;
                var partitionIndex = LogBufferDescriptor.ActivePartitionIndex(_logMetaDataBuffer);
                var termAppender   = _termAppenders[partitionIndex];
                var rawTail        = termAppender.RawTailVolatile();
                var termOffset     = rawTail & 0xFFFFFFFFL;
                var position       = LogBufferDescriptor.ComputeTermBeginPosition(LogBufferDescriptor.TermId(rawTail), _positionBitsToShift, InitialTermId) + termOffset;

                if (position < limit)
                {
                    long result;
                    if (length <= MaxPayloadLength)
                    {
                        result = termAppender.AppendUnfragmentedMessage(_headerWriter, buffer, offset, length, reservedValueSupplier);
                    }
                    else
                    {
                        CheckForMaxMessageLength(length);
                        result = termAppender.AppendFragmentedMessage(_headerWriter, buffer, offset, length, MaxPayloadLength, reservedValueSupplier);
                    }

                    newPosition = NewPosition(partitionIndex, (int)termOffset, position, result);
                }
                else if (_conductor.IsPublicationConnected(LogBufferDescriptor.TimeOfLastStatusMessage(_logMetaDataBuffer)))
                {
                    newPosition = BACK_PRESSURED;
                }
                else
                {
                    newPosition = NOT_CONNECTED;
                }
            }

            return(newPosition);
        }
Пример #5
0
        public void ShouldAppendFragmentedFromVectorsWithNonZeroOffsetToEmptyLog()
        {
            var mtu                  = 2048;
            var headerLength         = _defaultHeader.Capacity;
            var maxPayloadLength     = mtu - headerLength;
            var bufferOneLength      = 64;
            var offset               = 15;
            var bufferTwoTotalLength = 3000;
            var bufferTwoLength      = bufferTwoTotalLength - offset;
            var bufferOne            = new UnsafeBuffer(new byte[bufferOneLength]);
            var bufferTwo            = new UnsafeBuffer(new byte[bufferTwoTotalLength]);

            bufferOne.SetMemory(0, bufferOne.Capacity, (byte)'1');
            bufferTwo.SetMemory(0, bufferTwo.Capacity, (byte)'2');
            var msgLength       = bufferOneLength + bufferTwoLength;
            var tail            = 0;
            var frameOneLength  = mtu;
            var frameTwoLength  = (msgLength - (mtu - headerLength)) + headerLength;
            var resultingOffset = frameOneLength + BitUtil.Align(frameTwoLength, FrameDescriptor.FRAME_ALIGNMENT);

            _logMetaDataBuffer.PutLong(TermTailCounterOffset, LogBufferDescriptor.PackTail(TermID, tail));

            var vectors = new[]
            {
                new DirectBufferVector(bufferOne, 0, bufferOneLength),
                new DirectBufferVector(bufferTwo, offset, bufferTwoLength)
            };

            Assert.That(_termAppender.AppendFragmentedMessage(_headerWriter, vectors, msgLength, maxPayloadLength, RVS, TermID), Is.EqualTo(resultingOffset));

            var tail2                    = tail + frameOneLength;
            var bufferTwoOffset          = maxPayloadLength - bufferOneLength + offset;
            var fragmentTwoPayloadLength = bufferTwoLength - (maxPayloadLength - bufferOneLength);

            A.CallTo(() => _headerWriter.Write(_termBuffer, tail, frameOneLength, TermID)).MustHaveHappened()
            .Then(A.CallTo(() => _termBuffer.PutBytes(headerLength, bufferOne, 0, bufferOneLength)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutBytes(headerLength + bufferOneLength, bufferTwo, offset, maxPayloadLength - bufferOneLength)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutLong(tail + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, RV, ByteOrder.LittleEndian)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutIntOrdered(tail, frameOneLength)).MustHaveHappened())
            .Then(A.CallTo(() => _headerWriter.Write(_termBuffer, tail2, frameTwoLength, TermID)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutBytes(tail2 + headerLength, bufferTwo, bufferTwoOffset, fragmentTwoPayloadLength)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutLong(tail2 + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, RV, ByteOrder.LittleEndian)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutIntOrdered(tail2, frameTwoLength)).MustHaveHappened());
        }
Пример #6
0
        internal ExclusivePublication(
            ClientConductor clientConductor,
            string channel,
            int streamId,
            int sessionId,
            IReadablePosition positionLimit,
            int channelStatusId,
            LogBuffers logBuffers,
            long originalRegistrationId,
            long registrationId)
            : base(
                clientConductor,
                channel,
                streamId,
                sessionId,
                positionLimit,
                channelStatusId,
                logBuffers,
                originalRegistrationId,
                registrationId,
                FrameDescriptor.ComputeExclusiveMaxMessageLength(logBuffers.TermLength())
                )
        {
            var buffers           = logBuffers.DuplicateTermBuffers();
            var logMetaDataBuffer = logBuffers.MetaDataBuffer();

            for (var i = 0; i < LogBufferDescriptor.PARTITION_COUNT; i++)
            {
                _termAppenders[i] = new ExclusiveTermAppender(buffers[i], logMetaDataBuffer, i);
            }

            var termCount = LogBufferDescriptor.ActiveTermCount(logMetaDataBuffer);
            var index     = LogBufferDescriptor.IndexByTermCount(termCount);

            _activePartitionIndex = index;

            var rawTail = LogBufferDescriptor.RawTail(_logMetaDataBuffer, index);

            _termId            = LogBufferDescriptor.TermId(rawTail);
            _termOffset        = LogBufferDescriptor.TermOffset(rawTail);
            _termBeginPosition =
                LogBufferDescriptor.ComputeTermBeginPosition(_termId, _positionBitsToShift, InitialTermId);
        }
Пример #7
0
        private long NewPosition(int index, int currentTail, long position, long result)
        {
            var newPosition = ADMIN_ACTION;
            var termOffset  = TermAppender.TermOffset(result);

            if (termOffset > 0)
            {
                newPosition = (position - currentTail) + termOffset;
            }
            else if (termOffset == TermAppender.TRIPPED)
            {
                var nextIndex = LogBufferDescriptor.NextPartitionIndex(index);

                _termAppenders[nextIndex].TailTermId(TermAppender.TermId(result) + 1);
                LogBufferDescriptor.ActivePartitionIndexOrdered(_logMetaDataBuffer, nextIndex);
            }

            return(newPosition);
        }
Пример #8
0
        public void ShouldPadLogWhenAppendingWithInsufficientRemainingCapacity()
        {
            const int    msgLength         = 120;
            int          headerLength      = _defaultHeader.Capacity;
            int          requiredFrameSize = BitUtil.Align(headerLength + msgLength, FrameDescriptor.FRAME_ALIGNMENT);
            int          tailValue         = TermBufferLength - BitUtil.Align(msgLength, FrameDescriptor.FRAME_ALIGNMENT);
            UnsafeBuffer buffer            = new UnsafeBuffer(new byte[128]);
            int          frameLength       = TermBufferLength - tailValue;

            _logMetaDataBuffer.PutLong(TermTailCounterOffset, LogBufferDescriptor.PackTail(TermID, tailValue));

            Assert.That(_termAppender.AppendUnfragmentedMessage(_headerWriter, buffer, 0, msgLength, RVS, TermID), Is.EqualTo(TermAppender.FAILED));

            Assert.AreEqual(LogBufferDescriptor.RawTailVolatile(_logMetaDataBuffer, PartionIndex), LogBufferDescriptor.PackTail(TermID, tailValue + requiredFrameSize));

            A.CallTo(() => _headerWriter.Write(_termBuffer, tailValue, frameLength, TermID)).MustHaveHappened()
            .Then(A.CallTo(() => _termBuffer.PutShort(FrameDescriptor.TypeOffset(tailValue), FrameDescriptor.PADDING_FRAME_TYPE)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutIntOrdered(tailValue, frameLength)).MustHaveHappened());
        }
        /// <inheritdoc />
        public override long Offer(DirectBufferVector[] vectors, ReservedValueSupplier reservedValueSupplier = null)
        {
            int  length      = DirectBufferVector.ValidateAndComputeLength(vectors);
            long newPosition = CLOSED;

            if (!_isClosed)
            {
                long         limit        = _positionLimit.GetVolatile();
                int          termCount    = LogBufferDescriptor.ActiveTermCount(_logMetaDataBuffer);
                TermAppender termAppender = _termAppenders[LogBufferDescriptor.IndexByTermCount(termCount)];
                long         rawTail      = termAppender.RawTailVolatile();
                long         termOffset   = rawTail & 0xFFFF_FFFFL;
                int          termId       = LogBufferDescriptor.TermId(rawTail);
                long         position     = LogBufferDescriptor.ComputeTermBeginPosition(termId, PositionBitsToShift, InitialTermId) + termOffset;

                if (termCount != (termId - InitialTermId))
                {
                    return(ADMIN_ACTION);
                }

                if (position < limit)
                {
                    int resultingOffset;
                    if (length <= MaxPayloadLength)
                    {
                        resultingOffset = termAppender.AppendUnfragmentedMessage(_headerWriter, vectors, length, reservedValueSupplier, termId);
                    }
                    else
                    {
                        CheckMaxMessageLength(length);
                        resultingOffset = termAppender.AppendFragmentedMessage(_headerWriter, vectors, length, MaxPayloadLength, reservedValueSupplier, termId);
                    }

                    newPosition = NewPosition(termCount, (int)termOffset, termId, position, resultingOffset);
                }
                else
                {
                    newPosition = BackPressureStatus(position, length);
                }
            }

            return(newPosition);
        }
Пример #10
0
        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(messages, 1);

            A.CallTo(() => MockFragmentHandler(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()
                );
        }
Пример #11
0
        public void SetUp()
        {
            _sendBuffer        = new byte[SendBufferCapacity];
            _atomicSendBuffer  = new UnsafeBuffer(_sendBuffer);
            _logMetaDataBuffer = new UnsafeBuffer(new byte[LogBufferDescriptor.LOG_META_DATA_LENGTH]);
            _termBuffers       = new UnsafeBuffer[LogBufferDescriptor.PARTITION_COUNT];

            _conductor        = A.Fake <ClientConductor>();
            _logBuffers       = A.Fake <LogBuffers>();
            _publicationLimit = A.Fake <IReadablePosition>();

            A.CallTo(() => _publicationLimit.GetVolatile()).Returns(2 * SendBufferCapacity);
            A.CallTo(() => _logBuffers.DuplicateTermBuffers()).Returns(_termBuffers);
            A.CallTo(() => _logBuffers.TermLength()).Returns(LogBufferDescriptor.TERM_MIN_LENGTH);
            A.CallTo(() => _logBuffers.MetaDataBuffer()).Returns(_logMetaDataBuffer);

            LogBufferDescriptor.InitialTermId(_logMetaDataBuffer, TermID1);
            LogBufferDescriptor.MtuLength(_logMetaDataBuffer, MTU_LENGTH);
            LogBufferDescriptor.TermLength(_logMetaDataBuffer, LogBufferDescriptor.TERM_MIN_LENGTH);
            LogBufferDescriptor.PageSize(_logMetaDataBuffer, PAGE_SIZE);
            LogBufferDescriptor.IsConnected(_logMetaDataBuffer, false);

            for (var i = 0; i < LogBufferDescriptor.PARTITION_COUNT; i++)
            {
                _termBuffers[i] = new UnsafeBuffer(new byte[LogBufferDescriptor.TERM_MIN_LENGTH]);
            }

            _publication = new ConcurrentPublication(
                _conductor,
                Channel,
                StreamID1,
                SessionID1,
                _publicationLimit,
                ChannelEndpointStatus.NO_ID_ALLOCATED,
                _logBuffers,
                CorrelationID,
                CorrelationID);

            LogBufferDescriptor.InitialiseTailWithTermId(_logMetaDataBuffer, PartionIndex, TermID1);

            A.CallTo(() => _conductor.ReleasePublication(_publication)).Invokes(() => _publication.InternalClose());
        }
Пример #12
0
        public void ShouldPollFragmentsToBoundedControlledFragmentHandlerWithInitialOffsetNotZero()
        {
            var initialPosition = LogBufferDescriptor.ComputePosition(INITIAL_TERM_ID, OffsetForFrame(1), POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID);
            var maxPosition     = initialPosition + ALIGNED_FRAME_LENGTH;

            Position.SetOrdered(initialPosition);
            var image = CreateImage();

            InsertDataFrame(INITIAL_TERM_ID, OffsetForFrame(1));
            InsertDataFrame(INITIAL_TERM_ID, OffsetForFrame(2));

            A.CallTo(() => MockControlledFragmentHandler.OnFragment(A <UnsafeBuffer> ._, A <int> ._, A <int> ._, A <Header> ._)).Returns(ControlledFragmentHandlerAction.CONTINUE);

            var fragmentsRead = image.BoundedControlledPoll(MockControlledFragmentHandler, maxPosition, int.MaxValue);

            Assert.That(fragmentsRead, Is.EqualTo(1));
            Assert.That(Position.Get(), Is.EqualTo(maxPosition));

            A.CallTo(() => MockControlledFragmentHandler.OnFragment(A <UnsafeBuffer> ._, A <int> ._, A <int> ._, A <Header> ._)).MustHaveHappened();
        }
Пример #13
0
        /// <summary>
        /// Construct a new image over a log to represent a stream of messages from a <seealso cref="Publication"/>.
        /// </summary>
        /// <param name="subscription">       to which this <seealso cref="Image"/> belongs. </param>
        /// <param name="sessionId">          of the stream of messages. </param>
        /// <param name="subscriberPosition"> for indicating the position of the subscriber in the stream. </param>
        /// <param name="logBuffers">         containing the stream of messages. </param>
        /// <param name="errorHandler">       to be called if an error occurs when polling for messages. </param>
        /// <param name="sourceIdentity">     of the source sending the stream of messages. </param>
        /// <param name="correlationId">      of the request to the media driver. </param>
        public Image(Subscription subscription, int sessionId, IPosition subscriberPosition, LogBuffers logBuffers, ErrorHandler errorHandler, string sourceIdentity, long correlationId)
        {
            Subscription        = subscription;
            SessionId           = sessionId;
            _subscriberPosition = subscriberPosition;
            _logBuffers         = logBuffers;
            _errorHandler       = errorHandler;
            SourceIdentity      = sourceIdentity;
            CorrelationId       = correlationId;
            _joinPosition       = subscriberPosition.Get();

            _termBuffers = logBuffers.DuplicateTermBuffers();

            var termLength = logBuffers.TermLength();

            _termLengthMask      = termLength - 1;
            _positionBitsToShift = LogBufferDescriptor.PositionBitsToShift(termLength);
            _initialTermId       = LogBufferDescriptor.InitialTermId(logBuffers.MetaDataBuffer());
            _header = new Header(LogBufferDescriptor.InitialTermId(logBuffers.MetaDataBuffer()), _positionBitsToShift, this);
        }
Пример #14
0
        public void ShouldAppendFrameToEmptyLog()
        {
            int          headerLength       = _defaultHeader.Capacity;
            UnsafeBuffer buffer             = new UnsafeBuffer(new byte[128]);
            const int    msgLength          = 20;
            int          frameLength        = msgLength + headerLength;
            int          alignedFrameLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
            const int    tail = 0;

            _logMetaDataBuffer.PutLong(TermTailCounterOffset, LogBufferDescriptor.PackTail(TermID, tail));

            Assert.That(_termAppender.AppendUnfragmentedMessage(_headerWriter, buffer, 0, msgLength, RVS), Is.EqualTo((long)alignedFrameLength));

            Assert.AreEqual(LogBufferDescriptor.RawTailVolatile(_logMetaDataBuffer, PartionIndex), LogBufferDescriptor.PackTail(TermID, tail + alignedFrameLength));

            A.CallTo(() => _headerWriter.Write(_termBuffer, tail, frameLength, TermID)).MustHaveHappened()
            .Then(A.CallTo(() => _termBuffer.PutBytes(headerLength, buffer, 0, msgLength)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutLong(tail + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, RV)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutIntOrdered(tail, frameLength)).MustHaveHappened());
        }
Пример #15
0
        /// <summary>
        /// Construct a new image over a log to represent a stream of messages from a <seealso cref="Publication"/>.
        /// </summary>
        /// <param name="subscription">       to which this <seealso cref="Image"/> belongs. </param>
        /// <param name="sessionId">          of the stream of messages. </param>
        /// <param name="subscriberPosition"> for indicating the position of the subscriber in the stream. </param>
        /// <param name="logBuffers">         containing the stream of messages. </param>
        /// <param name="errorHandler">       to be called if an error occurs when polling for messages. </param>
        /// <param name="sourceIdentity">     of the source sending the stream of messages. </param>
        /// <param name="correlationId">      of the request to the media driver. </param>
        public Image(Subscription subscription, int sessionId, IPosition subscriberPosition, LogBuffers logBuffers, ErrorHandler errorHandler, string sourceIdentity, long correlationId)
        {
            Subscription        = subscription;
            SessionId           = sessionId;
            _subscriberPosition = subscriberPosition;
            _logBuffers         = logBuffers;
            _errorHandler       = errorHandler;
            SourceIdentity      = sourceIdentity;
            CorrelationId       = correlationId;

            var buffers = logBuffers.AtomicBuffers();

            Array.Copy(buffers, 0, _termBuffers, 0, LogBufferDescriptor.PARTITION_COUNT);

            var termLength = logBuffers.TermLength();

            _termLengthMask      = termLength - 1;
            _positionBitsToShift = IntUtil.NumberOfTrailingZeros(termLength);
            _header = new Header(LogBufferDescriptor.InitialTermId(buffers[LogBufferDescriptor.LOG_META_DATA_SECTION_INDEX]), _positionBitsToShift);
        }
Пример #16
0
        public void ShouldPollNoFragmentsToBoundedControlledFragmentHandlerWithMaxPositionBeforeInitialPosition()
        {
            var initialPosition = LogBufferDescriptor.ComputePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID);
            var maxPosition     = initialPosition - DataHeaderFlyweight.HEADER_LENGTH;

            Position.SetOrdered(initialPosition);
            var image = CreateImage();

            InsertDataFrame(INITIAL_TERM_ID, OffsetForFrame(0));
            InsertDataFrame(INITIAL_TERM_ID, OffsetForFrame(1));

            A.CallTo(() => MockControlledFragmentHandler.OnFragment(A <UnsafeBuffer> ._, A <int> ._, A <int> ._, A <Header> ._)).Returns(ControlledFragmentHandlerAction.CONTINUE);

            var fragmentsRead = image.BoundedControlledPoll(MockControlledFragmentHandler, maxPosition, int.MaxValue);

            Assert.That(fragmentsRead, Is.EqualTo(0));
            Assert.That(Position.Get(), Is.EqualTo(initialPosition));

            A.CallTo(() => MockControlledFragmentHandler.OnFragment(A <UnsafeBuffer> ._, DataHeaderFlyweight.HEADER_LENGTH, DATA.Length, A <Header> ._)).MustNotHaveHappened();
        }
Пример #17
0
        public LogBuffers(string logFileName, int termLength = LogBufferDescriptor.TERM_MIN_LENGTH)
        {
            try {
                long logLength = LogBufferDescriptor.PARTITION_COUNT *
                                 (LogBufferDescriptor.TERM_META_DATA_LENGTH + termLength) +
                                 LogBufferDescriptor.LOG_META_DATA_LENGTH;
                termLength = LogBufferDescriptor.ComputeTermLength(logLength);
                LogBufferDescriptor.CheckTermLength(termLength);
                _df         = new DirectFile(logFileName, logLength);
                _termLength = termLength;

                // if log length exceeds MAX_INT we need multiple mapped buffers, (see FileChannel.map doc).
                if (logLength < int.MaxValue)
                {
                    int metaDataSectionOffset = termLength * LogBufferDescriptor.PARTITION_COUNT;

                    for (int i = 0; i < LogBufferDescriptor.PARTITION_COUNT; i++)
                    {
                        int metaDataOffset = metaDataSectionOffset + (i * LogBufferDescriptor.TERM_META_DATA_LENGTH);

                        _buffers[i] = new DirectBuffer(termLength, _df.Buffer.Data + i * termLength);
                        _buffers[i + LogBufferDescriptor.PARTITION_COUNT] = new DirectBuffer(LogBufferDescriptor.TERM_META_DATA_LENGTH, _df.Buffer.Data + metaDataOffset);
                        _partitions[i] = new LogBufferPartition(_buffers[i], _buffers[i + LogBufferDescriptor.PARTITION_COUNT]);
                    }

                    _buffers[_buffers.Length - 1] = new DirectBuffer(LogBufferDescriptor.LOG_META_DATA_LENGTH,
                                                                     _df.Buffer.Data + (int)(logLength - LogBufferDescriptor.LOG_META_DATA_LENGTH));
                }
                else
                {
                    throw new NotImplementedException("TODO Check .NET mapping limit");
                }
            } catch (IOException ex) {
                throw new AggregateException(ex);
            }

            foreach (var buffer in _buffers)
            {
                buffer.VerifyAlignment(8);
            }
        }
Пример #18
0
        public long Offer(
            UnsafeBuffer buffer,
            int offset,
            int length,
            ReservedValueSupplier reservedValueSupplier = null)
        {
            var newPosition = CLOSED;

            if (!_isClosed)
            {
                var limit = _positionLimit.Volatile;
                ExclusiveTermAppender termAppender = _termAppenders[_activePartitionIndex];
                long position = _termBeginPosition + this._termOffset;

                if (position < limit)
                {
                    int result;
                    if (length <= MaxPayloadLength)
                    {
                        result = termAppender.AppendUnfragmentedMessage(_termId, _termOffset, _headerWriter, buffer, offset, length, reservedValueSupplier);
                    }
                    else
                    {
                        CheckForMaxMessageLength(length);
                        result = termAppender.AppendFragmentedMessage(_termId, _termOffset, _headerWriter, buffer, offset, length, MaxPayloadLength, reservedValueSupplier);
                    }

                    newPosition = NewPosition(result);
                }
                else if (_conductor.IsPublicationConnected(LogBufferDescriptor.TimeOfLastStatusMessage(_logMetaDataBuffer)))
                {
                    newPosition = BACK_PRESSURED;
                }
                else
                {
                    newPosition = NOT_CONNECTED;
                }
            }

            return(newPosition);
        }
Пример #19
0
        public void ShouldPollFragmentsToBoundedControlledFragmentHandlerWithMaxPositionAfterEndOfTerm()
        {
            var initialOffset   = TERM_BUFFER_LENGTH - (ALIGNED_FRAME_LENGTH * 2);
            var initialPosition = LogBufferDescriptor.ComputePosition(INITIAL_TERM_ID, initialOffset, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID);
            var maxPosition     = initialPosition + TERM_BUFFER_LENGTH;

            Position.SetOrdered(initialPosition);
            var image = CreateImage();

            InsertDataFrame(INITIAL_TERM_ID, initialOffset);
            InsertPaddingFrame(INITIAL_TERM_ID, initialOffset + ALIGNED_FRAME_LENGTH);

            A.CallTo(() => MockControlledFragmentHandler.OnFragment(A <UnsafeBuffer> ._, A <int> ._, A <int> ._, A <Header> ._)).Returns(ControlledFragmentHandlerAction.CONTINUE);

            var fragmentsRead = image.BoundedControlledPoll(MockControlledFragmentHandler, maxPosition, int.MaxValue);

            Assert.That(fragmentsRead, Is.EqualTo(1));

            A.CallTo(() => MockControlledFragmentHandler.OnFragment(A <UnsafeBuffer> ._, initialOffset + DataHeaderFlyweight.HEADER_LENGTH, DATA.Length, A <Header> ._)).MustHaveHappened()
            .Then(A.CallTo(() => Position.SetOrdered(TERM_BUFFER_LENGTH)).MustHaveHappened());
        }
Пример #20
0
        public void ShouldPollFragmentsToBoundedFragmentHandlerWithMaxPositionBeforeNextMessage()
        {
            var initialPosition =
                LogBufferDescriptor.ComputePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID);
            var maxPosition = initialPosition + ALIGNED_FRAME_LENGTH;

            Position.SetOrdered(initialPosition);
            var image = CreateImage();

            InsertDataFrame(INITIAL_TERM_ID, OffsetForFrame(0));
            InsertDataFrame(INITIAL_TERM_ID, OffsetForFrame(1));

            var fragmentsRead =
                image.BoundedPoll(MockFragmentHandler, maxPosition, int.MaxValue);

            Assert.That(fragmentsRead, Is.EqualTo(1));

            A.CallTo(() => MockFragmentHandler.OnFragment(A <UnsafeBuffer> ._,
                                                          DataHeaderFlyweight.HEADER_LENGTH, DATA.Length, A <Header> ._)).MustHaveHappened()
            .Then(A.CallTo(() => Position.SetOrdered(initialPosition + ALIGNED_FRAME_LENGTH)).MustHaveHappened());
        }
Пример #21
0
        internal ExclusivePublication(
            ClientConductor clientConductor,
            string channel,
            int streamId,
            int sessionId,
            IReadablePosition positionLimit,
            LogBuffers logBuffers,
            long registrationId)
        {
            var buffers           = logBuffers.TermBuffers();
            var logMetaDataBuffer = logBuffers.MetaDataBuffer();

            for (var i = 0; i < LogBufferDescriptor.PARTITION_COUNT; i++)
            {
                _termAppenders[i] = new ExclusiveTermAppender(buffers[i], logMetaDataBuffer, i);
            }

            var termLength = logBuffers.TermLength();

            MaxPayloadLength           = LogBufferDescriptor.MtuLength(logMetaDataBuffer) - DataHeaderFlyweight.HEADER_LENGTH;
            MaxMessageLength           = FrameDescriptor.ComputeExclusiveMaxMessageLength(termLength);
            _conductor                 = clientConductor;
            Channel                    = channel;
            StreamId                   = streamId;
            SessionId                  = sessionId;
            InitialTermId              = LogBufferDescriptor.InitialTermId(logMetaDataBuffer);
            _logMetaDataBuffer         = logMetaDataBuffer;
            RegistrationId             = registrationId;
            _positionLimit             = positionLimit;
            _logBuffers                = logBuffers;
            _positionBitsToShift       = IntUtil.NumberOfTrailingZeros(termLength);
            _headerWriter              = new HeaderWriter(LogBufferDescriptor.DefaultFrameHeader(logMetaDataBuffer));
            this._activePartitionIndex = LogBufferDescriptor.ActivePartitionIndex(logMetaDataBuffer);

            long rawTail = _termAppenders[_activePartitionIndex].RawTail();

            _termId            = LogBufferDescriptor.TermId(rawTail);
            _termOffset        = LogBufferDescriptor.TermOffset(rawTail, termLength);
            _termBeginPosition = LogBufferDescriptor.ComputeTermBeginPosition(_termId, _positionBitsToShift, InitialTermId);
        }
Пример #22
0
        public void SetUp()
        {
            _sendBuffer        = new byte[SendBufferCapacity];
            _atomicSendBuffer  = new UnsafeBuffer(_sendBuffer);
            _logMetaDataBuffer = new UnsafeBuffer(new byte[LogBufferDescriptor.LOG_META_DATA_LENGTH]);
            _termBuffers       = new UnsafeBuffer[LogBufferDescriptor.PARTITION_COUNT];

            _conductor        = A.Fake <ClientConductor>();
            _logBuffers       = A.Fake <LogBuffers>();
            _publicationLimit = A.Fake <IReadablePosition>();

            A.CallTo(() => _publicationLimit.Volatile).Returns(2 * SendBufferCapacity);
            A.CallTo(() => _logBuffers.TermBuffers()).Returns(_termBuffers);
            A.CallTo(() => _logBuffers.TermLength()).Returns(LogBufferDescriptor.TERM_MIN_LENGTH);
            A.CallTo(() => _logBuffers.MetaDataBuffer()).Returns(_logMetaDataBuffer);

            LogBufferDescriptor.InitialTermId(_logMetaDataBuffer, TermID1);
            LogBufferDescriptor.MtuLength(_logMetaDataBuffer, MTU_LENGTH);
            LogBufferDescriptor.TimeOfLastStatusMessage(_logMetaDataBuffer, 0);

            for (var i = 0; i < LogBufferDescriptor.PARTITION_COUNT; i++)
            {
                _termBuffers[i] = new UnsafeBuffer(new byte[LogBufferDescriptor.TERM_MIN_LENGTH]);
            }

            _publication = new Publication(
                _conductor,
                Channel,
                StreamID1,
                SessionID1,
                _publicationLimit,
                _logBuffers,
                CorrelationID,
                CorrelationID);

            _publication.IncRef();

            LogBufferDescriptor.InitialiseTailWithTermId(_logMetaDataBuffer, PartionIndex, TermID1);
        }
Пример #23
0
        public void ShouldReportCorrectPositionOnReceptionWithNonZeroPositionInNonInitialTermId()
        {
            var       activeTermId        = INITIAL_TERM_ID + 1;
            const int initialMessageIndex = 5;
            var       initialTermOffset   = OffsetForFrame(initialMessageIndex);
            var       initialPosition     = LogBufferDescriptor.ComputePosition(activeTermId, initialTermOffset, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID);

            Position.SetOrdered(initialPosition);
            var image = CreateImage();

            InsertDataFrame(activeTermId, OffsetForFrame(initialMessageIndex));

            var messages = image.Poll(MockFragmentHandler, int.MaxValue);

            Assert.AreEqual(1, messages);

            A.CallTo(() => MockFragmentHandler(A <UnsafeBuffer> ._, initialTermOffset + DataHeaderFlyweight.HEADER_LENGTH, DATA.Length, A <Header> ._)).MustHaveHappened();

            A.CallTo(() => Position.SetOrdered(initialPosition)).MustHaveHappened().Then(
                A.CallTo(() => Position.SetOrdered(initialPosition + ALIGNED_FRAME_LENGTH)).MustHaveHappened()
                );
        }
Пример #24
0
            /// <summary>
            /// Try to gap fill the current term at a given offset if the gap contains no data.
            ///
            /// Note: the gap offset plus gap length must end on a <seealso cref="FrameDescriptor.FRAME_ALIGNMENT"/> boundary.
            /// </summary>
            /// <param name="logMetaDataBuffer"> containing the default headers </param>
            /// <param name="termBuffer">        to gap fill </param>
            /// <param name="termId">            for the current term. </param>
            /// <param name="gapOffset">         to fill from </param>
            /// <param name="gapLength">         to length of the gap. </param>
            /// <returns> true if the gap has been filled with a padding record or false if data found. </returns>
            public static bool TryFillGap(UnsafeBuffer logMetaDataBuffer, UnsafeBuffer termBuffer, int termId, int gapOffset, int gapLength)
            {
                int offset = gapOffset + gapLength - FrameDescriptor.FRAME_ALIGNMENT;

                while (offset >= gapOffset)
                {
                    if (0 != termBuffer.GetInt(offset))
                    {
                        return(false);
                    }

                    offset -= FrameDescriptor.FRAME_ALIGNMENT;
                }

                LogBufferDescriptor.ApplyDefaultHeader(logMetaDataBuffer, termBuffer, gapOffset);
                FrameDescriptor.FrameType(termBuffer, gapOffset, HeaderFlyweight.HDR_TYPE_PAD);
                FrameDescriptor.FrameTermOffset(termBuffer, gapOffset);
                FrameDescriptor.FrameTermId(termBuffer, gapOffset, termId);
                FrameDescriptor.FrameLengthOrdered(termBuffer, gapOffset, gapLength);

                return(true);
            }
Пример #25
0
        private long NewPosition(int index, int currentTail, long position, long result)
        {
            var newPosition = ADMIN_ACTION;
            var termOffset  = LogBufferDescriptor.TermOffset(result);

            if (termOffset > 0)
            {
                newPosition = (position - currentTail) + termOffset;
            }
            else if ((position + currentTail) > _maxPossiblePosition)
            {
                newPosition = MAX_POSITION_EXCEEDED;
            }
            else if (termOffset == TermAppender.TRIPPED)
            {
                var nextIndex = LogBufferDescriptor.NextPartitionIndex(index);

                LogBufferDescriptor.InitialiseTailWithTermId(_logMetaDataBuffer, nextIndex, LogBufferDescriptor.TermId(result) + 1);
                LogBufferDescriptor.ActivePartitionIndexOrdered(_logMetaDataBuffer, nextIndex);
            }

            return(newPosition);
        }
Пример #26
0
        public void ShouldClaimRegionForZeroCopyEncoding()
        {
            int         headerLength       = _defaultHeader.Capacity;
            const int   msgLength          = 20;
            int         frameLength        = msgLength + headerLength;
            int         alignedFrameLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
            const int   tail        = 0;
            BufferClaim bufferClaim = new BufferClaim();

            _logMetaDataBuffer.PutLong(TermTailCounterOffset, LogBufferDescriptor.PackTail(TermID, tail));

            Assert.That(_termAppender.Claim(_headerWriter, msgLength, bufferClaim, TermID), Is.EqualTo((long)alignedFrameLength));

            Assert.That(bufferClaim.Offset, Is.EqualTo(tail + headerLength));
            Assert.That(bufferClaim.Length, Is.EqualTo(msgLength));

            // Map flyweight or encode to buffer directly then call commit() when done
            bufferClaim.Commit();

            Assert.AreEqual(LogBufferDescriptor.RawTailVolatile(_logMetaDataBuffer, PartionIndex), LogBufferDescriptor.PackTail(TermID, tail + alignedFrameLength));

            A.CallTo(() => _headerWriter.Write(_termBuffer, tail, frameLength, TermID)).MustHaveHappened();
        }
Пример #27
0
        private long NewPosition(int resultingOffset)
        {
            if (resultingOffset > 0)
            {
                _termOffset = resultingOffset;

                return(_termBeginPosition + resultingOffset);
            }
            else
            {
                int nextIndex  = LogBufferDescriptor.NextPartitionIndex(_activePartitionIndex);
                int nextTermId = _termId + 1;

                _activePartitionIndex = nextIndex;
                _termOffset           = 0;
                _termId            = nextTermId;
                _termBeginPosition = LogBufferDescriptor.ComputeTermBeginPosition(nextTermId, _positionBitsToShift, InitialTermId);

                _termAppenders[nextIndex].TailTermId(nextTermId);
                LogBufferDescriptor.ActivePartitionIndexOrdered(_logMetaDataBuffer, nextIndex);

                return(ADMIN_ACTION);
            }
        }
Пример #28
0
        internal Publication(
            ClientConductor clientConductor,
            string channel,
            int streamId,
            int sessionId,
            IReadablePosition positionLimit,
            LogBuffers logBuffers,
            long originalRegistrationId,
            long registrationId)
        {
            var buffers           = logBuffers.TermBuffers();
            var logMetaDataBuffer = logBuffers.MetaDataBuffer();

            for (var i = 0; i < LogBufferDescriptor.PARTITION_COUNT; i++)
            {
                _termAppenders[i] = new TermAppender(buffers[i], logMetaDataBuffer, i);
            }

            var termLength = logBuffers.TermLength();

            MaxPayloadLength     = LogBufferDescriptor.MtuLength(logMetaDataBuffer) - DataHeaderFlyweight.HEADER_LENGTH;
            MaxMessageLength     = FrameDescriptor.ComputeMaxMessageLength(termLength);
            _maxPossiblePosition = termLength * (1L << 31);
            _conductor           = clientConductor;
            Channel                 = channel;
            StreamId                = streamId;
            SessionId               = sessionId;
            InitialTermId           = LogBufferDescriptor.InitialTermId(logMetaDataBuffer);
            _logMetaDataBuffer      = logMetaDataBuffer;
            _originalRegistrationId = originalRegistrationId;
            RegistrationId          = registrationId;
            _positionLimit          = positionLimit;
            _logBuffers             = logBuffers;
            _positionBitsToShift    = IntUtil.NumberOfTrailingZeros(termLength);
            _headerWriter           = new HeaderWriter(LogBufferDescriptor.DefaultFrameHeader(logMetaDataBuffer));
        }
Пример #29
0
        public void ShouldUpdatePositionToEndOfCommittedFragmentOnCommit()
        {
            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));
            InsertDataFrame(INITIAL_TERM_ID, OffsetForFrame(1));
            InsertDataFrame(INITIAL_TERM_ID, OffsetForFrame(2));

            A.CallTo(() => MockControlledFragmentHandler.Invoke(A <UnsafeBuffer> ._, A <int> ._, A <int> ._, A <Header> ._))
            .ReturnsNextFromSequence(ControlledFragmentHandlerAction.CONTINUE, ControlledFragmentHandlerAction.COMMIT, ControlledFragmentHandlerAction.CONTINUE);

            var fragmentsRead = image.ControlledPoll(MockControlledFragmentHandler, int.MaxValue);

            Assert.AreEqual(3, fragmentsRead);

            A.CallTo(() => MockControlledFragmentHandler.Invoke(A <UnsafeBuffer> ._, DataHeaderFlyweight.HEADER_LENGTH, DATA.Length, A <Header> ._)).MustHaveHappened()
            .Then(A.CallTo(() => MockControlledFragmentHandler.Invoke(A <UnsafeBuffer> ._, ALIGNED_FRAME_LENGTH + DataHeaderFlyweight.HEADER_LENGTH, DATA.Length, A <Header> ._)).MustHaveHappened())
            .Then(A.CallTo(() => Position.SetOrdered(initialPosition + ALIGNED_FRAME_LENGTH * 2)).MustHaveHappened())
            .Then(A.CallTo(() => MockControlledFragmentHandler.Invoke(A <UnsafeBuffer> ._, 2 * ALIGNED_FRAME_LENGTH + DataHeaderFlyweight.HEADER_LENGTH, DATA.Length, A <Header> ._)).MustHaveHappened())
            .Then(A.CallTo(() => Position.SetOrdered(initialPosition + ALIGNED_FRAME_LENGTH * 3)).MustHaveHappened());
        }
Пример #30
0
 internal void Close()
 {
     _finalPosition = _subscriberPosition.GetVolatile();
     _isEos         = _finalPosition >= LogBufferDescriptor.EndOfStreamPosition(_logBuffers.MetaDataBuffer());
     _isClosed      = true;
 }