/// <summary> /// Poll for new messages in a stream. If new messages are found beyond the last consumed position then they /// will be delivered to the <seealso cref="IBlockHandler"/> up to a limited number of bytes. /// /// 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="handler"> to which block is delivered. </param> /// <param name="blockLengthLimit"> up to which a block may be in length. </param> /// <returns> the number of bytes that have been consumed. </returns> public int BlockPoll(BlockHandler handler, int blockLengthLimit) { if (_isClosed) { return(0); } var position = _subscriberPosition.Get(); var offset = (int)position & _termLengthMask; var termBuffer = ActiveTermBuffer(position); var limitOffset = Math.Min(offset + blockLengthLimit, termBuffer.Capacity); var resultingOffset = TermBlockScanner.Scan(termBuffer, offset, limitOffset); var length = resultingOffset - offset; if (resultingOffset > offset) { try { var termId = termBuffer.GetInt(offset + DataHeaderFlyweight.TERM_ID_FIELD_OFFSET); handler(termBuffer, offset, length, SessionId, termId); } catch (Exception t) { _errorHandler(t); } finally { _subscriberPosition.SetOrdered(position + length); } } return(length); }
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> /// Poll for new messages in a stream. If new messages are found beyond the last consumed position then they /// will be delivered to the <seealso cref="IBlockHandler"/> up to a limited number of bytes. /// </summary> /// <param name="blockHandler"> to which block is delivered. </param> /// <param name="blockLengthLimit"> up to which a block may be in length. </param> /// <returns> the number of bytes that have been consumed. </returns> public int BlockPoll(IBlockHandler blockHandler, int blockLengthLimit) { if (_isClosed) { return(0); } var position = _subscriberPosition.Get(); var termOffset = (int)position & _termLengthMask; var termBuffer = ActiveTermBuffer(position); var limit = Math.Min(termOffset + blockLengthLimit, termBuffer.Capacity); var resultingOffset = TermBlockScanner.Scan(termBuffer, termOffset, limit); var bytesConsumed = resultingOffset - termOffset; if (resultingOffset > termOffset) { try { var termId = termBuffer.GetInt(termOffset + DataHeaderFlyweight.TERM_ID_FIELD_OFFSET); blockHandler.OnBlock(termBuffer, termOffset, bytesConsumed, SessionId, termId); } catch (Exception t) { _errorHandler(t); } _subscriberPosition.SetOrdered(position + bytesConsumed); } return(bytesConsumed); }
/** * Poll for new messages in a stream. If new messages are found beyond the last consumed position then they * will be delivered to the {@link FileBlockHandler} up to a limited number of bytes. * * @param fileBlockHandler to which block is delivered. * @param blockLengthLimit up to which a block may be in length. * @return the number of bytes that have been consumed. */ public int filePoll(FileBlockHandler fileBlockHandler, int blockLengthLimit) { if (isClosed) { return(0); } long position = subscriberPosition.get(); int termOffset = (int)position & termLengthMask; int activeIndex = indexByPosition(position, positionBitsToShift); DirectBuffer termBuffer = termBuffers[activeIndex]; int capacity = termBuffer.capacity(); int limit = Math.min(termOffset + blockLengthLimit, capacity); int resultingOffset = TermBlockScanner.scan(termBuffer, termOffset, limit); int bytesConsumed = resultingOffset - termOffset; if (resultingOffset > termOffset) { try { long offset = ((long)capacity * activeIndex) + termOffset; int termId = termBuffer.getInt(termOffset + TERM_ID_FIELD_OFFSET, LITTLE_ENDIAN); fileBlockHandler.onBlock(logBuffers.fileChannel(), offset, bytesConsumed, sessionId, termId); } catch (Throwable t) { errorHandler.onError(t); } subscriberPosition.setOrdered(position + bytesConsumed); } return(bytesConsumed); }
/** * Poll for new messages in a stream. If new messages are found beyond the last consumed position then they * will be delivered to the {@link BlockHandler} up to a limited number of bytes. * * @param blockHandler to which block is delivered. * @param blockLengthLimit up to which a block may be in length. * @return the number of bytes that have been consumed. */ public int blockPoll(BlockHandler blockHandler, int blockLengthLimit) { if (isClosed) { return(0); } long position = subscriberPosition.get(); int termOffset = (int)position & termLengthMask; DirectBuffer termBuffer = activeTermBuffer(position); int limit = Math.min(termOffset + blockLengthLimit, termBuffer.capacity()); int resultingOffset = TermBlockScanner.scan(termBuffer, termOffset, limit); int bytesConsumed = resultingOffset - termOffset; if (resultingOffset > termOffset) { try { int termId = termBuffer.getInt(termOffset + TERM_ID_FIELD_OFFSET, LITTLE_ENDIAN); blockHandler.onBlock(termBuffer, termOffset, bytesConsumed, sessionId, termId); } catch (Throwable t) { errorHandler.onError(t); } subscriberPosition.setOrdered(position + bytesConsumed); } return(bytesConsumed); }
public void ShouldScanEmptyBuffer() { const int offset = 0; int limit = _termBuffer.Capacity; int newOffset = TermBlockScanner.Scan(_termBuffer, offset, limit); Assert.AreEqual(offset, newOffset); }
public void ShouldReadFirstMessage() { const int offset = 0; int limit = _termBuffer.Capacity; const int messageLength = 50; int alignedMessageLength = BitUtil.Align(messageLength, FrameDescriptor.FRAME_ALIGNMENT); A.CallTo(() => _termBuffer.GetIntVolatile(FrameDescriptor.LengthOffset(offset))) .Returns(messageLength); int newOffset = TermBlockScanner.Scan(_termBuffer, offset, limit); Assert.That(newOffset, Is.EqualTo(alignedMessageLength)); }
public void ShouldReadOneMessageOnLimit() { const int offset = 0; const int messageLength = 50; int alignedMessageLength = BitUtil.Align(messageLength, FrameDescriptor.FRAME_ALIGNMENT); int limit = alignedMessageLength; A.CallTo(() => _termBuffer.GetIntVolatile(FrameDescriptor.LengthOffset(offset))) .Returns(messageLength); int newOffset = TermBlockScanner.Scan(_termBuffer, offset, limit); Assert.AreEqual(alignedMessageLength, newOffset); }
public void ShouldReadFirstMessage() { const int offset = 0; int limit = _termBuffer.Capacity; const int messageLength = 50; int alignedMessageLength = BitUtil.Align(messageLength, FrameDescriptor.FRAME_ALIGNMENT); A.CallTo(() => _termBuffer.GetIntVolatile(FrameDescriptor.LengthOffset(offset))) .Returns(messageLength); A.CallTo(() => _termBuffer.GetShort(FrameDescriptor.TypeOffset(offset))) .Returns((short)HeaderFlyweight.HDR_TYPE_DATA); int newOffset = TermBlockScanner.Scan(_termBuffer, offset, limit); Assert.AreEqual(alignedMessageLength, newOffset); }
public void ShouldReadBlockOfOneMessageThenPadding() { const int offset = 0; int limit = _termBuffer.Capacity; int messageLength = 50; int alignedMessageLength = BitUtil.Align(messageLength, FrameDescriptor.FRAME_ALIGNMENT); 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_PAD); int firstOffset = TermBlockScanner.Scan(_termBuffer, offset, limit); Assert.That(firstOffset, Is.EqualTo(alignedMessageLength)); int secondOffset = TermBlockScanner.Scan(_termBuffer, firstOffset, limit); Assert.That(secondOffset, Is.EqualTo(alignedMessageLength * 2)); }