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