/// <summary> /// Clear the client pool and close all the connections in it. /// </summary> /// <remarks> /// This method has high cost. We need to be pretty sure that the exception /// happens on the connection between broker and proxy, then call this method. /// </remarks> /// <returns> /// is the specified client in the pool /// </returns> public override bool CleanupClient(IService client) { AzureServiceClient serviceClient = client as AzureServiceClient; Debug.Assert(serviceClient != null); BrokerTracing.TraceWarning( BrokerTracing.GenerateTraceString( "AzureDispatcher", "CleanupClient", this.TaskId, -1, serviceClient.ToString(), string.Empty, "Cleanup client.")); AzureServiceClient[] clients = null; lock (this.proxyClientPool) { clients = this.proxyClientPool.Clear(serviceClient); } if (clients != null) { BrokerTracing.TraceWarning( BrokerTracing.GenerateTraceString( "AzureDispatcher", "CleanupClient", this.TaskId, -1, serviceClient.ToString(), string.Empty, string.Format("Close clients in the pool. count = {0}", clients.Length))); // don't close client in above lock (this.proxyClientPool) scope to avoid deadlock foreach (AzureServiceClient asc in clients) { asc.AsyncClose(); } } return(clients != null); }
/// <summary> /// Opent the client and trigger GetNextRequest method. /// </summary> private static void AsyncStartWorker(object state) { BrokerTracing.TraceVerbose("[AzureServiceClient]. AsyncStartWorker is called."); object[] objs = state as object[]; Debug.Assert(objs != null && objs.Length == 2); AzureServiceClient client = objs[0] as AzureServiceClient; int serviceOperationTimeout = (int)objs[1]; bool validConnection = false; string clientInfo = string.Empty; try { clientInfo = client.ToString(); // open the channel explicitly when it is shared by multi threads client.ServiceClient.Open(); BrokerTracing.TraceVerbose("[AzureServiceClient]. AsyncStartWorker: Open the client succeeded, {0}", clientInfo); // setting client.InnerChannel.OperationTimeout causes the channel factory to open, and then causes client.Open to fail, // becasue we can't call Open when channel factory is already opened. // it is fine to set OperationTimeout after client.Open if (serviceOperationTimeout > 0) { BrokerTracing.TraceVerbose("[AzureServiceClient]. AsyncStartWorker: Set OperationTimeout {0} to the client {1}", serviceOperationTimeout, clientInfo); client.ServiceClient.InnerChannel.OperationTimeout = TimeSpan.FromMilliseconds(serviceOperationTimeout); } validConnection = true; } catch (Exception e) { BrokerTracing.TraceError("[AzureServiceClient]. AsyncStartWorker: Open the client failed, {0}, {1}", clientInfo, e); } try { if (validConnection) { try { if (client.waitHandleForOpen != null) { BrokerTracing.TraceVerbose("[AzureServiceClient]. AsyncStartWorker: Release the wait handle, {0}", clientInfo); client.waitHandleForOpen.Set(); } } catch (Exception ex) { BrokerTracing.TraceWarning("[AzureServiceClient].AsyncStartWorker: Exception {0}", ex); // Exception may happen if the client is already closed. Ignore this // exception because the client released that WaitHandle when closed. } BrokerTracing.TraceVerbose("[AzureServiceClient]. AsyncStartWorker: Call TriggerGetNextRequest, {0}", clientInfo); // the client.WaitHandleForOpen.Set() is already called above before this. client.TriggerGetNextRequest(); } else { client.RecreateClient(); } } catch (Exception e) { BrokerTracing.TraceError("[AzureServiceClient]. AsyncStartWorker: Execption happens, {0}, {1}", clientInfo, e); } }