Ejemplo n.º 1
0
    /// <summary>
    /// Create a <seealso cref="ReplayMerge"/> to manage the merging of a replayed stream and switching over to live stream as
    /// appropriate.
    /// </summary>
    /// <param name="subscription">           to use for the replay and live stream. Must be a multi-destination subscription. </param>
    /// <param name="archive">                to use for the replay. </param>
    /// <param name="replayChannel">          to use for the replay. </param>
    /// <param name="replayDestination">      to send the replay to and the destination added by the <seealso cref="Subscription"/>. </param>
    /// <param name="liveDestination">        for the live stream and the destination added by the <seealso cref="Subscription"/>. </param>
    /// <param name="recordingId">            for the replay. </param>
    /// <param name="startPosition">          for the replay. </param>
    /// <param name="epochClock">             to use for progress checks. </param>
    /// <param name="mergeProgressTimeoutMs"> to use for progress checks. </param>
    public ReplayMerge(Subscription subscription, AeronArchive archive, string replayChannel, string replayDestination,
                       string liveDestination, long recordingId, long startPosition, IEpochClock epochClock,
                       long mergeProgressTimeoutMs)
    {
        if (subscription.Channel.StartsWith(IPC_CHANNEL) || replayChannel.StartsWith(IPC_CHANNEL) ||
            replayDestination.StartsWith(IPC_CHANNEL) || liveDestination.StartsWith(IPC_CHANNEL))
        {
            throw new System.ArgumentException("IPC merging is not supported");
        }

        ChannelUri subscriptionChannelUri = ChannelUri.Parse(subscription.Channel);

        if (!MDC_CONTROL_MODE_MANUAL.Equals(subscriptionChannelUri.Get(MDC_CONTROL_MODE_PARAM_NAME)))
        {
            throw new ArgumentException("Subscription must have manual control-mode: control-mode=" +
                                        subscriptionChannelUri.Get(MDC_CONTROL_MODE_PARAM_NAME));
        }

        ChannelUri replayChannelUri = ChannelUri.Parse(replayChannel);

        replayChannelUri.Put(LINGER_PARAM_NAME, "0");
        replayChannelUri.Put(EOS_PARAM_NAME, "false");

        this.archive                = archive;
        this.subscription           = subscription;
        this.epochClock             = epochClock;
        this.replayDestination      = replayDestination;
        this.replayChannel          = replayChannelUri.ToString();
        this.liveDestination        = liveDestination;
        this.recordingId            = recordingId;
        this.startPosition          = startPosition;
        this.timeOfLastProgressMs   = epochClock.Time();
        this.mergeProgressTimeoutMs = mergeProgressTimeoutMs;

        subscription.AsyncAddDestination(replayDestination);
    }
Ejemplo n.º 2
0
    private int AttemptLiveJoin(long nowMs)
    {
        int workCount = 0;

        if (Aeron.NULL_VALUE == activeCorrelationId)
        {
            long correlationId = archive.Ctx().AeronClient().NextCorrelationId();

            if (archive.Proxy().GetRecordingPosition(recordingId, correlationId, archive.ControlSessionId()))
            {
                activeCorrelationId  = correlationId;
                timeOfLastProgressMs = nowMs;
                workCount           += 1;
            }
        }
        else if (PollForResponse(archive, activeCorrelationId))
        {
            nextTargetPosition  = PolledRelevantId(archive);
            activeCorrelationId = Aeron.NULL_VALUE;

            if (AeronArchive.NULL_POSITION == nextTargetPosition)
            {
                long correlationId = archive.Ctx().AeronClient().NextCorrelationId();

                if (archive.Proxy().GetRecordingPosition(recordingId, correlationId, archive.ControlSessionId()))
                {
                    activeCorrelationId  = correlationId;
                    timeOfLastProgressMs = nowMs;
                }
            }
            else
            {
                State nextState = State.CATCHUP;

                if (null != image)
                {
                    long position = image.Position;

                    if (ShouldAddLiveDestination(position))
                    {
                        subscription.AsyncAddDestination(liveDestination);
                        timeOfLastProgressMs = nowMs;
                        isLiveAdded          = true;
                    }
                    else if (ShouldStopAndRemoveReplay(position))
                    {
                        subscription.AsyncRemoveDestination(replayDestination);
                        StopReplay();
                        timeOfLastProgressMs = nowMs;
                        nextState            = State.MERGED;
                    }
                }

                SetState(nextState);
            }

            workCount += 1;
        }

        return(workCount);
    }