IAsyncResult IAsyncRelayTransport.BeginSendMessage(SerializedRelayMessage message, AsyncCallback callback, object state) { if (message == null) { throw new ArgumentNullException("message"); } if (message.IsTwoWayMessage) { throw new ApplicationException("Cannot send pre-serialized out message."); } var result = new SimpleAsyncResult(callback, state); asyncSocketClient.SendOneWayAsync <MemoryStream>( (short)SocketCommand.HandleOneWayMessage, message.MessageStream, (messageStream, stream) => stream.Write( messageStream.GetBuffer(), (int)messageStream.Position, (int)messageStream.Length), args => { result.Error = args.Error; result.CompleteOperation(args.CompletedSynchronously); }); return(result); }
/// <summary> /// Calls the NotifyDroppedMessage event with the supplied message. /// </summary> public static void RaiseMessageDropped(SerializedRelayMessage message) { if (MessageDropped != null) { MessageDropped(message); } }
/// <summary> /// Enqueues a single message to the error queue. /// </summary> /// <remarks> /// Two-way messages are ignored. /// </remarks> /// <param name="message">The message.</param> internal void Enqueue(SerializedRelayMessage message) { if (message.IsTwoWayMessage) return; SerializedRelayMessage discard = null; if (_enabled) { lock (_inMessageQueueLock) { NodeManager.Instance.Counters.IncrementErrorQueue(); InMessageQueue.Enqueue(message); if (_persistence == null && InMessageQueue.Count > _maxCount) { discard = InMessageQueue.Dequeue(); } } if (discard != null) { Forwarder.RaiseMessageDropped(discard); NodeManager.Instance.Counters.DecrementErrorQueue(); IncrementDiscardsBy(1); } StartSpill(); } else { Forwarder.RaiseMessageDropped(message); } }
void IRelayTransport.SendMessage(SerializedRelayMessage serializedMessage) { if (DoDispatchMessages) { RelayMessage message = RelayMessageFormatter.ReadRelayMessage(serializedMessage.MessageStream); _messageRecieved(message); } }
/// <summary> /// Calls the NotifyDroppedMessage event with the supplied message. /// </summary> public static void RaiseMessageDropped(RelayMessage message) { if (MessageDropped != null) { SerializedRelayMessage serializedMessage = new SerializedRelayMessage(message); MessageDropped(serializedMessage); } }
private void CalculateLife(SerializedRelayMessage message) { if (_avgMessageLife == null) { return; } _avgMessageLife.CalculateLife(message); }
public void SendMessage(SerializedRelayMessage message) { if (message.IsTwoWayMessage) { throw new ApplicationException("Cannot send pre-serialized out message."); } socketClient.SendOneWay((int)SocketCommand.HandleOneWayMessage, message.MessageStream); }
/// <summary> /// Enqueues a list of messages to the error queue. /// </summary> /// <remarks> /// Two-way messages in the message list are ignored. /// </remarks> /// <param name="messages">The list of messages.</param> internal void Enqueue(IList<SerializedRelayMessage> messages) { if (_enabled && messages.Count > 0) { int count = 0; SerializedRelayMessage[] discards = null; lock (_inMessageQueueLock) { for (int i = 0; i < messages.Count; ++i) { var message = messages[i]; if (!message.IsTwoWayMessage) { InMessageQueue.Enqueue(message); ++count; } } if (_persistence == null && InMessageQueue.Count > _maxCount) { discards = new SerializedRelayMessage[InMessageQueue.Count - _maxCount]; for (int i = 0; i < discards.Length; ++i) { discards[i] = InMessageQueue.Dequeue(); } } } if (discards != null) { for (int i = 0; i < discards.Length; ++i) { Forwarder.RaiseMessageDropped(discards[i]); } NodeManager.Instance.Counters.DecrementErrorQueueBy(discards.Length); IncrementDiscardsBy(discards.Length); } if (count > 0) { NodeManager.Instance.Counters.IncrementErrorQueueBy(count); StartSpill(); } } else { for (int i = 0; i < messages.Count; i++) { var message = messages[i]; if (!message.IsTwoWayMessage) Forwarder.RaiseMessageDropped(message); } } }
IAsyncResult IAsyncRelayTransport.BeginSendMessage(SerializedRelayMessage message, AsyncCallback callback, object state) { var result = new SimpleAsyncResult(callback, state); ThreadPool.QueueUserWorkItem(o => { ((IRelayTransport)this).SendMessage(message); result.SetComplete(); }); return(result); }
internal static void LogNodeException(SerializedRelayMessage message, Node node, Exception ex) { if (_log.IsErrorEnabled) { if (ex is SocketException) { SocketException sex = (SocketException)ex; _log.ErrorFormat("Socket error {0} while handling {1} for node {2}", sex.SocketErrorCode, message, node.ToExtendedString()); } else { _log.ErrorFormat("Error handling {0} for node {1}: {2}", message, node, ex); } } }
internal void CountMessage(SerializedRelayMessage message) { if (_countersInitialized) { CalculateLife(message); if (message.IsTwoWayMessage) { CountOutMessage(message.MessageType, message.PayloadLength); } else { CountInMessage(message.MessageType, message.PayloadLength); } } }
internal void Enqueue(SerializedRelayMessage message) { if (_enabled) { if (message.IsTwoWayMessage) { return; } lock (_inMessageQueueLock) { while (InMessageQueue.Count >= (_maxCount - 1)) { Forwarder.RaiseMessageDropped(InMessageQueue.Dequeue()); NodeManager.Instance.Counters.DecrementErrorQueue(); } NodeManager.Instance.Counters.IncrementErrorQueue(); InMessageQueue.Enqueue(message); } } else { Forwarder.RaiseMessageDropped(message); } }
/// <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)); } } } } }
internal void CountInMessages(SerializedRelayMessage[] messages) { if (_countersInitialized) { SerializedRelayMessage msg; for (int i = 0; i < messages.Length; i++) { msg = messages[i]; CalculateLife(msg); CountInMessage(msg.MessageType, msg.PayloadLength); } } }
/// <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)); } } } } }
private void CalculateLife(SerializedRelayMessage message) { if (_avgMessageLife == null) return; _avgMessageLife.CalculateLife(message); }
IAsyncResult IAsyncRelayTransport.BeginSendMessage(SerializedRelayMessage message, AsyncCallback callback, object state) { if (message == null) throw new ArgumentNullException("message"); if (message.IsTwoWayMessage) { throw new ApplicationException("Cannot send pre-serialized out message."); } var result = new SimpleAsyncResult(callback, state); asyncSocketClient.SendOneWayAsync<MemoryStream>( (short)SocketCommand.HandleOneWayMessage, message.MessageStream, (messageStream, stream) => stream.Write( messageStream.GetBuffer(), (int)messageStream.Position, (int)messageStream.Length), args => { result.Error = args.Error; result.CompleteOperation(args.CompletedSynchronously); }); return result; }
IAsyncResult IAsyncRelayTransport.BeginSendInMessageList(SerializedRelayMessage[] messages, AsyncCallback callback, object state) { throw new NotSupportedException(); }
private void CaculateStatisics(SerializedRelayMessage message, long milliseconds) { int index = (int)message.MessageType; Interlocked.Increment(ref _messageCounts[index]); Interlocked.Exchange(ref _lastMessageTimes[index], milliseconds); Interlocked.Exchange(ref _averageMessageTimes[index], CalculateAverage(_averageMessageTimes[index], milliseconds, _messageCounts[index])); }
/// <summary> /// Processes a single message /// Calls DoHandleMessage if the message is to be processed synchronously /// Posts message to process queue otherwise /// </summary> /// <param name="message">Message to be processed</param> /// <param name="useSyncForInMessages">Default: false /// The type (from TypeSettings.config) can require synchronous handling for messages /// </param> /// <param name="skipErrorQueueForSync">Default: false /// The type (from TypeSettings.config) can require that should the message processing fail, /// the message will NOT be sent to the Error Queue for retry. Instead, the function returns /// false. /// Has no effect if useSyncForInMessages is false. /// </param> /// <returns> /// useSyncForInMessages = false always returns True (message processed Async) /// useSyncForInMessages = true, skipErrorQueueForSync = false always returns True (errors placed in queue for retry) /// useSyncForInMessages = true, skipErrorQueueForSync = true returns true if the message processing succeeded /// </returns> internal bool HandleInMessageSync(RelayMessage message, bool useSyncForInMessages, bool skipErrorQueueForSync) { if (useSyncForInMessages) { return DoHandleMessage(message, useSyncForInMessages, skipErrorQueueForSync); } message.ResultOutcome = RelayOutcome.Queued; SerializedRelayMessage serializedMessage = new SerializedRelayMessage(message); _serializedMessagePort.Post(serializedMessage); return true; }
private void CaculateInStatisics(SerializedRelayMessage[] messages, long milliseconds) { Interlocked.Increment(ref _bulkInMessageCount); Interlocked.Exchange(ref _lastBulkInMessageLength, messages.Length); Interlocked.Exchange(ref _averageBulkInMessageLength, CalculateAverage(_averageBulkInMessageLength, _lastBulkInMessageLength, _bulkInMessageCount)); Interlocked.Exchange(ref _lastBulkInMessageTime, milliseconds); Interlocked.Exchange(ref _averageBulkInMessageTime, CalculateAverage(_averageBulkInMessageTime, _lastBulkInMessageTime, _bulkInMessageCount)); }
void IRelayTransport.SendMessage(SerializedRelayMessage message) { DoAllTransports(t => t.SendMessage(message)); }
internal void HandleInMessage(SerializedRelayMessage serializedRelayMessage) { _serializedMessagePort.Post(serializedRelayMessage); }
private void EnqueueMessage(SerializedRelayMessage message) { if (MessageErrorQueue != null) { MessageErrorQueue.Enqueue(message); } else { Forwarder.RaiseMessageDropped(message); } }
private void EnqueueInMessages(SerializedRelayMessage[] messages) { if (MessageErrorQueue != null) { MessageErrorQueue.Enqueue(messages); } else { for (int i = 0; i < messages.Length; i++) { Forwarder.RaiseMessageDropped(messages[i]); } } }
private void DoHandleMessage(SerializedRelayMessage message) { if (!Activated || message == null || message.MessageStream == null) { return; } if (DangerZone) { EnqueueMessage(message); return; } try { if (GatherStats) { Stopwatch watch = Stopwatch.StartNew(); _transport.SendMessage(message); watch.Stop(); CaculateStatisics(message, watch.ElapsedMilliseconds); } else { _transport.SendMessage(message); } NodeManager.Instance.Counters.CountMessage(message); } catch (Exception ex) { EnqueueMessage(message); InstrumentException(ex); NodeGroup.LogNodeException(message, this, ex); } }
/// <summary> /// Processes an array of RelayMessages /// </summary> /// <param name="messages">Array of messages to be processed</param> /// <param name="skipErrorQueueForSync">True if synchronous messages that fail should not be /// placed into the error queue for retry. /// </param> /// <returns> /// skipErrorQueueForSync = false always returns True (message processed Async) /// skipErrorQueueForSync = true returns true if the message processing succeeded /// </returns> internal bool DoHandleInMessages(SerializedRelayMessage[] messages, bool skipErrorQueueForSync) { if (!Activated) { return false; } if (DangerZone) { if (skipErrorQueueForSync) { return false; } EnqueueInMessages(messages); return true; } bool messagesHandled = true; try { if (GatherStats) { Stopwatch watch = Stopwatch.StartNew(); _transport.SendInMessageList(messages); watch.Stop(); CaculateInStatisics(messages, watch.ElapsedMilliseconds); } else { _transport.SendInMessageList(messages); } NodeManager.Instance.Counters.CountInMessages(messages); } catch (Exception ex) { if (!skipErrorQueueForSync) { EnqueueInMessages(messages); } else { messagesHandled = false; } InstrumentException(ex); NodeGroup.LogNodeInMessageException(messages, this, ex); } return messagesHandled; }
internal static void LogNodeInMessageException(SerializedRelayMessage[] messages, Node node, Exception ex) { if (_log.IsErrorEnabled) { if (ex is SocketException) { SocketException sex = (SocketException)ex; _log.ErrorFormat("Socket error {0} while handling {1} IN messages for node {2}", sex.SocketErrorCode, messages.Length, node.ToExtendedString()); } else { _log.ErrorFormat("Error handling {0} IN messages for node {1}: {2}.", messages.Length, node.ToExtendedString(), ex); } } }
public void SendInMessageList(SerializedRelayMessage[] messages) { ResourcePoolItem<MemoryStream> pooledBuffer; MemoryStream nextMessageChunk; int chunkLength = defaultChunkLength; int cursor = 0; if (messages.Length > 0) { if (chunkLength == 0 || chunkLength > messages.Length) { //0 means "don't chunk" chunkLength = messages.Length; } pooledBuffer = bufferPool.GetItem(); try { nextMessageChunk = pooledBuffer.Item; byte[] lengthBytes = BitConverter.GetBytes(chunkLength); while (cursor < messages.Length) { //make sure that the next chunk doesn't go past the end of the list if ((cursor + chunkLength) > messages.Length) { chunkLength = messages.Length - cursor; BitConverterEx.WriteBytes(lengthBytes, 0, chunkLength); } nextMessageChunk.Write(lengthBytes, 0, 4); for (int end = cursor + chunkLength; cursor < end; cursor++) { messages[cursor].MessageStream.WriteTo(nextMessageChunk); } socketClient.SendOneWay((int)SocketCommand.HandleOneWayMessages, nextMessageChunk); nextMessageChunk.Seek(0, SeekOrigin.Begin); nextMessageChunk.SetLength(0); } } finally { bufferPool.ReleaseItem(pooledBuffer); } } }
public void SendMessage(SerializedRelayMessage message) { }