/// <summary> /// the helper function to perform the retriable operations. /// </summary> /// <param name="retriableOperation">the delegation method.</param> /// <param name="format">the error format string when exception raised.</param> /// <param name="objParams">the params for the format string.</param> public static void PerformRetriableOperation(RetriableOperation retriableOperation, string format, params object[] objParams) { int retryNumber = 0; do { try { retriableOperation(retryNumber); return; } catch (MessageQueueException e) { // the msmq queue cannot access, then retry 3 times. if (MessageQueueHelper.CanRetry(e)) { retryNumber++; if (retryNumber < MessageQueueHelper.RetryCount) { string errorMessage = string.Empty; if (!string.IsNullOrEmpty(format)) { errorMessage = string.Format(CultureInfo.InvariantCulture, format, objParams) + ", and"; } errorMessage += "Will perform retry[" + retryNumber.ToString(CultureInfo.InvariantCulture) + "], the exception:" + e.ToString(); BrokerTracing.TraceWarning(errorMessage); } else { throw MessageQueueHelper.ConvertMessageQueueException(e); } } else { throw MessageQueueHelper.ConvertMessageQueueException(e); } } catch (Exception) { throw; } System.Threading.Thread.Sleep(100); }while (retryNumber > 0); }
/// <summary> /// Callback function invoked on BeginPeek completion. /// </summary> /// <param name="ar"></param> private void PeekMessageComplete(IAsyncResult ar) { BrokerTracing.TraceVerbose("[MSMQMessageFetcher] .PeekMessageComplete: Peek message complete."); Exception exception = null; System.Messaging.Message message = null; bool needRetry = false; RefCountedCursor storedMessagePeekCursor = ar.AsyncState as RefCountedCursor; this.rwlockMessagePeekCursorField.EnterReadLock(); try { try { // // Check if target queue is disposed. If so, don't call EndPeek. However, the check doesn't guarantee // that msmqQueueField is valid when EndPeek is invoked on it. So ObjectDisposedException shall be handled. // if (this.isQueueDisposed) { BrokerTracing.TraceWarning("[MSMQMessageFetcher]) .PeekMessageComplete: target queue is disposed"); return; } message = this.msmqQueueField.EndPeek(ar); Interlocked.Increment(ref this.peekCursorPosition); } catch (MessageQueueException e) { if (this.isDisposedField) { this.RevertFetchCount(); return; } needRetry = MessageQueueHelper.HandleAsyncCallbackError( e, ref this.messagePeekActionField, "[MSMQMessageFetcher] .PeekMessageComplete: EndPeek message failed, outstandingPeekCount:{0}, messageCount={1}", this.outstandingFetchCount, this.msmqMessageCount); if (!needRetry) { BrokerTracing.TraceError( "[MSMQMessageFetcher] .PeekMessageComplete: end peek message failed, outstandingPeekCount:{0}, messageCount:{1} Exception:{2}", this.outstandingFetchCount, this.msmqMessageCount, e); exception = e; } } catch (Exception e) { if (this.isDisposedField) { this.RevertFetchCount(); return; } BrokerTracing.TraceError("[MSMQMessageFetcher] .PeekMessageComplete: end peek message failed, Exception:{0}", e.ToString()); exception = e; } finally { storedMessagePeekCursor.Release(); } } finally { this.rwlockMessagePeekCursorField.ExitReadLock(); } if (needRetry) { Interlocked.Increment(ref this.pendingFetchCount); return; } if (message == null && exception == null) { BrokerTracing.TraceWarning("[MSMQMessageFetcher] .PeekMessageComplete: EndPeek return null."); } if (message != null) { // if the message is one of the partial messages if (message.AppSpecific > 0 && !string.IsNullOrEmpty(message.Label)) { try { BrokerTracing.TraceVerbose( "[MSMQMessageFetcher] .PeekMessageComplete: peek partial message with AppSpecific {0} and Label {1}.", message.AppSpecific, message.Label); string[] labels = message.Label.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries); string groupId = labels[0]; int msgNumber = int.Parse(labels[1]); ConcurrentDictionary <int, Message> messages = this.partialMessages.GetOrAdd(groupId, (k) => new ConcurrentDictionary <int, Message>()); if (!messages.TryAdd(msgNumber, message)) { BrokerTracing.TraceError( "[MSMQMessageFetcher] .PeekMessageComplete: try add one of the composed messages failed. Message Label {0}.", message.Label); } // check if all partial messages are peeked and cached if (this.partialMessageCounters.AddOrUpdate(groupId, 1, (k, v) => v + 1) == message.AppSpecific) { BrokerTracing.TraceVerbose( "[MSMQMessageFetcher] .PeekMessageComplete: all partial messages are peeked and cached for group {0}.", groupId); Message msg = new Message(); msg.BodyType = message.BodyType; byte[] buffer = new byte[Constant.MSMQChunkSize]; List <long> lookUpIds = new List <long>(message.AppSpecific); for (int i = 1; i <= message.AppSpecific; i++) { Message m = messages[i]; int count = m.BodyStream.Read(buffer, 0, Constant.MSMQChunkSize); msg.BodyStream.Write(buffer, 0, count); lookUpIds.Add(m.LookupId); } msg.BodyStream.Position = 0; BrokerQueueItem brokerQueueItem = null; // Deserialize message to BrokerQueueItem try { brokerQueueItem = (BrokerQueueItem)this.messageFormatter.Read(msg); brokerQueueItem.PersistAsyncToken.AsyncToken = lookUpIds.ToArray(); } catch (Exception e) { BrokerTracing.TraceError( "[MSMQMessageFetcher] .PeekMessageComplete: deserialize message failed for composed messages with groupId {0}, Exception:{1}", groupId, e); exception = e; } messages.Clear(); if (!this.partialMessages.TryRemove(groupId, out messages)) { BrokerTracing.TraceWarning( "[MSMQMessageFetcher] .PeekMessageComplete: try to remove partial messages with groupId {0} from cahce failed.", groupId); } int messageCount; if (!this.partialMessageCounters.TryRemove(groupId, out messageCount)) { BrokerTracing.TraceWarning( "[MSMQMessageFetcher] .PeekMessageComplete: try to remove partial message counters with groupId {0} from cahce failed.", groupId); } this.HandleMessageResult(new MessageResult(brokerQueueItem, exception)); } else { Interlocked.Increment(ref this.pendingFetchCount); } } catch (Exception ex) { BrokerTracing.TraceError( "[MSMQMessageFetcher] .PeekMessageComplete: peek composed message failed, Exception:{0}", ex); } } else { BrokerQueueItem brokerQueueItem = null; // Deserialize message to BrokerQueueItem try { brokerQueueItem = (BrokerQueueItem)this.messageFormatter.Read(message); brokerQueueItem.PersistAsyncToken.AsyncToken = new long[1] { message.LookupId }; } catch (Exception e) { BrokerTracing.TraceError( "[MSMQMessageFetcher] .PeekMessageComplete: deserialize message failed, Exception:{0}", e.ToString()); exception = e; } this.HandleMessageResult(new MessageResult(brokerQueueItem, exception)); } } }