Esempio n. 1
0
 /// <summary>
 /// Initializes a new instance of the PullResponseMessage class
 /// </summary>
 /// <param name="count">indicating the count</param>
 /// <param name="queue">indicating the queue</param>
 /// <param name="convertMessage">indicating the convert message delegate</param>
 /// <param name="resetTimeout">indicating the reset timeout delegate</param>
 /// <param name="sharedData">indicating the shared data</param>
 public PullResponseMessage(int count, BrokerQueue queue, ConvertMessageDelegate convertMessage, ResetTimeoutDelegate resetTimeout, SharedData sharedData)
 {
     this.count          = count;
     this.queue          = queue;
     this.convertMessage = convertMessage;
     this.resetTimeout   = resetTimeout;
     this.sharedData     = sharedData;
 }
Esempio n. 2
0
        /// <summary>
        /// Setup the namespace.
        /// </summary>
        /// <returns></returns>
        public async Task SetupAsync()
        {
            // create broker context
            _brokerContext = await BrokerContext.CreateAsync(_connectionUri.ToString());

            // create broker
            _broker = await _brokerContext.CreateBrokerAsync(_node.Configuration.ApplicationId);

            // add returned handler
            _broker.Returned += delegate(object s, BrokerReturnedEventArgs e) {
                if (e.ID != Guid.Empty)
                {
                    TaskCompletionSource <Envelope> tcs;

                    lock (_replyWaits) {
                        // try and get the reply wait
                        if (!_replyWaits.TryGetValue(e.ID, out ReplyWait replyWait))
                        {
                            return;
                        }

                        // if this is a multi-reply do nothing
                        if (replyWait.Results != null)
                        {
                            return;
                        }

                        // remove and set exception
                        tcs = replyWait.CompletionSource;
                        _replyWaits.Remove(e.ID);
                    }

                    tcs.TrySetException(new ServiceNotFoundException("The envelope was returned before delivery"));
                }
            };

            // create reply queue
            try {
                // declare queue with unique name
                using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) {
                    // get unique string
                    byte[] uniqueId = new byte[20];
                    rng.GetBytes(uniqueId);
                    string uniqueIdStr = BitConverter.ToString(uniqueId).Replace("-", "").ToLower();

                    // add the reply queue
                    _replyQueue = await _broker.CreateQueueAsync(string.Format("~reply:{1}%{0}", _node.UUID, uniqueIdStr), false, true, "", "", true, true, new Dictionary <string, object>() {
                        { "x-expires", (int)TimeSpan.FromMinutes(15).TotalMilliseconds }
                    }).ConfigureAwait(false);

                    // subscribe to reply queue
                    _replyQueue.AsObservable().Subscribe(new ReplyObserver(this));
                }
            } catch (Exception ex) {
                throw new InvalidOperationException("Failed to create node reply queue", ex);
            }
        }
Esempio n. 3
0
 /// <summary>
 /// Initializes a new instance of the BaseResponsesHandler class
 /// </summary>
 /// <param name="queue">indicating the broker queue</param>
 /// <param name="action">indicating the action</param>
 /// <param name="timeoutManager">indicating the timeout manager</param>
 /// <param name="observer">indicating the observer</param>
 /// <param name="sharedData">indicating the shared data</param>
 /// <param name="version">indicating the message version</param>
 protected BaseResponsesHandler(BrokerQueue queue, string action, TimeoutManager timeoutManager, BrokerObserver observer, SharedData sharedData, MessageVersion version)
 {
     this.queue          = queue;
     this.action         = action;
     this.timeoutManager = timeoutManager;
     this.observer       = observer;
     this.sharedData     = sharedData;
     this.version        = version;
 }
Esempio n. 4
0
        /// <summary>
        /// Changes the broker then creates the queue and internal consumer for this service.
        /// </summary>
        /// <param name="broker"></param>
        /// <returns></returns>
        internal Task <BrokerQueue> ResetupAsync(Broker broker)
        {
            // cancel existing loop
            _loopCancel.Cancel();

            // resetup
            _broker = broker;
            _queue  = null;
            return(SetupAsync());
        }
Esempio n. 5
0
            public void OrderEvents()
            {
                EventContainer eventContainer;

                while (EventList.TryGetValue(CurrentSeqNumber, out eventContainer))
                {
                    BrokerQueue.Enqueue(eventContainer);
                    SubscriberQueue.Enqueue(eventContainer.Event);
                    CurrentSeqNumber++;
                }
            }
Esempio n. 6
0
        /// <summary>
        /// Creates the queue and internal consumer for this service.
        /// </summary>
        /// <param name="broker">The broker.</param>
        /// <exception cref="InvalidOperationException">If the queue already exists.</exception>
        /// <returns></returns>
        internal async Task <BrokerQueue> SetupAsync(Broker broker)
        {
            // check if queue has already been created
            if (_queue != null)
            {
                throw new InvalidOperationException("The broker queue has already been created");
            }

            // set broker
            _broker = broker;

            // create queue
            _broker.DeclareExchange(_addr.Namespace, "topic", true, false);

            // check if already declared
            if (_namespace.Node.Services.Any(s => s.Type == ServiceType.Singleton && s._addr == _addr))
            {
                throw new InvalidOperationException("The service is already in use as a singleton");
            }

            if (Type == ServiceType.Singleton)
            {
                // declare one exclusive queue
                _queue = await _broker.CreateQueueAsync(_addr.ToString(), false, true, _addr.Namespace, _addr.RoutingKey).ConfigureAwait(false);
            }
            else if (Type == ServiceType.Fanout)
            {
                // declare queue with unique name
                using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) {
                    // get unique string
                    byte[] uniqueId = new byte[20];
                    rng.GetBytes(uniqueId);
                    string uniqueIdStr = BitConverter.ToString(uniqueId).Replace("-", "").ToLower();

                    _queue = await _broker.CreateQueueAsync(string.Format("{0}%{1}", _addr.ToString(), uniqueIdStr), false, false, _addr.Namespace, _addr.RoutingKey).ConfigureAwait(false);
                }
            }
            else if (Type == ServiceType.Balanced)
            {
                // declare one queue shared between many
                _queue = await _broker.CreateQueueAsync(_addr.ToString(), false, false, _addr.Namespace, _addr.RoutingKey).ConfigureAwait(false);
            }

            // setup semaphore
            _concurrencySlim = new SemaphoreSlim(_configuration.MaxConcurrency, _configuration.MaxConcurrency);

            // begin observing
            _queue.AsObservable().Subscribe(this);

            // set uptime
            _timeSetup = DateTimeOffset.UtcNow;

            return(_queue);
        }
Esempio n. 7
0
        private void Init(int cLists)
        {
            threadException = null;
            queue           = new BrokerQueue <Item>();

            lists = new Dictionary <int, Item> [cLists];
            for (int i = 0; i < cLists; i++)
            {
                lists[i] = new Dictionary <int, Item>();
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Subscribes to events matching the provided name.
        /// </summary>
        /// <param name="addr">The event address.</param>
        /// <returns>The subscription.</returns>
        public async Task <EventSubscription> SubscribeAsync(EventAddress addr)
        {
            // create the queue
            _broker.DeclareExchange(string.Format("!{0}", addr.Namespace), "topic", false, false);
            BrokerQueue brokerQueue = null;

            // declare queue with unique name
            using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) {
                // get unique string
                byte[] uniqueId = new byte[20];
                rng.GetBytes(uniqueId);
                string uniqueIdStr = BitConverter.ToString(uniqueId).Replace("-", "").ToLower();

                brokerQueue = await _broker.CreateQueueAsync(string.Format("!{0}%{1}", addr.ToString(), uniqueIdStr), false, true, string.Format("!{0}", addr.Namespace), $"{addr.Resource}.{addr.Name}", true, true).ConfigureAwait(false);
            }

            // create subscription
            return(new EventSubscription(addr, this, brokerQueue));
        }
Esempio n. 9
0
        /// <summary>
        /// Delete the correspoding queue
        /// </summary>
        public SessionPersistCounter DeleteQueue()
        {
            SessionPersistCounter counter = null;

            if (this.queue != null)
            {
                this.queue.OnEvent -= this.Queue_OnEvent;
                this.queue.OnPutResponsesSuccessEvent -= this.Queue_OnPutResponsesSuccessEvent;
                this.queue.OnFatalExceptionEvent      -= this.Queue_OnFatalExceptionEvent;

                counter    = this.queue.Close();
                this.queue = null;
            }

            // Send client purged when delete queue
            if (this.responsesClient != null)
            {
                this.responsesClient.ClientDisconnect(true);
            }

            return(counter);
        }
Esempio n. 10
0
        /// <summary>
        /// Initializes a new instance of the GetResponsesHandler class
        /// </summary>
        /// <param name="queue">indicating the broker queue</param>
        /// <param name="action">indicating the action</param>
        /// <param name="clientData">indicating the client data</param>
        /// <param name="clientId">indicating the client</param>
        /// <param name="timeoutManager">indicating the timeout manager</param>
        /// <param name="observer">indicating the observer</param>
        /// <param name="sharedData">indicating the shared data</param>
        /// <param name="version">indicating the message version</param>
        public GetResponsesHandler(BrokerQueue queue, string action, string clientData, string clientId, TimeoutManager timeoutManager, BrokerObserver observer, SharedData sharedData, MessageVersion version)
            : base(queue, action, timeoutManager, observer, sharedData, version)
        {
            this.clientId   = clientId;
            this.clientData = clientData;

            // For now, as REST service is the only frontend on Azure. Broker can know if it is
            // REST service connecting by checking if broker is running on Azure.
            // Need to fix this logic if we reopen net.tcp frontend on Azure.
            if (SoaHelper.IsOnAzure())
            {
                this.cacheBrokerQueueItem = true;
            }

#if DEBUG
            // For debug purpose, if the incoming message header contains a header which
            // indicates it is REST service calling, also set the flag to true
            // This is to enable on-premise test.
            if (OperationContext.Current != null && OperationContext.Current.IncomingMessageHeaders.FindHeader("HpcSOAWebSvc", Constant.HpcHeaderNS) >= 0)
            {
                this.cacheBrokerQueueItem = true;
            }
#endif
        }
Esempio n. 11
0
 /// <summary>
 /// Creates a new subscription.
 /// </summary>
 /// <param name="addr">The address.</param>
 /// <param name="namespace">The namespace.</param>
 /// <param name="queue">The queue.</param>
 internal EventSubscription(EventAddress addr, Namespace @namespace, BrokerQueue queue)
 {
     _queue     = queue;
     _namespace = @namespace;
     _address   = addr;
 }
Esempio n. 12
0
 /// <summary>
 /// Initializes a new instance of the ResponseEventArgs class.
 /// </summary>
 /// <param name="state">the registered response callback state object.</param>
 /// <param name="queue">the broker queue.</param>
 public ResponseEventArgs(object state, BrokerQueue queue)
     : base(queue)
 {
     this.stateField = state;
 }
Esempio n. 13
0
 /// <summary>
 /// Initializes a new instance of the PullResponsesHandler class
 /// </summary>
 /// <param name="queue">indicating the broker queue</param>
 /// <param name="action">indicating the action</param>
 /// <param name="timeoutManager">indicating the timeout manager</param>
 /// <param name="observer">indicating the observer</param>
 /// <param name="sharedData">indicating the shared data</param>
 /// <param name="version">indicating the message version</param>
 public PullResponsesHandler(BrokerQueue queue, string action, TimeoutManager timeoutManager, BrokerObserver observer, SharedData sharedData, MessageVersion version)
     : base(queue, action, timeoutManager, observer, sharedData, version)
 {
 }
Esempio n. 14
0
        /// <summary>
        /// Close the broker
        /// </summary>
        /// <param name="cleanData">indicate whether the broker should clean up the data</param>
        public async Task Close(bool cleanData)
        {
            BrokerTracing.TraceVerbose("[BrokerEntry] Close: Start closing: cleanData = {0}", cleanData);
            this.sharedData.WaitForInitializationComplete();

            if (Interlocked.Increment(ref this.closeFlag) != 1)
            {
                BrokerTracing.TraceInfo("[BrokerEntry] Close race condition detected, quit.");
                return;
            }

            this.cleanData = cleanData;
            int step = 0;

            // Step 1: Close Frontend
            if (this.frontendResult != null)
            {
                for (int i = 0; i < this.frontendResult.ServiceHostList.Length; i++)
                {
                    try
                    {
                        if (this.frontendResult.ServiceHostList[i] != null)
                        {
                            this.frontendResult.ServiceHostList[i].Close(CloseTimeout);
                            BrokerTracing.TraceVerbose("[BrokerEntry] Close: Step {0}: Close {1} controller frontend succeeded.", ++step, FrontendResult.GetTransportSchemeNameByIndex(i));
                        }
                    }
                    catch (Exception e)
                    {
                        BrokerTracing.TraceWarning("[BrokerEntry] Close: Step {1}: Close {2} controller frontend failed: {0}", e, ++step, FrontendResult.GetTransportSchemeNameByIndex(i));
                    }
                }

                for (int i = 0; i < this.frontendResult.FrontendList.Length; i++)
                {
                    try
                    {
                        if (this.frontendResult.FrontendList[i] != null)
                        {
                            this.frontendResult.FrontendList[i].Close();
                            BrokerTracing.TraceVerbose("[BrokerEntry] Close: Step {0}: Close {1} frontend succeeded.", ++step, FrontendResult.GetTransportSchemeNameByIndex(i));
                        }
                    }
                    catch (Exception e)
                    {
                        BrokerTracing.TraceWarning("[BrokerEntry] Close: Step {1}: Close {2} frontend failed: {0}", e, ++step, FrontendResult.GetTransportSchemeNameByIndex(i));
                    }
                }
            }

            // Step 2: Close client manager
            List <string> activeClientIdList;

            if (this.clientManager != null)
            {
                activeClientIdList = this.clientManager.GetAllActiveClientIds();
                try
                {
                    if (cleanData)
                    {
                        this.clientManager.DeleteAllQueues();
                    }

                    this.clientManager.Dispose();
                    this.clientManager = null;
                    BrokerTracing.TraceVerbose("[BrokerEntry] Close: Step {0}: Close client manager succeeded.", ++step);
                }
                catch (Exception e)
                {
                    BrokerTracing.TraceVerbose("[BrokerEntry] Close: Step {0}: Close client manager failed: {1}", ++step, e);
                }
            }
            else
            {
                activeClientIdList = new List <string>();
            }

            //Check the StrategyConfig.WithoutSessionLayer for the close progress.
            //Step 3: Finish the service job if it is needed.
            // We only finish the service job if clean data is required, in other cases, the service job monitor will finish the service job according to the service job life cycle before we enter this stage
            if (this.monitor != null && !SoaCommonConfig.WithoutSessionLayer)
            {
                try
                {
                    if (cleanData)
                    {
                        await this.monitor.FinishServiceJob("Close Session");

                        BrokerTracing.TraceVerbose("[BrokerEntry] Close: Step {0}: Finish service job succeeded.", ++step);
                    }
                }
                catch (Exception e)
                {
                    BrokerTracing.TraceWarning("[BrokerEntry] Close: Step {0}: Finish service job failed: {1}", ++step, e);
                }
            }

            // Step 4: Close monitor
            if (this.monitor != null)
            {
                try
                {
                    // Update suspended state
                    if (!SoaCommonConfig.WithoutSessionLayer)
                    {
                        await this.monitor.UpdateSuspended(!cleanData);
                    }
                    this.monitor.Close();
                    this.monitor = null;
                    BrokerTracing.TraceVerbose("[BrokerEntry] Close: Step {0}: Close monitor succeeded.", ++step);
                }
                catch (Exception e)
                {
                    BrokerTracing.TraceWarning("[BrokerEntry] Close: Step {1}: Close monitor failed: {0}", e, ++step);
                }
            }

            // Step 5: Close state manager
            if (this.stateManager != null)
            {
                try
                {
                    this.stateManager.Close();
                    this.stateManager = null;
                    BrokerTracing.TraceVerbose("[BrokerEntry] Close: Step {0}: Close state manager succeeded.", ++step);
                }
                catch (Exception e)
                {
                    BrokerTracing.TraceWarning("[BrokerEntry] Close: Step {1}: Close state manager failed: {0}", e, ++step);
                }
            }

            // Step 7: Close broker queue
            if (this.brokerQueueFactory != null)
            {
                foreach (ClientInfo clientInfo in this.brokerQueueFactory.AllClientInfos)
                {
                    if (activeClientIdList.Contains(clientInfo.ClientId))
                    {
                        continue;
                    }

                    try
                    {
                        bool        isNewCreated;
                        BrokerQueue queue = this.brokerQueueFactory.GetPersistQueueByClient(clientInfo.ClientId, clientInfo.UserName, out isNewCreated);
                        Debug.Assert(!isNewCreated, "[BrokerEntry] Close: Should only get exsiting persist queue");
                        if (cleanData)
                        {
                            queue.Close();
                        }
                        else
                        {
                            queue.Dispose();
                        }

                        BrokerTracing.TraceVerbose("[BrokerEntry] Close: Step {0}: Close broker queue {1} succeeded.", ++step, clientInfo.ClientId);
                    }
                    catch (Exception e)
                    {
                        BrokerTracing.TraceVerbose("[BrokerEntry] Close: Step {0}: Close broker queue {1} failed: {2}", ++step, clientInfo.ClientId, e);
                    }
                }

                try
                {
                    this.brokerQueueFactory.Dispose();
                    this.brokerQueueFactory = null;
                    BrokerTracing.TraceVerbose("[BrokerEntry] Close: Step {0}: Close broker queue factory succeeded.", ++step);
                }
                catch (Exception e)
                {
                    BrokerTracing.TraceWarning("[BrokerEntry] Close: Step {1}: Close broker queue factory failed: {0}", e, ++step);
                }
            }

            // Step 8: Clean up shared data
            if (this.sharedData != null)
            {
                try
                {
                    this.sharedData.Dispose();
                    this.sharedData = null;
                    BrokerTracing.TraceVerbose("[BrokerEntry] Close: Step {0}: Close shared data succeeded.", ++step);
                }
                catch (Exception e)
                {
                    BrokerTracing.TraceWarning("[BrokerEntry] Close: Step {0}: Close shared data failed: {1}", ++step, e);
                }
            }

            // Step 9: Dispose node mapping
            if (this.nodeMappingData != null)
            {
                try
                {
                    this.nodeMappingData.Dispose();
                    this.nodeMappingData = null;
                    BrokerTracing.TraceVerbose("[BrokerEntry] Close: Step {0}: Disposing node mapping succeeded.", ++step);
                }
                catch (Exception e)
                {
                    BrokerTracing.TraceWarning("[BrokerEntry] Close: Step {0}: Disposing node mapping failed: {1}", ++step, e);
                }
            }

#if DEBUG
            if (!ReferenceObject.CheckDisposed())
            {
                BrokerTracing.TraceEvent(TraceEventType.Warning, 0, "[BrokerEntry] Reference object not disposed after closing proceduer");
            }
#endif

            BrokerTracing.TraceVerbose("[BrokerEntry] Close finished.");

            if (this.BrokerFinished != null)
            {
                this.BrokerFinished(this, EventArgs.Empty);
            }
        }
 /// <summary>
 /// Initializes a new instance of the PutResponsesSuccessEventArgs class.
 /// </summary>
 /// <param name="successResponsesCount"> number of responses successfully put</param>
 /// <param name="faultResponsesCount"> number of fault responses</param>
 /// <param name="queue">the broker queue.</param>
 public PutResponsesSuccessEventArgs(int responsesCount, int faultResponsesCount, BrokerQueue queue)
     : base(queue)
 {
     this.responsesCountField      = responsesCount;
     this.faultResponsesCountField = faultResponsesCount;
 }
Esempio n. 16
0
        /// <summary>
        /// Setup the node, called internally.
        /// </summary>
        /// <returns></returns>
        internal async Task SetupAsync()
        {
            // add shutdown handler
            _broker.Shutdown += async delegate(object s, BrokerShutdownEventArgs e) {
                Debug.WriteLine(":Reconnect -> Reconnecting");

                try {
                    await ReconnectAsync().ConfigureAwait(false);

#if DEBUG
                } catch (Exception ex) {
                    Debug.Fail(":Reconnect -> Failed to reconnect: " + ex.Message);
#else
                } catch (Exception ex) {
#endif
                    Console.WriteLine("messaging", "failed to reconnect to broker: {0}", ex.ToString());
                    Dispose();
                }
            };

            // add returned handler
            _broker.Returned += delegate(object s, BrokerReturnedEventArgs e) {
                if (e.ID != Guid.Empty)
                {
                    TaskCompletionSource <Envelope> tcs;

                    lock (_replyWaits) {
                        // try and get the reply wait
                        if (!_replyWaits.TryGetValue(e.ID, out ReplyWait replyWait))
                        {
                            return;
                        }

                        // if this is a multi-reply do nothing
                        if (replyWait.Results != null)
                        {
                            return;
                        }

                        // remove and set exception
                        tcs = replyWait.CompletionSource;
                        _replyWaits.Remove(e.ID);
                    }

                    tcs.TrySetException(new Exception("The envelope was returned before delivery"));
                }
            };

            // create reply queue
            try {
                // declare queue with unique name
                using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) {
                    // get unique string
                    byte[] uniqueId = new byte[20];
                    rng.GetBytes(uniqueId);
                    string uniqueIdStr = BitConverter.ToString(uniqueId).Replace("-", "").ToLower();

                    _replyQueue = await _broker.CreateQueueAsync(string.Format("~reply:{1}%{0}", _uuid, uniqueIdStr), false, true, "", "", true, true, new Dictionary <string, object>() {
                        { "x-expires", (int)TimeSpan.FromMinutes(15).TotalMilliseconds }
                    }).ConfigureAwait(false);
                }
            } catch (Exception ex) {
                throw new InvalidOperationException("Failed to create node reply queue", ex);
            }

            // setup service
            if (_queryService == null)
            {
                _queryService = await AttachAsync(string.Format("node:{0}", _uuid), ServiceType.Singleton, ServiceExecution.Parallel, RpcBehaviour.Bind <INodeQuery001>(new NodeQueryImpl(this))).ConfigureAwait(false);
            }

            // start reply processor
            ReplyLoop();
        }
Esempio n. 17
0
 /// <summary>
 /// Creates a new subscription.
 /// </summary>
 /// <param name="addr">The address.</param>
 /// <param name="node">The node.</param>
 /// <param name="queue">The queue.</param>
 internal EventSubscription(EventAddress addr, Node node, BrokerQueue queue)
 {
     _queue   = queue;
     _node    = node;
     _address = addr;
 }
Esempio n. 18
0
        /// <summary>
        /// Dispose the broker client
        /// </summary>
        /// <param name="disposing">indicating whether it is disposing</param>
        private void Dispose(bool disposing)
        {
            this.disposing = disposing;
            try
            {
                // Set state
                this.state = BrokerClientState.Disconnected;

                // Copy all the connected instances out of lock
                List <object> connectedList = null;
                lock (this.connectedInstance)
                {
                    connectedList = new List <object>(this.connectedInstance.Keys);
                }

                foreach (object instance in connectedList)
                {
                    try
                    {
                        BrokerTracing.TraceInfo("[BrokerClient] Try to close the connected instance: {0} ({1})", instance.ToString(), instance.GetHashCode());
                        if (instance is IDisposable)
                        {
                            // BrokerController
                            ((IDisposable)instance).Dispose();
                        }
                        else if (instance is IChannel)
                        {
                            Utility.AsyncCloseICommunicationObject((ICommunicationObject)instance);
                        }
                        else
                        {
                            Debug.Fail("[BrokerClient] Connected instance must be IDisposable or IChannel.");
                        }
                    }
                    catch (Exception e)
                    {
                        BrokerTracing.TraceWarning("[BrokerClient] Failed to close the connected instance: {0}", e);
                    }
                }

                if (disposing)
                {
                    if (this.queue != null)
                    {
                        this.queue.OnEvent -= this.Queue_OnEvent;
                        this.queue.OnPutResponsesSuccessEvent -= this.Queue_OnPutResponsesSuccessEvent;
                        this.queue.OnFatalExceptionEvent      -= this.Queue_OnFatalExceptionEvent;

                        //for durable session, the queue is closed unless there were flushed requests, dispose if EOM was called.
                        if (this.sharedData.BrokerInfo.Durable)
                        {
                            if (this.queue.FlushedRequestsCount == 0)
                            {
                                BrokerTracing.TraceInfo("[BrokerClient] durable session broker client {0} close the queue.", this.clientId);
                                //if not ever flushed, reduce the count of all requests in the queue
                                this.observer.ReduceUncommittedCounter(this.queue.AllRequestsCount);
                                this.queue.Close();
                            }
                            else if (this.endOfMessageCalled)
                            {
                                // Only dispose the broker queue if it is a durable session. Non-durable broker queue for
                                // interactive session should be kept/reused and closed when closing the broker domain.
                                //
                                // Note (related bug #14224): logic in BrokerClient.SyncDisconnect() ensures that BrokerClient
                                // instance will not be disposed if EndRequests is called (this.state = BrokerClientState.EndRequests).
                                // So below code snippet could only be reached on broker entry exiting.
                                this.observer.ReduceUncommittedCounter(this.queue.AllRequestsCount - this.queue.FlushedRequestsCount);
                                this.queue.Dispose();
                            }
                        }
                        else //for interactive session, close the queue if EOM is not called.
                        {
                            if (!this.endOfMessageCalled)
                            {
                                BrokerTracing.TraceInfo("[BrokerClient] interactive session broker client {0} close the queue.", this.clientId);
                                if (!this.v2ProxyClient)
                                {
                                    //reduce the count of all unflushed requests in the queue
                                    this.observer.ReduceUncommittedCounter(this.queue.AllRequestsCount - this.queue.FlushedRequestsCount);
                                }
                                this.queue.Close();
                            }
                        }

                        this.queue = null;

                        this.batchMessageIds.Clear();
                    }
                }

                if (this.responsesClient != null)
                {
                    this.responsesClient.Dispose();
                    this.responsesClient = null;
                }

                if (this.timeoutManager != null)
                {
                    this.timeoutManager.Dispose();
                    this.timeoutManager = null;
                }

                // do not dispose this.lockForDiscardRequests for this may block the threads in the write queue, which may lead to the hang when broker entry exits.
                // do not dispose this.batchIdChangedEvent for any wait for the event would hang
            }
            catch (Exception e)
            {
                BrokerTracing.TraceWarning("[BrokerClient] Exception thrown while disposing: {0}", e);
            }
        }
Esempio n. 19
0
        /// <summary>
        /// Initializes a new instance of the BrokerClient class
        /// </summary>
        /// <param name="clientId">indicating the client Id</param>
        /// <param name="userName">indicating the user name</param>
        /// <param name="queueFactory">indicating the queue factory</param>
        /// <param name="observer">indicating the observer</param>
        /// <param name="stateManager">indicating the state manager</param>
        /// <param name="monitor">indicating the monitor</param>
        /// <param name="sharedData">indicating the shared data</param>
        public BrokerClient(string clientId, string userName, BrokerQueueFactory queueFactory, BrokerObserver observer, BrokerStateManager stateManager, ServiceJobMonitorBase monitor, SharedData sharedData)
        {
            bool isNewCreated;

            // Set the "signletonInstanceConnected" property if
            // SessionStartInfo.AutoDisposeBrokerClient is set. This property is only possibly to
            // be set to true after if HTTP transport scheme is specified. And it is by design so.
            if (sharedData.StartInfo.AutoDisposeBrokerClient.HasValue)
            {
                this.singletonInstanceConnected = !sharedData.StartInfo.AutoDisposeBrokerClient.Value;
            }

            this.clientId               = clientId;
            this.v2ProxyClient          = clientId.StartsWith(FrontEndBase.DefaultClientPrefix);
            this.sharedData             = sharedData;
            this.observer               = observer;
            this.monitor                = monitor;
            this.stateManager           = stateManager;
            this.stateManager.OnFailed += new BrokerStateManager.SessionFailedEventHandler(this.StateManager_OnFailed);

            try
            {
                this.queue = queueFactory.GetPersistQueueByClient(clientId, userName, out isNewCreated);
            }
            catch (BrokerQueueException e)
            {
                // Catch the exception about the username not match and translte it to session fault
                if (e.ErrorCode == (int)BrokerQueueErrorCode.E_BQ_USER_NOT_MATCH)
                {
                    ThrowHelper.ThrowSessionFault(SOAFaultCode.AccessDenied_BrokerQueue, SR.AccessDenied_BrokerQueue, clientId, userName);
                }
                else
                {
                    throw;
                }
            }

            this.queue.OnEvent += new BrokerQueueEventDelegate(this.Queue_OnEvent);
            this.queue.OnPutResponsesSuccessEvent += new EventHandler <PutResponsesSuccessEventArgs>(this.Queue_OnPutResponsesSuccessEvent);
            this.queue.OnFatalExceptionEvent      += new EventHandler <ExceptionEventArgs>(this.Queue_OnFatalExceptionEvent);
            this.timeoutManager = new TimeoutManager("BrokerClient " + clientId);
            BrokerTracing.EtwTrace.LogBrokerClientCreated(this.sharedData.BrokerInfo.SessionId, clientId);

            if (this.queue.IsAllRequestsProcessed || monitor.ServiceJobState == ServiceJobState.Finished)
            {
                // If the queue has processed all the request or the service job is finished, the broker client can only get responses
                this.state = BrokerClientState.GetResponse;
                this.endOfMessageCalled = true;
                BrokerTracing.EtwTrace.LogBrokerClientStateTransition(this.sharedData.BrokerInfo.SessionId, this.clientId, "GetResponse");
                this.timeoutManager.RegisterTimeout(this.sharedData.Config.Monitor.ClientIdleTimeout, this.TimeoutToDisconnected, this.state);
            }
            else
            {
                if (!this.queue.EOMReceived)
                {
                    // If EndOfMessage is not received, the client is in the ClientConnected state and is ready to accept messages
                    this.state = BrokerClientState.ClientConnected;
                    BrokerTracing.EtwTrace.LogBrokerClientStateTransition(this.sharedData.BrokerInfo.SessionId, this.clientId, "ClientConnected");
                    this.timeoutManager.RegisterTimeout(this.sharedData.Config.Monitor.ClientIdleTimeout, this.TimeoutToDisconnected, this.state);
                }
                else
                {
                    // If EndOfMessage has been received, the client is in the EndOfMessage state and does not accept any more requests.
                    this.state = BrokerClientState.EndRequests;
                    this.endOfMessageCalled = true;
                    BrokerTracing.EtwTrace.LogBrokerClientStateTransition(this.sharedData.BrokerInfo.SessionId, this.clientId, "EndOfMessage");
                }
            }
        }