/// <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); }
/// <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(); }
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}"); }
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); }
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); } }
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()); }
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); }
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}"); }
/// <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)); }
public abstract long TryClaim(int length, BufferClaim bufferClaim);
/// <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; }
/// <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; }