/**
   * Called from the {@link DriverConductor}.
   *
   * @param now in nanoseconds
   * @param statusMessageTimeout for sending of Status Messages.
   */
  void trackRebuild(final long now, final long statusMessageTimeout) {
    long minSubscriberPosition = Long.MAX_VALUE;
    long maxSubscriberPosition = Long.MIN_VALUE;

    for (final ReadablePosition subscriberPosition : subscriberPositions) {
      final long position = subscriberPosition.getVolatile();
      minSubscriberPosition = Math.min(minSubscriberPosition, position);
      maxSubscriberPosition = Math.max(maxSubscriberPosition, position);
    }

    final long rebuildPosition = Math.max(this.rebuildPosition.get(), maxSubscriberPosition);
    final long hwmPosition = this.hwmPosition.getVolatile();

    final long scanOutcome =
        lossDetector.scan(
            termBuffers[indexByPosition(rebuildPosition, positionBitsToShift)],
            rebuildPosition,
            hwmPosition,
            now,
            termLengthMask,
            positionBitsToShift,
            initialTermId);

    final int rebuildTermOffset = (int) rebuildPosition & termLengthMask;
    final long newRebuildPosition =
        (rebuildPosition - rebuildTermOffset) + rebuildOffset(scanOutcome);
    this.rebuildPosition.proposeMaxOrdered(newRebuildPosition);

    final long ccOutcome =
        congestionControl.onTrackRebuild(
            now,
            minSubscriberPosition,
            nextSmPosition,
            hwmPosition,
            rebuildPosition,
            newRebuildPosition,
            lossFound(scanOutcome));

    final int window = CongestionControlUtil.receiverWindowLength(ccOutcome);
    final long threshold = CongestionControlUtil.positionThreshold(window);

    if (CongestionControlUtil.shouldForceStatusMessage(ccOutcome)
        || (now > (lastStatusMessageTimestamp + statusMessageTimeout))
        || (minSubscriberPosition > (nextSmPosition + threshold))) {
      scheduleStatusMessage(now, minSubscriberPosition, window);
      cleanBufferTo(minSubscriberPosition - (termLengthMask + 1));
    }
  }