Example #1
0
 /// <summary>
 /// Informs that the client is disposed
 /// </summary>
 /// <param name="reason">indicating the reason</param>
 public void ClientDisposed(EndOfResponsesReason reason)
 {
     if (this.queue.ProcessedRequestsCount <= 0)
     {
         this.GenerateFaultMessage(reason);
         this.eom = true;
         this.completeEvent.Set();
     }
 }
Example #2
0
        /// <summary>
        /// Throw session exception according to the reason if needed
        /// </summary>
        /// <param name="reason">indicating the reason</param>
        private static void ThrowIfNeed(EndOfResponsesReason reason)
        {
            switch (reason)
            {
            case EndOfResponsesReason.ClientPurged:
                throw SessionBase.ClientPurgedException;

            case EndOfResponsesReason.ClientTimeout:
                throw SessionBase.ClientTimeoutException;
            }
        }
Example #3
0
            /// <summary>
            /// generate the fault message when the session failed.
            /// </summary>
            private void GenerateFaultMessage(EndOfResponsesReason reason)
            {
                XmlDocument doc = new XmlDocument()
                {
                    XmlResolver = null
                };
                Message soap11FaultMessage = null;

                switch (reason)
                {
                case EndOfResponsesReason.ClientPurged:
                    soap11FaultMessage = FrontEndFaultMessage.GenerateFaultMessage(null, MessageVersion.Soap11, SOAFaultCode.ClientPurged, SR.ClientPurged);
                    break;

                case EndOfResponsesReason.ClientTimeout:
                    soap11FaultMessage = FrontEndFaultMessage.GenerateFaultMessage(null, MessageVersion.Soap11, SOAFaultCode.ClientTimeout, SR.ClientTimeout);
                    break;
                }

                XPathNavigator nav = soap11FaultMessage.CreateBufferedCopy(BrokerEntry.MaxMessageSize).CreateNavigator();

                doc.Load(nav.ReadSubtree());
                this.messages.Add(doc.DocumentElement);
            }
Example #4
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
            }
        }
Example #5
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);
            }
        }