Пример #1
0
        /// <summary>
        ///	Performs processing on single message
        /// </summary>
        /// <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 "in" executions will throw this exception
        /// </exception>
        /// <param name="message">Message to be processed</param>
        public void HandleMessage(RelayMessage message)
        {
            Node node;

            if (message.IsTwoWayMessage)
            {
                int  allowedRetries = NodeManager.Instance.GetRetryCountForMessage(message);
                bool triedBefore    = false;
                do
                {
                    if (PrepareMessage(message, triedBefore).Pop(out node))
                    {
                        triedBefore = true;
                        node.HandleOutMessage(message);
                    }
                    else
                    {
                        message.SetError(RelayErrorType.NoNodesAvailable);
                    }
                }while (message.ErrorType == RelayErrorType.NodeUnreachable && --allowedRetries >= 0);
            }
            else
            {
                SimpleLinkedList <Node> nodes                      = PrepareMessage(message, false);
                SerializedRelayMessage  serializedMessage          = new SerializedRelayMessage(message);
                SerializedRelayMessage  serializedMessageInterZone = null;

                bool messageHandled = true;                 // start with "true" so that we do not pop
                // if there are no items in "nodes"
                if (nodes.Count == 0)
                {
                    message.SetError(RelayErrorType.NoNodesAvailable);
                }
                else
                {
                    while (nodes.Pop(out node))
                    {
                        TypeSetting typeSetting = NodeManager.Instance.Config.TypeSettings.TypeSettingCollection[message.TypeId];

                        bool typesettingThrowOnSyncFailure = false;
                        bool typesettingSyncInMessages     = false;
                        if (null != typeSetting && !node.NodeCluster.MeInThisCluster)
                        {
                            typesettingSyncInMessages     = typeSetting.SyncInMessages;
                            typesettingThrowOnSyncFailure = typeSetting.ThrowOnSyncFailure;
                        }

                        if (_myNodeDefinition != null && _myNodeDefinition.Zone != node.NodeDefinition.Zone)
                        {
                            // Message needs to cross Zone bounderies
                            if (serializedMessageInterZone == null)
                            {
                                serializedMessageInterZone = new SerializedRelayMessage(RelayMessage.CreateInterZoneMessageFrom(message));
                            }

                            if (message.ResultOutcome == null)
                            {
                                message.ResultOutcome = RelayOutcome.Queued;
                            }
                            node.HandleInMessage(serializedMessageInterZone);
                        }
                        else if (typesettingSyncInMessages)
                        {
                            messageHandled = node.HandleInMessageSync(message, typesettingSyncInMessages, typesettingThrowOnSyncFailure);
                        }
                        else
                        {
                            if (message.ResultOutcome == null)
                            {
                                message.ResultOutcome = RelayOutcome.Queued;
                            }
                            node.HandleInMessage(serializedMessage);
                        }

                        if (!messageHandled)
                        {
                            throw new SyncRelayOperationException(string.Format("Node {0} failed to process message {1}\r\n", node, message));
                        }
                    }
                }
            }
        }
        /// <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);
        }