예제 #1
0
        /// <summary>
        /// Begins asynchronous processing of a single <see cref="T:MySpace.DataRelay.RelayMessage"/>.
        /// </summary>
        /// <param name="message">The <see cref="T:MySpace.DataRelay.RelayMessage"/>.</param>
        /// <param name="state">Callers can put any state they like here.</param>
        /// <param name="callback">The method to call upon completion.</param>
        /// <returns>
        /// Returns an <see cref="T:System.IAsyncResult"/>.
        /// </returns>
        public IAsyncResult BeginHandleMessage(RelayMessage message, object state, AsyncCallback callback)
        {
            if (!message.IsTwoWayMessage)
            {
                // cheat for now and just handle in messages synchronously
                // as long as the type doesn't use sync in messages then
                // we won't block on IO anyway.
                HandleMessage(message);
                return(SynchronousAsyncResult.CreateAndComplete(callback, state));
            }


            SimpleLinkedList <Node> nodes = PrepareMessage(message, false);

            Node node;

            if (nodes.Pop(out node))
            {
                var result = new AsynchronousResult <Node>((ar, n, m) =>
                {
                    n.EndHandleOutMessage(ar);
                    int allowedRetries = NodeManager.Instance.GetRetryCountForMessage(message);
                    while (message.ErrorType == RelayErrorType.NodeUnreachable && --allowedRetries >= 0)
                    {
                        if (PrepareMessage(message, true).Pop(out node))
                        {
                            node.HandleOutMessage(message);
                        }
                        else
                        {
                            message.SetError(RelayErrorType.NoNodesAvailable);
                        }
                    }
                }, node, message);
                var origCallback = callback;
                if (callback != null)
                {
                    callback = ar =>
                    {
                        result.InnerResult = ar;
                        origCallback(result);
                    };
                }
                result.InnerResult = node.BeginHandleOutMessage(message, callback, state);
                return(result);
            }
            else
            {
                message.SetError(RelayErrorType.NoNodesAvailable);
            }
            return(SynchronousAsyncResult.CreateAndComplete(callback, state));
        }
예제 #2
0
        internal void Add(RelayMessage message, SimpleLinkedList <Node> nodes)
        {
            TypeSetting typeSetting = NodeManager.Instance.Config.TypeSettings.TypeSettingCollection[message.TypeId];

            Node node;

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

                // Contains no longer works now that the NodeWithMessages structure has
                // been added, loop through and check the settings
                bool bAdded = false;
                foreach (NodeWithMessages nwm in this)
                {
                    NodeWithInfo nwi = GetKeyForItem(nwm);
                    if ((nwi.Node == node) &&
                        (nwi.SyncInMessages == typesettingSyncInMessages) &&
                        (nwi.SkipErrorQueueForSync == typesettingThrowOnSyncFailure))
                    {
                        bAdded = true;
                        this[nwi].Messages.Add(message);
                        break;
                    }
                }
                if (!bAdded)
                {
                    NodeWithInfo     newNWI  = new NodeWithInfo(node, typesettingSyncInMessages, typesettingThrowOnSyncFailure);
                    NodeWithMessages newNode = new NodeWithMessages(newNWI);
                    Add(newNode);
                    this[newNWI].Messages.Add(message);
                }
            }
        }
예제 #3
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);
        }