Exemplo n.º 1
0
        /// <summary>
        ///     an idempotent method processing all requests to close a request with a GUID
        ///     it is safe to call it multiple times with the same GUID
        /// </summary>
        internal void ProcessTitanicClose([CanBeNull] IMDPWorker mdpWorker = null)
        {
            // get a MDP worker with an automatic id and register with the service "titanic.Close"
            // the worker will automatically start and connect to MDP Broker with the indicated address
            using (var worker = mdpWorker ?? new MDPWorker(m_titanicAddress, TitanicOperation.Close.ToString()))
            {
                NetMQMessage reply = null;

                while (true)
                {
                    // initiate the communication with sending a null, since there is no reply yet
                    var request = worker.Receive(reply);

                    Log(string.Format("[TITANIC CLOSE] received: {0}", request));

                    //! has there been a breaking cause? -> exit
                    if (ReferenceEquals(request, null))
                    {
                        break;
                    }

                    // we expect [Guid] as the only frame
                    var guidAsString = request.Pop().ConvertToString();
                    var guid         = Guid.Parse(guidAsString);

                    Log(string.Format("[TITANIC CLOSE] closing {0}", guid));

                    // close the request
                    m_io.CloseRequest(guid);
                    // send back the confirmation
                    reply = new NetMQMessage();
                    reply.Push(TitanicReturnCode.Ok.ToString());
                }
            }
        }
Exemplo n.º 2
0
        // ======================= HELPER =========================

        private void EchoWorker(IMDPWorker worker, int heartbeatinterval = 2500)
        {
            worker.HeartbeatDelay = TimeSpan.FromMilliseconds(heartbeatinterval);
            // send the reply and wait for a request
            var request = worker.Receive(null);

            // was the worker interrupted
            Assert.That(request, Is.Not.Null);
            // echo the request and wait for next request which will not come
            // here the task will be canceled
            var newrequest = worker.Receive(request);
        }
Exemplo n.º 3
0
        /// <summary>
        ///     process any titanic reply request by a client
        ///
        ///     <para>will send an OK, PENDING or UNKNOWN as result of the request for the reply</para>
        /// </summary>
        internal void ProcessTitanicReply([CanBeNull] IMDPWorker mdpWorker = null)
        {
            // get a MDP worker with an automatic id and register with the service "titanic.reply"
            // the worker will automatically start and connect to the indicated address
            using (var worker = mdpWorker ?? new MDPWorker(m_titanicAddress, TitanicOperation.Reply.ToString()))
            {
                NetMQMessage reply = null;

                while (true)
                {
                    // initiate the communication to MDP Broker with sending a 'null',
                    // since there is no initial reply everytime thereafter the reply will be send
                    var request = worker.Receive(reply);

                    Log(string.Format("TITANIC REPLY] received: {0}", request));

                    //! has there been a breaking cause? -> exit
                    if (ReferenceEquals(request, null))
                    {
                        break;
                    }

                    var requestIdAsString = request.Pop().ConvertToString();
                    var requestId         = Guid.Parse(requestIdAsString);

                    if (m_io.ExistsMessage(TitanicOperation.Reply, requestId))
                    {
                        Log(string.Format("[TITANIC REPLY] reply for request exists: {0}", requestId));

                        reply = m_io.GetMessage(TitanicOperation.Reply, requestId);     // [service][reply]
                        reply.Push(TitanicReturnCode.Ok.ToString());                    // ["OK"][service][reply]
                    }
                    else
                    {
                        reply = new NetMQMessage();

                        var replyCommand = (m_io.ExistsMessage(TitanicOperation.Request, requestId)
                                                ? TitanicReturnCode.Pending
                                                : TitanicReturnCode.Unknown);

                        reply.Push(replyCommand.ToString());
                    }

                    Log(string.Format("[TITANIC REPLY] reply: {0}", reply));
                }
            }
        }
Exemplo n.º 4
0
        private void DoubleEchoWorker(IMDPWorker worker, int heartbeatinterval = 2500)
        {
            worker.HeartbeatDelay = TimeSpan.FromMilliseconds(heartbeatinterval);
            var request = worker.Receive(null);

            // was the worker interrupted
            Assert.That(request, Is.Not.Null);
            // double the content of the request
            var payload = request.Last.ConvertToString();

            payload += " - " + payload;
            request.RemoveFrame(request.Last);
            request.Append(payload);
            // echo the request and wait for next request which will not come
            // here the task will be canceled
            var newrequest = worker.Receive(request);
        }
Exemplo n.º 5
0
        private static void AddHelloWorker(IMDPWorker worker, int heartbeatinterval = 2500)
        {
            worker.HeartbeatDelay = TimeSpan.FromMilliseconds(heartbeatinterval);
            // send the reply and wait for a request
            var request = worker.Receive(null);

            // was the worker interrupted
            Assert.That(request, Is.Not.Null);
            // add the extra the content to request
            var payload = request.Last.ConvertToString();

            payload += " - HELLO";
            request.RemoveFrame(request.Last);
            request.Append(payload);
            // echo the request and wait for next request which will not come
            // here the task will be canceled
            var newrequest = worker.Receive(request);
        }
Exemplo n.º 6
0
        /// <summary>
        ///     process a titanic request according to TITANIC Protocol
        ///
        ///     <para>it connects via provided PAIR socket to main thread</para>
        ///     <para>write request to disk and return the GUID to client</para>
        ///     sends the GUID of the request back via the pipe for further processing
        /// </summary>
        internal void ProcessTitanicRequest([NotNull] PairSocket pipe, [CanBeNull] IMDPWorker mdpWorker = null)
        {
            // get a MDP worker with an automatic id and register with the service "titanic.request"
            // the worker will automatically start and connect to a MDP Broker at the indicated address
            using (var worker = mdpWorker ?? new MDPWorker(m_titanicAddress, TitanicOperation.Request.ToString()))
            {
                NetMQMessage reply = null;

                while (true)
                {
                    // initiate the communication with sending a 'null', since there is no initial reply
                    // a request should be [service name][request data]
                    var request = worker.Receive(reply);

                    Log(string.Format("[TITANIC REQUEST] Received request: {0}", request));

                    //! has there been a breaking cause? -> exit
                    if (ReferenceEquals(request, null))
                    {
                        break;
                    }

                    //! check if service exists! and return 'Unknown' if not

                    // generate Guid for the request
                    var requestId = Guid.NewGuid();
                    // save request to file -> [service name][request data]
                    m_io.SaveMessage(TitanicOperation.Request, requestId, request);

                    Log(string.Format("[TITANIC REQUEST] sending through pipe: {0}", requestId));

                    // send GUID through message queue to main thread
                    pipe.Send(requestId.ToString());
                    // return GUID via reply message via worker.Receive call
                    reply = new NetMQMessage();
                    // [Guid]
                    reply.Push(requestId.ToString());
                    // [Ok][Guid]
                    reply.Push(TitanicReturnCode.Ok.ToString());

                    Log(string.Format("[TITANIC REQUEST] sending reply: {0}", reply));
                }
            }
        }
Exemplo n.º 7
0
        private static void MultipleRequestWorker(IMDPWorker worker = null, string endpoint = null, int heartbeatinterval = 2500)
        {
            var idW01 = new[] { (byte)'W', (byte)'1' };

            worker = worker ?? new MDPWorker(endpoint, "echo", idW01);
            worker.HeartbeatDelay = TimeSpan.FromMilliseconds(heartbeatinterval);

            NetMQMessage reply = null;

            while (true)
            {
                // send the reply and wait for a request
                var request = worker.Receive(reply);
                // was the worker interrupted
                Assert.That(request, Is.Not.Null);
                // echo the request and wait for next request which will not come
                // here the task will be canceled
                reply = worker.Receive(request);
            }
        }
Exemplo n.º 8
0
 private void AddHelloWorker(IMDPWorker worker, int heartbeatinterval = 2500)
 {
     worker.HeartbeatDelay = TimeSpan.FromMilliseconds(heartbeatinterval);
     // send the reply and wait for a request
     var request = worker.Receive(null);
     // was the worker interrupted
     Assert.That(request, Is.Not.Null);
     // add the extra the content to request
     var payload = request.Last.ConvertToString();
     payload += " - HELLO";
     request.RemoveFrame(request.Last);
     request.Append(payload);
     // echo the request and wait for next request which will not come
     // here the task will be canceled
     var newrequest = worker.Receive(request);
 }
Exemplo n.º 9
0
        private void MultipleRequestWorker(IMDPWorker worker = null, string endpoint = null, int heartbeatinterval = 2500)
        {
            var idW01 = new[] { (byte)'W', (byte)'1' };

            worker = worker ?? new MDPWorker(endpoint, "echo", idW01);
            worker.HeartbeatDelay = TimeSpan.FromMilliseconds(heartbeatinterval);

            NetMQMessage reply = null;

            while (true)
            {
                // send the reply and wait for a request
                var request = worker.Receive(reply);
                // was the worker interrupted
                Assert.That(request, Is.Not.Null);
                // echo the request and wait for next request which will not come
                // here the task will be canceled
                reply = worker.Receive(request);
            }
        }
Exemplo n.º 10
0
        // ======================= HELPER =========================

        private void EchoWorker(IMDPWorker worker, int heartbeatinterval = 2500)
        {
            worker.HeartbeatDelay = TimeSpan.FromMilliseconds(heartbeatinterval);
            // send the reply and wait for a request
            var request = worker.Receive(null);
            // was the worker interrupted
            Assert.That(request, Is.Not.Null);
            // echo the request and wait for next request which will not come
            // here the task will be canceled
            var newrequest = worker.Receive(request);
        }
Exemplo n.º 11
0
 private static void DoubleEchoWorker (IMDPWorker worker, int heartbeatinterval = 2500)
 {
     worker.HeartbeatDelay = TimeSpan.FromMilliseconds (heartbeatinterval);
     var request = worker.Receive (null);
     // was the worker interrupted
     Assert.That (request, Is.Not.Null);
     // double the content of the request
     var payload = request.Last.ConvertToString ();
     payload += " - " + payload;
     request.RemoveFrame (request.Last);
     request.Append (payload);
     // echo the request and wait for next request which will not come
     // here the task will be canceled
     var newrequest = worker.Receive (request);
 }
Exemplo n.º 12
0
        /// <summary>
        ///     process a titanic request according to TITANIC Protocol
        ///
        ///     <para>it connects via provided PAIR socket to main thread</para>
        ///     <para>write request to disk and return the GUID to client</para>
        ///     sends the GUID of the request back via the pipe for further processing
        /// </summary>
        internal void ProcessTitanicRequest( PairSocket pipe, IMDPWorker mdpWorker = null)
        {
            // get a MDP worker with an automatic id and register with the service "titanic.request"
            // the worker will automatically start and connect to a MDP Broker at the indicated address
            using (var worker = mdpWorker ?? new MDPWorker (m_titanicAddress, TitanicOperation.Request.ToString ()))
            {
                NetMQMessage reply = null;

                while (true)
                {
                    // initiate the communication with sending a 'null', since there is no initial reply
                    // a request should be [service name][request data]
                    var request = worker.Receive (reply);

                    Log (string.Format ("[TITANIC REQUEST] Received request: {0}", request));

                    //! has there been a breaking cause? -> exit
                    if (ReferenceEquals (request, null))
                        break;

                    //! check if service exists! and return 'Unknown' if not

                    // generate Guid for the request
                    var requestId = Guid.NewGuid ();
                    // save request to file -> [service name][request data]
                    m_io.SaveMessage (TitanicOperation.Request, requestId, request);

                    Log (string.Format ("[TITANIC REQUEST] sending through pipe: {0}", requestId));

                    // send GUID through message queue to main thread
                    pipe.SendFrame (requestId.ToString ());
                    // return GUID via reply message via worker.Receive call
                    reply = new NetMQMessage ();
                    // [Guid]
                    reply.Push (requestId.ToString ());
                    // [Ok][Guid]
                    reply.Push (TitanicReturnCode.Ok.ToString ());

                    Log (string.Format ("[TITANIC REQUEST] sending reply: {0}", reply));
                }
            }
        }
Exemplo n.º 13
0
        /// <summary>
        ///     process any titanic reply request by a client
        ///
        ///     <para>will send an OK, PENDING or UNKNOWN as result of the request for the reply</para>
        /// </summary>
        internal void ProcessTitanicReply( IMDPWorker mdpWorker = null)
        {
            // get a MDP worker with an automatic id and register with the service "titanic.reply"
            // the worker will automatically start and connect to the indicated address
            using (var worker = mdpWorker ?? new MDPWorker (m_titanicAddress, TitanicOperation.Reply.ToString ()))
            {
                NetMQMessage reply = null;

                while (true)
                {
                    // initiate the communication to MDP Broker with sending a 'null',
                    // since there is no initial reply everytime thereafter the reply will be send
                    var request = worker.Receive (reply);

                    Log (string.Format ("TITANIC REPLY] received: {0}", request));

                    //! has there been a breaking cause? -> exit
                    if (ReferenceEquals (request, null))
                        break;

                    var requestIdAsString = request.Pop ().ConvertToString ();
                    var requestId = Guid.Parse (requestIdAsString);

                    if (m_io.ExistsMessage (TitanicOperation.Reply, requestId))
                    {
                        Log (string.Format ("[TITANIC REPLY] reply for request exists: {0}", requestId));

                        reply = m_io.GetMessage (TitanicOperation.Reply, requestId);    // [service][reply]
                        reply.Push (TitanicReturnCode.Ok.ToString ());                  // ["OK"][service][reply]
                    }
                    else
                    {
                        reply = new NetMQMessage ();

                        var replyCommand = (m_io.ExistsMessage (TitanicOperation.Request, requestId)
                                                ? TitanicReturnCode.Pending
                                                : TitanicReturnCode.Unknown);

                        reply.Push (replyCommand.ToString ());
                    }

                    Log (string.Format ("[TITANIC REPLY] reply: {0}", reply));
                }
            }
        }
Exemplo n.º 14
0
        /// <summary>
        ///     an idempotent method processing all requests to close a request with a GUID
        ///     it is safe to call it multiple times with the same GUID
        /// </summary>
        internal void ProcessTitanicClose(IMDPWorker mdpWorker = null)
        {
            // get a MDP worker with an automatic id and register with the service "titanic.Close"
            // the worker will automatically start and connect to MDP Broker with the indicated address
            using (var worker = mdpWorker ?? new MDPWorker (m_titanicAddress, TitanicOperation.Close.ToString ()))
            {
                NetMQMessage reply = null;

                while (true)
                {
                    // initiate the communication with sending a null, since there is no reply yet
                    var request = worker.Receive (reply);

                    Log (string.Format ("[TITANIC CLOSE] received: {0}", request));

                    //! has there been a breaking cause? -> exit
                    if (ReferenceEquals (request, null))
                        break;

                    // we expect [Guid] as the only frame
                    var guidAsString = request.Pop ().ConvertToString ();
                    var guid = Guid.Parse (guidAsString);

                    Log (string.Format ("[TITANIC CLOSE] closing {0}", guid));

                    // close the request
                    m_io.CloseRequest (guid);
                    // send back the confirmation
                    reply = new NetMQMessage ();
                    reply.Push (TitanicReturnCode.Ok.ToString ());
                }
            }
        }
Exemplo n.º 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;
                    }
                }
            }
        }
Exemplo n.º 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;
                                }
                            }
                        }
        }