Beispiel #1
0
        /// <summary>
        /// Initializes a new instance of the BrokerClientManager class
        /// </summary>
        /// <param name="clientList">indicating the client info list</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 BrokerClientManager(ClientInfo[] clientList, BrokerQueueFactory queueFactory, BrokerObserver observer, BrokerStateManager stateManager, ServiceJobMonitorBase monitor, SharedData sharedData)
        {
            this.clientDic    = new Dictionary <string, BrokerClient>(StringComparer.OrdinalIgnoreCase);
            this.queueFactory = queueFactory;
            this.observer     = observer;
            this.stateManager = stateManager;
            this.monitor      = monitor;
            this.sharedData   = sharedData;

            foreach (ClientInfo client in clientList)
            {
                try
                {
                    // Bug 5193: Only raise client that has requests to process.
                    if (client.TotalRequestsCount != client.ProcessedRequestsCount)
                    {
                        this.AddNewClient(client.ClientId, client.UserName);
                    }
                }
                catch (Exception e)
                {
                    // Create client may fail because of broker queue failure, ignore the client in this situation and trys other client instead.
                    BrokerTracing.TraceError("[BrokerClientManager] Failed to create client {0}, Exception = {1}", client.ClientId, e);
                }
            }

            this.CheckIfAllRequestDone();
            this.CheckIfEOMCalled();
        }
Beispiel #2
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;
 }
Beispiel #3
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)
 {
 }
Beispiel #4
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
        }
Beispiel #5
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");
                }
            }
        }
Beispiel #6
0
        /// <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();
                }
            }
        }