// Peeks message (first/application-specified correlationId) from status queue private Message PeekFromStatusQueue(string correlationId) { string statusQueuePath = "FormatName:DIRECT=OS:" + this.queue.MachineName + @"\" + Parameters.STATUS_QUEUE; MessageQueue statusQueue = new MessageQueue(statusQueuePath); statusQueue.Formatter = new BinaryMessageFormatter(); statusQueue.MessageReadPropertyFilter.AppSpecific = true; statusQueue.MessageReadPropertyFilter.CorrelationId = true; Message statusMessage = null; try { if (correlationId == null) { statusMessage = statusQueue.PeekByLookupId(MessageLookupAction.First, 0); } else { statusMessage = statusQueue.PeekByCorrelationId(correlationId, TimeSpan.Zero); } } catch (MessageQueueException) { // If status queue is empty, peek will throw MessageQueueException throw new InvalidOperationException(); } statusQueue.Dispose(); statusQueue.Close(); return statusMessage; }
// throws exception if hole is found in the large message sequence // If not found, message is moved to the subqueue if moveMessage flag is true private int CheckReceiveMessage(MessageQueue subQueue, string correlationId, string largeSequenceId) { LargeMessageProperties largeMessageProperties = null; IMessageFormatter formatter = new BinaryMessageFormatter(); // If AppSpecific is zero, it is first fragment if (this.message.AppSpecific != Parameters.HEADER_FRAGMENT_ID) { try { Message lastMessageInSubQueue = subQueue.PeekByLookupId(MessageLookupAction.Last, 0); lastMessageInSubQueue.Formatter = formatter; if (this.message.AppSpecific == Parameters.TRAILER_FRAGMENT_ID) { // If message in main queue is a trailer fragment, check if the last message in subqueue // corresponds to the last expected message with application data largeMessageProperties = this.GetLargeMessageHeader(this.message); if (lastMessageInSubQueue.AppSpecific != largeMessageProperties.FragmentCount) { // Fragment(s) in the middle (before the trailer fragment) missing, send delete status message this.SendToStatusQueue(correlationId, (int)Parameters.ReceiveAction.Delete, largeSequenceId); return (int)Parameters.ReceiveAction.Restart; } } else if (((this.message.AppSpecific != (lastMessageInSubQueue.AppSpecific + 1)) && (lastMessageInSubQueue.AppSpecific != Parameters.HEADER_FRAGMENT_ID)) || ((this.message.AppSpecific != 1) && (lastMessageInSubQueue.AppSpecific == Parameters.HEADER_FRAGMENT_ID))) { // Fragment(s) in the middle missing, send delete status message this.SendToStatusQueue(correlationId, (int)Parameters.ReceiveAction.Delete, largeSequenceId); return (int)Parameters.ReceiveAction.Restart; } } catch (InvalidOperationException) { // No message in subqueue, send delete status message this.SendToStatusQueue(correlationId, (int)Parameters.ReceiveAction.Delete, largeSequenceId); return (int)Parameters.ReceiveAction.Restart; } } else { largeMessageProperties = this.GetLargeMessageHeader(this.message); } // Move message to sub-queue try { NativeMethods.MoveLargeMessage(this.queue, subQueue.FormatName, this.message.LookupId); } catch (InvalidOperationException) { // look for another large message sequence return ((int)Parameters.ReceiveAction.Restart); } if (this.message.AppSpecific == Parameters.TRAILER_FRAGMENT_ID) { // All fragments available in subqueue return ((int)Parameters.ReceiveAction.Complete); } // More fragments are expected return ((int)Parameters.ReceiveAction.Pending); }
// this.message is set to the first message in queue that is not same as large message id // If queue is empty, peek will throw MessageQueueException private void GetNextMessageSequenceInQueue(MessageQueue mq, string largeSequenceId) { int nextSequenceFlag = 0; try { if (this.message == null) { this.message = mq.PeekByLookupId(MessageLookupAction.First, 0); nextSequenceFlag = 1; } else { do { string currentLargeSequenceId = null; long prevLookupId = this.message.LookupId; this.message = mq.PeekByLookupId(MessageLookupAction.Next, prevLookupId); if (this.message.AppSpecific == Parameters.HEADER_FRAGMENT_ID) { currentLargeSequenceId = this.message.Id; } else { currentLargeSequenceId = this.message.CorrelationId; } nextSequenceFlag = String.Compare(currentLargeSequenceId, 0, largeSequenceId, 0, currentLargeSequenceId.Length, StringComparison.OrdinalIgnoreCase); } while (nextSequenceFlag == 0); } } catch (MessageQueueException) { throw new InvalidOperationException(); } }
// Returns true if the large message sequence in the sub-queue is completed private bool CheckCompleteMessage(MessageQueue subQueue) { Message firstMessageInSubQueue = subQueue.PeekByLookupId(MessageLookupAction.First, 0); firstMessageInSubQueue.Formatter = new BinaryMessageFormatter(); if (firstMessageInSubQueue.AppSpecific == Parameters.HEADER_FRAGMENT_ID) { Message lastMessageInSubQueue = subQueue.PeekByLookupId(MessageLookupAction.Last, 0); if (lastMessageInSubQueue.AppSpecific == Parameters.TRAILER_FRAGMENT_ID) { return true; } } return false; }