/// <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)); }
/// <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)); }
/// <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); }
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); } } }