Ejemplo n.º 1
0
        /// <summary>
        /// Abort the given session.
        /// </summary>
        /// <param name="session">Session to Abort</param>
        /// <returns>true if session aborted, false otherwise</returns>
        bool AbortSession(IReliableMessagingSession session)
        {
            bool abortOccurred = true;

            try
            {
                LogHelper.Log("SessionId: {0}; Entering AbortSession", this.SessionId);

                session.Abort();
            }
            catch (Exception e)
            {
                // this may occur because either the session closed before abort or because the abort at the
                // opposite end caused a message driven abort before the API could be invoked
                Assert.AreEqual(e.GetType(), typeof(InvalidOperationException), "Unexpected exception in AbortSession");
                abortOccurred = false;
            }

            LogHelper.Log("SessionId: {0}; Exiting AbortSession", this.SessionId);
            return(abortOccurred);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// When the OutBoundSessionDriver is disposed, Abort and clear the corresponding outbound session.
        /// </summary>
        /// <param name="targetPartition">Clear the Reliable MessagingSession for the target Partition</param>
        internal void ClearOutboundSession(PartitionKey targetPartition)
        {
            FabricEvents.Events.ClearOutboundSession("Start@" + this.streamManager.TraceType, targetPartition.ToString(), "");
            IReliableMessagingSession outboundSession = null;

            var normalizedPartition = this.GetNormalizedPartitionKey(targetPartition);

            var found = this.activeOutboundSessions.TryRemove(normalizedPartition, out outboundSession);

            if (found)
            {
                var snapshot = outboundSession.GetDataSnapshot();
                outboundSession.Abort();
                FabricEvents.Events.ClearOutboundSession(
                    "Aborted@" + this.streamManager.TraceType,
                    normalizedPartition.ToString(),
                    snapshot.SessionId.ToString());
            }
            else
            {
                FabricEvents.Events.ClearOutboundSession("NotFound@" + this.streamManager.TraceType, normalizedPartition.ToString(), "");
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Instantiates a Reliable Messaging Session for a given target partition.
        /// </summary>
        /// <param name="targetPartition">Target Partition</param>
        /// <param name="timeout">Timeout for the operation to complete</param>
        /// <returns>Reliable Messaging Session for the Target Partition</returns>
        internal async Task <IReliableMessagingSession> SetupSession(PartitionKey targetPartition, TimeSpan timeout)
        {
            string endpoint     = null;
            var    setupSuccess = false;
            IReliableMessagingSession session = null;
            var baseOpenAsyncTimeout          = 0;
            var remainingTimeout         = timeout;
            SessionDataSnapshot snapshot = null;

            try
            {
                while (!setupSuccess)
                {
                    var beforeGetEndpoint = DateTime.UtcNow;

                    // Get End point for this Partition
                    var partitionInfo = await this.GetEndpointAsync(targetPartition, remainingTimeout);

                    endpoint = partitionInfo.EndPoint;

                    FabricEvents.Events.SetupSession("Start@" + this.streamManager.TraceType, targetPartition.ToString(), endpoint, Guid.Empty.ToString());

                    var afterGetEndpoint = DateTime.UtcNow;

                    remainingTimeout = TimeoutHandler.UpdateTimeout(remainingTimeout, beforeGetEndpoint, afterGetEndpoint);

                    session = await this.CreateSession(targetPartition, endpoint);

                    var retry = false;

                    snapshot = session.GetDataSnapshot();

                    FabricEvents.Events.SetupSession(
                        "OpenSession.Start@" + this.streamManager.TraceType,
                        targetPartition.ToString(),
                        endpoint,
                        snapshot.SessionId.ToString());

                    var openTask = session.OpenAsync(CancellationToken.None);

                    var beforeOpenWait = DateTime.UtcNow;

                    baseOpenAsyncTimeout = baseOpenAsyncTimeout >= StreamConstants.MaxDelayForValidSessionEndpoint
                        ? StreamConstants.MaxDelayForValidSessionEndpoint
                        : baseOpenAsyncTimeout + StreamConstants.BaseDelayForValidSessionEndpoint;

                    var baseTimeSpan     = new TimeSpan(0, 0, 0, 0, baseOpenAsyncTimeout);
                    var openAsyncTimeout = (baseTimeSpan < remainingTimeout) || (remainingTimeout == Timeout.InfiniteTimeSpan) ? baseTimeSpan : remainingTimeout;

                    // this timeout is a retry mechanism in case we are going to the wrong endpoint because the primary replica is moving
                    var openTaskCompleted = await TimeoutHandler.WaitWithDelay(openAsyncTimeout, openTask);

                    var afterOpenWait = DateTime.UtcNow;
                    remainingTimeout = TimeoutHandler.UpdateTimeout(remainingTimeout, beforeOpenWait, afterOpenWait);

                    if (openTaskCompleted && openTask.Exception == null)
                    {
                        FabricEvents.Events.SetupSession(
                            "OpenSession.Finish@" + this.streamManager.TraceType,
                            targetPartition.ToString(),
                            endpoint,
                            snapshot.SessionId.ToString());
                        setupSuccess = true;
                    }
                    else if (openTask.Exception != null)
                    {
                        if (openTask.Exception.InnerException.GetType() == typeof(FabricException))
                        {
                            var fabricException = openTask.Exception.InnerException as FabricException;

                            if (fabricException.ErrorCode == FabricErrorCode.ReliableSessionManagerNotFound)
                            {
                                // Target partition primary may be moving to a different host process before session manager was created
                                retry = true;
                            }
                        }
                        else
                        {
                            Tracing.WriteExceptionAsError(
                                "SetupSession.OpenSession.UnrecoverableError",
                                openTask.Exception,
                                "{0} Target: {1}",
                                this.tracer,
                                targetPartition);
                            throw openTask.Exception;
                        }
                    }
                    else
                    {
                        FabricEvents.Events.SetupSession(
                            "OpenSession.RetryTimeout@" + this.streamManager.TraceType,
                            targetPartition.ToString(),
                            endpoint,
                            snapshot.SessionId.ToString());
                        retry = true;
                    }

                    if (retry)
                    {
                        session.Abort();
                        session      = null;
                        setupSuccess = false;
                    }
                    else
                    {
                        // control should never come here if we did not succeed; we should have thrown any non-retriable exception or set retry=true for a retriable exception
                        Diagnostics.Assert(setupSuccess, "SetupSession.CodingError {0} Target: {1}", this.tracer, targetPartition);
                    }
                }
            }
            catch (TimeoutException)
            {
                if (session != null)
                {
                    // Abort the session and leave a clean slate for the next time we try to set up the session: we don't want a ReliableSessionAlreadyExists exception
                    session.Abort();
                    session = null;
                }

                throw;
            }
            catch (FabricObjectClosedException)
            {
                // this can happen if the session manager was closed by a parallel thread due to role change
                var endpointString  = endpoint ?? "NullEndpoint";
                var sessionIdString = snapshot == null ? "NoSessionCreated" : snapshot.SessionId.ToString();

                FabricEvents.Events.SetupSession(
                    "ObjectClosed@" + this.streamManager.TraceType,
                    targetPartition.ToString(),
                    endpointString,
                    sessionIdString);
                throw;
            }
            catch (Exception e)
            {
                Tracing.WriteExceptionAsError("SetupSession.Failure", e, "Source: {0} Target: {1}", this.tracer, targetPartition);

                Diagnostics.Assert(
                    false,
                    "{0} Unexpected exception {1} in SessionConnectionManager.SetupSession for Target: {2}",
                    this.tracer,
                    e.GetType(),
                    targetPartition);
            }

            Diagnostics.Assert(
                session != null,
                "{0} SessionConnectionManager.SetupSession returning null session for Target: {1}",
                this.tracer,
                targetPartition);

            if (session != null)
            {
                snapshot = session.GetDataSnapshot();

                Diagnostics.Assert(
                    snapshot.IsOpenForSend,
                    "SessionConnectionManager.SetupSession returning session that is not open for send for Source: {0} Target: {1}",
                    this.tracer,
                    targetPartition);

                FabricEvents.Events.SetupSession(
                    "Finish@" + this.streamManager.TraceType,
                    targetPartition.ToString(),
                    endpoint,
                    snapshot.SessionId.ToString());
            }
            return(session);
        }