Exemplo n.º 1
0
        /// <summary>
        /// Constructor to create an instance of the OutboundSessionDriver for a given Partition.
        /// </summary>
        /// <param name="targetPartition">Session for the Target Partition</param>
        /// <param name="streamManager">Steam Manager where messages are sent to the session queue</param>
        /// <param name="sessionConnectionManager">Session Connection manager, which creates and actively manages the session</param>
        /// <param name="outboundSession">The session we will use to send out messages</param>
        internal OutboundSessionDriver(
            PartitionKey targetPartition, StreamManager streamManager, SessionConnectionManager sessionConnectionManager,
            IReliableMessagingSession outboundSession)
        {
            // Assign relevent association to targetPartitions, Stream manager, and connection manager.
            this.targetPartition          = targetPartition;
            this.streamManager            = streamManager;
            this.sessionConnectionManager = sessionConnectionManager;
            // Instantiate the message queue.
            this.sessionQueue = new ConcurrentQueue <IOperationData>();
            // The targetPartition Session
            this.outboundSession = outboundSession;
            // The appropriate Session ID for tracing
            var snapshot = outboundSession.GetDataSnapshot();

            this.SessionId = snapshot.SessionId;
            // Set default values.
            this.drainQueueBarrier = 0;
            this.tracer            = streamManager.Tracer + " Target: " + this.targetPartition;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Called to find(or create if one is not found) the appropriate OutboundSessionDriver for a given partition.
        /// This method will ensure that we have a one(targetPartition)-to-one(outBoundSessionDriver) relationship.
        ///
        /// TODO: this layer must catch all exceptions and decide what to do with them -- lower layer functions like ResolveAndNormalizeTargetPartition
        /// will throw in case of unrecoverable errors like FabricObjectClosedException
        /// </summary>
        /// <param name="targetPartition">Find or Create OutBoundSessionDriver for this Partition</param>
        /// <param name="streamManager">Stream manager that manages the reference to the driver</param>
        /// <param name="sessionConnectionManager">Use this session connection manager to create a new session if one if not found</param>
        /// <param name="timeout">Timeout</param>
        /// <returns>Returns OutboundSessionDriver if successfull, null otherwise</returns>
        internal static async Task <OutboundSessionDriver> FindOrCreateDriverAsync(
            PartitionKey targetPartition,
            StreamManager streamManager,
            SessionConnectionManager sessionConnectionManager,
            TimeSpan timeout)
        {
            OutboundSessionDriver streamOutboundSessionDriver = null;
            // Complete the call within this time.
            var remainingTimeout = timeout;

            try
            {
                FabricEvents.Events.FindOrCreateOutboundSessionDriver("Start@" + streamManager.TraceType, targetPartition.ToString());
                var beforeResolve = DateTime.UtcNow;

                // The sync point pattern is used here because lock() pattern is not compatible with await pattern
                var normalizedPartitionKey = await streamManager.SessionConnectionManager.ResolveAndNormalizeTargetPartition(targetPartition, remainingTimeout);

                Diagnostics.Assert(
                    null != normalizedPartitionKey,
                    "normalizedPartitionKey is not expected to be null in OutboundSessionDriver.FindOrCreateDriverAsync().");

                // Update remaining time for timeout
                var afterResolve = DateTime.UtcNow;
                remainingTimeout = TimeoutHandler.UpdateTimeout(remainingTimeout, beforeResolve, afterResolve);

                var syncPoint
                    = new SyncPoint <PartitionKey>(
                          streamManager,
                          normalizedPartitionKey,
                          streamManager.RuntimeResources.OutboundSessionDriverSyncpoints);

                try
                {
                    // this is entering an await compatible critical section -- syncPoint.Dispose will leave it
                    await syncPoint.EnterAsync(remainingTimeout);

                    var afterEnter = DateTime.UtcNow;
                    remainingTimeout = TimeoutHandler.UpdateTimeout(remainingTimeout, afterResolve, afterEnter);

                    // Check if the driver already exists
                    var exists = streamManager.RuntimeResources.OutboundSessionDrivers.TryGetValue(normalizedPartitionKey, out streamOutboundSessionDriver);

                    // TODO: should we refcount how many streams depend on this session?

                    // create a new driver if if it does not exist already
                    if (!exists)
                    {
                        FabricEvents.Events.FindOrCreateOutboundSessionDriver("Creating@" + streamManager.TraceType, normalizedPartitionKey.ToString());

                        // we are actually the first stream attaching to this partition on start or recovery or all previous ones closed

                        // Find or create a new reliable messaging session
                        var session = await sessionConnectionManager.FindOrCreateOutboundSessionAsync(normalizedPartitionKey, remainingTimeout);

                        Diagnostics.Assert(null != session, "Session is not expected to be null in OutboundSessionDriver.FindOrCreateDriverAsync().");

                        // Create a new outbound session driver
                        streamOutboundSessionDriver = new OutboundSessionDriver(normalizedPartitionKey, streamManager, sessionConnectionManager, session);
                        Diagnostics.Assert(
                            null != streamOutboundSessionDriver,
                            "Stream OutboundSessionDriver is not expected to be null in OutboundSessionDriver.FindOrCreateDriverAsync().");

                        // Add ref. to stream manager active runtime resources
                        var addSuccess = streamManager.RuntimeResources.OutboundSessionDrivers.TryAdd(normalizedPartitionKey, streamOutboundSessionDriver);
                        Diagnostics.Assert(
                            addSuccess,
                            "{0} Unexpected failure to add newSessionDriver in OutboundSessionDriver.FindOrCreateDriverAsync",
                            streamManager.Tracer);
                    }
                    else
                    {
                        FabricEvents.Events.FindOrCreateOutboundSessionDriver("Found@" + streamManager.TraceType, normalizedPartitionKey.ToString());
                    }
                }
                finally
                {
                    syncPoint.Dispose();
                }
                FabricEvents.Events.FindOrCreateOutboundSessionDriver("Finish@" + streamManager.TraceType, normalizedPartitionKey.ToString());
            }
            catch (TimeoutException)
            {
                FabricEvents.Events.FindOrCreateOutboundSessionDriver("Timeout@" + streamManager.TraceType, targetPartition.ToString());
                throw;
            }
            catch (Exception e)
            {
                Tracing.WriteExceptionAsWarning("FindOrCreateDriverAsync.Failure", e, "{0}", streamManager.Tracer);
                throw;
            }

            return(streamOutboundSessionDriver);
        }