Beispiel #1
0
                private void HttpGetResponseThread()
                {
                    try
                    {
                        // List<IAsyncResult> results = new List<IAsyncResult>();
                        bool isEOM = false;

                        // ProcessResponseDelegate p = ProcessResponses;
                        int responseCount = 0;

                        // while (!isEOM)
                        // {
                        SessionBase.TraceSource.TraceInformation("Begin PullResponse : count {0} : clientId {1}", this.count, this.clientId);
                        BrokerResponseMessages responseMessages = this.controller.PullResponses(this.action, this.resetToBegin, this.count, this.clientId);
                        SessionBase.TraceSource.TraceInformation("End PullResponse : count {0} : isEOM {1}", responseMessages.SOAPMessage.Length, responseMessages.EOM);

                        // responseCount += responseMessages.SOAPMessage.Length;
                        responseCount = responseMessages.SOAPMessage.Length;

                        // results.Add(p.BeginInvoke(responseMessages, clientData, null, null));
                        this.ProcessResponses(responseMessages, this.clientData);
                        Interlocked.Add(ref this.responseClient.totalResponseCount, responseCount);
                        isEOM = responseMessages.EOM;

                        if (isEOM)
                        {
                            // construct endofreponses message
                            TypedMessageConverter converter      = TypedMessageConverter.Create(typeof(EndOfResponses), Constant.EndOfMessageAction);
                            EndOfResponses        endOfResponses = new EndOfResponses();
                            endOfResponses.Count  = this.responseClient.totalResponseCount;
                            endOfResponses.Reason = EndOfResponsesReason.Success;
                            Message eom = converter.ToMessage(endOfResponses, MessageVersion.Soap11);
                            eom.Headers.Add(MessageHeader.CreateHeader(Constant.ResponseCallbackIdHeaderName, Constant.ResponseCallbackIdHeaderNS, this.clientData));

                            this.callback.SendResponse(eom);
                        }
                    }
                    catch (Exception e)
                    {
                        SessionBase.TraceSource.TraceInformation("PullResponse Exception: {0}", e.ToString());

                        if (this.disposeFlag)
                        {
                            return;
                        }

                        Message exceptionMessage = Message.CreateMessage(MessageVersion.Soap11, @"http://hpc.microsoft.com/ClientSideExeption");
                        exceptionMessage.Headers.Add(MessageHeader.CreateHeader(Constant.ResponseCallbackIdHeaderName, Constant.ResponseCallbackIdHeaderNS, this.clientData));
                        exceptionMessage.Properties.Add(@"HttpClientException", e);

                        this.callback.SendResponse(exceptionMessage);
                    }
                    finally
                    {
                        if (this.Completed != null)
                        {
                            this.Completed(this, EventArgs.Empty);
                        }
                    }
                }
Beispiel #2
0
        /// <summary>
        /// reply the end of message to the client.
        /// </summary>
        /// <param name="callback">the response service callback.</param>
        /// <param name="clientData">the client data.</param>
        /// <param name="clientPurged">indicating the client purged flag</param>
        private void ReplyEndOfMessage(IResponseServiceCallback callback, string clientData, EndOfResponsesReason reason)
        {
            if (this.callbackChannelDisposed)
            {
                return;
            }

            BrokerTracing.TraceInfo("[GetResponsesHandler] Client {0}: Send end of response, clientPurged = {1}", this.clientId, reason);
            this.ResetTimeout();
            TypedMessageConverter converter      = TypedMessageConverter.Create(typeof(EndOfResponses), Constant.EndOfMessageAction);
            EndOfResponses        endOfResponses = new EndOfResponses();

            endOfResponses.Count  = this.ResponsesCount;
            endOfResponses.Reason = reason;
            Message eom = converter.ToMessage(endOfResponses, this.Version);

            eom.Headers.Add(MessageHeader.CreateHeader(Constant.ResponseCallbackIdHeaderName, Constant.ResponseCallbackIdHeaderNS, clientData));
            this.eorReplied = true;
            try
            {
                if (callback is AzureQueueProxy)
                {
                    callback.SendResponse(eom, clientData);
                }
                else
                {
                    callback.SendResponse(eom);
                }
            }
            catch (ObjectDisposedException)
            {
                BrokerTracing.TraceEvent(System.Diagnostics.TraceEventType.Error, 0, "[BrokerClient] Client {0}: Send end of response error: communication object is disposed.", this.clientId);
                this.callbackChannelDisposed = true;
                this.Queue.ResetResponsesCallback();
            }
            catch (Exception ce)
            {
                BrokerTracing.TraceEvent(System.Diagnostics.TraceEventType.Error, 0, "[BrokerClient] Client {0}: Send end of response error: {1}", this.clientId, ce);

                // Swallow exception
            }
        }
        /// <summary>
        /// Receives response messages from broker's response service
        /// </summary>
        /// <param name="message">Response message</param>
        public void SendResponse(Message message)
        {
            try
            {
                int currentResponseCount = 0;

                // Reset the heartbeat since operation just succeeded
                this.session.ResetHeartbeat();

                // Reset timeout timer since a response was received
                if (this.responseHandlerTimeoutTimer != null)
                {
                    this.responseHandlerTimeoutTimer.Change(this.responseHanderTimeout, 0);
                }

                // Bug #15946: handling client side exception thrown from WebResponseHandler(when talking to rest service)
                if (string.Equals(message.Headers.Action, Constant.WebAPI_ClientSideException, StringComparison.Ordinal))
                {
                    Exception e = message.Properties[Constant.WebAPI_ClientSideException] as Exception;
                    this.InvokeCallback(new BrokerResponse <TMessage>(e, message.Headers.RelatesTo));
                    return;
                }

                // TODO: Consider whether user callback should get an EOM message
                if (!Utility.IsEOM(message))
                {
                    // If the handler is closed, timed out, closed or broker heartbeat signaled, dont forward any more requests to the user.
                    // NOTE: If some responses already slipped through its OK because we prefer that over adding a lock here
                    if (this.shuttingDown)
                    {
                        return;
                    }

                    // Create a BrokerResponse object wrapper for the message object. A copy of the message must be created
                    MessageBuffer messageBuffer = null;
                    try
                    {
                        messageBuffer = message.CreateBufferedCopy(Constant.MaxBufferSize);
                    }
                    catch (Exception e)
                    {
                        Utility.LogError("AsyncResponseCallback.SendResponse received exception - {0}", e);
                        this.InvokeCallback(new BrokerResponse <TMessage>(e, message.Headers.RelatesTo));
                        return;
                    }

                    BrokerResponse <TMessage> brokerResponse = this.CreateResponse(BrokerClientBase.GetActionFromResponseMessage(message),
                                                                                   !message.IsFault ? message.Headers.Action : String.Empty,
                                                                                   messageBuffer,
                                                                                   message.Headers.RelatesTo == null ? SoaHelper.GetMessageId(message) : message.Headers.RelatesTo);

                    BrokerResponse <TMessage> lastResponse = null;

                    if (this.ignoreIsLastResponseProperty)
                    {
                        lastResponse = brokerResponse;
                    }
                    else
                    {
                        // Atomically swap out the last response.
                        lastResponse = Interlocked.Exchange <BrokerResponse <TMessage> >(ref this.lastBrokerResponse, brokerResponse);
                    }

                    // If there was a previous last response
                    if (lastResponse != null)
                    {
                        // Send it to the callback
                        this.InvokeCallback(lastResponse);

                        // Increment response count
                        currentResponseCount = Interlocked.Increment(ref this.currentResponseCount);
                    }

                    // If the caller wants all messages at once, do so.
                    // Else we always request ResponseWindowSize * 2 messages. If we get to
                    // the end of a window, request another
                    if (this.responseWindowSize != Constant.GetResponse_All && currentResponseCount != 0 &&
                        (currentResponseCount + 1) % this.responseWindowSize == 0)
                    {
                        // Call async version and block on completion in order to workaround System.Net.Socket bug #750028
                        try
                        {
                            SessionBase.TraceSource.TraceInformation("GetResponse : currentResponseCount {0} : clientId {1}", currentResponseCount, this.clientId);
                            this.responseService.GetResponses(
                                this.action,
                                this.callbackManagerId,
                                GetResponsePosition.Current,
                                this.responseWindowSize,
                                this.clientId);
                        }
                        catch (FaultException <SessionFault> e)
                        {
                            throw Utility.TranslateFaultException(e);
                        }
                    }
                }

                // If this is a client purged fault, return that exception in a BrokerResponse
                else
                {
                    TypedMessageConverter endOfResponsesConverter = TypedMessageConverter.Create(typeof(EndOfResponses), Constant.EndOfMessageAction);
                    EndOfResponses        endOfResponses          = (EndOfResponses)endOfResponsesConverter.FromMessage(message);

                    switch (endOfResponses.Reason)
                    {
                    case EndOfResponsesReason.ClientPurged:
                        this.InvokeCallback(new BrokerResponse <TMessage>(SessionBase.ClientPurgedException, new UniqueId(Guid.Empty)));
                        break;

                    case EndOfResponsesReason.ClientTimeout:
                        this.InvokeCallback(new BrokerResponse <TMessage>(SessionBase.ClientTimeoutException, new UniqueId(Guid.Empty)));
                        break;

                    default:
                        // Save how many responses are expected (minus 1 for the last response)
                        System.Diagnostics.Debug.Assert(endOfResponses.Count > 0, "Response count should also be positive number");
                        this.expectedResponseCount = endOfResponses.Count - 1;
                        break;
                    }
                }

                if (!this.ignoreIsLastResponseProperty)
                {
                    // Check to see if we receive the EOM message and all the responses.
                    // If so pass last response to callback marked as such. Also make
                    // sure this isnt called again with a lock.
                    if (this.expectedResponseCount == this.currentResponseCount)
                    {
                        lock (this.lastResponseLock)
                        {
                            if (this.expectedResponseCount == this.currentResponseCount)
                            {
                                // Mark the response as the last one
                                this.lastBrokerResponse.isLastResponse = true;

                                // Send last response to callback. Note since currentResponseCount
                                // is incremented after responses are sent to the callback, the
                                // callback will not be processing any other responses at this time.
                                this.InvokeCallback(this.lastBrokerResponse);

                                this.expectedResponseCount = -1;
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // Log and eat unhandled user exceptions from their calback
                Utility.LogError("Unhandled exception processing response - {0}", e);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Receives new response messages from broker
        /// </summary>
        /// <param name="response">Response message</param>
        void IResponseServiceCallback.SendResponse(Message response)
        {
            MessageBuffer  messageBuffer       = null;
            EndOfResponses endOfResponses      = null;
            Exception      clientSideException = null;
            bool           isEOM = false;

            // Reset the heartbeat since operation just succeeded
            this.session.ResetHeartbeat();

            try
            {
                // Check whether this is an EOM message
                isEOM = Utility.IsEOM(response);

                if (!isEOM)
                {
                    // If not EOM, create a copy of the message's buffer so it can be deserialized
                    // A copy is needed because WCF will dispose this message when the callback returns
                    // Alternatively we could deserialize the entire message but we want
                    //  callback to be quick and we may wind up deserializing messages the user
                    //  never looks at (i.e. just checks user data or exits enum early)
                    try
                    {
                        messageBuffer = response.CreateBufferedCopy(Constant.MaxBufferSize);
                    }
                    catch (Exception e)
                    {
                        SessionBase.TraceSource.TraceEvent(TraceEventType.Error, 0, "[Session:{0}][BrokerResponseEnumerator] Failed to create message buffer from the response message: {1}", this.session.Id, e);
                        clientSideException = e;
                    }
                }
                else
                {
                    // If EOM, deserialize EndOfResponses message
                    endOfResponses = (EndOfResponses)this.endOfResponsesConverter.FromMessage(response);
                }

                string messageId = String.Empty;
                try
                {
                    messageId = SoaHelper.GetMessageId(response).ToString();
                }
                catch
                {
                    // Swallow possible ObjectDisposedException
                }

                SessionBase.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "[Session:{0}][BrokerResponseEnumerator] Response received from broker. IsEOM = {1}, MessageId = {2}", this.session.Id, isEOM, messageId);

                lock (this.responsesLock)
                {
                    // If the enumerator is disposing or disposed, return
                    if (this.isDisposeCalled)
                    {
                        return;
                    }

                    // If this is not an EOM message
                    if (!isEOM)
                    {
                        string actionFromResponse = BrokerClientBase.GetActionFromResponseMessage(response);

                        // Save the response in the current window
                        MessageWindowItem messageItem = new MessageWindowItem(
                            messageBuffer,
                            actionFromResponse,
                            !response.IsFault ? response.Headers.Action : String.Empty,
                            response.Headers.RelatesTo == null ? SoaHelper.GetMessageId(response) : response.Headers.RelatesTo);

                        // Bug #15946: handling client side exception thrown from WebResponseHandler(when talking to rest service)
                        // To propagate the client side exception to BrokerResponseEnumerator api, store the exception in MessageWindowItem
                        if (string.Equals(response.Headers.Action, Constant.WebAPI_ClientSideException, StringComparison.Ordinal))
                        {
                            clientSideException = response.Properties[Constant.WebAPI_ClientSideException] as Exception;
                        }
                        messageItem.CarriedException = clientSideException;

                        this.currentReceiveWindow.Enqueue(messageItem);

                        // Increment the current number of responses
                        this.currentResponseCount++;

                        // Lower number of outstanding requests
                        if (Interlocked.Decrement(ref this.outstandingRequestCount) == 0)
                        {
                            try
                            {
                                this.GetMoreResponses(false, ResponseWindowSize);
                            }
                            catch (Exception e)
                            {
                                SessionBase.TraceSource.TraceEvent(TraceEventType.Error,
                                                                   0, "[Session:{0}][BrokerResponseEnumerator] Failed to get more responses in SendResponse context: {1}", this.session.Id, e);

                                // Send broker down signal since connection to broker might be bad
                                ((IResponseServiceCallback)this).SendBrokerDownSignal(false);
                            }
                        }

                        // If the current window is full or there are no more responses
                        if (this.currentReceiveWindow.Count == ResponseWindowSize ||
                            this.currentResponseCount == this.totalResponseCount)
                        {
                            // Disable the flush timer
                            this.flushResponsesTimer.Change(Timeout.Infinite, Timeout.Infinite);

                            // Immediately flush the receive window
                            this.FlushCurrentReceiveWindow();
                        }

                        // Otherwise reset the flushtimer to the full interval
                        else
                        {
                            this.flushResponsesTimer.Change(this.flushResponsesTimerInterval, Timeout.Infinite);
                        }
                    }
                    else
                    {
                        // If we already received an EOM, ignore any others. We may get multiple EOM since
                        // more responses are requested until we get EOM. This can lead to overrequesting.
                        if (this.totalResponseCount != -1)
                        {
                            return;
                        }

                        // Save total response count
                        this.totalResponseCount   = endOfResponses.Count;
                        this.endOfResponsesReason = endOfResponses.Reason;

                        // If there are no more responses
                        if (this.currentResponseCount == this.totalResponseCount)
                        {
                            // Make the current receive window available to enumerator if it has responses
                            if (this.currentReceiveWindow.Count != 0)
                            {
                                this.responsesWindows.Enqueue(this.currentReceiveWindow);
                                this.currentReceiveWindow = new Queue <MessageWindowItem>();
                            }

                            // Notify enumerator that a new window is available. Notify even if
                            // its empty since it allows MoveNext to exit and return there are no
                            // more items
                            this.newResponseWindowOrEOM.Set();
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // If we get an exception here log and dispose the enum
                this.Dispose();

                SessionBase.TraceSource.TraceEvent(TraceEventType.Error, 0, "[Session:{0}][BrokerResponseEnumerator] Unhandled exception in response enumerator callback :{1}", this.session.Id, e);
            }
        }