Beispiel #1
0
        //  .split recv method
        //  This is the {{recv}} method; it's a little misnamed because it first sends
        //  any reply and then waits for a new request. If you have a better name
        //  for this, let me know.

        //  Send reply, if any, to broker and wait for next request.
        public ZMessage Recv(ZMessage reply, CancellationTokenSource cancellor)
        {
            if (reply == null &&
                _expectReply)
            {
                throw new InvalidOperationException();
            }

            if (reply != null)
            {
                if (_replyTo == null)
                {
                    throw new InvalidOperationException();
                }
                reply.Wrap(_replyTo);
                SendToBroker(MdpCommon.MdpwCmd.REPLY.ToHexString(), string.Empty, reply);
            }
            _expectReply = true;

            while (true)
            {
                if (cancellor.IsCancellationRequested ||
                    (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape))
                {
                    _context.Shutdown();
                }

                var      p = ZPollItem.CreateReceiver();
                ZMessage msg;
                ZError   error;
                if (Worker.PollIn(p, out msg, out error, Heartbeat))
                {
                    using (msg)
                    {
                        // If we got a reply
                        if (Verbose)
                        {
                            msg.DumpZmsg("I: received message from broker:");
                        }

                        Liveness = MdpCommon.HEARTBEAT_LIVENESS;

                        // Don't try to handle errors, just assert noisily
                        if (msg.Count < 3)
                        {
                            throw new InvalidOperationException();
                        }

                        using (ZFrame empty = msg.Pop())
                        {
                            if (!empty.ToString().Equals(""))
                            {
                                throw new InvalidOperationException();
                            }
                        }

                        using (ZFrame header = msg.Pop())
                        {
                            if (!header.ToString().Equals(MdpCommon.MDPW_WORKER))
                            {
                                throw new InvalidOperationException();
                            }
                        }
                        //header.ReadString().Equals(MDPW_WORKER);
                        using (ZFrame command = msg.Pop())
                        {
                            if (command.StrHexEq(MdpCommon.MdpwCmd.REQUEST))
                            {
                                //  We should pop and save as many addresses as there are
                                //  up to a null part, but for now, just save one...
                                _replyTo = msg.Unwrap();

                                //  .split process message
                                //  Here is where we actually have a message to process; we
                                //  return it to the caller application:
                                return(msg.Duplicate());
                            }
                            else if (command.StrHexEq(MdpCommon.MdpwCmd.HEARTBEAT))
                            {
                                // Do nothing for heartbeats
                            }
                            else if (command.StrHexEq(MdpCommon.MdpwCmd.DISCONNECT))
                            {
                                ConnectToBroker();
                            }
                            else
                            {
                                "E: invalid input message: '{0}'".DumpString(command.ToString());
                            }
                        }
                    }
                }
                else if (Equals(error, ZError.ETERM))
                {
                    cancellor.Cancel();
                    break; // Interrupted
                }
                else if (Equals(error, ZError.EAGAIN) &&
                         --Liveness == 0)
                {
                    if (Verbose)
                    {
                        "W: disconnected from broker - retrying...".DumpString();
                    }
                    Thread.Sleep(Reconnect);
                    ConnectToBroker();
                }

                // Send HEARTBEAT if it's time
                if (DateTime.UtcNow > HeartbeatAt)
                {
                    SendToBroker(MdpCommon.MdpwCmd.HEARTBEAT.ToHexString(), null, null);
                    HeartbeatAt = DateTime.UtcNow + Heartbeat;
                }
            }
            if (cancellor.IsCancellationRequested)
            {
                "W: interrupt received, killing worker...\n".DumpString();
            }

            return(null);
        }
Beispiel #2
0
            //  .split broker worker_msg method
            //  This method processes one READY, REPLY, HEARTBEAT, or
            //  DISCONNECT message sent to the broker by a worker:
            public void WorkerMsg(ZFrame sender, ZMessage msg)
            {
                if (msg.Count < 1) // At least, command
                {
                    throw new InvalidOperationException();
                }

                ZFrame command = msg.Pop();
                //string id_string = sender.ReadString();
                bool isWorkerReady;

                //string id_string;
                using (var sfrm = sender.Duplicate())
                {
                    var idString = sfrm.Read().ToHexString();
                    isWorkerReady = Workers.ContainsKey(idString);
                }
                Worker worker = RequireWorker(sender);

                using (msg)
                    using (command)
                    {
                        if (command.StrHexEq(MdpCommon.MdpwCmd.READY))
                        {
                            if (isWorkerReady)
                            {
                                // Not first command in session
                                worker.Delete(true);
                            }
                            else if (command.Length >= 4 &&
                                     command.ToString().StartsWith("mmi."))
                            {
                                // Reserd servicee name
                                worker.Delete(true);
                            }
                            else
                            {
                                // Attach worker to service and mark as idle
                                using (ZFrame serviceFrame = msg.Pop())
                                {
                                    worker.Service = RequireService(serviceFrame);
                                    worker.Service.Workers++;
                                    worker.Waiting();
                                }
                            }
                        }
                        else if (command.StrHexEq(MdpCommon.MdpwCmd.REPLY))
                        {
                            if (isWorkerReady)
                            {
                                //  Remove and save client return envelope and insert the
                                //  protocol header and service name, then rewrap envelope.
                                ZFrame client = msg.Unwrap();
                                msg.Prepend(new ZFrame(worker.Service.Name));
                                msg.Prepend(new ZFrame(MdpCommon.MDPC_CLIENT));
                                msg.Wrap(client);
                                Socket.Send(msg);
                                worker.Waiting();
                            }
                            else
                            {
                                worker.Delete(true);
                            }
                        }
                        else if (command.StrHexEq(MdpCommon.MdpwCmd.HEARTBEAT))
                        {
                            if (isWorkerReady)
                            {
                                worker.Expiry = DateTime.UtcNow + MdpCommon.HEARTBEAT_EXPIRY;
                            }
                            else
                            {
                                worker.Delete(true);
                            }
                        }
                        else if (command.StrHexEq(MdpCommon.MdpwCmd.DISCONNECT))
                        {
                            worker.Delete(false);
                        }
                        else
                        {
                            msg.DumpZmsg("E: invalid input message");
                        }
                    }
            }