/// <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; } } } }
/// <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 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($"[TITANIC BROKER] Received request GUID {msg} via pipe"); // 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)) { // stop all threads cts.Cancel(); // stop processing! break; } } } }