/// <inheritdoc />
        public override long TryClaim(int length, BufferClaim bufferClaim)
        {
            CheckPayloadLength(length);
            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 = termAppender.Claim(_headerWriter, length, bufferClaim, termId);
                    newPosition = NewPosition(termCount, (int)termOffset, termId, position, resultingOffset);
                }
                else
                {
                    newPosition = BackPressureStatus(position, length);
                }
            }

            return(newPosition);
        }
Пример #2
0
        private long NewPosition(int resultingOffset)
        {
            if (resultingOffset > 0)
            {
                _termOffset = resultingOffset;

                return(_termBeginPosition + resultingOffset);
            }

            if ((_termBeginPosition + TermBufferLength) >= MaxPossiblePosition)
            {
                return(MAX_POSITION_EXCEEDED);
            }

            int nextIndex  = LogBufferDescriptor.NextPartitionIndex(_activePartitionIndex);
            int nextTermId = _termId + 1;

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

            var termCount = nextTermId - InitialTermId;

            LogBufferDescriptor.InitialiseTailWithTermId(_logMetaDataBuffer, nextIndex, nextTermId);
            LogBufferDescriptor.ActiveTermCountOrdered(_logMetaDataBuffer, termCount);

            return(ADMIN_ACTION);
        }
Пример #3
0
        /// <summary>
        /// Try to claim a range in the publication log into which a message can be written with zero copy semantics.
        /// Once the message has been written then <seealso cref="BufferClaim#commit()"/> should be called thus making it available.
        /// <para>
        /// <b>Note:</b> This method can only be used for message lengths less than MTU length minus header.
        ///
        /// <pre>{@code
        ///     final BufferClaim bufferClaim = new BufferClaim(); // Can be stored and reused to avoid allocation
        ///
        ///     if (publication.tryClaim(messageLength, bufferClaim) > 0L)
        ///     {
        ///         try
        ///         {
        ///              final MutableDirectBuffer buffer = bufferClaim.buffer();
        ///              final int offset = bufferClaim.offset();
        ///
        ///              // Work with buffer directly or wrap with a flyweight
        ///         }
        ///         finally
        ///         {
        ///             bufferClaim.commit();
        ///         }
        ///     }
        /// }</pre>
        ///
        /// </para>
        /// </summary>
        /// <param name="length">      of the range to claim, in bytes.. </param>
        /// <param name="bufferClaim"> to be populated if the claim succeeds. </param>
        /// <returns> The new stream position, otherwise <seealso cref="NOT_CONNECTED"/>, <seealso cref="BACK_PRESSURED"/>,
        /// <seealso cref="ADMIN_ACTION"/> or <seealso cref="CLOSED"/>. </returns>
        /// <exception cref="ArgumentException"> if the length is greater than max payload length within an MTU. </exception>
        /// <seealso cref="BufferClaim.Commit()" />
        /// <seealso cref="BufferClaim.Abort()" />
        public long TryClaim(int length, BufferClaim bufferClaim)
        {
            var newPosition = CLOSED;

            if (!_isClosed)
            {
                CheckForMaxPayloadLength(length);

                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)
                {
                    var result = termAppender.Claim(_headerWriter, length, bufferClaim);
                    newPosition = NewPosition(partitionIndex, (int)termOffset, position, result);
                }
                else if (_clientConductor.IsPublicationConnected(LogBufferDescriptor.TimeOfLastStatusMessage(_logMetaDataBuffer)))
                {
                    newPosition = BACK_PRESSURED;
                }
                else
                {
                    newPosition = NOT_CONNECTED;
                }
            }

            return(newPosition);
        }
Пример #4
0
        public long TryClaim(int length, BufferClaim bufferClaim)
        {
            CheckForMaxPayloadLength(length);
            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)
                {
                    var result = termAppender.Claim(_headerWriter, length, bufferClaim);
                    newPosition = NewPosition(partitionIndex, (int)termOffset, position, result);
                }
                else
                {
                    newPosition = BackPressureStatus(position, length);
                }
            }

            return(newPosition);
        }
        /// <inheritdoc />
        public override long Offer(IDirectBuffer buffer, int offset, int length, ReservedValueSupplier reservedValueSupplier = null)
        {
            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)
                    {
                        CheckPositiveLength(length);
                        resultingOffset = termAppender.AppendUnfragmentedMessage(
                            _headerWriter,
                            buffer,
                            offset,
                            length,
                            reservedValueSupplier,
                            termId);
                    }
                    else
                    {
                        CheckMaxMessageLength(length);
                        resultingOffset = termAppender.AppendFragmentedMessage(
                            _headerWriter,
                            buffer,
                            offset,
                            length,
                            MaxPayloadLength,
                            reservedValueSupplier,
                            termId);
                    }

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

            return(newPosition);
        }
Пример #6
0
        internal ExclusivePublication(
            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 ExclusiveTermAppender(buffers[i], logMetaDataBuffer, i);
            }

            var termLength = logBuffers.TermLength();

            _termBufferLength    = termLength;
            MaxPayloadLength     = LogBufferDescriptor.MtuLength(logMetaDataBuffer) - DataHeaderFlyweight.HEADER_LENGTH;
            MaxMessageLength     = FrameDescriptor.ComputeExclusiveMaxMessageLength(termLength);
            _maxPossiblePosition = termLength * (1L << 31);
            _conductor           = clientConductor;
            Channel   = channel;
            StreamId  = streamId;
            SessionId = sessionId;

            _logMetaDataBuffer      = logMetaDataBuffer;
            _originalRegistrationId = originalRegistrationId;
            RegistrationId          = registrationId;
            _positionLimit          = positionLimit;
            _logBuffers             = logBuffers;
            _positionBitsToShift    = IntUtil.NumberOfTrailingZeros(termLength);
            _headerWriter           = new HeaderWriter(LogBufferDescriptor.DefaultFrameHeader(logMetaDataBuffer));
            InitialTermId           = LogBufferDescriptor.InitialTermId(logMetaDataBuffer);

            var activeIndex = LogBufferDescriptor.ActivePartitionIndex(logMetaDataBuffer);

            _activePartitionIndex = activeIndex;

            long rawTail = LogBufferDescriptor.RawTail(_logMetaDataBuffer, activeIndex);

            _termId            = LogBufferDescriptor.TermId(rawTail);
            _termOffset        = LogBufferDescriptor.TermOffset(rawTail, termLength);
            _termBeginPosition =
                LogBufferDescriptor.ComputeTermBeginPosition(_termId, _positionBitsToShift, InitialTermId);
        }
Пример #7
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);
        }
Пример #8
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);
        }
Пример #9
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);
            }
        }