/// <summary> /// This method is called by the framework /// </summary> internal void _Main() { RegisterWorker(this); try { Main(); if (_monitoringWorker != null) { Message msg = new Message(MessageLevel.System, _monitoringWorker, new WorkerAddress(_node.GetId(), _id), SystemMessages.WorkerTerminated, null); _node.QueueMessage(msg); } OnWorkerTerminated(); } catch (Exception e) { WorkerAddress workerAddress = new WorkerAddress(_node.GetId(), _id); Log.Error("Worker {0} crashed with exception {1}", workerAddress, e.Message); if (_monitoringWorker != null) { Message msg = new Message(MessageLevel.System, _monitoringWorker, workerAddress, SystemMessages.WorkerTerminatedAbnormally, e); _node.QueueMessage(msg); } OnWorkerTerminatedAbnormally(e); } _node.WorkerTerminated(_id); UnregisterWorker(); }
public void PutMessage(MessageLevel messageLevel, ushort receiverNodeId, ushort receiverWorkerId, ushort senderNodeId, ushort senderWorkerId, int messageType, object content) { //see if it is a local worker that is the receiver lock (_localWorkers) { //Message msg = new Message(messageLevel, new WorkerAddress(receiverNodeId, receiverWorkerId), new WorkerAddress(senderNodeId, senderWorkerId), messageType, content); if (WorkerAddress.IsBroadcastAddress(receiverNodeId, receiverWorkerId)) //broadcast address { foreach (var worker in _localWorkers.Values) { worker.PutMessage(messageLevel, receiverNodeId, receiverWorkerId, senderNodeId, senderWorkerId, messageType, CloneContent(content)); //clone the message to prevent shared state } } else if (_localWorkers.ContainsKey(receiverWorkerId)) { _localWorkers[receiverWorkerId].PutMessage(messageLevel, receiverNodeId, receiverWorkerId, senderNodeId, senderWorkerId, messageType, CloneContent(content)); } else if (!SystemMessages.IsSystemMessageType(messageType)) //we don't care about that { Log.Error("Node.PutMessage : Cannot dispatch message"); } } }
/// <summary> /// Fetches a message from the message queue with the specified sender address and message type. /// This method blocks until there are any messages fullfilling the criteria. /// </summary> /// <param name="senderAddress">The sender address.</param> /// <param name="messageType">The message type.</param> /// <returns>The first message in the queue with the specified sender address and message type</returns> public Message Receive(WorkerAddress senderAddress, int messageType) { Message msg = null; LinkedListNode <Message> msgNode; do { _messageQueueWaitHandle.WaitOne(); lock (_messageQueue) { msgNode = _messageQueue.First; //traverse all messages to see if there are any that matches the search criteria while (msgNode != null && msg == null) { if (msgNode.Value.SenderAddress == senderAddress && msgNode.Value.MessageType == messageType) { msg = msgNode.Value; _messageQueue.Remove(msgNode); } else { msgNode = msgNode.Next; } } if (msg == null) //nothing yet { _messageQueueWaitHandle.Reset(); } } }while (msg == null); return(msg); }
internal void _Monitor(WorkerAddress monitor, WorkerAddress monitoree) { if (monitoree.NodeId == _id) { Monitor(monitor, monitoree); } else { lock (_remoteNodes) { ushort monitoreeNodeId = monitoree.NodeId; if (_remoteNodes.ContainsKey(monitoreeNodeId)) { try { _remoteNodes[monitoree.NodeId].Monitor(monitor, monitoree); } catch (Exception) { Log.Error("Node._Monitor({0}, {1}) : Remote node {2} appears to be offline", monitor, monitoree, monitoree.NodeId); _remoteNodes.Remove(monitoreeNodeId); _registrationServerProxy.UnregisterNode(monitoreeNodeId); } } else { Log.Error("Node._Monitor({0}, {1}) : Unable to find remote monitoree", monitor, monitoree); } } } }
public Message(MessageLevel messageLevel, WorkerAddress receiverAddress, WorkerAddress senderAddress, int messageType, object content) { _messageLevel = messageLevel; _receiverAddress = receiverAddress; _senderAddress = senderAddress; _messageType = messageType; _content = content; }
public Message(MessageLevel messageLevel, WorkerAddress receiverAddress, WorkerAddress senderAddress, int messageType, object content) { MessageLevel = messageLevel; ReceiverAddress = receiverAddress; SenderAddress = senderAddress; MessageType = messageType; Content = content; }
/// <summary> /// Spawns a new worker at the specified node. /// </summary> /// <param name="workerTypeName">Fully qualified name of worker type. Must inherit from Worker.</param> /// <param name="nodeId">Id of the node to spawn the worker at.</param> /// <returns>The address of the new worker if successfull, otherwise null.</returns> public WorkerAddress Spawn(string workerTypeName, ushort nodeId) { WorkerAddress workerAddress = null; if (_node.Spawn(workerTypeName, nodeId, out ushort workerId)) { workerAddress = new WorkerAddress(nodeId, workerId); } return(workerAddress); }
/// <summary> /// Spawns a new worker at the specified node. /// </summary> /// <typeparam name="TWorkerType">The type of worker to spawn. Must inherit from Worker.</typeparam> /// <param name="nodeId">Id of the node to spawn the worker at.</param> /// <returns>The address of the new worker if successfull, otherwise null.</returns> public WorkerAddress Spawn <TWorkerType>(ushort nodeId) where TWorkerType : Worker { WorkerAddress workerAddress = null; if (_node.Spawn(typeof(TWorkerType), nodeId, out ushort workerId)) { workerAddress = new WorkerAddress(nodeId, workerId); } return(workerAddress); }
/// <summary> /// Spawns a new worker locally. /// </summary> /// <typeparam name="TWorkerType">The type of worker to spawn. Must inherit from Worker.</typeparam> /// <returns>The address of the new worker if successfull, otherwise null.</returns> public WorkerAddress Spawn <TWorkerType>() where TWorkerType : Worker { ushort workerId; WorkerAddress workerAddress = null; if (_node.Spawn(typeof(TWorkerType), out workerId)) { workerAddress = new WorkerAddress(_node.GetId(), workerId); } return(workerAddress); }
/// <summary> /// Sends a message. /// </summary> /// <param name="receiverAddress">Address of the receicer.</param> /// <param name="messageType">Type of message - user specific.</param> /// <param name="content">The contents of the message.</param> public void Send(WorkerAddress receiverAddress, int messageType, object content) { if (SystemMessages.IsSystemMessageType(messageType)) { Log.Error("Message types smaller than 0 are reserved for system messages. Message type : {0}", messageType); return; } Message msg = new Message(MessageLevel.User, receiverAddress, new WorkerAddress(_node.GetId(), _id), messageType, content); _node.QueueMessage(msg); }
/// <summary> /// Checks if there are any message from the specified sender and with the specified message type in the message queue. /// </summary> /// <param name="senderAddress"></param> /// <param name="messageType"></param> /// <returns></returns> public bool HasMessages(WorkerAddress senderAddress, int messageType) { lock (_messageQueue) { foreach (Message msg in _messageQueue) { if (msg.SenderAddress == senderAddress && msg.MessageType == messageType) { return(true); } } } return(false); }
public void Monitor(WorkerAddress monitor, WorkerAddress monitoree) { if (monitoree.NodeId == _id) { lock (_localWorkers) { if (_localWorkers.ContainsKey(monitoree.WorkerId)) { _localWorkers[monitoree.WorkerId].SetMonitoringWorker(monitor); } else { Log.Error("Node.Monitor({0}, {1}) : unable to find monitoree", monitor, monitoree); } } } }
internal void SetMonitoringWorker(WorkerAddress monitoringWorker) { _monitoringWorker = monitoringWorker; }
public void Monitor(WorkerAddress monitor, WorkerAddress monitoree) { Proxy.Monitor(monitor, monitoree); }
/// <summary> /// This method handles the dispatching of messages in the send buffer. /// /// This is done in a separate thread so that local workers do not wait for each other, /// or wait for the relatively slow communication over the remoting framework. /// </summary> /// <param name="state"></param> private void SendBufferThreadProc(object state) { while (!SendBufferThreadTerminate) { _sendBufferWaitHandle.WaitOne(); //fetch the first message Message msg = null; lock (_sendBuffer) { LinkedListNode <Message> firstNode = _sendBuffer.First; if (firstNode != null) { msg = firstNode.Value; _sendBuffer.RemoveFirst(); } else { _sendBufferWaitHandle.Reset(); } } /* Keep processing messages if there are any (no sleep - the thread * will be switched out naturally), otherwise force the thread to be switched * out of context. */ if (msg != null) { //is it a broad cast message? if (WorkerAddress.IsBroadcastAddress(msg.ReceiverAddress)) { //send it to all local workers (except the sender) lock (_localWorkers) { foreach (Worker worker in _localWorkers.Values) { if (msg.SenderAddress.NodeId != _id || worker.Id != msg.SenderAddress.WorkerId) { worker.PutMessage(msg.MessageLevel, msg.ReceiverAddress.NodeId, msg.ReceiverAddress.WorkerId, msg.SenderAddress.NodeId, msg.SenderAddress.WorkerId, msg.MessageType, CloneContent(msg.Content)); //clone to prevent shared state } } } //broadcast it to all remote nodes lock (_remoteNodes) { foreach (INode remoteNode in _remoteNodes.Values) { remoteNode.PutMessage(msg.MessageLevel, msg.ReceiverAddress.NodeId, msg.ReceiverAddress.WorkerId, msg.SenderAddress.NodeId, msg.SenderAddress.WorkerId, msg.MessageType, msg.Content); } } } else if (msg.ReceiverAddress.NodeId == _id) //it is a local receiver { lock (_localWorkers) { if (_localWorkers.ContainsKey(msg.ReceiverAddress.WorkerId)) { _localWorkers[msg.ReceiverAddress.WorkerId].PutMessage(msg.MessageLevel, msg.ReceiverAddress.NodeId, msg.ReceiverAddress.WorkerId, msg.SenderAddress.NodeId, msg.SenderAddress.WorkerId, msg.MessageType, CloneContent(msg.Content)); } } } else //not a broadcast, not a local receiver, then find the remote node to send it to { lock (_remoteNodes) { ushort nodeId = msg.ReceiverAddress.NodeId; if (_remoteNodes.ContainsKey(nodeId)) { try { _remoteNodes[nodeId].PutMessage(msg.MessageLevel, msg.ReceiverAddress.NodeId, msg.ReceiverAddress.WorkerId, msg.SenderAddress.NodeId, msg.SenderAddress.WorkerId, msg.MessageType, msg.Content); } catch (Exception) { Log.Error("Node.SendBufferThreadProc : Remote node {0} appears to be offline", nodeId); _remoteNodes.Remove(nodeId); _registrationServerProxy.UnregisterNode(nodeId); } } } } } } }
public static bool IsBroadcastAddress(WorkerAddress address) { return(address.NodeId == ushort.MaxValue && address.WorkerId == ushort.MaxValue); }
/// <summary> /// Enables this worker to receive system messages when the monitoree terminates, either /// normally or abnormally. /// </summary> /// <param name="monitoree"></param> public void Monitor(WorkerAddress monitoree) { _node._Monitor(new WorkerAddress(_node.GetId(), _id), monitoree); }