Пример #1
0
        /// <summary>
        /// Create a list of nodes with messages that can be retried according to Relay Group settings.
        /// </summary>
        /// <param name="distributedMessages">A list of distributed messages have been previously attempted.</param>
        /// <returns>A redistribution of nodes with messages left to retry, or null if no retries are needed or allowed.</returns>
        internal NodeWithMessagesCollection RedistributeRetryMessages(NodeWithMessagesCollection distributedMessages)
        {
            var redistributedMessages = new NodeWithMessagesCollection();

            foreach (var nodeWithMessages in distributedMessages)
            {
                var retriesAllowed   = nodeWithMessages.NodeWithInfo.Node.NodeGroup.GroupDefinition.RetryCount;
                var retriesAttempted = nodeWithMessages.AttemptedNodes.Count;

                if (nodeWithMessages.Messages.OutMessageCount > 0 && retriesAttempted < retriesAllowed)
                {
                    var firstMessage = nodeWithMessages.Messages.OutMessages[0];

                    var retryable = firstMessage.IsRetryable(Instance.GetRelayRetryPolicyForMessage(firstMessage));

                    // the first message's outcome should be the same as every message in the list for these specific conditions
                    if (retryable)
                    {
                        nodeWithMessages.AttemptedNodes.Add(nodeWithMessages.NodeWithInfo.Node);

                        var retryNode =
                            nodeWithMessages.NodeWithInfo.Node.GetRetryNodeFromCluster(nodeWithMessages.AttemptedNodes);
                        if (retryNode != null)
                        {
                            // only try to redistribute this node if a retryNode is available.  Otherwise, retries are not possible.
                            nodeWithMessages.NodeWithInfo.Node = retryNode;

                            // prepare each message in the list for retry.
                            foreach (var message in nodeWithMessages.Messages.OutMessages)
                            {
                                message.RelayTTL++;
                                message.SetError(RelayErrorType.None);
                                message.ResultOutcome = RelayOutcome.NotSent;
                            }

                            // wipe out any potential IN messages.
                            nodeWithMessages.Messages.InMessages = null;
                            redistributedMessages.Add(nodeWithMessages);
                        }
                    }
                }
            }
            return(redistributedMessages);
        }
        /// <summary>
        /// Splits messages into various lists of in and out message destined for different nodes.
        /// </summary>
        /// <param name="messages"></param>
        /// <returns></returns>
        internal NodeWithMessagesCollection DistributeMessages(IList <RelayMessage> messages)
        {
            NodeWithMessagesCollection distribution = new NodeWithMessagesCollection();
            RelayMessage message;
            Node         node;

            for (int i = 0; i < messages.Count; i++)
            {
                if (messages[i] != null)
                {
                    message = messages[i];

                    RelayMessage interZoneMessage = null;

                    SimpleLinkedList <Node> nodesForMessage          = GetNodesForMessage(message);
                    SimpleLinkedList <Node> nodesForInterZoneMessage = null;

                    if (nodesForMessage.Count > 0)
                    {
                        message.AddressHistory.Add(MyIpAddress);
                    }
                    message.RelayTTL--;

                    #region Identify InterZone Messages
                    if (message.IsTwoWayMessage == false)
                    {
                        message.ResultOutcome = RelayOutcome.Queued;                         //will be queued, if sync will not get overwritten

                        // Identify nodes in foreign zones
                        int nodeCount = nodesForMessage.Count;
                        for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
                        {
                            nodesForMessage.Pop(out node);
                            if (_myNodeDefinition != null && _myNodeDefinition.Zone != node.NodeDefinition.Zone)
                            {
                                // Message needs to cross Zone bounderies
                                if (interZoneMessage == null)
                                {
                                    interZoneMessage         = RelayMessage.CreateInterZoneMessageFrom(message);
                                    nodesForInterZoneMessage = new SimpleLinkedList <Node>();
                                }
                                nodesForInterZoneMessage.Push(node);
                            }
                            else
                            {
                                nodesForMessage.Push(node);
                            }
                        }
                    }
                    #endregion

                    if (nodesForMessage.Count > 0)
                    {
                        DebugWriter.WriteDebugInfo(message, nodesForMessage);
                        distribution.Add(message, nodesForMessage);
                    }

                    if (nodesForInterZoneMessage != null && nodesForInterZoneMessage.Count > 0)
                    {
                        DebugWriter.WriteDebugInfo(interZoneMessage, nodesForInterZoneMessage);
                        distribution.Add(interZoneMessage, nodesForInterZoneMessage);
                    }
                }
            }

            return(distribution);
        }