/// <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 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 unsafe void CouldCreateLogBuffers() { var sw = new Stopwatch(); var l1 = new LogBuffers("../AeronLogBufferTests"); Assert.IsTrue(l1.TermLength >= LogBufferDescriptor.TERM_MIN_LENGTH); Console.WriteLine($"TermLength: {l1.TermLength}"); var activePartitionIndex = LogBufferDescriptor.ActivePartitionIndex(l1.LogMetaData); Console.WriteLine($"Active partition: {activePartitionIndex}"); var activePartition = l1.Partitions[activePartitionIndex]; var rawTail = activePartition.RawTailVolatile; Console.WriteLine($"Raw tail: {rawTail}"); var ta = new TermAppender(activePartition); var defaultHeader = DataHeaderFlyweight.CreateDefaultHeader(0, 0, activePartition.TermId); var headerWriter = new HeaderWriter(defaultHeader); BufferClaim claim; ta.Claim(headerWriter, 100, out claim); claim.Commit(); }
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); }
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); }
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.ActivePartitionIndex(_logMetaDataBuffer, nextIndex); } return(newPosition); }