예제 #1
0
        /// <summary>
        /// Run the test (send and receive messages) with sessions abort activity.
        /// </summary>
        /// <param name="delay"></param>
        public void RunTest(int delay)
        {
            LogHelper.Log("SessionId: {0}; Entering RunTest", this.SessionId);

            Assert.IsNotNull(this.InboundSession, "Null inbound session in RunTest for SessionId#{0}", this.SessionId);
            Assert.IsNotNull(this.OutboundSession, "Null outbound session in RunTest for SessionId#{0}", this.SessionId);

            Thread.Sleep(delay);

            Random myRandGen = new Random(unchecked ((int)DateTime.Now.Ticks));

            DateTime start = DateTime.Now;

            LogHelper.Log("SessionId: {0}; Started; MessageCount: {1}", this.SessionId, this.messageCount);

            // Send Action Delegate - Prepare and send the messages
            Action sendAction = (() => this.SendAndRecordMessages(myRandGen));
            // Receive Action Delegate - receive and record the messages
            Action receiveAction = (() => this.ReceiveAndRecordMessages());

            // Start the send and receive actions
            Task sendTask    = Task.Factory.StartNew(sendAction);
            Task receiveTask = Task.Factory.StartNew(receiveAction);

            // While the tests are running, randomly abort the sessions.
            bool abortOccurred = this.RunRandomSessionAbortTest(myRandGen);

            // Wait for the send and receive tasks to complete
            bool sendCompleted    = sendTask.Wait(Int32.MaxValue);
            bool receiveCompleted = receiveTask.Wait(Int32.MaxValue);

            Assert.IsTrue(sendCompleted, "sendCOmpleted false in RunTest for SessionId: {0} MessageCount: {1} Aborted: {2}", this.SnapshotOutbound.SessionId, this.messageCount, abortOccurred);
            Assert.IsTrue(receiveCompleted, "receiveCompleted false in RunTest for SessionId: {0} MessageCount: {1} Aborted: {2}", this.SnapshotInbound.SessionId, this.messageCount, abortOccurred);

            this.SnapshotInbound  = this.InboundSession.GetDataSnapshot();
            this.SnapshotOutbound = this.OutboundSession.GetDataSnapshot();

            DateTime finish = DateTime.Now;

            if (!abortOccurred)
            {
                Assert.AreEqual(this.totalBytesSent, this.totalBytesReceived,
                                "totalBytesSent != totalBytesReceived in RunTest for SessionId#{0}", this.SessionId);

                for (int i = 0; i < this.messageCount; i++)
                {
                    Assert.IsNotNull(this.flatMessagesSent[i], "flatMessagesSent[{0}] is NULL in RunTest for SessionId#{1}", i, this.SessionId);
                    Assert.IsNotNull(this.flatMessagesReceived[i], "flatMessagesReceived[{0}] is NULL in RunTest for SessionId#{1}", i, this.SessionId);

                    // message content is the same: sent and received
                    bool checkContent = Enumerable.SequenceEqual(this.flatMessagesReceived[i], this.flatMessagesSent[i]);

                    //message structure is the same: sent and received
                    int[] sentSizes      = this.actualMessagesSent[i].Select(elem => elem.Length).ToArray();
                    int[] receivedSizes  = this.actualMessagesReceived[i].Select(elem => elem.Length).ToArray();
                    bool  checkStructure = Enumerable.SequenceEqual(sentSizes, receivedSizes);

                    Assert.IsTrue(checkContent, "flatMessagesReceived[{0}] != flatMessagesSent[{0}] in RunTest for SessionId#{1}", i, this.SessionId);
                    Assert.IsTrue(checkStructure, "receivedSizes[{0}] != sentSizes[{0}] in RunTest for SessionId#{1}", i, this.SessionId);
                }

                LogHelper.Log("SessionId: {0}; Completed; MessageCount: {1}; Avg Size: {2}; Duration {3} MilliSeconds", this.SessionId, this.messageCount, this.totalBytesSent / this.messageCount, (finish.Ticks - start.Ticks) / TimeSpan.TicksPerMillisecond);
            }
            else
            {
                LogHelper.Log("SessionId: {0}; Aborted; MessageCount: {1}; Avg Size: {2}; Duration {3} MilliSeconds", this.SessionId, this.messageCount, this.totalBytesSent / this.messageCount, (finish.Ticks - start.Ticks) / TimeSpan.TicksPerMillisecond);
            }


            LogHelper.Log("SessionId: {0}; Exiting RunTest", this.SessionId);
        }
예제 #2
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);
        }