/// <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);
        }
Exemple #2
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);
        }
        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();

            A.CallTo(() => _termBuffer.PutIntOrdered(A <int> ._, A <int> ._));

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

            Assert.That(_termAppender.Claim(_headerWriter, msgLength, bufferClaim), 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();
        }
Exemple #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);
        }
            public void Run()
            {
                var  publication       = Publication;
                var  bufferClaim       = new BufferClaim();
                long backPressureCount = 0;
                long totalMessageCount = 0;

                while (Running.Get())
                {
                    for (var i = 0; i < BurstLength; i++)
                    {
                        while (publication.TryClaim(MessageLength, bufferClaim) <= 0)
                        {
                            ++backPressureCount;
                            if (!Running.Get())
                            {
                                break;
                            }
                        }

                        var offset = bufferClaim.Offset;
                        bufferClaim.Buffer.PutInt(offset, i); // Example field write
                        // Real app would write whatever fields are required via a flyweight like SBE

                        bufferClaim.Commit();

                        ++totalMessageCount;
                    }
                }


                var backPressureRatio = backPressureCount / (double)totalMessageCount;

                Console.WriteLine($"Publisher back pressure ratio: {backPressureRatio}");
            }
Exemple #6
0
        public void ShouldEnsureThePublicationIsOpenBeforeClaim()
        {
            _publication.Dispose();
            var bufferClaim = new BufferClaim();

            Assert.AreEqual(_publication.TryClaim(SendBufferCapacity, bufferClaim), Publication.CLOSED);
        }
        public long TryClaim(int length, BufferClaim bufferClaim, IDirectBuffer sessionHeader)
        {
            long result = _publication.TryClaim(length, bufferClaim);

            if (result > 0)
            {
                bufferClaim.PutBytes(sessionHeader, 0, AeronCluster.SESSION_HEADER_LENGTH);
            }

            return(result);
        }
Exemple #8
0
        public long Claim(int length, out BufferClaim claim)
        {
            while (true)
            {
                var  partitionIndex = ActivePartitionIndex(_logBuffers.LogMetaData);
                var  termAppender   = _termAppenders[partitionIndex];
                long rawTail        = termAppender.RawTailVolatile;
                long termOffset     = rawTail & 0xFFFFFFFFL;

                long position = ComputeTermBeginPosition(TermId(rawTail), _positionBitsToShift, _initialTermId) + termOffset;

                long result      = termAppender.Claim(_headerWriter, length, out claim);
                long newPosition = NewPosition(partitionIndex, (int)termOffset, position, result);

                if (newPosition < 0)
                {
                    continue;
                }
                return(newPosition);
            }
        }
Exemple #9
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();

            A.CallTo(() => _metaDataBuffer.GetAndAddLong(LogBufferDescriptor.TERM_TAIL_COUNTER_OFFSET, alignedFrameLength))
            .Returns(TermAppender.Pack(TermID, tail));

            Assert.That(_termAppender.Claim(_headerWriter, msgLength, bufferClaim), 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();

            A.CallTo(() => _metaDataBuffer.GetAndAddLong(LogBufferDescriptor.TERM_TAIL_COUNTER_OFFSET, alignedFrameLength)).MustHaveHappened()
            .Then(A.CallTo(() => _headerWriter.Write(_termBuffer, tail, frameLength, TermID)).MustHaveHappened());
        }
Exemple #10
0
        public override long TryClaim(int length, BufferClaim bufferClaim)
        {
            CheckPayloadLength(length);
            var newPosition = CLOSED;

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

                if (position < limit)
                {
                    int result = termAppender.Claim(_termId, _termOffset, _headerWriter, length, bufferClaim);
                    newPosition = NewPosition(result);
                }
                else
                {
                    newPosition = BackPressureStatus(position, length);
                }
            }

            return(newPosition);
        }
Exemple #11
0
            public void Run()
            {
                var publication = Publication;
                var bufferClaim = new BufferClaim();
                long backPressureCount = 0;
                long totalMessageCount = 0;

                while (Running.Get())
                {
                    for (var i = 0; i < BurstLength; i++)
                    {
                        while (publication.TryClaim(MessageLength, bufferClaim) <= 0)
                        {
                            ++backPressureCount;
                            if (!Running.Get())
                            {
                                break;
                            }
                        }

                        var offset = bufferClaim.Offset;
                        bufferClaim.Buffer.PutInt(offset, i); // Example field write
                        // Real app would write whatever fields are required via a flyweight like SBE

                        bufferClaim.Commit();

                        ++totalMessageCount;
                    }
                }


                var backPressureRatio = backPressureCount/(double) totalMessageCount;
                Console.WriteLine($"Publisher back pressure ratio: {backPressureRatio}");
            }
Exemple #12
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>
 /// On successful claim, the Cluster egress header will be written to the start of the claimed buffer section.
 /// Clients <b>MUST</b> write into the claimed buffer region at offset + <seealso cref="AeronCluster.SESSION_HEADER_LENGTH"/>.
 /// <pre>{@code
 ///     final IDirectBuffer srcBuffer = AcquireMessage();
 ///
 ///     if (clientSession.TryClaim(length, bufferClaim) > 0L)
 ///     {
 ///         try
 ///         {
 ///              final IMutableDirectBuffer buffer = bufferClaim.Buffer;
 ///              final int offset = bufferClaim.Offset;
 ///              // ensure that data is written at the correct offset
 ///              buffer.PutBytes(offset + AeronCluster.SESSION_HEADER_LENGTH, srcBuffer, 0, length);
 ///         }
 ///         finally
 ///         {
 ///             bufferClaim.Commit();
 ///         }
 ///     }
 /// }</pre>
 ///
 /// </para>
 /// </summary>
 /// <param name="length">      of the range to claim in bytes. The additional bytes for the session header will be added. </param>
 /// <param name="bufferClaim"> to be populated if the claim succeeds. </param>
 /// <returns> The new stream position, otherwise a negative error value as specified in
 ///         <seealso cref="Publication.TryClaim(int, BufferClaim)"/>.when in <seealso cref="ClusterRole.Leader"/>,
 ///         otherwise <seealso cref="MOCKED_OFFER"/> when a follower.</returns>
 /// <exception cref="ArgumentException"> if the length is greater than <seealso cref="Publication.MaxPayloadLength"/>. </exception>
 /// <seealso cref="Publication.TryClaim(int, BufferClaim)"/>
 /// <seealso cref="BufferClaim.Commit()"/>
 /// <seealso cref="BufferClaim.Abort()"/>
 public long TryClaim(int length, BufferClaim bufferClaim)
 {
     return(_clusteredServiceAgent.TryClaim(Id, _responsePublication, length, bufferClaim));
 }
Exemple #13
0
 public abstract long TryClaim(int length, BufferClaim bufferClaim);
Exemple #14
0
        /// <summary>
        /// Claim length of a the term buffer for writing in the message with zero copy semantics.
        /// </summary>
        /// <param name="header">      for writing the default header. </param>
        /// <param name="length">      of the message to be written. </param>
        /// <param name="bufferClaim"> to be updated with the claimed region. </param>
        /// <returns> the resulting offset of the term after the append on success otherwise <seealso cref="#TRIPPED"/> or <seealso cref="#FAILED"/>
        /// packed with the termId if a padding record was inserted at the end. </returns>
        public long Claim(HeaderWriter header, int length, BufferClaim bufferClaim)
        {
            int frameLength = length + DataHeaderFlyweight.HEADER_LENGTH;
            int alignedLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
            long rawTail = GetAndAddRawTail(alignedLength);
            long termOffset = rawTail & 0xFFFFFFFFL;

            IAtomicBuffer termBuffer = _termBuffer;
            int termLength = termBuffer.Capacity;

            long resultingOffset = termOffset + alignedLength;
            if (resultingOffset > termLength)
            {
                resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, TermId(rawTail));
            }
            else
            {
                int offset = (int) termOffset;
                header.Write(termBuffer, offset, frameLength, TermId(rawTail));
                bufferClaim.Wrap(termBuffer, offset, frameLength);
            }

            return resultingOffset;
        }
Exemple #15
0
 public void ShouldEnsureThePublicationIsOpenBeforeClaim()
 {
     _publication.Dispose();
     var bufferClaim = new BufferClaim();
     Assert.AreEqual(_publication.TryClaim(SendBufferCapacity, bufferClaim), Publication.CLOSED);
 }
Exemple #16
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;
        }