internal MessagesWithLock(List<RelayMessage> messages, HandleWithCount locker) { Messages = messages; Locker = locker; }
/// <summary> /// Performs processing on a block of messages /// </summary> /// <param name="messages">A list of RealyMessage objects to be processed</param> /// <exception cref="SyncRelayOperationException"> /// When the type of an object is defined with settings /// <see cref="MySpace.DataRelay.Common.Schemas.TypeSettings"></see> with /// SyncInMessages=true and /// ThrowOnSyncFailure=true /// failed executions will throw this exception /// </exception> /// <remarks> /// Procssing steps: /// 1. Splits the list of messages into several lists, each containing /// the node, messages of a single type and settings for that type /// 2. Processes each list individually /// 3. Tracks the success/failure of each list /// 4. If a list (or a message from a list) fails, and the type of message /// requires a "Throw" when sync fails: throws a SyncRelayOperationException, /// otherwise, places failed messages into the exception queue /// </remarks> public void HandleMessages(IList <RelayMessage> messages) { SetHydrationPolicy(messages); NodeManager.Instance.Counters.CountMessageList(messages); NodeWithMessagesCollection distributedMessages = NodeManager.Instance.DistributeMessages(messages); NodeWithMessages nodeMessages; AutoResetEvent resetEvent = null; HandleWithCount finishedLock = null; List <NodeWithMessages> unhandledNodes = new List <NodeWithMessages>(); if (_enableAsyncBulkGets && distributedMessages.Count > 1) //only do the async if there's more than 1 node to send to. No point in hitting a wait handle if we don't need to coordinate a response { int numberOfGets = 0, getsLefts = 0; for (int i = 0; i < distributedMessages.Count; i++) { if (distributedMessages[i].Messages.OutMessageCount > 0) { numberOfGets++; } } if (numberOfGets > 0) { resetEvent = OutMessageWaitHandle; finishedLock = new HandleWithCount(resetEvent, numberOfGets); getsLefts = numberOfGets; //use this to determine when we're at the last get so we use this thread to process it } for (int i = 0; i < distributedMessages.Count; i++) { nodeMessages = distributedMessages[i]; if (nodeMessages.Messages.InMessageCount > 0) { bool inMessagesHandled = nodeMessages.NodeWithInfo.Node.HandleInMessages(nodeMessages.Messages.InMessages, nodeMessages.NodeWithInfo.SyncInMessages, nodeMessages.NodeWithInfo.SkipErrorQueueForSync); if (!inMessagesHandled) { unhandledNodes.Add(nodeMessages); } } if (nodeMessages.Messages.OutMessageCount > 0) { if (--getsLefts > 0) { nodeMessages.NodeWithInfo.Node.PostOutMessages( new MessagesWithLock(nodeMessages.Messages.OutMessages, finishedLock)); } else { nodeMessages.NodeWithInfo.Node.HandleOutMessages(nodeMessages.Messages.OutMessages); finishedLock.Decrement(); } } } if (numberOfGets > 0) { resetEvent.WaitOne(); } return; } else { for (int i = 0; i < distributedMessages.Count; i++) { nodeMessages = distributedMessages[i]; if (nodeMessages.Messages.InMessageCount > 0) { bool inMessagesHandled = nodeMessages.NodeWithInfo.Node.HandleInMessages(nodeMessages.Messages.InMessages, nodeMessages.NodeWithInfo.SyncInMessages, nodeMessages.NodeWithInfo.SkipErrorQueueForSync); if (!inMessagesHandled) { unhandledNodes.Add(nodeMessages); } } if (nodeMessages.Messages.OutMessageCount > 0) { nodeMessages.NodeWithInfo.Node.HandleOutMessages(nodeMessages.Messages.OutMessages); } } } if (unhandledNodes.Count > 0) { bool bThrow = false; StringBuilder detailBuilder = new StringBuilder(); detailBuilder.Append("Error handling sync in messages\r\n"); foreach (NodeWithMessages nwm in unhandledNodes) { if (nwm.NodeWithInfo.SkipErrorQueueForSync && nwm.NodeWithInfo.SyncInMessages) { detailBuilder.AppendFormat("Node:{0}\r\n", nwm.NodeWithInfo.Node.GetType().Name); detailBuilder.AppendFormat("\tMessages: {0}\r\n", nwm.Messages.InMessageCount); bThrow = true; } } if (bThrow) { throw new SyncRelayOperationException(detailBuilder.ToString()); } if (_log.IsInfoEnabled) { _log.Info(detailBuilder.ToString()); } } }
internal MessagesWithLock(List <RelayMessage> messages, HandleWithCount locker) { Messages = messages; Locker = locker; }
/// <summary> /// Performs processing on a block of messages /// </summary> /// <param name="messages">A list of RealyMessage objects to be processed</param> /// <exception cref="SyncRelayOperationException"> /// When the type of an object is defined with settings /// <see cref="MySpace.DataRelay.Common.Schemas.TypeSettings"></see> with /// SyncInMessages=true and /// ThrowOnSyncFailure=true /// failed executions will throw this exception /// </exception> /// <remarks> /// Procssing steps: /// 1. Splits the list of messages into several lists, each containing /// the node, messages of a single type and settings for that type /// 2. Processes each list individually /// 3. Tracks the success/failure of each list /// 4. If a list (or a message from a list) fails, and the type of message /// requires a "Throw" when sync fails: throws a SyncRelayOperationException, /// otherwise, places failed messages into the exception queue /// </remarks> public void HandleMessages(IList<RelayMessage> messages) { SetHydrationPolicy(messages); NodeManager.Instance.Counters.CountMessageList(messages); NodeWithMessagesCollection distributedMessages = NodeManager.Instance.DistributeMessages(messages); NodeWithMessages nodeMessages; AutoResetEvent resetEvent = null; HandleWithCount finishedLock = null; List<NodeWithMessages> unhandledNodes = new List<NodeWithMessages>(); if (_enableAsyncBulkGets && distributedMessages.Count > 1) //only do the async if there's more than 1 node to send to. No point in hitting a wait handle if we don't need to coordinate a response { int numberOfGets = 0, getsLefts = 0; for (int i = 0; i < distributedMessages.Count; i++) { if (distributedMessages[i].Messages.OutMessageCount > 0) { numberOfGets++; } } if (numberOfGets > 0) { resetEvent = OutMessageWaitHandle; finishedLock = new HandleWithCount(resetEvent, numberOfGets); getsLefts = numberOfGets; //use this to determine when we're at the last get so we use this thread to process it } for (int i = 0; i < distributedMessages.Count; i++) { nodeMessages = distributedMessages[i]; if (nodeMessages.Messages.InMessageCount > 0) { bool inMessagesHandled = nodeMessages.NodeWithInfo.Node.HandleInMessages(nodeMessages.Messages.InMessages, nodeMessages.NodeWithInfo.SyncInMessages, nodeMessages.NodeWithInfo.SkipErrorQueueForSync); if (!inMessagesHandled) { unhandledNodes.Add(nodeMessages); } } if (nodeMessages.Messages.OutMessageCount > 0) { if (--getsLefts > 0) { nodeMessages.NodeWithInfo.Node.PostOutMessages( new MessagesWithLock(nodeMessages.Messages.OutMessages, finishedLock)); } else { nodeMessages.NodeWithInfo.Node.HandleOutMessages(nodeMessages.Messages.OutMessages); finishedLock.Decrement(); } } } if (numberOfGets > 0) { resetEvent.WaitOne(); } return; } else { for (int i = 0; i < distributedMessages.Count; i++) { nodeMessages = distributedMessages[i]; if (nodeMessages.Messages.InMessageCount > 0) { bool inMessagesHandled = nodeMessages.NodeWithInfo.Node.HandleInMessages(nodeMessages.Messages.InMessages, nodeMessages.NodeWithInfo.SyncInMessages, nodeMessages.NodeWithInfo.SkipErrorQueueForSync); if (!inMessagesHandled) { unhandledNodes.Add(nodeMessages); } } if (nodeMessages.Messages.OutMessageCount > 0) { nodeMessages.NodeWithInfo.Node.HandleOutMessages(nodeMessages.Messages.OutMessages); } } } if (unhandledNodes.Count > 0) { bool bThrow = false; StringBuilder detailBuilder = new StringBuilder(); detailBuilder.Append("Error handling sync in messages\r\n"); foreach (NodeWithMessages nwm in unhandledNodes) { if (nwm.NodeWithInfo.SkipErrorQueueForSync && nwm.NodeWithInfo.SyncInMessages) { detailBuilder.AppendFormat("Node:{0}\r\n", nwm.NodeWithInfo.Node.GetType().Name); detailBuilder.AppendFormat("\tMessages: {0}\r\n", nwm.Messages.InMessageCount); bThrow = true; } } if (bThrow) { throw new SyncRelayOperationException(detailBuilder.ToString()); } if (_log.IsInfoEnabled) _log.Info(detailBuilder.ToString()); } }
private static void AsyncBulkHandleMessages(NodeWithMessagesCollection distributedMessages, List <NodeWithMessages> unhandledNodes) { if (log.IsDebugEnabled) { log.Debug("Starting asyncbulk handle messages"); } AutoResetEvent resetEvent = null; HandleWithCount finishedLock = null; int numberOfGets = 0; int getsLefts = 0; for (int i = 0; i < distributedMessages.Count; i++) { if (distributedMessages[i].Messages.OutMessageCount > 0) { numberOfGets++; } } if (numberOfGets > 0) { resetEvent = OutMessageWaitHandle; finishedLock = new HandleWithCount(resetEvent, numberOfGets); getsLefts = numberOfGets; //use this to determine when we're at the last get so we use this thread to process it } for (int i = 0; i < distributedMessages.Count; i++) { NodeWithMessages nodeWithMessages = distributedMessages[i]; NodeWithInfo nodeWithInfo = nodeWithMessages.NodeWithInfo; if (nodeWithMessages.Messages.InMessageCount > 0) { bool inMessagesHandled = nodeWithInfo.Node.HandleInMessages(nodeWithMessages.Messages.InMessages, nodeWithInfo.SyncInMessages, nodeWithInfo.SkipErrorQueueForSync); if (!inMessagesHandled) { unhandledNodes.Add(nodeWithMessages); } } if (nodeWithMessages.Messages.OutMessageCount > 0) { if (--getsLefts > 0) //post all the last group to be handled async { nodeWithInfo.Node.PostOutMessages( new MessagesWithLock(nodeWithMessages.Messages.OutMessages, finishedLock)); } else { nodeWithInfo.Node.SendOutMessages(nodeWithMessages.Messages.OutMessages); //do the last set on this thread rather than punting the duty finishedLock.Decrement(); } } } if (numberOfGets > 0) { resetEvent.WaitOne(); //wait for all operations to complete. the event will be signaled with lock.decrement hits 0 } }