Example #1
0
        /// <summary>
        /// Threadpool callback that invokes callback of GetMessageAsync call
        /// </summary>
        /// <param name="state">callback state of the threadpool callback</param>
        private void GetMessageAsyncCallback(object state)
        {
            object[]        objs            = (object[])state;
            GetMessageState getMessageState = objs[0] as GetMessageState;
            MessageResult   result          = objs[1] as MessageResult;

            try
            {
                if (getMessageState.MessageCallback != null)
                {
                    getMessageState.MessageCallback(result.Message, getMessageState.CallbackState, result.Exception);
                }
            }
            catch (Exception e)
            {
                BrokerTracing.TraceError(
                    "[MSMQMessageFetcher] .GetMessageAsyncCallback: perform the message callback failed, the exception, {0}",
                    e.ToString());
            }
        }
Example #2
0
        private void GetMessageAsyncCallback(object state)
        {
            object[]        objs            = (object[])state;
            GetMessageState getMessageState = objs[0] as GetMessageState;
            MessageResult   result          = objs[1] as MessageResult;

            try
            {
                if (getMessageState.MessageCallback != null)
                {
                    getMessageState.MessageCallback(result.Message, getMessageState.CallbackState, result.Exception);
                }
            }
            catch (Exception e)
            {
                BrokerTracing.TraceError(
                    "[AzureQueueMessageFetcher] .GetMessageAsyncCallbck: fetcherId={0} perform the message callback failed, the exception, {1}",
                    this.fetcherId,
                    e);
            }
        }
Example #3
0
        public void GetMessageAsync(PersistCallback callback, object state)
        {
            if (this.isDisposedField)
            {
                BrokerTracing.TraceWarning(
                    "[AzureQueueMessageFetcher] .GetMessageAsync: fetcherId={0} the instance is disposed.",
                    this.fetcherId);
                return;
            }

            BrokerTracing.TraceVerbose(
                "[AzureQueueMessageFetcher] .GetMessageAsync: fetcherId={0} Get message come in.",
                this.fetcherId);

            // GetMessageAsync:
            // step 1, try to get message from prefetch cache. If succeeded, invoke the callback directly; or else,
            // step 2, save context of this GetMessageAsync call, including callback and callback state into this.currentGetMessageState, which will be handled when a message is retrieved back from MSMQ.
            // step 3, check if need to get more messages.  If so, initiate more BeginPeek calls into MSMQ
            GetMessageState       getMessageState = new GetMessageState(callback, state);
            MessageResult         result          = null;
            Queue <MessageResult> messageQueue    = new Queue <MessageResult>();

#if DEBUG
            bool getResponse = false;
#endif

            long getMessageCount = 1;
            ResponseCallbackItem responseCallbackItem = state as ResponseCallbackItem;
            if (responseCallbackItem != null)
            {
#if DEBUG
                getResponse = true;
#endif
                getMessageCount = responseCallbackItem.ExpectedResponseCount;
                Debug.WriteLine(
                    $"[AzureQueueMessageFetcher] .GetMessageAsync: working to get response. getMessageCount={getMessageCount}.");
            }
            else
            {
                Debug.WriteLine(
                    $"[AzureQueueMessageFetcher] .GetMessageAsync: working to get request. getMessageCount={getMessageCount}.");
            }

            this.lockPrefetchCache.EnterReadLock();
            try
            {
                if (this.prefetchCache == null)
                {
                    // this instance is disposed
                    BrokerTracing.TraceWarning(
                        "[AzureQueueMessageFetcher] .GetMessageAsync: the instance is disposed.");
                    return;
                }

                while (getMessageCount > 0)
                {
                    if (!(this.prefetchCache.Count > 0 && this.prefetchCache.TryDequeue(out result)))
                    {
                        BrokerTracing.TraceVerbose("[AzureQueueMessageFetcher] .GetMessageAsync: cache miss");
                        result = null;
                        this.currentGetMessageQueue.Enqueue(getMessageState);
                        break;
                    }

                    BrokerTracing.TraceVerbose("[AzureQueueMessageFetcher] .GetMessageAsync: hit cache");
                    messageQueue.Enqueue(result);
                    getMessageCount--;
                }
            }
            finally
            {
                this.lockPrefetchCache.ExitReadLock();
            }

            Debug.WriteLine(
                $"[AzureQueueMessageFetcher] .GetMessageAsync: getMessageCount={getMessageCount} after dequeue.");

            while (messageQueue.Any())
            {
                var message = messageQueue.Dequeue();
                if (message != null)
                {
                    // There is one more space available in prefetch cache
                    lock (this.lockFetchCount)
                    {
                        this.prefetchCredit++;
                    }

                    // GetMessageAsync is a light-weight call and is supposed to return very soon.  While in its callback,
                    // there may be time-consuming operations. So here we always invoke the callback in another thread.
                    ThreadPool.QueueUserWorkItem(
                        this.GetMessageAsyncCallback,
                        new object[] { getMessageState, message });
                }
                else
                {
                    BrokerTracing.TraceWarning(
                        "[AzureQueueMessageFetcher] .GetMessageAsync: fetcherId={0} encountered null message result.",
                        this.fetcherId);
                }
            }

            this.CheckAndGetMoreMessages();
        }
Example #4
0
        protected void HandleMessageResult(MessageResult messageResult)
        {
            lock (this.lockFetchCount)
            {
                this.outstandingFetchCount--;
                if (messageResult.Message != null)
                {
                    this.messageCount--;
                }
            }

            GetMessageState getMessageState = null;

            this.lockPrefetchCache.EnterUpgradeableReadLock();

            bool TryGetMessageFromQueue(out GetMessageState state)
            {
                state = null;
                return(this.currentGetMessageQueue != null && this.currentGetMessageQueue.TryDequeue(out state));
            }

            try
            {
                if (this.prefetchCache == null)
                {
                    // this instance is disposed
                    return;
                }

                if (!TryGetMessageFromQueue(out getMessageState))
                {
                    this.lockPrefetchCache.EnterWriteLock();
                    try
                    {
                        if (!TryGetMessageFromQueue(out getMessageState))
                        {
                            getMessageState = null;
                            this.prefetchCache.Enqueue(messageResult);
                        }
                    }
                    finally
                    {
                        this.lockPrefetchCache.ExitWriteLock();
                    }
                }
            }
            finally
            {
                this.lockPrefetchCache.ExitUpgradeableReadLock();
            }

            if (getMessageState != null)
            {
                lock (this.lockFetchCount)
                {
                    this.prefetchCredit++;
                }

                ThreadPool.QueueUserWorkItem(
                    this.GetMessageAsyncCallback,
                    new object[] { getMessageState, messageResult });
            }

            this.CheckAndGetMoreMessages();
        }