Esempio n. 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));
        }
Esempio n. 2
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 virtual 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));
            }

            LinkedListStack <Node> nodes = PrepareMessage(message);

            Node node;

            if (nodes.Pop(out node))
            {
                var result = new AsynchronousResult <Node>((ar, n, m) =>
                {
                    try
                    {
                        n.EndHandleOutMessage(ar);
                        RetryHandleMessageOnError(message, node);
                    }
                    catch (Exception ex)
                    {
                        log.Error(ex);
                    }
                }, node, message);

                var origCallback = callback;
                if (callback != null)
                {
                    callback = ar =>
                    {
                        result.InnerResult = ar;
                        origCallback(result);
                    };
                }
                result.InnerResult = node.BeginHandleOutMessage(message, callback, state);
                return(result);
            }

            message.SetError(RelayErrorType.NoNodesAvailable);

            return(SynchronousAsyncResult.CreateAndComplete(callback, state));
        }
Esempio n. 3
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);
		}
Esempio n. 4
0
		private IAsyncResult BeginDoHandleMessage(RelayMessage message, bool useSyncForInMessages, bool skipErrorQueueForSync, AsyncCallback callback, object asyncState)
		{
			var asyncTransport = _transport as IAsyncRelayTransport;

			if (asyncTransport == null) 
			{
				return NodeSynchronousAsyncResult.CreateAndComplete(DoHandleMessage(message, useSyncForInMessages, skipErrorQueueForSync), callback, asyncState);
			}

			bool alwaysHandled = !useSyncForInMessages || !skipErrorQueueForSync;

			if (!Activated || message == null)
			{
				if (message != null) message.ResultOutcome = RelayOutcome.NotSent;
				return NodeSynchronousAsyncResult.CreateAndComplete(alwaysHandled, callback, asyncState);
			}

			if (DangerZone)
			{
				//this is only called for synchronous messages, which aren't error queued
				message.SetError(RelayErrorType.NodeInDanagerZone);
				return NodeSynchronousAsyncResult.CreateAndComplete(alwaysHandled, callback, asyncState);
			}

			var watch = GatherStats ? Stopwatch.StartNew() : null;
			try
			{
				NodeManager.Instance.Counters.CountMessage(message);
				var result = new AsynchronousResult(message, useSyncForInMessages, skipErrorQueueForSync);
				message.ResultOutcome = RelayOutcome.Queued; // close enough
				result.InnerResult = asyncTransport.BeginSendMessage(message, useSyncForInMessages, asyncResult =>
				{
					if (watch != null)
					{
						watch.Stop();
						CaculateStatisics(message, watch.ElapsedMilliseconds);
					}
					if (callback != null)
					{
						result.InnerResult = asyncResult;
						callback(result);
					}
				}, asyncState);
				return result;
			}
			catch (Exception ex)
			{
				//this is only called for get messages, which aren't error queued
				InstrumentException(ex);
				message.SetError(ex);
				NodeGroup.LogNodeException(message, this, ex);

				return NodeSynchronousAsyncResult.CreateAndComplete(alwaysHandled, callback, asyncState);
			}
			finally
			{
				if (watch != null)
				{
					watch.Stop();
					CaculateStatisics(message, watch.ElapsedMilliseconds);
				}
			}
		}