예제 #1
0
 /// <summary>
 /// Adds a remote application to communication layer.
 /// </summary>
 /// <param name="application">Remote application to add</param>
 public void AddRemoteApplication(NGRIDRemoteApplication application)
 {
     lock (_remoteApplications)
     {
         if (!_remoteApplications.ContainsKey(application.ApplicationId))
         {
             _remoteApplications.Add(application.ApplicationId, application);
         }
     }
 }
예제 #2
0
        /// <summary>
        /// Removes a remote application from communication layer.
        /// </summary>
        /// <param name="application">Remote application to remove</param>
        public void RemoveRemoteApplication(NGRIDRemoteApplication application)
        {
            lock (_remoteApplications)
            {
                if (_remoteApplications.ContainsKey(application.ApplicationId))
                {
                    if (application.ConnectedCommunicatorCount > 0)
                    {
                        throw new NGRIDException("Remote application can not be removed. It has " +
                                                 application.ConnectedCommunicatorCount + " communicators connected.");
                    }

                    _remoteApplications.Remove(application.ApplicationId);
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Processes NGRIDRegisterMessage objects.
        /// </summary>
        /// <param name="communicator">Sender communicator of message</param>
        /// <param name="message">Message</param>
        private void ProcessRegisterMessage(ICommunicator communicator, NGRIDRegisterMessage message)
        {
            //Set the communicator properties
            communicator.CommunicationWay = message.CommunicationWay;

            NGRIDRemoteApplication remoteApplication = null;

            //Find remote application
            lock (_remoteApplications)
            {
                foreach (var app in _remoteApplications.Values)
                {
                    if (app.Name == message.Name && message.CommunicatorType == app.CommunicatorType)
                    {
                        remoteApplication = app;
                        break;
                    }
                }
            }

            //If application is found...
            if (remoteApplication != null)
            {
                try
                {
                    //Add communicator to communicator list of remote application
                    remoteApplication.AddCommunicator(communicator);
                    //Remove communicator from tempoary communicators list.
                    RemoveFromCommunicators(communicator.ComminicatorId);
                    //Send success message to remote application
                    SendOperationResultMessage(communicator, true, communicator.ComminicatorId.ToString(), message.MessageId);
                }
                catch (Exception ex)
                {
                    Logger.Warn(ex.Message, ex);
                    //An error occured, send failed message to remote application
                    SendOperationResultMessage(communicator, false, ex.Message, message.MessageId);
                    communicator.Stop(false);
                }
            }
            else //application == null
            {
                //Stop communicator, because a remote application can not connect this server that is not defined in settings file
                SendOperationResultMessage(communicator, false, "No remote application found with name: " + message.Name, message.MessageId);
                communicator.Stop(false);
            }
        }
예제 #4
0
        /// <summary>
        /// Removes a remote application from communication layer.
        /// </summary>
        /// <param name="application">Remote application to remove</param>
        public void RemoveRemoteApplication(NGRIDRemoteApplication application)
        {
            lock (_remoteApplications)
            {
                if (_remoteApplications.ContainsKey(application.ApplicationId))
                {
                    if(application.ConnectedCommunicatorCount > 0)
                    {
                        throw new NGRIDException("Remote application can not be removed. It has " +
                                               application.ConnectedCommunicatorCount + " communicators connected.");
                    }

                    _remoteApplications.Remove(application.ApplicationId);
                }
            }
        }
예제 #5
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="remoteApplication">Reference to the NGRIDRemoteApplication object that is used with this MessageDeliverer</param>
 public MessageDeliverer(NGRIDRemoteApplication remoteApplication)
 {
     _remoteApplication            = remoteApplication;
     _asynchronMessageControlTimer = new Timer(AsynchronMessageControlTimer_Elapsed, null, Timeout.Infinite, Timeout.Infinite);
 }
예제 #6
0
 /// <summary>
 /// Adds a remote application to communication layer.
 /// </summary>
 /// <param name="application">Remote application to add</param>
 public void AddRemoteApplication(NGRIDRemoteApplication application)
 {
     lock (_remoteApplications)
     {
         if (!_remoteApplications.ContainsKey(application.ApplicationId))
         {
             _remoteApplications.Add(application.ApplicationId, application);
         }
     }
 }
예제 #7
0
 /// <summary>
 /// Adds message to destination's send queue.
 /// </summary>
 /// <param name="senderApplication">Sender application/server</param>
 /// <param name="senderCommunicator">Sender communicator</param>
 /// <param name="destApplication">Destination application/server</param>
 /// <param name="message">Message</param>
 private static void EnqueueMessage(NGRIDRemoteApplication senderApplication, ICommunicator senderCommunicator, NGRIDPersistentRemoteApplicationBase destApplication, NGRIDDataTransferMessage message)
 {
     destApplication.EnqueueMessage(message);
     SendOperationResultMessage(senderApplication, senderCommunicator, message, true, "Success.");
 }
예제 #8
0
        /// <summary>
        /// To send a NGRIDOperationResultMessage to remote application's spesific communicator.
        /// </summary>
        /// <param name="senderApplication">Sender application/server</param>
        /// <param name="communicator">Communicator to send message</param>
        /// <param name="repliedMessage">Replied Message</param>
        /// <param name="success">Operation result</param>
        /// <param name="resultText">Details</param>
        private static void SendOperationResultMessage(NGRIDRemoteApplication senderApplication, ICommunicator communicator, NGRIDDataTransferMessage repliedMessage, bool success, string resultText)
        {
            try
            {
                if (success)
                {
                    //Save MessageId of acknowledged message to do not receive same message again
                    senderApplication.LastAcknowledgedMessageId = repliedMessage.MessageId;
                }

                senderApplication.SendMessage(new NGRIDOperationResultMessage
                {
                    RepliedMessageId = repliedMessage.MessageId,
                    Success = success,
                    ResultText = resultText
                }, communicator);
            }
            catch (Exception ex)
            {
                Logger.Warn(ex.Message, ex);
            }
        }
예제 #9
0
        /// <summary>
        /// This method is called by ProcessDataTransferMessage when a message must be sent to a server
        /// that is not an adjacent of this server. Message is forwarded to next server.
        /// </summary>
        /// <param name="senderApplication">Sender application/server</param>
        /// <param name="senderCommunicator">Sender communicator</param>
        /// <param name="message">Message</param>
        private void SendToNextServer(NGRIDRemoteApplication senderApplication, ICommunicator senderCommunicator, NGRIDDataTransferMessage message)
        {
            //If there is a path from this server to destination server...
            if (_serverGraph.ThisServerNode.BestPathsToServers.ContainsKey(message.DestinationServerName))
            {
                //Find best path to destination server 
                var bestPath = _serverGraph.ThisServerNode.BestPathsToServers[message.DestinationServerName];
                //If path is regular (a path must consist of 2 nodes at least)...
                if (bestPath.Count > 1)
                {
                    //Next server
                    var nextServerName = bestPath[1].Name;

                    /* On one of these conditions, message is stored:
                     * - TransmitRule = StoreAndForward
                     * - (TransmitRule = StoreOnSource OR StoreOnEndPoints) AND (This server is the source server)
                     */
                    if (message.TransmitRule == MessageTransmitRules.StoreAndForward ||
                        message.TransmitRule == MessageTransmitRules.NonPersistent)
                    {
                        EnqueueMessage(
                            senderApplication,
                            senderCommunicator,
                            _serverGraph.AdjacentServers[nextServerName],
                            message
                            );
                    }
                    /* Else, message is not stored in these conditions:
                     * - TransmitRule = DirectlySend OR StoreOnDestination (this server can not be destination because message is being sent to another server right now)
                     * - All Other conditions
                     */
                    else
                    {
                        SendMessageDirectly(
                            senderApplication,
                            senderCommunicator,
                            _serverGraph.AdjacentServers[nextServerName],
                            message
                            );
                    }
                }
                //Server graph may be wrong (this is just for checking case, normally this situation must not become)
                else
                {
                    SendOperationResultMessage(senderApplication, senderCommunicator, message, false, "Server graph is wrong.");
                }
            }
            //No path from this server to destination server
            else
            {
                SendOperationResultMessage(senderApplication, senderCommunicator, message, false, "There is no path from this server to destination.");
            }
        }
예제 #10
0
        /// <summary>
        /// Sends message directly to application (not stores) and waits ACK.
        /// This method adds message to queue by NGRIDPersistentRemoteApplicationBase.AddMessageToHeadOfQueue method
        /// and waits a signal/pulse from RemoteApplication_MessageReceived method to get ACK/Reject.
        /// </summary>
        /// <param name="senderApplication">Sender application/server</param>
        /// <param name="senderCommunicator">Sender communicator</param>
        /// <param name="destApplication">Destination application/server</param>
        /// <param name="message">Message</param>
        private void SendMessageDirectly(NGRIDRemoteApplication senderApplication, ICommunicator senderCommunicator, NGRIDPersistentRemoteApplicationBase destApplication, NGRIDDataTransferMessage message)
        {
            //Create a WaitingMessage to wait and get ACK/Reject message and add it to waiting messages
            var waitingMessage = new WaitingMessage();
            lock (_waitingMessages)
            {
                _waitingMessages[message.MessageId] = waitingMessage;
            }

            try
            {
                //Add message to head of queue of remote application
                destApplication.AddMessageToHeadOfQueue(message);

                //Wait until thread is signalled by another thread to get response (Signalled by RemoteApplication_MessageReceived method)
                waitingMessage.WaitEvent.WaitOne((int) (_settings.MessageResponseTimeout*1.2));

                //Evaluate response
                if (waitingMessage.ResponseMessage.Success)
                {
                    SendOperationResultMessage(senderApplication, senderCommunicator, message, true, "Success.");
                }
                else
                {
                    SendOperationResultMessage(senderApplication, senderCommunicator, message, false, "Message is not acknowledged. Reason: " + waitingMessage.ResponseMessage.ResultText);
                }
            }
            finally
            {
                //Remove message from waiting messages
                lock (_waitingMessages)
                {
                    _waitingMessages.Remove(message.MessageId);
                }
            }
        }
예제 #11
0
 /// <summary>
 /// This method is called by ProcessDataTransferMessage when a message must be sent to an adjacent server of this server.
 /// </summary>
 /// <param name="senderApplication">Sender application/server</param>
 /// <param name="senderCommunicator">Sender communicator</param>
 /// <param name="message">Message</param>
 private void SentToAdjacentServer(NGRIDRemoteApplication senderApplication, ICommunicator senderCommunicator, NGRIDDataTransferMessage message)
 {
     /* On one of these conditions, message is stored:
      * - TransmitRule = StoreAndForward
      * - (TransmitRule = StoreOnSource OR StoreOnEndPoints) AND (This server is the source server)
      */
     if (message.TransmitRule == MessageTransmitRules.StoreAndForward || 
         message.TransmitRule == MessageTransmitRules.NonPersistent)
     {
         EnqueueMessage(
             senderApplication,
             senderCommunicator,
             _serverGraph.AdjacentServers[message.DestinationServerName],
             message
             );
     }
     /* Else, message is not stored in these conditions:
      * - TransmitRule = DirectlySend OR StoreOnDestination (this server can not be destination because message is being sent to another server right now)
      * - All Other conditions
      */
     else
     {
         SendMessageDirectly(
             senderApplication,
             senderCommunicator,
             _serverGraph.AdjacentServers[message.DestinationServerName],
             message
             );
     }
 }
예제 #12
0
        /// <summary>
        /// This method is called by ProcessDataTransferMessage when a message must be sent to a aclient application
        /// that is running on this server.
        /// </summary>
        /// <param name="senderApplication">Sender application/server</param>
        /// <param name="senderCommunicator">Sender communicator</param>
        /// <param name="message">Message</param>
        private void SentToClientApplication(NGRIDRemoteApplication senderApplication, ICommunicator senderCommunicator, NGRIDDataTransferMessage message)
        {
            NGRIDClientApplication destinationApplication = null;

            //If application exists on this server, get it
            lock (_clientApplicationList.Applications)
            {
                if (_clientApplicationList.Applications.ContainsKey(message.DestinationApplicationName))
                {
                    destinationApplication = _clientApplicationList.Applications[message.DestinationApplicationName];
                }
            }
            
            //If application doesn't exist on this server...
            if (destinationApplication == null)
            {
                SendOperationResultMessage(senderApplication, senderCommunicator, message, false, "Application does not exists on this server (" + _settings.ThisServerName + ").");
                return;
            }

            //Send message according TransmitRule
            switch (message.TransmitRule)
            {
                case MessageTransmitRules.DirectlySend:
                    SendMessageDirectly(
                        senderApplication,
                        senderCommunicator,
                        destinationApplication,
                        message
                        );
                    break;
                default:
                    // case MessageTransmitRules.StoreAndForward:
                    // case MessageTransmitRules.NonPersistent:
                    EnqueueMessage(
                        senderApplication,
                        senderCommunicator,
                        destinationApplication,
                        message
                        );
                    break;
            }
        }
예제 #13
0
        /// <summary>
        /// Checks a NGRIDDataTransferMessage and fills it's empty fields by default values.
        /// </summary>
        /// <param name="dataTransferMessage">Message</param>
        /// <param name="senderApplication">Sender application</param>
        /// <param name="communicator">Sender communicator of application</param>
        private void FillEmptyMessageFields(NGRIDDataTransferMessage dataTransferMessage, NGRIDRemoteApplication senderApplication, ICommunicator communicator)
        {
            //Default SourceApplicationName: Name of the sender application.
            if (string.IsNullOrEmpty(dataTransferMessage.SourceApplicationName))
            {
                dataTransferMessage.SourceApplicationName = senderApplication.Name;
            }

            //Default SourceServerName: Name of this server.
            if (string.IsNullOrEmpty(dataTransferMessage.SourceServerName))
            {
                dataTransferMessage.SourceServerName = _settings.ThisServerName;
            }

            //Default DestinationApplicationName: Name of the sender application.
            if (string.IsNullOrEmpty(dataTransferMessage.DestinationApplicationName))
            {
                dataTransferMessage.DestinationApplicationName = senderApplication.Name;
            }

            //Default DestinationServerName: Name of this server.
            if (string.IsNullOrEmpty(dataTransferMessage.DestinationServerName))
            {
                dataTransferMessage.DestinationServerName = _settings.ThisServerName;
            }

            if (dataTransferMessage.SourceServerName == _settings.ThisServerName)
            {
                //Sender communicator id is being set.
                dataTransferMessage.SourceCommunicatorId = communicator.ComminicatorId;
            }
        }
예제 #14
0
        /// <summary>
        /// This method is used to process a NGRIDDataTransferMessage that is gotten from a ngrid server or client application.
        /// Message is sent to destination or next server in one of these three conditions:
        /// - Destination server is this server and application exists on this server
        /// - Destination server is an adjacent server of this server
        /// - Destination server in server graph and there is a path from this server to destination server
        /// </summary>
        /// <param name="senderApplication">Sender application/server</param>
        /// <param name="senderCommunicator">Sender communicator</param>
        /// <param name="message">Message</param>
        private void ProcessDataTransferMessage(NGRIDRemoteApplication senderApplication, ICommunicator senderCommunicator, NGRIDDataTransferMessage message)
        {
            //Check for duplicate messages
            if (senderApplication.LastAcknowledgedMessageId == message.MessageId)
            {
                SendOperationResultMessage(senderApplication, senderCommunicator, message, true, "Duplicate message.");
                return;
            }

            try
            {
                AddThisServerToPassedServerList(message);

                FillEmptyMessageFields(message, senderApplication, senderCommunicator);

                _routingTable.ApplyRouting(message);

                //If Destination server is this server then deliver message to the destination application
                if (message.DestinationServerName.Equals(_settings.ThisServerName, StringComparison.OrdinalIgnoreCase))
                {
                    SentToClientApplication(senderApplication, senderCommunicator, message);
                }
                //Else, if destination server is an adjacent of this server (so they can communicate directly)
                else if (_serverGraph.AdjacentServers.ContainsKey(message.DestinationServerName))
                {
                    SentToAdjacentServer(senderApplication, senderCommunicator, message);
                }
                //Else, if destination server is not adjacent but in server graph (so, send message to next server)
                else if (_serverGraph.ServerNodes.ContainsKey(message.DestinationServerName))
                {
                    SendToNextServer(senderApplication, senderCommunicator, message);
                }
                else
                {
                    //return error to sender
                    SendOperationResultMessage(senderApplication, senderCommunicator, message, false, "Destination does not exists.");
                }
            }
            catch (Exception ex)
            {
                SendOperationResultMessage(senderApplication, senderCommunicator, message, false, ex.Message);
            }
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="remoteApplication">Reference to the NGRIDRemoteApplication object that is used with this MessageDeliverer</param>
 public MessageDeliverer(NGRIDRemoteApplication remoteApplication)
 {
     _remoteApplication = remoteApplication;
     _asynchronMessageControlTimer = new Timer(AsynchronMessageControlTimer_Elapsed, null, Timeout.Infinite, Timeout.Infinite);
 }