Beispiel #1
0
        /// <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);
            }
        }