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()); }
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(); }
/// <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); }
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); }
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()); }
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); }
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); }
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); }
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() ); }
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()); }
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(); }
/// <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); }
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()); }
/// <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); }
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(); }
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); } }
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); }
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()); }
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()); }
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); }
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); }
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() ); }
/// <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); }
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); }
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(); }
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); } }
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)); }
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()); }
internal void Close() { _finalPosition = _subscriberPosition.GetVolatile(); _isEos = _finalPosition >= LogBufferDescriptor.EndOfStreamPosition(_logBuffers.MetaDataBuffer()); _isClosed = true; }