/// <summary> /// Build initialization result /// </summary> /// <param name="frontendResult">indicating the frontend result</param> /// <param name="dispatcherManager">indicating the dispatcher manager</param> /// <param name="serviceOperationTimeout">indicating service operation timeout</param> /// <param name="clientBrokerHeartbeatInterval">indicating client broker heartbeat interval</param> /// <param name="clientBrokerHeartbeatRetryCount">indicating client broker heartbeat retry count</param> /// <param name="azureRequestQueueUris">the Azure storage queue SAS Uri</param> /// <param name="azureRequestBlobUri">the Azure storage blob container SAS Uri</param> /// <param name="useAzureQueue">if the azure storage queue(blob) is used</param> /// <returns>returns the initialization result</returns> private static BrokerInitializationResult BuildInitializationResult( FrontendResult frontendResult, DispatcherManager dispatcherManager, int serviceOperationTimeout, int clientBrokerHeartbeatInterval, int clientBrokerHeartbeatRetryCount, string[] azureRequestQueueUris, string azureRequestBlobUri, bool?useAzureQueue) { BrokerInitializationResult info = new BrokerInitializationResult(); info.BrokerEpr = frontendResult.FrontendUriList; info.ControllerEpr = frontendResult.ControllerUriList; info.ResponseEpr = frontendResult.GetResponseUriList; info.ServiceOperationTimeout = serviceOperationTimeout; info.ClientBrokerHeartbeatInterval = clientBrokerHeartbeatInterval; info.ClientBrokerHeartbeatRetryCount = clientBrokerHeartbeatRetryCount; info.MaxMessageSize = frontendResult.MaxMessageSize; info.SupportsMessageDetails = frontendResult.FrontendSupportsMessageDetails && dispatcherManager.BackendSupportsMessageDetails; info.AzureRequestQueueUris = azureRequestQueueUris; info.AzureRequestBlobUri = azureRequestBlobUri; info.UseAzureQueue = (useAzureQueue == true); return(info); }
/// <summary> /// Attach to a session /// </summary> /// <param name="sessionId">session id</param> /// <returns>returns broker initialization result</returns> public BrokerInitializationResult Attach(string sessionId) { if (!this.AllowNewSession) { ThrowHelper.ThrowSessionFault(SOAFaultCode.Broker_BrokerIsOffline, SR.BrokerIsOffline); } try { this.CheckAccess(sessionId); TraceHelper.TraceEvent(sessionId, System.Diagnostics.TraceEventType.Information, "[BrokerLauncher] Attach: SessionId = {0}", sessionId); BrokerInitializationResult returnValue = this.brokerManager.AttachBroker(sessionId).GetAwaiter().GetResult(); #region Debug Failure Test SimulateFailure.FailOperation(1); #endregion TraceHelper.TraceEvent(sessionId, System.Diagnostics.TraceEventType.Information, "[BrokerLauncher] Attach Broker {0} Succeeded.", sessionId); return(returnValue); } catch (Exception e) { // Bug 10614: Throw a proper exception when the broker node is being taken offline if (!this.AllowNewSession) { ThrowHelper.ThrowSessionFault(SOAFaultCode.Broker_BrokerIsOffline, SR.BrokerIsOffline); } TraceHelper.TraceEvent(sessionId, System.Diagnostics.TraceEventType.Error, "[BrokerLauncher] Attach Broker {0} failed: {1}", sessionId, e); throw ExceptionHelper.ConvertExceptionToFaultException(e); } }
/// <summary> /// Initializes a new instance of the BrokerEntry class /// </summary> /// <param name="startInfo">indicating the start info</param> /// <param name="brokerInfo">indicating the broker info</param> public BrokerEntry(SessionStartInfoContract startInfo, BrokerStartInfo brokerInfo, BrokerManagementService serviceInstance) { if (startInfo.TransportScheme != TransportScheme.NetTcp) { throw new NotSupportedException("Sample broker does not support transport scheme other than NetTcp."); } if (brokerInfo.Durable) { throw new NotSupportedException("Sample broker does not support durable session."); } this.clientManager = new ServiceClientManager(brokerInfo.SessionId, brokerInfo.Headnode, serviceInstance); Frontend frontend = new Frontend(this.clientManager); WebHttpBinding binding = new WebHttpBinding(); binding.MaxBufferPoolSize = 5000000; binding.MaxBufferSize = 5000000; binding.MaxReceivedMessageSize = 5000000; binding.ReaderQuotas.MaxArrayLength = 5000000; binding.ReaderQuotas.MaxBytesPerRead = 5000000; binding.ReaderQuotas.MaxDepth = 5000000; binding.ReaderQuotas.MaxNameTableCharCount = 5000000; binding.ReaderQuotas.MaxStringContentLength = 5000000; this.frontendServiceHost = new WebServiceHost(frontend, new Uri(String.Format("http://{0}:8081/", Environment.MachineName))); ServiceEndpoint endpoint = this.frontendServiceHost.AddServiceEndpoint(typeof(IWebHttpFrontendService), binding, String.Empty); endpoint.Behaviors.Add(new WebHttpBehavior()); string listenUri = endpoint.ListenUri.AbsoluteUri; this.frontendServiceHost.Open(); this.result = new BrokerInitializationResult(); this.result.BrokerEpr = new string[3] { listenUri, null, null }; this.result.ControllerEpr = new string[3]; this.result.ResponseEpr = new string[3]; }
/// <summary> /// Create a session /// </summary> /// <param name="info">session start info</param> /// <param name="sessionId">session id</param> /// <returns>returns broker initialization result</returns> public BrokerInitializationResult Create(SessionStartInfoContract info, string sessionId) { if ((!this.AllowNewSession) || (!this.IsOnline && String.IsNullOrEmpty(info.DiagnosticBrokerNode))) { ThrowHelper.ThrowSessionFault(SOAFaultCode.Broker_BrokerIsOffline, SR.BrokerIsOffline); } // Handle invalid input parameters try { ParamCheckUtility.ThrowIfNull(info, "info"); if (!BrokerLauncherEnvironment.Standalone) { this.CheckAccess(sessionId); } TraceHelper.TraceEvent(sessionId, System.Diagnostics.TraceEventType.Information, "[BrokerLauncher] Create: SessionId = {0}", sessionId); //TODO: make it async BrokerInitializationResult returnValue = this.brokerManager.CreateNewBrokerDomain(info, sessionId, false).GetAwaiter().GetResult(); #region Debug Failure Test SimulateFailure.FailOperation(1); #endregion TraceHelper.RuntimeTrace.LogSessionCreated(sessionId); TraceHelper.TraceEvent(sessionId, System.Diagnostics.TraceEventType.Information, "[BrokerLauncher] Create Broker {0} Succeeded.", sessionId); return(returnValue); } catch (Exception e) { TraceHelper.RuntimeTrace.LogFailedToCreateSession(sessionId); // Bug 10614: Throw a proper exception when the broker node is being taken offline if ((!this.AllowNewSession) || (!this.IsOnline && String.IsNullOrEmpty(info.DiagnosticBrokerNode))) { ThrowHelper.ThrowSessionFault(SOAFaultCode.Broker_BrokerIsOffline, SR.BrokerIsOffline); } TraceHelper.TraceEvent(sessionId, System.Diagnostics.TraceEventType.Error, "[BrokerLauncher] Create Broker {0} failed: {1}", sessionId, e.ToString()); throw ExceptionHelper.ConvertExceptionToFaultException(e); } }
/// <summary> /// Initializes a new instance of the BrokerEntry class /// </summary> /// <param name="startInfo">indicating the start info</param> /// <param name="brokerInfo">indicating the broker info</param> public BrokerEntry(SessionStartInfoContract startInfo, BrokerStartInfo brokerInfo, BrokerManagementService serviceInstance) { if (startInfo.TransportScheme != TransportScheme.NetTcp) { throw new NotSupportedException("Sample broker does not support transport scheme other than NetTcp."); } if (brokerInfo.Durable) { throw new NotSupportedException("Sample broker does not support durable session."); } this.clientManager = new ServiceClientManager(brokerInfo.SessionId, brokerInfo.Headnode, serviceInstance); Frontend frontend = new Frontend(this.clientManager); // Choose different binding configuration by start info NetTcpBinding frontendBinding; if (startInfo.Secure) { frontendBinding = new NetTcpBinding(); } else { frontendBinding = new NetTcpBinding(SecurityMode.None); } frontendBinding.PortSharingEnabled = true; this.frontendServiceHost = new ServiceHost(frontend, new Uri(String.Format("net.tcp://{0}:9091/SampleBroker", Environment.MachineName))); string listenUri = this.frontendServiceHost.AddServiceEndpoint(typeof(IDuplexService), frontendBinding, String.Empty).ListenUri.AbsoluteUri; this.frontendServiceHost.Open(); this.result = new BrokerInitializationResult(); this.result.BrokerEpr = new string[3] { listenUri, null, null }; this.result.ControllerEpr = new string[3]; this.result.ResponseEpr = new string[3]; }
/// <summary> /// Create broker /// </summary> /// <param name="sessionId">indicating the session id</param> private async Task CreateInternal(string sessionId) { AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(this.CurrentDomain_AssemblyResolve); this.SetIsDiagTraceEnabledProperty(); Assembly brokerCoreAsm = Assembly.LoadFile(this.brokerCoreServiceLibPath); ConstructorInfo ci = brokerCoreAsm.GetType(BrokerEntryClassFullName).GetConstructor(new Type[1] { typeof(string) }); this.brokerEntry = (IBrokerEntry)ci.Invoke(new object[1] { sessionId }); this.brokerEntry.BrokerFinished += new EventHandler(this.Entry_BrokerFinished); this.result = this.brokerEntry.Run(this.startInfoContract, this.brokerInfo); //set isDebugModeEnabled True to jump UpdateBrokerInfo method. if (!this.isDebugModeEnabled && !this.isNoSession) { await this.UpdateBrokerInfo(this.brokerInfo).ConfigureAwait(false); } }
/// <summary> /// Create broker /// </summary> /// <param name="startInfo">indicating the session start information</param> /// <param name="sessionId">indicating the session id</param> /// <param name="targetTimeout">indicating the target timeout</param> /// <param name="eprs">indicating the broker epr list</param> /// <param name="epr">output selected epr</param> /// <param name="binding">indicting the binding</param> /// <returns>returns the session information</returns> public async Task <SessionBase> CreateBroker(SessionStartInfo startInfo, string sessionId, DateTime targetTimeout, string[] eprs, Binding binding) { Exception innerException = null; IEnumerable <string> endpoints = eprs; if (startInfo.UseAzureQueue.GetValueOrDefault() && !endpoints.Contains(SessionInternalConstants.BrokerConnectionStringToken)) { endpoints = endpoints.Concat(new[] { SessionInternalConstants.BrokerConnectionStringToken }); } foreach (string epr in endpoints) { TimeSpan timeout = SessionBase.GetTimeout(targetTimeout); IBrokerLauncher brokerLauncher = null; try { SessionBase.TraceSource.TraceInformation("[Session:{0}] Try to create broker... BrokerLauncherEpr = {1}", sessionId, epr); void RenewBrokerLauncherClient() { if (epr == SessionInternalConstants.BrokerConnectionStringToken) { brokerLauncher = new BrokerLauncherCloudQueueClient(startInfo.BrokerLauncherStorageConnectionString); } else { var client = new BrokerLauncherClient(new Uri(epr), startInfo, binding); client.InnerChannel.OperationTimeout = timeout; brokerLauncher = client; } } RenewBrokerLauncherClient(); BrokerInitializationResult result = null; int retry = 20; while (retry > 0) { try { if (this.durable) { result = brokerLauncher.CreateDurable(startInfo.Data, sessionId); } else { result = brokerLauncher.Create(startInfo.Data, sessionId); } break; } catch (Exception ex) { if (retry <= 0) { throw; } retry--; Debug.WriteLine($"Waiting for Broker Launcher running. Detail: {ex.Message}"); await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false); RenewBrokerLauncherClient(); } } Debug.Assert(result != null); SessionBase.TraceSource.TraceInformation("[Session:{0}] Succesfully created broker.", sessionId); SessionInfo info = SessionBase.BuildSessionInfo(result, this.durable, sessionId, epr, startInfo.Data.ServiceVersion, startInfo); if (this.durable) { #if net40 return(new DurableSession(info, startInfo.Headnode, binding)); #else return(new DurableSession(info, startInfo.Headnode, binding)); #endif } else { var session = new V3Session(info, startInfo.Headnode, startInfo.ShareSession, binding); if (startInfo.UseAzureStorage) { session.BrokerLauncherClient = brokerLauncher; } return(session); } } catch (FaultException <SessionFault> e) { SessionBase.TraceSource.TraceEvent(TraceEventType.Warning, 0, "[Session:{0}] Fault exception occured while creating broker: {1}. FaultCode = {2}", sessionId, e, e.Detail.Code); switch (e.Detail.Code) { // Continue if current broker node is being taken offline case SOAFaultCode.Broker_BrokerIsOffline: continue; } throw Utility.TranslateFaultException(e); } catch (TimeoutException te) { SessionBase.TraceSource.TraceEvent(TraceEventType.Error, 0, "[Session:{0}] TimeoutException occured while creating broker: {1}", sessionId, te); // don't continue when we timeout throw new TimeoutException(string.Format(SR.ConectBrokerLauncherTimeout, epr, Constant.DefaultCreateSessionTimeout), te); } catch (CommunicationException ex) { SessionBase.TraceSource.TraceEvent(TraceEventType.Warning, 0, "[Session:{0}] Failed to create broker: {1}", sessionId, ex); innerException = ex; SessionBase.TraceSource.TraceInformation(ex.ToString()); continue; } finally { var client = brokerLauncher as BrokerLauncherClient; if (client != null) { Utility.SafeCloseCommunicateObject(client); } } } SessionBase.TraceSource.TraceEvent(TraceEventType.Error, 0, "[Session:{0}] Failed to create broker after trying all available eprs.", sessionId); throw new SessionException(SR.NoBrokerNodeFound, innerException); }
/// <summary> /// Attach to a broker, returns session instance /// </summary> /// <param name="attachInfo">indicating the attach information</param> /// <param name="info">indicating the session info to be updated</param> /// <param name="timeout">indicating the timeout</param> /// <param name="binding">indicting the binding</param> /// <returns>returns the session instance</returns> public Task <SessionBase> AttachBroker(SessionAttachInfo attachInfo, SessionInfo info, TimeSpan timeout, Binding binding) { SessionBase.TraceSource.TraceInformation("[Session:{0}] Try to attach broker...", attachInfo.SessionId); BrokerLauncherClient broker = new BrokerLauncherClient(new Uri(info.BrokerLauncherEpr), attachInfo, binding); broker.InnerChannel.OperationTimeout = timeout; try { BrokerInitializationResult result = broker.Attach(info.Id); info.BrokerEpr = result.BrokerEpr; info.ControllerEpr = result.ControllerEpr; info.ResponseEpr = result.ResponseEpr; info.ServiceOperationTimeout = result.ServiceOperationTimeout; info.MaxMessageSize = result.MaxMessageSize; info.ClientBrokerHeartbeatInterval = result.ClientBrokerHeartbeatInterval; info.ClientBrokerHeartbeatRetryCount = result.ClientBrokerHeartbeatRetryCount; info.BrokerUniqueId = result.BrokerUniqueId; info.UseAzureQueue = result.UseAzureQueue; info.AzureRequestQueueUris = result.AzureRequestQueueUris; info.AzureRequestBlobUri = result.AzureRequestBlobUri; info.Username = attachInfo.Username; info.InternalPassword = attachInfo.InternalPassword; info.Headnode = attachInfo.Headnode; info.UseWindowsClientCredential = attachInfo.UseWindowsClientCredential; } catch (FaultException <SessionFault> e) { SessionBase.TraceSource.TraceEvent(TraceEventType.Error, 0, "[Session:{0}] Fault exception occured while attaching broker: {1}. FaultCode = {2}", attachInfo.SessionId, e, e.Detail.Code); throw Utility.TranslateFaultException(e); } catch (CommunicationException e) { SessionBase.TraceSource.TraceEvent(TraceEventType.Error, 0, "[Session:{0}] Failed to attach to broker: {1}", attachInfo.SessionId, e); throw new SessionException(SOAFaultCode.ConnectBrokerLauncherFailure, SR.ConnectBrokerLauncherFailure, e); } catch (Exception e) { SessionBase.TraceSource.TraceEvent(TraceEventType.Error, 0, "[Session:{0}] Failed to attach to broker: {1}", attachInfo.SessionId, e); throw new SessionException(SOAFaultCode.UnknownError, e.ToString()); } finally { Utility.SafeCloseCommunicateObject(broker); } if (SoaHelper.IsSchedulerOnIaaS(attachInfo.Headnode)) { string suffix = SoaHelper.GetSuffixFromHeadNodeEpr(attachInfo.Headnode); if (info.BrokerEpr != null) { SoaHelper.UpdateEprWithCloudServiceName(info.BrokerEpr, suffix); } if (info.ControllerEpr != null) { SoaHelper.UpdateEprWithCloudServiceName(info.ControllerEpr, suffix); } if (info.ResponseEpr != null) { SoaHelper.UpdateEprWithCloudServiceName(info.ResponseEpr, suffix); } } if (this.durable) { if (!info.Durable) { throw new SessionException(SOAFaultCode.InvalidAttachInteractiveSession, SR.InvalidAttachInteractiveSession); } #if net40 return(TaskEx.FromResult <SessionBase>(new DurableSession(info, attachInfo.Headnode, binding))); #else return(Task.FromResult <SessionBase>(new DurableSession(info, attachInfo.Headnode, binding))); #endif } else { if (info.Durable) { throw new SessionException(SOAFaultCode.InvalidAttachDurableSession, SR.InvalidAttachDurableSession); } #if net40 return(TaskEx.FromResult <SessionBase>(new V3Session(info, attachInfo.Headnode, true, binding))); #else return(Task.FromResult <SessionBase>(new V3Session(info, attachInfo.Headnode, true, binding))); #endif } }
/// <summary> /// Attach to a existing broker /// </summary> /// <param name="sessionId">session id</param> /// <returns>returns initialization result</returns> public async Task <BrokerInitializationResult> AttachBroker(string sessionId) { BrokerInfo info; BrokerInitializationResult result = null; Exception lastException = null; TraceHelper.TraceEvent(sessionId, System.Diagnostics.TraceEventType.Information, "[BrokerManager] Client attached"); for (int i = 0; i < RecoverBrokerRetryLimit; i++) { // Try to find broker that is still running bool success; lock (this.brokerDic) { success = this.brokerDic.TryGetValue(sessionId, out info); if (success) { Monitor.Enter(info); } } if (success) { try { info.CheckAccess(); TraceHelper.TraceEvent(sessionId, System.Diagnostics.TraceEventType.Information, "[BrokerManager] Attaching exsiting broker: {0}", sessionId); if (info.Disposed) { TraceHelper.TraceEvent(sessionId, System.Diagnostics.TraceEventType.Information, "[BrokerManager] Broker is exiting..."); ThrowHelper.ThrowSessionFault(SOAFaultCode.Session_ValidateJobFailed_AlreadyFinished, SR.BrokerFinishing, sessionId.ToString()); } else { bool needRestart = false; try { info.Attach(); } catch (EndpointNotFoundException e) { // Bug 8236: Need to catch EndpointNotFoundException and try to recover and retry attaching. TraceHelper.TraceEvent(sessionId, TraceEventType.Warning, "[BrokerManager] Attach failed with EndpointNotFoundException, broker might be unloading. Will wait for broker exit and try raise it again. Exception: {0}", e); // Wait until the process is exited and all event are finished // This means that this broker info instance is removed from brokerDic so that we can start from create broker for attaching info.WaitForProcessExit(TimeoutForWaitingProcessExit); TraceHelper.TraceEvent(sessionId, TraceEventType.Information, "[BrokerManager] Broker process is exited and all events are finished, restart that broker for attaching"); needRestart = true; } catch (FaultException <SessionFault> e) { if (e.Detail.Code == (int)SOAFaultCode.Broker_BrokerSuspending) { TraceHelper.TraceEvent(sessionId, TraceEventType.Warning, "[BrokerManager] Attach failed, broker is unloading to suspended state. Will wait for broker exit and try raise it again."); // Wait until the process is exited and all event are finished // This means that this broker info instance is removed from brokerDic so that we can start from create broker for attaching info.WaitForProcessExit(TimeoutForWaitingProcessExit); TraceHelper.TraceEvent(sessionId, TraceEventType.Information, "[BrokerManager] Broker process is exited and all events are finished, restart that broker for attaching"); needRestart = true; } else { TraceHelper.TraceEvent(sessionId, TraceEventType.Error, "[BrokerManager] Attach failed: {0}", e); throw; } } if (!needRestart) { //TODO: check whether need to obtain the cluster id, hash and Azure storage SAS here. return(info.InitializationResult); } } } finally { Monitor.Exit(info); } } // Try to find service job from finished jobs. // If no such service job is found, exception will throw by the scheduler helper and back to the client BrokerRecoverInfo recoverInfo = await this.schedulerHelper.TryGetSessionStartInfoFromFininshedJobs(sessionId); ClusterInfoContract clusterInfo = await this.schedulerHelper.GetClusterInfoAsync(); try { result = await this.CreateBrokerAndRun(recoverInfo, true, clusterInfo); } catch (FaultException <SessionFault> e) { if (e.Detail.Code == SOAFaultCode.Broker_SessionIdAlreadyExists) { // Bug 9840: This exception means that someone already raised up the broker // Should goto the very beginning to load initialization result lastException = e; // TODO: We don't know if this retry period is enough // We need to investigate this more in SP2 and we might // need an event wait handle to synchronize these rather // than a retry period await Task.Delay(AttachSessionRetryPeriod); continue; } else { throw; } } if (this.IsCallingFromHeadNode(OperationContext.Current.ServiceSecurityContext.WindowsIdentity)) { TraceHelper.RuntimeTrace.LogSessionRaisedUpFailover(sessionId); } else { TraceHelper.RuntimeTrace.LogSessionRaisedUp(sessionId, OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name); } lastException = null; break; } if (lastException == null) { return(result); } else { throw lastException; } }
/// <summary> /// Start broker process /// </summary> public void StartBroker() { bool failoverMode = false; if (Interlocked.Increment(ref this.retryCount) > 1) { // Bug 7150: Need to set attach to true when retrying failoverMode = true; this.brokerInfo.Attached = true; } if (this.customBroker == null || String.IsNullOrEmpty(this.customBroker.Executive)) { this.brokerProcess = this.pool.GetBrokerProcess(); } else { this.brokerProcess = CreateCustomBrokerProcess(this.customBroker); } // Log a trace mapping broker worker pid to session id. TraceHelper.TraceEvent( this.sessionId, TraceEventType.Information, "[BrokerInfo].StartBroker: Init broker worker {0} for session {1}.", this.brokerProcess.Id, this.sessionId); BrokerManagementServiceClient client = this.CreateClient(); try { this.result = client.Initialize(this.sessionStartInfo, this.brokerInfo); // Set broker's unique id to the initialization result when the process // is (re)started. this.result.BrokerUniqueId = this.UniqueId; this.brokerProcess.Exited += new EventHandler(this.BrokerProcess_Exited); } catch (Exception e) { TraceHelper.TraceEvent(this.sessionId, TraceEventType.Error, "[BrokerInfo] Failed to initialize broker: {0}", e.ToString()); // If in failover mode, close this broker and do not retry anymore if (failoverMode) { try { this.CloseBroker(true); } catch (Exception ex) { TraceHelper.TraceEvent(TraceEventType.Warning, "[BrokerInfo].StartBroker: Exception {0}", ex); } } throw; } finally { Utility.AsyncCloseICommunicationObject(client); } }
/// <summary> /// Run the broker /// </summary> /// <param name="startInfo">session start info</param> /// <param name="brokerInfo">indicate the broker start info</param> /// <returns>initialization result</returns> public BrokerInitializationResult Run(SessionStartInfoContract startInfo, BrokerStartInfo brokerInfo) { BrokerTracing.TraceEvent(System.Diagnostics.TraceEventType.Information, 0, "[BrokerEntry] Broker is starting initialization, ID = {0}", brokerInfo.SessionId); try { BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: ClusterTopology is {0}", brokerInfo.NetworkTopology); // Step 1: Initialize configuration and shared data ServiceConfiguration serviceConfig; BrokerConfigurations brokerConfig; BindingsSection bindings; SoaCommonConfig.WithoutSessionLayer = startInfo.IsNoSession; // TODO: this is a hack. Working mode should be decided by something like a *SchedulerType* filed. ConfigurationHelper.LoadConfiguration(startInfo, brokerInfo, out brokerConfig, out serviceConfig, out bindings); this.sharedData = new SharedData(brokerInfo, startInfo, brokerConfig, serviceConfig); BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 1: Loading configuration and shared data succeeded."); Debug.WriteLine($"[BrokerEntry](Debug) UseAad:{startInfo.UseAad}"); // Step 2: Initialize broker queue ClientInfo[] clientInfo; this.brokerQueueFactory = BrokerEntry.InitBrokerQueue(this.sharedData, out clientInfo); BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 2: Initialize broker queue succeeded."); // Step 3: Initialize observer this.observer = new BrokerObserver(this.sharedData, clientInfo); this.sharedData.Observer = this.observer; BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 3: Initialize broker observer succeeded."); // Step 4: Initialize state manager this.stateManager = new BrokerStateManager(this.sharedData, clientInfo.Length != 0); this.stateManager.UnloadBroker += this.UnloadBroker; BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 4: Initialize broker state manager succeeded."); // Step 5: Initialize service job monitor var context = TelepathyContext.GetOrAdd(this.sharedData.BrokerInfo.Headnode); if (SoaCommonConfig.WithoutSessionLayer) { this.monitor = new DummyServiceJobMonitor(this.sharedData, this.stateManager, this.nodeMappingData, context); } else { this.monitor = new ServiceJobMonitor.ServiceJobMonitor(this.sharedData, this.stateManager, this.nodeMappingData, context); } BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 5: Initialize service job monitor succeeded."); // Step 6: Initalize broker authorization this.brokerAuth = BrokerEntry.BuildBrokerAuthorization(this.sharedData); BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 6: Initialize broker authorization succeeded."); // Step 7: Initialize dispatcher manager DispatcherManager dispatcherManager = new DispatcherManager(bindings, this.sharedData, this.observer, this.monitor, this.brokerQueueFactory, context); BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 7: Initialize dispatcher manager succeeded."); // Step 8: Start service job monitor this.monitor.Start(startInfo, dispatcherManager, this.observer).GetAwaiter().GetResult(); BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 8: Start service job monitor succeeded."); // Step 9: Initailize client manager this.clientManager = new BrokerClientManager(clientInfo, this.brokerQueueFactory, this.observer, this.stateManager, this.monitor, this.sharedData); BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 9: Initialize client manager succeeded."); // if using AzureQueue, retrieve the connection string and build the request and response message queues if not exist string[] requestQueueUris = { }; string requestBlobUri = string.Empty; string controllerRequestQueueUri = string.Empty; string controllerResponseQueueUri = string.Empty; if (startInfo.UseAzureStorage) { int clusterHash = 0; if (!string.IsNullOrEmpty(brokerInfo.ClusterId)) { string clusterIdString = brokerInfo.ClusterId.ToLowerInvariant(); clusterHash = clusterIdString.GetHashCode(); } else if (!string.IsNullOrEmpty(brokerInfo.ClusterName)) { string clusterNameString = brokerInfo.ClusterName.ToLowerInvariant(); clusterHash = clusterNameString.GetHashCode(); } else { throw new InvalidOperationException($"Both {nameof(brokerInfo.ClusterId)} and {nameof(brokerInfo.ClusterName)} are null or empty. No {nameof(clusterHash)} can be determined."); } if (!string.IsNullOrEmpty(brokerInfo.AzureStorageConnectionString)) { this.azureQueueProxy = new AzureQueueProxy(brokerInfo.ClusterName, clusterHash, this.SessionId, brokerInfo.AzureStorageConnectionString); requestQueueUris = this.azureQueueProxy.RequestQueueUris; requestBlobUri = this.azureQueueProxy.RequestBlobUri; var requestQName = CloudQueueConstants.GetBrokerWorkerControllerRequestQueueName(this.SessionId); var responseQName = CloudQueueConstants.GetBrokerWorkerControllerResponseQueueName(this.SessionId); controllerRequestQueueUri = CloudQueueCreationModule.CreateCloudQueueAndGetSas( brokerInfo.AzureStorageConnectionString, requestQName, CloudQueueCreationModule.AddMessageSasPolicy).GetAwaiter().GetResult(); controllerResponseQueueUri = CloudQueueCreationModule.CreateCloudQueueAndGetSas( brokerInfo.AzureStorageConnectionString, responseQName, CloudQueueCreationModule.ProcessMessageSasPolicy).GetAwaiter().GetResult(); if (this.SessionId == SessionStartInfo.StandaloneSessionId) { CloudQueueCreationModule.ClearCloudQueuesAsync(brokerInfo.AzureStorageConnectionString, new[] { requestQName, responseQName }); } } else { BrokerTracing.TraceError("[BrokerEntry] Initialization: Use Azure Queue is specified, however the Azure connection string is not set."); ThrowHelper.ThrowSessionFault(SOAFaultCode.Broker_AzureConnectionStringNotAvailable, SR.Broker_AzureConnectionStringNotAvailable); } } // Step 10: Initialize frontend this.frontendResult = FrontEndBuilder.BuildFrontEnd(this.sharedData, this.observer, this.clientManager, this.brokerAuth, bindings, this.azureQueueProxy); ////this.maxMessageSize = (int)this.frontendResult.MaxMessageSize; ////this.readerQuotas = this.frontendResult.ReaderQuotas; BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 10: Initialize frontend succeeded."); // Step 11: Start frontend, Initialization finished after this step this.OpenFrontend(); BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 11: Open frontend succeeded."); // Step 12: Build initialization result and retrun to client BrokerInitializationResult result = BrokerEntry.BuildInitializationResult( this.frontendResult, dispatcherManager, this.sharedData.Config.LoadBalancing.ServiceOperationTimeout, this.sharedData.Config.Monitor.ClientBrokerHeartbeatInterval, this.sharedData.Config.Monitor.ClientBrokerHeartbeatRetryCount, requestQueueUris, requestBlobUri, controllerRequestQueueUri, controllerResponseQueueUri, startInfo.UseAzureStorage); BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 12: Build initialization result suceeded."); BrokerTracing.TraceInfo("[BrokerEntry] Initialization succeeded."); return(result); } catch (Exception ex) { BrokerTracing.TraceError(ex.ToString()); throw; } finally { if (this.sharedData != null) { this.sharedData.InitializationFinished(); } } }