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()); }
/// <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 ShouldInsertIntoEmptyBuffer() { UnsafeBuffer packet = new UnsafeBuffer(new byte[256]); const int termOffset = 0; const int srcOffset = 0; const int length = 256; packet.PutInt(srcOffset, length); TermRebuilder.Insert(_termBuffer, termOffset, packet, length); A.CallTo(() => _termBuffer.PutBytes(termOffset + DataHeaderFlyweight.HEADER_LENGTH, packet, srcOffset + DataHeaderFlyweight.HEADER_LENGTH, length - DataHeaderFlyweight.HEADER_LENGTH)).MustHaveHappened() .Then(A.CallTo(() => _termBuffer.PutLong(termOffset + 24, packet.GetLong(24))).MustHaveHappened()) .Then(A.CallTo(() => _termBuffer.PutLong(termOffset + 16, packet.GetLong(16))).MustHaveHappened()) .Then(A.CallTo(() => _termBuffer.PutLong(termOffset + 8, packet.GetLong(8))).MustHaveHappened()) .Then(A.CallTo(() => _termBuffer.PutLongOrdered(termOffset, packet.GetLong(0))).MustHaveHappened()); }
/// <summary> /// Insert a packet of frames into the log at the appropriate offset as indicated by the term offset header. /// </summary> /// <param name="termBuffer"> into which the packet should be inserted. </param> /// <param name="offset"> offset in the term at which the packet should be inserted. </param> /// <param name="packet"> containing a sequence of frames. </param> /// <param name="length"> of the sequence of frames in bytes. </param> public static void Insert(IAtomicBuffer termBuffer, int offset, UnsafeBuffer packet, int length) { var firstFrameLength = packet.GetInt(0); // LITTLE_ENDIAN packet.PutIntOrdered(0, 0); termBuffer.PutBytes(offset, packet, 0, length); FrameDescriptor.FrameLengthOrdered(termBuffer, offset, firstFrameLength); }
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; A.CallTo(() => _metaDataBuffer.GetAndAddLong(LogBufferDescriptor.TERM_TAIL_COUNTER_OFFSET, alignedFrameLength)).Returns(TermAppender.Pack(TermID, tail)); Assert.That(_termAppender.AppendUnfragmentedMessage(_headerWriter, buffer, 0, msgLength), Is.EqualTo((long)alignedFrameLength)); 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()); }
/// <summary> /// Insert a packet of frames into the log at the appropriate offset as indicated by the term termOffset header. /// </summary> /// <param name="termBuffer"> into which the packet should be inserted. </param> /// <param name="termOffset"> offset in the term at which the packet should be inserted. </param> /// <param name="packet"> containing a sequence of frames. </param> /// <param name="length"> of the sequence of frames in bytes. </param> public static void Insert(IAtomicBuffer termBuffer, int termOffset, UnsafeBuffer packet, int length) { var firstFrameLength = packet.GetInt(0); // LITTLE_ENDIAN packet.PutIntOrdered(0, 0); Thread.MemoryBarrier(); // UnsafeAccess.UNSAFE.storeFence(); termBuffer.PutBytes(termOffset, packet, 0, length); FrameDescriptor.FrameLengthOrdered(termBuffer, termOffset, firstFrameLength); }
/// <summary> /// Append a fragmented message to the the term buffer. /// The message will be split up into fragments of MTU length minus header. /// </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> /// <param name="maxPayloadLength"> that the message will be fragmented into. </param> /// <returns> the resulting offset of the term after the append on success otherwise <seealso cref="#TRIPPED"/> or <seealso cref="#FAILED"/> /// packed with the termId if a padding record was inserted at the end. </returns> public long AppendFragmentedMessage(HeaderWriter header, IDirectBuffer srcBuffer, int srcOffset, int length, int maxPayloadLength) { 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 = TermId(rawTail); long termOffset = rawTail & 0xFFFFFFFFL; IAtomicBuffer termBuffer = _termBuffer; int termLength = termBuffer.Capacity; long resultingOffset = termOffset + requiredLength; if (resultingOffset > termLength) { resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, termId); } else { int offset = (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, offset, frameLength, termId); termBuffer.PutBytes(offset + DataHeaderFlyweight.HEADER_LENGTH, srcBuffer, srcOffset + (length - remaining), bytesToWrite); if (remaining <= maxPayloadLength) { flags |= FrameDescriptor.END_FRAG_FLAG; } FrameDescriptor.FrameFlags(termBuffer, offset, flags); FrameDescriptor.FrameLengthOrdered(termBuffer, offset, frameLength); flags = 0; offset += alignedLength; remaining -= bytesToWrite; } while (remaining > 0); } return(resultingOffset); }
/// <summary> /// Insert a packet of frames into the log at the appropriate termOffset as indicated by the term termOffset header. /// /// If the packet has already been inserted then this is a noop. /// </summary> /// <param name="termBuffer"> into which the packet should be inserted. </param> /// <param name="termOffset"> in the term at which the packet should be inserted. </param> /// <param name="packet"> containing a sequence of frames. </param> /// <param name="length"> of the packet of frames in bytes. </param> public static void Insert(IAtomicBuffer termBuffer, int termOffset, UnsafeBuffer packet, int length) { if (0 == termBuffer.GetInt(termOffset)) { termBuffer.PutBytes(termOffset + DataHeaderFlyweight.HEADER_LENGTH, packet, DataHeaderFlyweight.HEADER_LENGTH, length - DataHeaderFlyweight.HEADER_LENGTH); termBuffer.PutLong(termOffset + 24, packet.GetLong(24)); termBuffer.PutLong(termOffset + 16, packet.GetLong(16)); termBuffer.PutLong(termOffset + 8, packet.GetLong(8)); termBuffer.PutLongOrdered(termOffset, packet.GetLong(0)); } }
public void ShouldPutBytesToBuffer(IAtomicBuffer buffer) { var testBytes = Encoding.UTF8.GetBytes("Hello World"); buffer.PutBytes(Index, testBytes); var buff = new byte[testBytes.Length]; for (var i = 0; i < testBytes.Length; i++) { buff[i] = Marshal.ReadByte(buffer.BufferPointer, Index + i); } Assert.That(buff, Is.EqualTo(testBytes)); }
public void ShouldInsertIntoEmptyBuffer() { UnsafeBuffer packet = new UnsafeBuffer(new byte[256]); const int termOffset = 0; const int srcOffset = 0; const int length = 256; packet.PutInt(srcOffset, length); A.CallTo(() => _termBuffer.GetInt(0)).Returns(length); TermRebuilder.Insert(_termBuffer, termOffset, packet, length); A.CallTo(() => _termBuffer.PutBytes(termOffset, packet, srcOffset, length)).MustHaveHappened() .Then(A.CallTo(() => _termBuffer.PutIntOrdered(termOffset, length)).MustHaveHappened()); }