/// <summary>
        /// /// push the result ticket out to the client. The client then needs to turn around and call GetAsyncResponseData
        /// or GetAsyncResponseStreamData to get the data
        /// </summary>
        /// <param name="targetClientProxy"></param>
        /// <param name="message"></param>
        /// <param name="dataAttachment"></param>
        /// <param name="streamAttachment"></param>
        /// <param name="response"></param>
        public void PublishSendResponseTicket(ClientProxy targetClientProxy, string message, object dataAttachment, Stream streamAttachment, AsyncMethodResponse response)
        {
            QueuedResponsePayload payload = null;

            if (dataAttachment != null ||
                streamAttachment != null)
            {
                payload = new QueuedResponsePayload(dataAttachment, response.AsyncTicket, response.ClientId, streamAttachment);
                if (payload.PayloadStream != null)
                {
                    string payloadStreamId = string.Format("{0}.{1}", response.ClientId, payload.PayloadTicket);
                    response.StreamDataId = payloadStreamId;
                    lock (streamIdToPayloadMap)
                        streamIdToPayloadMap[payloadStreamId] = payload;
                }
                else if (payload.PayloadData != null)
                {
                    lock (payloadTicketToResponseMap)
                        payloadTicketToResponseMap[payload.PayloadTicketGuid] = payload;
                }
            }

            Dictionary <Guid, ClientProxy> targetClientProxyMap = new Dictionary <Guid, ClientProxy>();

            targetClientProxyMap.Add(targetClientProxy.ClientId, targetClientProxy);
            PublishSendResponseTicketEventArg psrtea = new PublishSendResponseTicketEventArg(DateTime.UtcNow, response, message, payload);

            this.Publish(targetClientProxyMap, true, psrtea, this.publishSendResponseTicketHandler);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="clientId"></param>
        /// <returns></returns>
        public ClientProxy LookupClientProxy(Guid clientId)
        {
            ClientProxy clientProxy = null;

            lock (this.subscribers)
                subscribers.TryGetValue(clientId, out clientProxy);

            return(clientProxy);
        }
        /// <summary>
        /// Add a client to subscription list
        /// </summary>
        /// <param name="clientId"></param>
        /// <returns></returns>
        public AsyncMethodResponse Subscribe(Guid clientId)
        {
            try
            {
                Guid newClientId = clientId;
                if (newClientId == Guid.Empty)
                {
                    newClientId = Guid.NewGuid();
                }

                IServerAdminCallback callback    = OperationContext.Current.GetCallbackChannel <IServerAdminCallback>();
                ClientProxy          clientProxy = new ClientProxy(newClientId, callback);
                lock (subscribers)
                {
                    ClientProxy existingClientProxy;
                    if (clientId != Guid.Empty)
                    {
                        subscribers.TryGetValue(clientId, out existingClientProxy);
                    }
                    else
                    {
                        existingClientProxy = null;
                    }

                    if (existingClientProxy == null)
                    {
                        subscribers[newClientId] = clientProxy;
                    }
                    else
                    {
                        existingClientProxy.AssignNewCallback(callback);
                        List <KeyValuePair <PublishEventArgs, PublishEventHandler> > pendingList = existingClientProxy.PopPendingMessageList();
                        if (pendingList != null)
                        {
                            Dictionary <Guid, ClientProxy> targetClientProxyMap = new Dictionary <Guid, ClientProxy>();
                            targetClientProxyMap[existingClientProxy.ClientId] = existingClientProxy;

                            foreach (KeyValuePair <PublishEventArgs, PublishEventHandler> pair in pendingList)
                            {
                                Publish(targetClientProxyMap, true, pair.Key, pair.Value);
                            }
                        }
                    }
                }
                AsyncMethodResponse response = new AsyncMethodResponse(newClientId, null);

                return(response);
            }
            catch (Exception ex)
            {
                AsyncMethodResponse errorResponse = new AsyncMethodResponse(clientId, null);
                errorResponse.AddError(ex.Message, ErrorCode.Fatal);
                return(errorResponse);
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="clientProxy"></param>
        /// <param name="dpea"></param>
        /// <param name="publishHandler"></param>
        public void AddPublish(ClientProxy clientProxy, PublishEventArgs dpea, PublishEventHandler publishHandler)
        {
            if (clientProxy.PublishingThread == null)
            {
                lock (clientProxy)
                {
                    if (clientProxy.PublishingThread == null)
                    {
                        lock (this.publishThreadList)
                        {
                            foreach (PublishThread curPublishThread in this.publishThreadList)
                            {
                                if (curPublishThread.ClientCount == 0)
                                {
                                    clientProxy.PublishingThread = curPublishThread;
                                    break;
                                }
                            }

                            if (clientProxy.PublishingThread == null)
                            {
                                PublishThread publishThread = null;
                                if (this.publishThreadList.Count < MaxThreads)
                                {
                                    publishThread = new PublishThread(this.publishThreadList.Count);
                                    this.publishThreadList.Add(publishThread);
                                }
                                else
                                {
                                    int minClientCount = int.MaxValue;
                                    foreach (PublishThread curPublishThread in this.publishThreadList)
                                    {
                                        if (curPublishThread.ClientCount < minClientCount)
                                        {
                                            publishThread  = curPublishThread;
                                            minClientCount = curPublishThread.ClientCount;
                                        }
                                    }
                                }
                                clientProxy.PublishingThread = publishThread;
                            }
                        }
                    }
                }
            }

            clientProxy.PublishingThread.AddPublish(clientProxy, dpea, publishHandler);
        }
 /// <summary>
 /// remove client from subscription list
 /// </summary>
 /// <param name="clientId"></param>
 /// <returns></returns>
 public AsyncMethodResponse Unsubscribe(Guid clientId)
 {
     try
     {
         ClientProxy clientProxy = null;
         lock (this.subscribers)
         {
             if (subscribers.TryGetValue(clientId, out clientProxy))
             {
                 clientProxy.Unsubscribe();
                 subscribers.Remove(clientId);
             }
         }
         return(null);
     }
     catch (Exception ex)
     {
         AsyncMethodResponse response = new AsyncMethodResponse(clientId, null);
         response.AddError(ex.Message, ErrorCode.Fatal);
         return(response);
     }
 }
        private void PublishSendResponseTicketHandlerProc(ClientProxy clientProxy, PublishEventArgs pea)
        {
            PublishSendResponseTicketEventArg psrtea = (PublishSendResponseTicketEventArg)pea;

            clientProxy.CallBack.OnPendingResponseObject(psrtea.Message, psrtea.Payload.PayloadTicket, psrtea.MessageTimeUtc, psrtea.Response);
        }
        private void PublishMessageHandlerProc(ClientProxy clientProxy, PublishEventArgs dpea)
        {
            PublishMessageEventArg dpmea = (PublishMessageEventArg)dpea;

            clientProxy.CallBack.OnServerMessage(dpmea.Message, dpmea.MessageTimeUtc, dpmea.Response);
        }
 /// <summary>
 ///
 /// </summary>
 /// <param name="clientProxy"></param>
 /// <param name="dpea"></param>
 /// <param name="publishHandler"></param>
 public PublishParameters(ClientProxy clientProxy, PublishEventArgs dpea, PublishEventHandler publishHandler)
 {
     this.ClientProxy     = clientProxy;
     this.PublishEventArg = dpea;
     this.PublishHandler  = publishHandler;
 }
 /// <summary>
 ///
 /// </summary>
 /// <param name="clientProxy"></param>
 /// <param name="dpea"></param>
 /// <param name="publishHandler"></param>
 public void AddPublish(ClientProxy clientProxy, PublishEventArgs dpea, PublishEventHandler publishHandler)
 {
     this.waitQueue.Enqueue(new PublishParameters(clientProxy, dpea, publishHandler));
 }
 /// <summary>
 ///
 /// </summary>
 /// <param name="clientProxy"></param>
 public void RemoveClientProxy(ClientProxy clientProxy)
 {
     lock (this.clientProxySet)
         this.clientProxySet.Remove(clientProxy);
 }
 /// <summary>
 ///
 /// </summary>
 /// <param name="clientProxy"></param>
 public void AddClientProxy(ClientProxy clientProxy)
 {
     lock (this.clientProxySet)
         this.clientProxySet.Add(clientProxy);
 }