private LossDetector getLossHandlerWithImmediate() { return new LossDetector(DELAY_GENERATOR_WITH_IMMEDIATE, lossHandler); }
final long hwmPosition = this.hwmPosition.getVolatile(); final long scanOutcome = lossDetector.scan( termBuffers[indexByPosition(rebuildPosition, positionBitsToShift)], rebuildPosition, final long newRebuildPosition = (rebuildPosition - rebuildTermOffset) + rebuildOffset(scanOutcome); this.rebuildPosition.proposeMaxOrdered(newRebuildPosition); rebuildPosition, newRebuildPosition, lossFound(scanOutcome));
activateGap(nowNs, scannedGap); lossFound = true; checkTimerExpiry(nowNs); return pack(rebuildOffset, lossFound);
@Test public void shouldNotSendNakWhenBufferIsEmpty() { final long rebuildPosition = ACTIVE_TERM_POSITION; final long hwmPosition = ACTIVE_TERM_POSITION; lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); currentTime = TimeUnit.MILLISECONDS.toNanos(100); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); verifyZeroInteractions(lossHandler); }
@Test public void shouldStopNakOnReceivingData() { long rebuildPosition = ACTIVE_TERM_POSITION; final long hwmPosition = ACTIVE_TERM_POSITION + (ALIGNED_FRAME_LENGTH * 3); insertDataFrame(offsetOfMessage(0)); insertDataFrame(offsetOfMessage(2)); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); currentTime = TimeUnit.MILLISECONDS.toNanos(20); insertDataFrame(offsetOfMessage(1)); rebuildPosition += (ALIGNED_FRAME_LENGTH * 3); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); currentTime = TimeUnit.MILLISECONDS.toNanos(100); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); verifyZeroInteractions(lossHandler); }
final long hwmPosition = this.hwmPosition.getVolatile(); final long scanOutcome = lossDetector.scan( termBuffers[indexByPosition(rebuildPosition, positionBitsToShift)], rebuildPosition, final long newRebuildPosition = (rebuildPosition - rebuildTermOffset) + rebuildOffset(scanOutcome); this.rebuildPosition.proposeMaxOrdered(newRebuildPosition); rebuildPosition, newRebuildPosition, lossFound(scanOutcome));
activateGap(nowNs); lossFound = true; checkTimerExpiry(nowNs); return pack(rebuildOffset, lossFound);
@Test public void shouldRetransmitNakForMissingData() { final long rebuildPosition = ACTIVE_TERM_POSITION; final long hwmPosition = ACTIVE_TERM_POSITION + (ALIGNED_FRAME_LENGTH * 3); insertDataFrame(offsetOfMessage(0)); insertDataFrame(offsetOfMessage(2)); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); currentTime = TimeUnit.MILLISECONDS.toNanos(30); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); currentTime = TimeUnit.MILLISECONDS.toNanos(60); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); verify(lossHandler, atLeast(2)).onGapDetected(TERM_ID, offsetOfMessage(1), gapLength()); }
public LossDetectorTest() { lossHandler = mock(LossHandler.class); lossDetector = new LossDetector(DELAY_GENERATOR, lossHandler); dataHeader.wrap(rcvBuffer); }
final long hwmPosition = this.hwmPosition.getVolatile(); final long scanOutcome = lossDetector.scan( termBuffers[indexByPosition(rebuildPosition, positionBitsToShift)], rebuildPosition, final long newRebuildPosition = (rebuildPosition - rebuildTermOffset) + rebuildOffset(scanOutcome); this.rebuildPosition.proposeMaxOrdered(newRebuildPosition); rebuildPosition, newRebuildPosition, lossFound(scanOutcome));
activateGap(nowNs); lossFound = true; checkTimerExpiry(nowNs); return pack(rebuildOffset, lossFound);
@Test public void shouldNotNakIfNoMissingData() { final long rebuildPosition = ACTIVE_TERM_POSITION; final long hwmPosition = ACTIVE_TERM_POSITION + (ALIGNED_FRAME_LENGTH * 3); insertDataFrame(offsetOfMessage(0)); insertDataFrame(offsetOfMessage(1)); insertDataFrame(offsetOfMessage(2)); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); currentTime = TimeUnit.MILLISECONDS.toNanos(40); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); verifyZeroInteractions(lossHandler); }
lossDetector = new LossDetector(lossFeedbackDelayGenerator, this);
@Test public void shouldNakMissingData() { final long rebuildPosition = ACTIVE_TERM_POSITION; final long hwmPosition = ACTIVE_TERM_POSITION + (ALIGNED_FRAME_LENGTH * 3); insertDataFrame(offsetOfMessage(0)); insertDataFrame(offsetOfMessage(2)); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); currentTime = TimeUnit.MILLISECONDS.toNanos(40); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); verify(lossHandler).onGapDetected(TERM_ID, offsetOfMessage(1), gapLength()); }
lossDetector = new LossDetector(lossFeedbackDelayGenerator, this);
@Test public void shouldReplaceOldNakWithNewNak() { long rebuildPosition = ACTIVE_TERM_POSITION; long hwmPosition = ACTIVE_TERM_POSITION + (ALIGNED_FRAME_LENGTH * 3); insertDataFrame(offsetOfMessage(0)); insertDataFrame(offsetOfMessage(2)); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); currentTime = TimeUnit.MILLISECONDS.toNanos(20); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); insertDataFrame(offsetOfMessage(4)); insertDataFrame(offsetOfMessage(1)); rebuildPosition += (ALIGNED_FRAME_LENGTH * 3); hwmPosition = (ALIGNED_FRAME_LENGTH * 5); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); currentTime = TimeUnit.MILLISECONDS.toNanos(100); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); verify(lossHandler, atLeast(1)).onGapDetected(TERM_ID, offsetOfMessage(3), gapLength()); }
lossDetector = new LossDetector(lossFeedbackDelayGenerator, this);
@Test public void shouldOnlySendNaksOnceOnMultipleScans() { lossDetector = getLossHandlerWithImmediate(); final long rebuildPosition = ACTIVE_TERM_POSITION; final long hwmPosition = ACTIVE_TERM_POSITION + (ALIGNED_FRAME_LENGTH * 3); insertDataFrame(offsetOfMessage(0)); insertDataFrame(offsetOfMessage(2)); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); verify(lossHandler).onGapDetected(TERM_ID, offsetOfMessage(1), gapLength()); }
@Test public void shouldNotNakImmediatelyByDefault() { final long rebuildPosition = ACTIVE_TERM_POSITION; final long hwmPosition = ACTIVE_TERM_POSITION + (ALIGNED_FRAME_LENGTH * 3); insertDataFrame(offsetOfMessage(0)); insertDataFrame(offsetOfMessage(2)); lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); verifyZeroInteractions(lossHandler); }
@Test public void shouldHandleHwmGreaterThanCompletedBuffer() { lossDetector = getLossHandlerWithImmediate(); long rebuildPosition = ACTIVE_TERM_POSITION; final long hwmPosition = ACTIVE_TERM_POSITION + TERM_BUFFER_LENGTH + ALIGNED_FRAME_LENGTH; insertDataFrame(offsetOfMessage(0)); rebuildPosition += ALIGNED_FRAME_LENGTH; lossDetector.scan(termBuffer, rebuildPosition, hwmPosition, currentTime, MASK, POSITION_BITS_TO_SHIFT, TERM_ID); verify(lossHandler).onGapDetected(TERM_ID, offsetOfMessage(1), TERM_BUFFER_LENGTH - (int)rebuildPosition); }