/// <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; }
/// <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); } }
/// <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; }
/// <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()); }
public void OrderEvents() { EventContainer eventContainer; while (EventList.TryGetValue(CurrentSeqNumber, out eventContainer)) { BrokerQueue.Enqueue(eventContainer); SubscriberQueue.Enqueue(eventContainer.Event); CurrentSeqNumber++; } }
/// <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); }
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>(); } }
/// <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)); }
/// <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); }
/// <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 }
/// <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; }
/// <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; }
/// <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) { }
/// <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; }
/// <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(); }
/// <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; }
/// <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); } }
/// <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"); } } }