Esempio 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);
    }
Esempio n. 2
0
        /// <summary>
        /// To be called when a new leader event is delivered. This method needs to be called when using the
        /// <seealso cref="EgressAdapter"/> or <seealso cref="EgressPoller"/> rather than <seealso cref="#pollEgress()"/> method.
        /// </summary>
        /// <param name="clusterSessionId"> which must match <seealso cref="#clusterSessionId()"/>. </param>
        /// <param name="leaderMemberId">   which has become the new leader. </param>
        /// <param name="memberEndpoints">  comma separated list of cluster members endpoints to connect to with the leader first. </param>
        public void OnNewLeader(long clusterSessionId, int leaderMemberId, string memberEndpoints)
        {
            if (clusterSessionId != _clusterSessionId)
            {
                throw new ClusterException("invalid clusterSessionId=" + clusterSessionId + " expected " +
                                           _clusterSessionId);
            }

            _leaderMemberId = leaderMemberId;

            if (_isUnicast)
            {
                _publication?.Dispose();
                _fragmentAssembler.Clear();
                UpdateMemberEndpoints(memberEndpoints);

                ChannelUri channelUri = ChannelUri.Parse(_ctx.IngressChannel());
                channelUri.Put(Aeron.Aeron.Context.ENDPOINT_PARAM_NAME, _endpointByMemberIdMap[leaderMemberId]);
                _publication = AddIngressPublication(channelUri.ToString(), _ctx.IngressStreamId());
            }
        }
Esempio n. 3
0
        private Publication ConnectToCluster()
        {
            Publication publication     = null;
            string      ingressChannel  = _ctx.IngressChannel();
            int         ingressStreamId = _ctx.IngressStreamId();
            long        deadlineNs      = _nanoClock.NanoTime() + _ctx.MessageTimeoutNs();

            if (_isUnicast)
            {
                ChannelUri    channelUri   = ChannelUri.Parse(ingressChannel);
                int           memberCount  = _endpointByMemberIdMap.Count;
                Publication[] publications = new Publication[memberCount];

                foreach (var entry in _endpointByMemberIdMap)
                {
                    channelUri.Put(Aeron.Aeron.Context.ENDPOINT_PARAM_NAME, entry.Value);
                    string channel = channelUri.ToString();
                    publications[entry.Key] = AddIngressPublication(channel, ingressStreamId);
                }

                int connectedIndex = -1;
                while (true)
                {
                    for (int i = 0; i < memberCount; i++)
                    {
                        if (publications[i].IsConnected)
                        {
                            connectedIndex = i;
                            break;
                        }
                    }

                    if (-1 != connectedIndex)
                    {
                        for (int i = 0; i < memberCount; i++)
                        {
                            if (i == connectedIndex)
                            {
                                publication = publications[i];
                            }
                            else
                            {
                                publications[i]?.Dispose();
                            }
                        }

                        break;
                    }

                    if (_nanoClock.NanoTime() > deadlineNs)
                    {
                        for (int i = 0; i < memberCount; i++)
                        {
                            CloseHelper.QuietDispose(publications[i]);
                        }

                        throw new TimeoutException("awaiting connection to cluster");
                    }

                    _idleStrategy.Idle();
                }
            }
            else
            {
                publication = AddIngressPublication(ingressChannel, ingressStreamId);

                _idleStrategy.Reset();
                while (!publication.IsConnected)
                {
                    if (_nanoClock.NanoTime() > deadlineNs)
                    {
                        CloseHelper.QuietDispose(publication);

                        throw new TimeoutException("awaiting connection to cluster");
                    }

                    _idleStrategy.Idle();
                }
            }

            return(publication);
        }