예제 #1
0
        public void ShouldLimitReadOfMessages()
        {
            const int  msgLength           = 16;
            var        recordLength        = RecordDescriptor.HeaderLength + msgLength;
            var        alignedRecordLength = BitUtil.Align(recordLength, RecordDescriptor.Alignment);
            const long head      = 0L;
            var        headIndex = (int)head;

            A.CallTo(() => _buffer.GetLong(HeadCounterIndex)).Returns(head);
            A.CallTo(() => _buffer.GetLongVolatile(headIndex))
            .Returns(RecordDescriptor.MakeHeader(recordLength, MsgTypeID));

            var times = new int[1];

            MessageHandler handler      = (msgTypeId, buffer, index, length) => times[0]++;
            const int      limit        = 1;
            var            messagesRead = _ringBuffer.Read(handler, limit);

            Assert.AreEqual(messagesRead, 1);
            Assert.AreEqual(times[0], 1);

            A.CallTo(() => _buffer.SetMemory(headIndex, alignedRecordLength, 0)).MustHaveHappened(1, Times.Exactly)
            .Then(
                A.CallTo(() => _buffer.PutLongOrdered(HeadCounterIndex, head + alignedRecordLength))
                .MustHaveHappened(1, Times.Exactly));
        }
예제 #2
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(() => _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();
        }
예제 #3
0
        static LogBufferDescriptor()
        {
            var offset = 0;

            TERM_TAIL_COUNTERS_OFFSET = offset;

            offset += BitUtil.SIZE_OF_LONG * PARTITION_COUNT;
            LOG_ACTIVE_TERM_COUNT_OFFSET = offset;

            offset = BitUtil.CACHE_LINE_LENGTH * 2;
            LOG_END_OF_STREAM_POSITION_OFFSET = offset;
            LOG_IS_CONNECTED_OFFSET           = LOG_END_OF_STREAM_POSITION_OFFSET + BitUtil.SIZE_OF_LONG;

            offset += BitUtil.CACHE_LINE_LENGTH * 2;
            LOG_CORRELATION_ID_OFFSET              = offset;
            LOG_INITIAL_TERM_ID_OFFSET             = LOG_CORRELATION_ID_OFFSET + BitUtil.SIZE_OF_LONG;
            LOG_DEFAULT_FRAME_HEADER_LENGTH_OFFSET = LOG_INITIAL_TERM_ID_OFFSET + BitUtil.SIZE_OF_INT;
            LOG_MTU_LENGTH_OFFSET  = LOG_DEFAULT_FRAME_HEADER_LENGTH_OFFSET + BitUtil.SIZE_OF_INT;
            LOG_TERM_LENGTH_OFFSET = LOG_MTU_LENGTH_OFFSET + BitUtil.SIZE_OF_INT;
            LOG_PAGE_SIZE_OFFSET   = LOG_TERM_LENGTH_OFFSET + BitUtil.SIZE_OF_INT;

            offset += BitUtil.CACHE_LINE_LENGTH;
            LOG_DEFAULT_FRAME_HEADER_OFFSET = offset;

            LOG_META_DATA_LENGTH = BitUtil.Align(offset + LOG_DEFAULT_FRAME_HEADER_MAX_LENGTH, PAGE_MIN_SIZE);
        }
예제 #4
0
        /// <summary>
        /// Non-blocking receive of next message from the transmission stream.
        /// <para>
        /// If loss has occurred then <seealso cref="LappedCount()"/> will be incremented.
        ///
        /// </para>
        /// </summary>
        /// <returns> true if transmission is available with <seealso cref="Offset()"/>, <seealso cref="Length()"/> and <seealso cref="TypeId()"/>
        /// set for the next message to be consumed. If no transmission is available then false. </returns>
        public bool ReceiveNext()
        {
            var isAvailable = false;
            var buffer      = _buffer;
            var tail        = buffer.GetLongVolatile(_tailCounterIndex);
            var cursor      = _nextRecord;

            if (tail > cursor)
            {
                var recordOffset = (int)cursor & (_capacity - 1);

                if (!Validate(cursor))
                {
                    _lappedCount.LazySet(_lappedCount.Get() + 1);

                    cursor       = buffer.GetLong(_latestCounterIndex);
                    recordOffset = (int)cursor & (_capacity - 1);
                }

                _cursor     = cursor;
                _nextRecord = cursor + BitUtil.Align(buffer.GetInt(RecordDescriptor.GetLengthOffset(recordOffset)), RecordDescriptor.RecordAlignment);

                if (RecordDescriptor.PaddingMsgTypeID == buffer.GetInt(RecordDescriptor.GetTypeOffset(recordOffset)))
                {
                    recordOffset = 0;
                    _cursor      = _nextRecord;
                    _nextRecord += BitUtil.Align(buffer.GetInt(RecordDescriptor.GetLengthOffset(recordOffset)), RecordDescriptor.RecordAlignment);
                }

                _recordOffset = recordOffset;
                isAvailable   = true;
            }

            return(isAvailable);
        }
예제 #5
0
        public void ShouldAppendUnfragmentedFromVectorsToEmptyLog()
        {
            var headerLength = _defaultHeader.Capacity;
            var bufferOne    = new UnsafeBuffer(new byte[64]);
            var bufferTwo    = new UnsafeBuffer(new byte[256]);

            bufferOne.SetMemory(0, bufferOne.Capacity, (byte)'1');
            bufferTwo.SetMemory(0, bufferTwo.Capacity, (byte)'2');
            var msgLength          = bufferOne.Capacity + 200;
            var framgeLength       = msgLength + headerLength;
            var alignedFrameLength = BitUtil.Align(framgeLength, FrameDescriptor.FRAME_ALIGNMENT);
            var tail = 0;

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

            var vectors = new[]
            {
                new DirectBufferVector(bufferOne, 0, bufferOne.Capacity),
                new DirectBufferVector(bufferTwo, 0, 200)
            };

            Assert.That(_termAppender.AppendUnfragmentedMessage(_headerWriter, vectors, msgLength, RVS, TermID), Is.EqualTo(alignedFrameLength));

            Assert.AreEqual(LogBufferDescriptor.RawTailVolatile(_logMetaDataBuffer, PartionIndex), LogBufferDescriptor.PackTail(TermID, tail + alignedFrameLength));
        }
예제 #6
0
        public void ShouldNotReadLastMessageWhenPadding()
        {
            const int msgLength          = 1;
            int       frameLength        = HEADER_LENGTH + msgLength;
            int       alignedFrameLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
            int       frameOffset        = TERM_BUFFER_CAPACITY - alignedFrameLength;
            long      startingPosition   = LogBufferDescriptor.ComputePosition(
                INITIAL_TERM_ID, frameOffset, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID);

            A.CallTo(() => termBuffer.GetIntVolatile(frameOffset)).Returns(frameLength);
            A.CallTo(() => termBuffer.GetShort(FrameDescriptor.TypeOffset(frameOffset)))
            .Returns((short)FrameDescriptor.PADDING_FRAME_TYPE);
            A.CallTo(() => subscriberPosition.GetVolatile()).Returns(startingPosition);

            int readOutcome = TermReader.Read(
                termBuffer,
                frameOffset,
                handler,
                int.MaxValue,
                header,
                errorHandler,
                startingPosition,
                subscriberPosition);

            Assert.AreEqual(0, readOutcome);

            A.CallTo(() => termBuffer.GetIntVolatile(frameOffset)).MustHaveHappened()
            .Then(A.CallTo(() => subscriberPosition.SetOrdered(TERM_BUFFER_CAPACITY)).MustHaveHappened());

            A.CallTo(() => handler.OnFragment(A <UnsafeBuffer> ._, A <int> ._, A <int> ._, A <Header> ._))
            .MustNotHaveHappened();
        }
예제 #7
0
        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;

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

            long resultingOffset = termOffset + alignedLength;

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

            return(resultingOffset);
        }
예제 #8
0
        public int AppendFragmentedMessage(HeaderWriter header, IDirectBuffer srcBuffer, int srcOffset, int length,
                                           int maxPayloadLength, ReservedValueSupplier reservedValueSupplier, int activeTermId)
        {
            int          numMaxPayloads   = length / maxPayloadLength;
            int          remainingPayload = length % maxPayloadLength;
            int          lastFrameLength  = remainingPayload > 0 ? BitUtil.Align(remainingPayload + DataHeaderFlyweight.HEADER_LENGTH, FrameDescriptor.FRAME_ALIGNMENT) : 0;
            int          requiredLength   = (numMaxPayloads * (maxPayloadLength + DataHeaderFlyweight.HEADER_LENGTH)) + lastFrameLength;
            long         rawTail          = GetAndAddRawTail(requiredLength);
            int          termId           = LogBufferDescriptor.TermId(rawTail);
            long         termOffset       = rawTail & 0xFFFFFFFFL;
            UnsafeBuffer termBuffer       = _termBuffer;
            int          termLength       = termBuffer.Capacity;

            CheckTerm(activeTermId, termId);

            long resultingOffset = termOffset + requiredLength;

            if (resultingOffset > termLength)
            {
                resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, termId);
            }
            else
            {
                int  frameOffset = (int)termOffset;
                byte flags       = FrameDescriptor.BEGIN_FRAG_FLAG;
                int  remaining   = length;

                do
                {
                    int bytesToWrite  = Math.Min(remaining, maxPayloadLength);
                    int frameLength   = bytesToWrite + DataHeaderFlyweight.HEADER_LENGTH;
                    int alignedLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);

                    header.Write(termBuffer, frameOffset, frameLength, termId);
                    termBuffer.PutBytes(frameOffset + DataHeaderFlyweight.HEADER_LENGTH, srcBuffer,
                                        srcOffset + (length - remaining), bytesToWrite);

                    if (remaining <= maxPayloadLength)
                    {
                        flags |= FrameDescriptor.END_FRAG_FLAG;
                    }

                    FrameDescriptor.FrameFlags(termBuffer, frameOffset, flags);

                    if (null != reservedValueSupplier)
                    {
                        long reservedValue = reservedValueSupplier(termBuffer, frameOffset, frameLength);
                        termBuffer.PutLong(frameOffset + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, reservedValue, ByteOrder.LittleEndian);
                    }

                    FrameDescriptor.FrameLengthOrdered(termBuffer, frameOffset, frameLength);

                    flags        = 0;
                    frameOffset += alignedLength;
                    remaining   -= bytesToWrite;
                } while (remaining > 0);
            }

            return((int)resultingOffset);
        }
예제 #9
0
        public void ShouldAppendFrameTwiceToLog()
        {
            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);
            int          tail = 0;

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

            Assert.That(_termAppender.AppendUnfragmentedMessage(_headerWriter, buffer, 0, msgLength), Is.EqualTo((long)alignedFrameLength));
            Assert.That(_termAppender.AppendUnfragmentedMessage(_headerWriter, buffer, 0, msgLength), Is.EqualTo((long)alignedFrameLength * 2));

            A.CallTo(() => _metaDataBuffer.GetAndAddLong(LogBufferDescriptor.TERM_TAIL_COUNTER_OFFSET, alignedFrameLength)).MustHaveHappened()
            .Then(A.CallTo(() => _headerWriter.Write(_termBuffer, tail, frameLength, TermID)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutBytes(headerLength, buffer, 0, msgLength)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutIntOrdered(tail, frameLength)).MustHaveHappened())

            .Then(A.CallTo(() => _metaDataBuffer.GetAndAddLong(LogBufferDescriptor.TERM_TAIL_COUNTER_OFFSET, alignedFrameLength)).MustHaveHappened())
            .Then(A.CallTo(() => _headerWriter.Write(_termBuffer, alignedFrameLength, frameLength, TermID)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutBytes(alignedFrameLength + headerLength, buffer, 0, msgLength)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutIntOrdered(alignedFrameLength, frameLength)).MustHaveHappened());
        }
예제 #10
0
        public static Counter Allocate(Aeron.Aeron aeron, UnsafeBuffer tempBuffer, long recordingId,
                                       int sessionId, int streamId, string strippedChannel, string sourceIdentity)
        {
            tempBuffer.PutLong(RECORDING_ID_OFFSET, recordingId);
            tempBuffer.PutInt(SESSION_ID_OFFSET, sessionId);

            var sourceIdentityLength =
                Math.Min(sourceIdentity.Length, MAX_KEY_LENGTH - SOURCE_IDENTITY_OFFSET);

            tempBuffer.PutStringAscii(SOURCE_IDENTITY_LENGTH_OFFSET, sourceIdentity);
            var keyLength = SOURCE_IDENTITY_OFFSET + sourceIdentityLength;

            int labelOffset = BitUtil.Align(keyLength, BitUtil.SIZE_OF_INT);
            int labelLength = 0;

            labelLength += tempBuffer.PutStringWithoutLengthAscii(labelOffset, NAME + ": ");
            labelLength += tempBuffer.PutLongAscii(labelOffset + labelLength, recordingId);
            labelLength += tempBuffer.PutStringWithoutLengthAscii(labelOffset + labelLength, " ");
            labelLength += tempBuffer.PutIntAscii(labelOffset + labelLength, sessionId);
            labelLength += tempBuffer.PutStringWithoutLengthAscii(labelOffset + labelLength, " ");
            labelLength += tempBuffer.PutIntAscii(labelOffset + labelLength, streamId);
            labelLength += tempBuffer.PutStringWithoutLengthAscii(labelOffset + labelLength, " ");
            labelLength += tempBuffer.PutStringWithoutLengthAscii(labelOffset + labelLength, strippedChannel, 0,
                                                                  MAX_LABEL_LENGTH - labelLength);

            return(aeron.AddCounter(RECORDING_POSITION_TYPE_ID, tempBuffer, 0, keyLength, tempBuffer, labelOffset,
                                    labelLength));
        }
예제 #11
0
        /// <summary>
        /// Scan a term buffer for a block of message fragments from and offset up to a limitOffset.
        ///
        /// A scan will terminate if a padding frame is encountered. If first frame in a scan is padding then a block
        /// for the padding is notified. If the padding comes after the first frame in a scan then the scan terminates
        /// at the offset the padding frame begins. Padding frames are delivered singularly in a block.
        ///
        /// Padding frames may be for a greater range than the limit offset but only the header needs to be valid so
        /// relevant length of the frame is <see cref="DataHeaderFlyweight.HEADER_LENGTH"/>
        /// </summary>
        /// <param name="termBuffer"> to scan for message fragments. </param>
        /// <param name="termOffset">     at which the scan should begin. </param>
        /// <param name="limitOffset">      at which the scan should stop. </param>
        /// <returns> the offset at which the scan terminated. </returns>
        public static int Scan(IAtomicBuffer termBuffer, int termOffset, int limitOffset)
        {
            var offset = termOffset;

            while (offset < limitOffset)
            {
                int frameLength = FrameDescriptor.FrameLengthVolatile(termBuffer, offset);
                if (frameLength <= 0)
                {
                    break;
                }

                int alignedFrameLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);

                if (FrameDescriptor.IsPaddingFrame(termBuffer, offset))
                {
                    if (termOffset == offset)
                    {
                        offset += alignedFrameLength;
                    }

                    break;
                }

                if (offset + alignedFrameLength > limitOffset)
                {
                    break;
                }

                offset += alignedFrameLength;
            }


            return(offset);
        }
예제 #12
0
        public void ShouldReadBlockOfThreeMessagesThatFillBuffer()
        {
            const int offset               = 0;
            int       limit                = _termBuffer.Capacity;
            const int messageLength        = 50;
            int       alignedMessageLength = BitUtil.Align(messageLength, FrameDescriptor.FRAME_ALIGNMENT);
            int       thirdMessageLength   = limit - (alignedMessageLength * 2);

            A.CallTo(() => _termBuffer.GetIntVolatile(FrameDescriptor.LengthOffset(offset)))
            .Returns(messageLength);
            A.CallTo(() => _termBuffer.GetShort(FrameDescriptor.TypeOffset(offset)))
            .Returns((short)HeaderFlyweight.HDR_TYPE_DATA);
            A.CallTo(() => _termBuffer.GetIntVolatile(FrameDescriptor.LengthOffset(alignedMessageLength)))
            .Returns(messageLength);
            A.CallTo(() => _termBuffer.GetShort(FrameDescriptor.TypeOffset(alignedMessageLength)))
            .Returns((short)HeaderFlyweight.HDR_TYPE_DATA);
            A.CallTo(() => _termBuffer.GetIntVolatile(FrameDescriptor.LengthOffset(alignedMessageLength * 2)))
            .Returns(thirdMessageLength);
            A.CallTo(() => _termBuffer.GetShort(FrameDescriptor.TypeOffset(alignedMessageLength * 2)))
            .Returns((short)HeaderFlyweight.HDR_TYPE_DATA);

            int newOffset = TermBlockScanner.Scan(_termBuffer, offset, limit);

            Assert.That(newOffset, Is.EqualTo(limit));
        }
예제 #13
0
        /// <summary>
        /// Append an unfragmented message to the the term buffer.
        /// </summary>
        /// <param name="header">    for writing the default header. </param>
        /// <param name="srcBuffer"> containing the message. </param>
        /// <param name="srcOffset"> at which the message begins. </param>
        /// <param name="length">    of the message in the source buffer. </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 virtual long AppendUnfragmentedMessage(HeaderWriter header, IDirectBuffer srcBuffer, int srcOffset, int length)
        {
            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));
                termBuffer.PutBytes(offset + DataHeaderFlyweight.HEADER_LENGTH, srcBuffer, srcOffset, length);
                FrameDescriptor.FrameLengthOrdered(termBuffer, offset, frameLength);
            }

            return(resultingOffset);
        }
예제 #14
0
        public void ShouldWriteToEmptyBuffer()
        {
            const int  length              = 8;
            var        recordLength        = length + RecordDescriptor.HeaderLength;
            var        alignedRecordLength = BitUtil.Align(recordLength, RecordDescriptor.Alignment);
            const long tail = 0L;
            const long head = 0L;

            A.CallTo(() => _buffer.GetLongVolatile(HeadCounterIndex)).Returns(head);
            A.CallTo(() => _buffer.GetLongVolatile(TailCounterIndex)).Returns(tail);
            A.CallTo(() => _buffer.CompareAndSetLong(TailCounterIndex, tail, tail + alignedRecordLength)).Returns(true);


            var       srcBuffer = new UnsafeBuffer(new byte[1024]);
            const int srcIndex  = 0;

            Assert.True(_ringBuffer.Write(MsgTypeID, srcBuffer, srcIndex, length));

            A.CallTo(() => _buffer.PutLongOrdered((int)tail, RecordDescriptor.MakeHeader(-recordLength, MsgTypeID)))
            .MustHaveHappened()
            .Then(A.CallTo(() =>
                           _buffer.PutBytes(RecordDescriptor.EncodedMsgOffset((int)tail), srcBuffer, srcIndex, length))
                  .MustHaveHappened())
            .Then(A.CallTo(() => _buffer.PutIntOrdered(RecordDescriptor.LengthOffset((int)tail), recordLength))
                  .MustHaveHappened());
        }
예제 #15
0
        private DistinctObservation NewObservation(long timestamp, DistinctObservation[] existingObservations, Exception observation)
        {
            DistinctObservation existingObservation = null;

            if (existingObservations != _distinctObservations)
            {
                existingObservation = Find(_distinctObservations, observation);
            }

            if (existingObservation == null)
            {
                byte[] encodedError = Encoding.UTF8.GetBytes(observation.ToString());

                int length = EncodedErrorOffset + encodedError.Length;
                int offset = _nextOffset;

                if ((offset + length) > _buffer.Capacity)
                {
                    return(InsufficientSpace);
                }

                _buffer.PutBytes(offset + EncodedErrorOffset, encodedError);
                _buffer.PutLong(offset + FirstObservationTimestampOffset, timestamp);
                _nextOffset = BitUtil.Align(offset + length, RecordAlignment);

                existingObservation   = new DistinctObservation(observation, offset);
                _distinctObservations = Prepend(_distinctObservations, existingObservation);

                _buffer.PutIntOrdered(offset + LengthOffset, length);
            }

            return(existingObservation);
        }
예제 #16
0
        public void ShouldLateJoinTransmission()
        {
            const int length              = 8;
            var       recordLength        = length + RecordDescriptor.HeaderLength;
            var       recordLengthAligned = BitUtil.Align(recordLength, RecordDescriptor.RecordAlignment);
            var       tail         = Capacity * 3L + RecordDescriptor.HeaderLength + recordLengthAligned;
            var       latestRecord = tail - recordLengthAligned;
            var       recordOffset = (int)latestRecord & (Capacity - 1);

            A.CallTo(() => _buffer.GetLongVolatile(TailIntentCounterOffset)).Returns(tail);
            A.CallTo(() => _buffer.GetLongVolatile(TailCounterIndex)).Returns(tail);
            A.CallTo(() => _buffer.GetLong(LatestCounterIndex)).Returns(latestRecord);

            A.CallTo(() => _buffer.GetInt(RecordDescriptor.GetLengthOffset(recordOffset))).Returns(recordLength);
            A.CallTo(() => _buffer.GetInt(RecordDescriptor.GetTypeOffset(recordOffset))).Returns(MsgTypeID);

            Assert.IsTrue(_broadcastReceiver.ReceiveNext());
            Assert.AreEqual(MsgTypeID, _broadcastReceiver.TypeId());
            Assert.AreEqual(_buffer, _broadcastReceiver.Buffer());
            Assert.AreEqual(RecordDescriptor.GetMsgOffset(recordOffset), _broadcastReceiver.Offset());
            Assert.AreEqual(length, _broadcastReceiver.Length());
            Assert.True(_broadcastReceiver.Validate());

            Assert.Greater(_broadcastReceiver.LappedCount(), 0);
        }
예제 #17
0
        public void ShouldReadMultipleMessages()
        {
            const int msgLength          = 1;
            int       frameLength        = HEADER_LENGTH + msgLength;
            int       alignedFrameLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
            const int termOffset         = 0;

            A.CallTo(() => termBuffer.GetIntVolatile(0)).Returns(frameLength);
            A.CallTo(() => termBuffer.GetIntVolatile(alignedFrameLength)).Returns(frameLength);
            A.CallTo(() => termBuffer.GetShort(A <int> ._)).Returns((short)HeaderFlyweight.HDR_TYPE_DATA);

            int readOutcome = TermReader.Read(termBuffer, termOffset, handler, int.MaxValue, header, errorHandler, 0,
                                              subscriberPosition);

            Assert.AreEqual(2, readOutcome);

            A.CallTo(() => termBuffer.GetIntVolatile(0)).MustHaveHappened()
            .Then(A.CallTo(() => handler.OnFragment(termBuffer, HEADER_LENGTH, msgLength, A <Header> ._))
                  .MustHaveHappened())
            .Then(A.CallTo(() => termBuffer.GetIntVolatile(alignedFrameLength)).MustHaveHappened())
            .Then(A.CallTo(() =>
                           handler.OnFragment(termBuffer, alignedFrameLength + HEADER_LENGTH, msgLength, A <Header> ._))
                  .MustHaveHappened())
            .Then(A.CallTo(() => subscriberPosition.SetOrdered(alignedFrameLength * 2)).MustHaveHappened());
        }
예제 #18
0
        public void ShouldCopeWithPaddingRecordAndWrapOfBufferForNextRecord()
        {
            const int length              = 120;
            var       recordLength        = length + RecordDescriptor.HeaderLength;
            var       recordLengthAligned = BitUtil.Align(recordLength, RecordDescriptor.RecordAlignment);
            var       catchupTail         = (Capacity * 2L) - RecordDescriptor.HeaderLength;
            var       postPaddingTail     = catchupTail + RecordDescriptor.HeaderLength + recordLengthAligned;
            var       latestRecord        = catchupTail - recordLengthAligned;
            var       catchupOffset       = (int)latestRecord & (Capacity - 1);

            A.CallTo(() => _buffer.GetLongVolatile(TailIntentCounterOffset)).ReturnsNextFromSequence(catchupTail, postPaddingTail);
            A.CallTo(() => _buffer.GetLongVolatile(TailCounterIndex)).ReturnsNextFromSequence(catchupTail, postPaddingTail);
            A.CallTo(() => _buffer.GetLong(LatestCounterIndex)).Returns(latestRecord);

            A.CallTo(() => _buffer.GetInt(RecordDescriptor.GetLengthOffset(catchupOffset))).Returns(recordLength);
            A.CallTo(() => _buffer.GetInt(RecordDescriptor.GetTypeOffset(catchupOffset))).Returns(MsgTypeID);

            var paddingOffset = (int)catchupTail & (Capacity - 1);
            var recordOffset  = (int)(postPaddingTail - recordLengthAligned) & (Capacity - 1);

            A.CallTo(() => _buffer.GetInt(RecordDescriptor.GetTypeOffset(paddingOffset))).Returns(RecordDescriptor.PaddingMsgTypeID);
            A.CallTo(() => _buffer.GetInt(RecordDescriptor.GetLengthOffset(recordOffset))).Returns(recordLength);
            A.CallTo(() => _buffer.GetInt(RecordDescriptor.GetTypeOffset(recordOffset))).Returns(MsgTypeID);

            Assert.IsTrue(_broadcastReceiver.ReceiveNext()); // To catch up to record before padding.
            Assert.IsTrue(_broadcastReceiver.ReceiveNext()); // no skip over the padding and read next record.
            Assert.AreEqual(MsgTypeID, _broadcastReceiver.TypeId());
            Assert.AreEqual(_buffer, _broadcastReceiver.Buffer());
            Assert.AreEqual(RecordDescriptor.GetMsgOffset(recordOffset), _broadcastReceiver.Offset());
            Assert.AreEqual(length, _broadcastReceiver.Length());
            Assert.True(_broadcastReceiver.Validate());
        }
예제 #19
0
        public long AppendUnfragmentedMessage(HeaderWriter header, UnsafeBuffer srcBuffer, int srcOffset, int length, ReservedValueSupplier reservedValueSupplier)
#endif
        {
            int  frameLength   = length + DataHeaderFlyweight.HEADER_LENGTH;
            int  alignedLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
            long rawTail       = GetAndAddRawTail(alignedLength);
            long termOffset    = rawTail & 0xFFFFFFFFL;

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

            long resultingOffset = termOffset + alignedLength;

            if (resultingOffset > termLength)
            {
                resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, LogBufferDescriptor.TermId(rawTail));
            }
            else
            {
                int offset = (int)termOffset;
                header.Write(termBuffer, offset, frameLength, LogBufferDescriptor.TermId(rawTail));
                termBuffer.PutBytes(offset + DataHeaderFlyweight.HEADER_LENGTH, srcBuffer, srcOffset, length);

                if (null != reservedValueSupplier)
                {
                    long reservedValue = reservedValueSupplier(termBuffer, offset, frameLength);
                    termBuffer.PutLong(offset + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, reservedValue);
                }

                FrameDescriptor.FrameLengthOrdered(termBuffer, offset, frameLength);
            }

            return(resultingOffset);
        }
예제 #20
0
        public void ShouldDealWithRecordBecomingInvalidDueToOverwrite()
        {
            const int length              = 8;
            var       recordLength        = length + RecordDescriptor.HeaderLength;
            var       recordLengthAligned = BitUtil.Align(recordLength, RecordDescriptor.RecordAlignment);
            long      tail         = recordLengthAligned;
            var       latestRecord = tail - recordLengthAligned;
            var       recordOffset = (int)latestRecord;


            A.CallTo(() => _buffer.GetLongVolatile(TailIntentCounterOffset)).ReturnsNextFromSequence(tail, tail + (Capacity - recordLengthAligned));
            A.CallTo(() => _buffer.GetLongVolatile(TailCounterIndex)).Returns(tail);

            A.CallTo(() => _buffer.GetInt(RecordDescriptor.GetLengthOffset(recordOffset))).Returns(recordLength);
            A.CallTo(() => _buffer.GetInt(RecordDescriptor.GetTypeOffset(recordOffset))).Returns(MsgTypeID);

            Assert.IsTrue(_broadcastReceiver.ReceiveNext());
            Assert.AreEqual(MsgTypeID, _broadcastReceiver.TypeId());
            Assert.AreEqual(_buffer, _broadcastReceiver.Buffer());
            Assert.AreEqual(RecordDescriptor.GetMsgOffset(recordOffset), _broadcastReceiver.Offset());
            Assert.AreEqual(length, _broadcastReceiver.Length());

            Assert.False(_broadcastReceiver.Validate()); // Need to receiveNext() to catch up with transmission again.

            A.CallTo(() => _buffer.GetLongVolatile(TailCounterIndex)).MustHaveHappened();
        }
예제 #21
0
        /// <summary>
        /// Read all the errors in a log since a given timestamp.
        /// </summary>
        /// <param name="buffer">         containing the <seealso cref="DistinctErrorLog"/>. </param>
        /// <param name="consumer">       to be called for each exception encountered. </param>
        /// <param name="sinceTimestamp"> for filtering errors that have been recorded since this time. </param>
        /// <returns> the number of entries that has been read. </returns>
        public static int Read(IAtomicBuffer buffer, ErrorConsumer consumer, long sinceTimestamp)
        {
            int entries  = 0;
            int offset   = 0;
            int capacity = buffer.Capacity;

            while (offset < capacity)
            {
                int length = buffer.GetIntVolatile(offset + DistinctErrorLog.LengthOffset);
                if (0 == length)
                {
                    break;
                }

                long lastObservationTimestamp = buffer.GetLongVolatile(offset + DistinctErrorLog.LastObservationTimestampOffset);
                if (lastObservationTimestamp >= sinceTimestamp)
                {
                    ++entries;

                    consumer(
                        buffer.GetInt(offset + DistinctErrorLog.ObservationCountOffset),
                        buffer.GetLong(offset + DistinctErrorLog.FirstObservationTimestampOffset),
                        lastObservationTimestamp,
                        buffer.GetStringWithoutLengthUtf8(offset + DistinctErrorLog.EncodedErrorOffset, length - DistinctErrorLog.EncodedErrorOffset));
                }

                offset += BitUtil.Align(length, DistinctErrorLog.RecordAlignment);
            }

            return(entries);
        }
예제 #22
0
        public void ShouldReceiveFirstMessageFromBuffer()
        {
            const int length              = 8;
            var       recordLength        = length + RecordDescriptor.HeaderLength;
            var       recordLengthAligned = BitUtil.Align(recordLength, RecordDescriptor.RecordAlignment);
            long      tail         = recordLengthAligned;
            var       latestRecord = tail - recordLengthAligned;
            var       recordOffset = (int)latestRecord;

            A.CallTo(() => _buffer.GetLongVolatile(TailIntentCounterOffset)).Returns(tail);
            A.CallTo(() => _buffer.GetLongVolatile(TailCounterIndex)).Returns(tail);
            A.CallTo(() => _buffer.GetInt(RecordDescriptor.GetLengthOffset(recordOffset))).Returns(recordLength);
            A.CallTo(() => _buffer.GetInt(RecordDescriptor.GetTypeOffset(recordOffset))).Returns(MsgTypeID);

            Assert.True(_broadcastReceiver.ReceiveNext());
            Assert.AreEqual(MsgTypeID, _broadcastReceiver.TypeId());
            Assert.AreEqual(_buffer, _broadcastReceiver.Buffer());
            Assert.AreEqual(RecordDescriptor.GetMsgOffset(recordOffset), _broadcastReceiver.Offset());
            Assert.AreEqual(length, _broadcastReceiver.Length());

            Assert.True(_broadcastReceiver.Validate());

            A.CallTo(() => _buffer.GetLongVolatile(TailCounterIndex)).MustHaveHappened();
            A.CallTo(() => _buffer.GetLongVolatile(TailIntentCounterOffset)).MustHaveHappened();
        }
예제 #23
0
        public static long Read(UnsafeBuffer termBuffer, int offset, FragmentHandler handler, int fragmentsLimit, Header header, ErrorHandler errorHandler)
        {
            int fragmentsRead = 0;
            int capacity      = termBuffer.Capacity;

            try
            {
                do
                {
                    int frameLength = FrameDescriptor.FrameLengthVolatile(termBuffer, offset);
                    if (frameLength <= 0)
                    {
                        break;
                    }

                    int termOffset = offset;
                    offset += BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);

                    if (!FrameDescriptor.IsPaddingFrame(termBuffer, termOffset))
                    {
                        header.SetBuffer(termBuffer, termOffset);

                        handler(termBuffer, termOffset + DataHeaderFlyweight.HEADER_LENGTH, frameLength - DataHeaderFlyweight.HEADER_LENGTH, header);

                        ++fragmentsRead;
                    }
                } while (fragmentsRead < fragmentsLimit && offset < capacity);
            }
            catch (Exception t)
            {
                errorHandler(t);
            }

            return(Pack(offset, fragmentsRead));
        }
예제 #24
0
        /// <summary>
        /// Scan a term buffer for a block of message fragments from and offset up to a limit.
        /// </summary>
        /// <param name="termBuffer"> to scan for message fragments. </param>
        /// <param name="termOffset">     at which the scan should begin. </param>
        /// <param name="limit">      at which the scan should stop. </param>
        /// <returns> the offset at which the scan terminated. </returns>
        public static int Scan(IAtomicBuffer termBuffer, int termOffset, int limit)
        {
            var offset = termOffset;

            do
            {
                int frameLength = FrameDescriptor.FrameLengthVolatile(termBuffer, offset);
                if (frameLength <= 0)
                {
                    break;
                }

                int alignedFrameLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
                offset += alignedFrameLength;
                if (offset >= limit)
                {
                    if (offset > limit)
                    {
                        offset -= alignedFrameLength;
                    }

                    break;
                }
            } while (true);

            return(offset);
        }
예제 #25
0
        public void ShouldFragmentMessageOverTwoFrames()
        {
            int          msgLength        = MaxPayloadLength + 1;
            int          headerLength     = _defaultHeader.Capacity;
            int          frameLength      = headerLength + 1;
            int          requiredCapacity = BitUtil.Align(headerLength + 1, FrameDescriptor.FRAME_ALIGNMENT) + MaxFrameLength;
            UnsafeBuffer buffer           = new UnsafeBuffer(new byte[msgLength]);
            int          tail             = 0;

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

            Assert.That(_termAppender.AppendFragmentedMessage(_headerWriter, buffer, 0, msgLength, MaxPayloadLength, RVS), Is.EqualTo((long)requiredCapacity));

            Assert.AreEqual(LogBufferDescriptor.RawTailVolatile(_logMetaDataBuffer, PartionIndex), LogBufferDescriptor.PackTail(TermID, tail + requiredCapacity));

            A.CallTo(() => _headerWriter.Write(_termBuffer, tail, MaxFrameLength, TermID)).MustHaveHappened()
            .Then(A.CallTo(() => _termBuffer.PutBytes(tail + headerLength, buffer, 0, MaxPayloadLength)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutByte(FrameDescriptor.FlagsOffset(tail), FrameDescriptor.BEGIN_FRAG_FLAG)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutLong(tail + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, RV)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutIntOrdered(tail, MaxFrameLength)).MustHaveHappened())
            .Then(A.CallTo(() => _headerWriter.Write(_termBuffer, MaxFrameLength, frameLength, TermID)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutBytes(MaxFrameLength + headerLength, buffer, MaxPayloadLength, 1)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutByte(FrameDescriptor.FlagsOffset(MaxFrameLength), FrameDescriptor.END_FRAG_FLAG)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutLong(MaxFrameLength + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, RV)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutIntOrdered(MaxFrameLength, frameLength)).MustHaveHappened());
        }
예제 #26
0
        public void ShouldAppendUnfragmentedFromVectorsToEmptyLog()
        {
            var headerLength = _defaultHeader.Capacity;
            var bufferOne    = new UnsafeBuffer(new byte[64]);
            var bufferTwo    = new UnsafeBuffer(new byte[256]);

            bufferOne.SetMemory(0, bufferOne.Capacity, (byte)'1');
            bufferTwo.SetMemory(0, bufferTwo.Capacity, (byte)'2');
            var msgLength          = bufferOne.Capacity + 200;
            var framgeLength       = msgLength + headerLength;
            var alignedFrameLength = BitUtil.Align(framgeLength, FrameDescriptor.FRAME_ALIGNMENT);
            var tail = 0;

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

            var vectors = new[]
            {
                new DirectBufferVector(bufferOne, 0, bufferOne.Capacity),
                new DirectBufferVector(bufferTwo, 0, 200)
            };

            Assert.AreEqual(alignedFrameLength, _termAppender.AppendUnfragmentedMessage(_headerWriter, vectors, msgLength, RVS, TermID));

            Assert.AreEqual(LogBufferDescriptor.PackTail(TermID, tail + alignedFrameLength), LogBufferDescriptor.RawTailVolatile(_logMetaDataBuffer, PartionIndex));

            A.CallTo(() => _headerWriter.Write(_termBuffer, tail, framgeLength, TermID)).MustHaveHappened()
            .Then(A.CallTo(() => _termBuffer.PutBytes(headerLength, bufferOne, 0, bufferOne.Capacity)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutBytes(headerLength + bufferOne.Capacity, bufferTwo, 0, 200)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutLong(tail + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, RV, ByteOrder.LittleEndian)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutIntOrdered(tail, framgeLength)).MustHaveHappened());
        }
예제 #27
0
        public void ShouldAppendFrameTwiceToLog()
        {
            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);
            int          tail = 0;

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

            Assert.That(_termAppender.AppendUnfragmentedMessage(_headerWriter, buffer, 0, msgLength, RVS), Is.EqualTo((long)alignedFrameLength));
            Assert.That(_termAppender.AppendUnfragmentedMessage(_headerWriter, buffer, 0, msgLength, RVS), Is.EqualTo((long)alignedFrameLength * 2));

            Assert.AreEqual(LogBufferDescriptor.RawTailVolatile(_logMetaDataBuffer, PartionIndex), LogBufferDescriptor.PackTail(TermID, tail + alignedFrameLength * 2));

            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())
            .Then(A.CallTo(() => _headerWriter.Write(_termBuffer, alignedFrameLength, frameLength, TermID)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutBytes(alignedFrameLength + headerLength, buffer, 0, msgLength)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutLong(alignedFrameLength + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, RV)).MustHaveHappened())
            .Then(A.CallTo(() => _termBuffer.PutIntOrdered(alignedFrameLength, frameLength)).MustHaveHappened());
        }
예제 #28
0
        /// <summary>
        /// Non-blocking write of an message to an underlying ring-buffer.
        /// </summary>
        /// <param name="msgTypeId"> type of the message encoding. </param>
        /// <param name="srcBuffer"> containing the encoded binary message. </param>
        /// <param name="srcIndex"> at which the encoded message begins. </param>
        /// <param name="length"> of the encoded message in bytes. </param>
        /// <returns> true if written to the ring-buffer, or false if insufficient space exists. </returns>
        /// <exception cref="ArgumentException"> if the length is greater than <seealso cref="IRingBuffer.MaxMsgLength()"/> </exception>
        public bool Write(int msgTypeId, IDirectBuffer srcBuffer, int srcIndex, int length)
        {
            RecordDescriptor.CheckTypeId(msgTypeId);
            CheckMsgLength(length);

            var isSuccessful = false;

            var buffer           = _buffer;
            var recordLength     = length + RecordDescriptor.HeaderLength;
            var requiredCapacity = BitUtil.Align(recordLength, RecordDescriptor.Alignment);
            var recordIndex      = ClaimCapacity(buffer, requiredCapacity);

            if (InsufficientCapacity != recordIndex)
            {
                buffer.PutLongOrdered(recordIndex, RecordDescriptor.MakeHeader(-recordLength, msgTypeId));
                // TODO JPW original: UnsafeAccess.UNSAFE.storeFence();
                Thread.MemoryBarrier();
                buffer.PutBytes(RecordDescriptor.EncodedMsgOffset(recordIndex), srcBuffer, srcIndex, length);
                buffer.PutIntOrdered(RecordDescriptor.LengthOffset(recordIndex), recordLength);

                isSuccessful = true;
            }

            return(isSuccessful);
        }
예제 #29
0
        public int Claim(
            int termId,
            int termOffset,
            HeaderWriter header,
            int length,
            BufferClaim bufferClaim)
        {
            int          frameLength   = length + DataHeaderFlyweight.HEADER_LENGTH;
            int          alignedLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
            UnsafeBuffer termBuffer    = _termBuffer;
            int          termLength    = termBuffer.Capacity;

            int resultingOffset = termOffset + alignedLength;

            PutRawTailOrdered(termId, resultingOffset);

            if (resultingOffset > termLength)
            {
                resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, termId);
            }
            else
            {
                header.Write(termBuffer, termOffset, frameLength, termId);
                bufferClaim.Wrap(termBuffer, termOffset, frameLength);
            }

            return(resultingOffset);
        }
예제 #30
0
        public void ShouldInsertPaddingRecordPlusMessageOnBufferWrapWithHeadEqualToTail()
        {
            const int length              = 200;
            var       recordLength        = length + RecordDescriptor.HeaderLength;
            var       alignedRecordLength = BitUtil.Align(recordLength, RecordDescriptor.Alignment);
            long      tail = Capacity - RecordDescriptor.HeaderLength;
            var       head = tail;

            A.CallTo(() => _buffer.GetLongVolatile(HeadCounterIndex)).Returns(head);
            A.CallTo(() => _buffer.GetLongVolatile(TailCounterIndex)).Returns(tail);
            A.CallTo(() =>
                     _buffer.CompareAndSetLong(TailCounterIndex, tail,
                                               tail + alignedRecordLength + RecordDescriptor.Alignment)).Returns(true);

            var srcBuffer = new UnsafeBuffer(new byte[1024]);

            const int srcIndex = 0;

            Assert.True(_ringBuffer.Write(MsgTypeID, srcBuffer, srcIndex, length));


            A.CallTo(() => _buffer.PutLongOrdered((int)tail,
                                                  RecordDescriptor.MakeHeader(RecordDescriptor.HeaderLength, ManyToOneRingBuffer.PaddingMsgTypeId)))
            .MustHaveHappened()
            .Then(A.CallTo(() => _buffer.PutLongOrdered(0, RecordDescriptor.MakeHeader(-recordLength, MsgTypeID)))
                  .MustHaveHappened())
            .Then(A.CallTo(
                      () => _buffer.PutBytes(RecordDescriptor.EncodedMsgOffset(0), srcBuffer, srcIndex, length))
                  .MustHaveHappened())
            .Then(A.CallTo(() => _buffer.PutIntOrdered(RecordDescriptor.LengthOffset(0), recordLength))
                  .MustHaveHappened());
        }