Exemple #1
0
        /// <summary>
        ///     dispatch the request with the specified GUID th the next available worker if any
        /// </summary>
        /// <param name="requestId">request's GUID</param>
        /// <param name="serviceClient">mdp client to handle mdp broker communication</param>
        /// <returns><c>true</c> if successfull <c>false</c> otherwise</returns>
        internal bool DispatchRequests(Guid requestId, [CanBeNull] IMDPClient serviceClient = null)
        {
            // has the request already been processed? -> file does not exist
            // threat this as successfully processed
            if (!m_io.ExistsMessage(TitanicOperation.Request, requestId))
            {
                Log(string.Format("[TITANIC DISPATCH] Request {0} does not exist. Removing it from queue.", requestId));
                // close request inorder to avoid any further processing
                m_io.CloseRequest(requestId);

                return(true);
            }

            // load request from file
            var request = m_io.GetMessage(TitanicOperation.Request, requestId);
            // [service name][data]
            var serviceName = request[0].ConvertToString();

            Log(string.Format("[TITANIC DISPATCH] Do a ServiceCall for {0} - {1}.", serviceName, request));

            var reply = ServiceCall(serviceName, request, serviceClient);

            if (ReferenceEquals(reply, null))
            {
                return(false);       // no reply
            }
            // a reply has been received -> save it
            Log(string.Format("[TITANIC DISPATCH] Saving reply for request {0}.", requestId));
            // save the reply for further use
            m_io.SaveMessage(TitanicOperation.Reply, requestId, reply);

            return(true);
        }
Exemple #2
0
        /// <summary>
        ///     carry out the actual call to the worker via a broker in order
        ///     to process the request and get the reply which we wait for
        ///
        ///     <para>it creates a MDPClient and requests from MDPBroker the service.
        ///     if that service exists it uses the returned worker address and issues
        ///     a request with the appropriate data and waits for the reply</para>
        /// </summary>
        /// <param name="serviceName">the service's name requested</param>
        /// <param name="request">request to process by worker</param>
        /// <param name="serviceClient">mdp client handling the forwarding of requests
        ///             to service offering mdp worker via mdp broker and collecting
        ///             the replies from the mdp worker</param>
        /// <returns><c>true</c> if successfull and <c>false</c> otherwise</returns>
        private NetMQMessage ServiceCall(string serviceName, NetMQMessage request, IMDPClient serviceClient = null)
        {
            // create MDPClient session and send the request to MDPBroker
            using (var session = serviceClient ?? new MDPClient(m_titanicAddress))
            {
                session.Timeout = TimeSpan.FromMilliseconds(1000);      // 1s
                session.Retries = 1;                                    // only 1 retry
                // use MMI protocol to check if service is available
                var mmi = new NetMQMessage();
                // add name of service to inquire
                mmi.Push(serviceName);
                // request mmi.service resolution
                var reply = session.Send("mmi.service", mmi);
                // first frame should be result of inquiry
                var rc     = reply[0].ConvertToString();
                var answer = (MmiCode)Enum.Parse(typeof(MmiCode), rc);
                // answer == "Ok" -> service is available -> make the request
                if (answer == MmiCode.Ok)
                {
                    Log(string.Format("[TITANIC SERVICECALL] -> {0} - {1}", serviceName, request));

                    return(session.Send(serviceName, request));
                }

                Log(string.Format("[TITANIC SERVICECALL] Service {0} (RC = {1}/{2}) is not available.",
                                  serviceName,
                                  answer,
                                  request));

                //! shall this information be available for request? Unknown or Pending
                //! so TitanicRequest could utilize this information

                return(null);
            }
        }
        private void RecreateClient()
        {
            var adr = m_client.Address;
            var id  = m_client.Identity;

            m_client.Dispose();

            // recreate the client with the old config values
            m_client = new MDPClient(adr, id);
        }
Exemple #4
0
        private void EchoClient(IMDPClient client, string serviceName)
        {
            var request = new NetMQMessage();

            // set the request data
            request.Push("Helo World!");
            // send the request to the service
            var reply = client.Send(serviceName, request);

            Assert.That(reply, Is.Not.Null, "[ECHO CLIENT] REPLY was <null>");
            Assert.That(reply.FrameCount, Is.EqualTo(1));
            Assert.That(reply.First.ConvertToString(), Is.EqualTo("Helo World!"));
        }
Exemple #5
0
        private void AddHelloClient(IMDPClient client, string serviceName)
        {
            const string _PAYLOAD = "Hello World";
            var          request  = new NetMQMessage();

            // set the request data
            request.Push(_PAYLOAD);
            // send the request to the service
            var reply = client.Send(serviceName, request);

            Assert.That(reply, Is.Not.Null, "[ADD HELLO CLIENT] REPLY was <null>");
            Assert.That(reply.FrameCount, Is.EqualTo(1));
            Assert.That(reply.First.ConvertToString(), Is.EqualTo(_PAYLOAD + " - HELLO"));
        }
        private Tuple <NetMQMessage, TitanicReturnCode> ServiceCall(IMDPClient session, TitanicOperation op, NetMQMessage message)
        {
            // message can be:
            //  REQUEST:
            //      in goes -> [titanic operation][service requested][request]
            //      returns -> [return code][Guid]
            //  REPLY
            //      in goes -> [titanic operation][request id]
            //      returns -> [return code][reply]
            //  CLOSE
            //      in goes -> [titanic operation][request id]
            var reply = session.Send(op.ToString(), message);

            Log(string.Format("received message: {0}", reply));

            if (ReferenceEquals(reply, null) || reply.IsEmpty)
            {
                return(null); // went wrong - why? I don't care!
            }
            // we got a reply -> [return code][data]
            var rc     = reply.Pop().ConvertToString();     // [return code] <- [data] or [service name] if 'Unknown'
            var status = (TitanicReturnCode)Enum.Parse(typeof(TitanicReturnCode), rc);

            switch (status)
            {
            case TitanicReturnCode.Ok:
                return(new Tuple <NetMQMessage, TitanicReturnCode> (reply, TitanicReturnCode.Ok));

            case TitanicReturnCode.Pending:
                return(new Tuple <NetMQMessage, TitanicReturnCode> (reply, TitanicReturnCode.Pending));

            case TitanicReturnCode.Unknown:
                Log("ERROR: Service unknown!");
                return(new Tuple <NetMQMessage, TitanicReturnCode> (reply, TitanicReturnCode.Unknown));

            default:
                Log("ERROR: FATAL ERROR ABANDONING!");
                return(new Tuple <NetMQMessage, TitanicReturnCode> (null, TitanicReturnCode.Failure));
            }
        }
Exemple #7
0
        private void MultipleRequestClient(string serviceName, string endpoint, IMDPClient client = null)
        {
            const int _NO_OF_RUNS = 100;

            var reply = new NetMQMessage[_NO_OF_RUNS];
            var idC01 = new[] { (byte)'C', (byte)'1' };

            client = client ?? new MDPClient(endpoint, idC01);

            var request = new NetMQMessage();

            // set the request data
            request.Push("Helo World!");
            // send the request to the service
            for (int i = 0; i < _NO_OF_RUNS; i++)
            {
                reply[i] = client.Send(serviceName, request);
            }

            client.Dispose();

            Assert.That(reply, Has.None.Null);
            Assert.That(reply.All(r => r.First.ConvertToString() == "Helo World!"));
        }
        private void AddHelloClient(IMDPClient client, string serviceName)
        {
            const string _PAYLOAD = "Hello World";
            var request = new NetMQMessage();
            // set the request data
            request.Push(_PAYLOAD);
            // send the request to the service
            var reply = client.Send(serviceName, request);

            Assert.That(reply, Is.Not.Null, "[ADD HELLO CLIENT] REPLY was <null>");
            Assert.That(reply.FrameCount, Is.EqualTo(1));
            Assert.That(reply.First.ConvertToString(), Is.EqualTo(_PAYLOAD + " - HELLO"));
        }
        private void MultipleRequestClient(string serviceName, string endpoint, IMDPClient client = null)
        {
            const int _NO_OF_RUNS = 100;

            var reply = new NetMQMessage[_NO_OF_RUNS];
            var idC01 = new[] { (byte)'C', (byte)'1' };

            client = client ?? new MDPClient(endpoint, idC01);

            var request = new NetMQMessage();
            // set the request data
            request.Push("Helo World!");
            // send the request to the service
            for (int i = 0; i < _NO_OF_RUNS; i++)
                reply[i] = client.Send(serviceName, request);

            client.Dispose();

            Assert.That(reply, Has.None.Null);
            Assert.That(reply.All(r => r.First.ConvertToString() == "Helo World!"));
        }
        private void EchoClient(IMDPClient client, string serviceName)
        {
            var request = new NetMQMessage();
            // set the request data
            request.Push("Helo World!");
            // send the request to the service
            var reply = client.Send(serviceName, request);

            Assert.That(reply, Is.Not.Null, "[ECHO CLIENT] REPLY was <null>");
            Assert.That(reply.FrameCount, Is.EqualTo(1));
            Assert.That(reply.First.ConvertToString(), Is.EqualTo("Helo World!"));
        }
 /// <summary>
 ///     ctor - creates a titanic client API object
 ///     for easy access to titanic services
 /// </summary>
 /// <param name="client">a valid Major Domo Protocol Client</param>
 public TitanicClient(IMDPClient client)
 {
     m_client = client;
 }
 /// <summary>
 ///     ctor - creates a titanic client API object
 ///     for easy access to titanic services
 /// </summary>
 /// <param name="address">a valid NetMQ address string</param>
 /// <remarks>
 ///     valid NetMQ address string are i.e.
 ///
 ///         tcp:\\localhost:5555
 ///         tcp:\\172.12.2.34
 ///
 ///     or alike for more information
 ///     <see cref="http://netmq.readthedocs.org/en/latest/transports/"/>
 /// </remarks>
 public TitanicClient(string address)
 {
     m_client = new MDPClient(address);
 }
Exemple #13
0
        /// <summary>
        ///     carry out the actual call to the worker via a broker in order
        ///     to process the request and get the reply which we wait for
        ///
        ///     <para>it creates a MDPClient and requests from MDPBroker the service.
        ///     if that service exists it uses the returned worker address and issues
        ///     a request with the appropriate data and waits for the reply</para>
        /// </summary>
        /// <param name="serviceName">the service's name requested</param>
        /// <param name="request">request to process by worker</param>
        /// <param name="serviceClient">mdp client handling the forwarding of requests
        ///             to service offering mdp worker via mdp broker and collecting
        ///             the replies from the mdp worker</param>
        /// <returns><c>true</c> if successfull and <c>false</c> otherwise</returns>
        private NetMQMessage ServiceCall( string serviceName,  NetMQMessage request, IMDPClient serviceClient = null)
        {
            // create MDPClient session and send the request to MDPBroker
            using (var session = serviceClient ?? new MDPClient (m_titanicAddress))
            {
                session.Timeout = TimeSpan.FromMilliseconds (1000);     // 1s
                session.Retries = 1;                                    // only 1 retry
                // use MMI protocol to check if service is available
                var mmi = new NetMQMessage ();
                // add name of service to inquire
                mmi.Push (serviceName);
                // request mmi.service resolution
                var reply = session.Send ("mmi.service", mmi);
                // first frame should be result of inquiry
                var rc = reply[0].ConvertToString ();
                var answer = (MmiCode) Enum.Parse (typeof (MmiCode), rc);
                // answer == "Ok" -> service is available -> make the request
                if (answer == MmiCode.Ok)
                {
                    Log (string.Format ("[TITANIC SERVICECALL] -> {0} - {1}", serviceName, request));

                    return session.Send (serviceName, request);
                }

                Log (string.Format ("[TITANIC SERVICECALL] Service {0} (RC = {1}/{2}) is not available.",
                                    serviceName,
                                    answer,
                                    request));

                //! shall this information be available for request? Unknown or Pending
                //! so TitanicRequest could utilize this information

                return null;
            }
        }
Exemple #14
0
        /// <summary>
        ///     dispatch the request with the specified GUID th the next available worker if any
        /// </summary>
        /// <param name="requestId">request's GUID</param>
        /// <param name="serviceClient">mdp client to handle mdp broker communication</param>
        /// <returns><c>true</c> if successfull <c>false</c> otherwise</returns>
        internal bool DispatchRequests(Guid requestId,  IMDPClient serviceClient = null)
        {
            // has the request already been processed? -> file does not exist
            // threat this as successfully processed
            if (!m_io.ExistsMessage (TitanicOperation.Request, requestId))
            {
                Log (string.Format ("[TITANIC DISPATCH] Request {0} does not exist. Removing it from queue.", requestId));
                // close request inorder to avoid any further processing
                m_io.CloseRequest (requestId);

                return true;
            }

            // load request from file
            var request = m_io.GetMessage (TitanicOperation.Request, requestId);
            // [service name][data]
            var serviceName = request[0].ConvertToString ();

            Log (string.Format ("[TITANIC DISPATCH] Do a ServiceCall for {0} - {1}.", serviceName, request));

            var reply = ServiceCall (serviceName, request, serviceClient);

            if (ReferenceEquals (reply, null))
                return false;       // no reply

            // a reply has been received -> save it
            Log (string.Format ("[TITANIC DISPATCH] Saving reply for request {0}.", requestId));
            // save the reply for further use
            m_io.SaveMessage (TitanicOperation.Reply, requestId, reply);

            return true;
        }
Exemple #15
0
        /// <summary>
        ///     <para>is the main thread of the broker</para>
        ///     <para>it spawns threads handling titanic operations</para>
        ///     <para>it receives GUID from Titanic Request Service and dispatches the requests
        ///     to available workers via MDPBroker</para>
        ///     <para>it also manages the appropriate changes in the file system as well as in queue</para>
        /// </summary>
        /// <param name="requestWorker">mdp worker processing the incoming requests for services</param>
        /// <param name="replyWorker">mdp worker processing incoming reply requests</param>
        /// <param name="closeWorker">mdp worker processing incoming close requests</param>
        /// <param name="serviceCallClient">mdp client forwarding requests to service providing mdp worker
        ///                                 via mdp broker and collecting replies</param>
        /// <exception cref="TerminatingException">The socket has been stopped.</exception>
        /// <exception cref="AddressAlreadyInUseException">The specified address is already in use.</exception>
        /// <exception cref="NetMQException">No IO thread was found, or the protocol's listener encountered an
        ///                                  error during initialization.</exception>
        /// <exception cref="ObjectDisposedException">thrown if the socket was already disposed</exception>
        public void Run( IMDPWorker requestWorker = null,
                          IMDPWorker replyWorker = null,
                          IMDPWorker closeWorker = null,
                          IMDPClient serviceCallClient = null)
        {
            using (var pipeStart = new PairSocket ())
            using (var pipeEnd = new PairSocket ())
            using (var cts = new CancellationTokenSource ())
            {
                // set up the inter thread communication pipe
                pipeStart.Bind (_titanic_internal_communication);
                pipeEnd.Connect (_titanic_internal_communication);

                // start the three child tasks
                var requestTask = Task.Run (() => ProcessTitanicRequest (pipeEnd, requestWorker), cts.Token);
                var replyTask = Task.Run (() => ProcessTitanicReply (replyWorker), cts.Token);
                var closeTask = Task.Run (() => ProcessTitanicClose (closeWorker), cts.Token);

                var tasks = new[] { requestTask, replyTask, closeTask };

                while (true)
                {
                    // wait for 1s for a new request from 'Request' to process
                    var input = pipeStart.Poll (PollEvents.PollIn, TimeSpan.FromMilliseconds (1000));

                    // any message available? -> process it
                    if ((input & PollEvents.PollIn) == PollEvents.PollIn)
                    {
                        // only one frame will be send [Guid]
                        var msg = pipeStart.ReceiveFrameString ();

                        Guid guid;
                        if (!Guid.TryParse (msg, out guid))
                            Log ("[TITANIC BROKER] Received a malformed GUID via pipe - throw it away");
                        else
                        {
                            Log (string.Format ("[TITANIC BROKER] Received request GUID {0} via pipe", msg));
                            // now we have a valid GUID - save it to disk for further use
                            m_io.SaveNewRequestEntry (guid);
                        }
                    }
                    //! now dispatch (brute force) the requests -> SHOULD BE MORE INTELLIGENT (!)
                    // dispatching will also worry about the handling of a potential reply
                    // dispatch only requests which have not been closed
                    foreach (var entry in m_io.GetNotClosedRequestEntries ().Where (entry => entry != default (RequestEntry)))
                    {
                        if (DispatchRequests (entry.RequestId, serviceCallClient))
                            m_io.SaveProcessedRequestEntry (entry);
                    }

                    //! should implement some sort of restart
                    // beware of the silently dieing threads - must be detected!
                    if (DidAnyTaskStopp (tasks))
                    {
                        // stopp all threads
                        cts.Cancel ();
                        // stop processing!
                        break;
                    }
                }
            }
        }
Exemple #16
0
        /// <summary>
        ///     <para>is the main thread of the broker</para>
        ///     <para>it spawns threads handling titanic operations</para>
        ///     <para>it receives GUID from Titanic Request Service and dispatches the requests
        ///     to available workers via MDPBroker</para>
        ///     <para>it also manages the appropriate changes in the file system as well as in queue</para>
        /// </summary>
        /// <param name="requestWorker">mdp worker processing the incoming requests for services</param>
        /// <param name="replyWorker">mdp worker processing incoming reply requests</param>
        /// <param name="closeWorker">mdp worker processing incoming close requests</param>
        /// <param name="serviceCallClient">mdp client forwarding requests to service providing mdp worker
        ///                                 via mdp broker and collecting replies</param>
        /// <exception cref="TerminatingException">The socket has been stopped.</exception>
        /// <exception cref="AddressAlreadyInUseException">The specified address is already in use.</exception>
        /// <exception cref="NetMQException">No IO thread was found, or the protocol's listener encountered an
        ///                                  error during initialization.</exception>
        /// <exception cref="ObjectDisposedException">thrown if the socket was already disposed</exception>
        public void Run([CanBeNull] IMDPWorker requestWorker     = null,
                        [CanBeNull] IMDPWorker replyWorker       = null,
                        [CanBeNull] IMDPWorker closeWorker       = null,
                        [CanBeNull] IMDPClient serviceCallClient = null)
        {
            using (var ctx = NetMQContext.Create())
                using (var pipeStart = ctx.CreatePairSocket())
                    using (var pipeEnd = ctx.CreatePairSocket())
                        using (var cts = new CancellationTokenSource())
                        {
                            // set up the inter thread communication pipe
                            pipeStart.Bind(_titanic_internal_communication);
                            pipeEnd.Connect(_titanic_internal_communication);

                            // start the three child tasks
                            var requestTask = Task.Run(() => ProcessTitanicRequest(pipeEnd, requestWorker), cts.Token);
                            var replyTask   = Task.Run(() => ProcessTitanicReply(replyWorker), cts.Token);
                            var closeTask   = Task.Run(() => ProcessTitanicClose(closeWorker), cts.Token);

                            var tasks = new[] { requestTask, replyTask, closeTask };

                            while (true)
                            {
                                // wait for 1s for a new request from 'Request' to process
                                var input = pipeStart.Poll(PollEvents.PollIn, TimeSpan.FromMilliseconds(1000));

                                // any message available? -> process it
                                if ((input & PollEvents.PollIn) == PollEvents.PollIn)
                                {
                                    // only one frame will be send [Guid]
                                    var msg = pipeStart.ReceiveFrameString();

                                    Guid guid;
                                    if (!Guid.TryParse(msg, out guid))
                                    {
                                        Log("[TITANIC BROKER] Received a malformed GUID via pipe - throw it away");
                                    }
                                    else
                                    {
                                        Log(string.Format("[TITANIC BROKER] Received request GUID {0} via pipe", msg));
                                        // now we have a valid GUID - save it to disk for further use
                                        m_io.SaveNewRequestEntry(guid);
                                    }
                                }
                                //! now dispatch (brute force) the requests -> SHOULD BE MORE INTELLIGENT (!)
                                // dispatching will also worry about the handling of a potential reply
                                // dispatch only requests which have not been closed
                                foreach (var entry in m_io.GetNotClosedRequestEntries().Where(entry => entry != default(RequestEntry)))
                                {
                                    if (DispatchRequests(entry.RequestId, serviceCallClient))
                                    {
                                        m_io.SaveProcessedRequestEntry(entry);
                                    }
                                }

                                //! should implement some sort of restart
                                // beware of the silently dieing threads - must be detected!
                                if (DidAnyTaskStopp(tasks))
                                {
                                    // stopp all threads
                                    cts.Cancel();
                                    // stop processing!
                                    break;
                                }
                            }
                        }
        }