/// <summary> /// Open the frontend /// </summary> private void OpenFrontend() { for (int i = 0; i < this.frontendResult.ServiceHostList.Length; i++) { if (this.frontendResult.ServiceHostList[i] != null) { this.frontendResult.ServiceHostList[i].Open(); BrokerTracing.TraceVerbose("[BrokerEntry] {0} controller frontend opened.", FrontendResult.GetTransportSchemeNameByIndex(i)); } } for (int i = 0; i < this.frontendResult.FrontendList.Length; i++) { if (this.frontendResult.FrontendList[i] != null) { this.frontendResult.FrontendList[i].Open(); BrokerTracing.TraceVerbose("[BrokerEntry] {0} frontend opened.", FrontendResult.GetTransportSchemeNameByIndex(i)); } } }
/// <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); } }