Beispiel #1
0
 /// <summary>
 /// Based on zmsg_dump
 /// https://github.com/imatix/zguide/blob/f94e8995a5e02d843434ace904a7afc48e266b3f/articles/src/multithreading/zmsg.c
 /// </summary>
 /// <param name="zmsg"></param>
 /// <param name="format"></param>
 /// <param name="args"></param>
 public static void DumpZmsg(this ZMessage zmsg, string format = null, params object[] args)
 {
     if (!string.IsNullOrWhiteSpace(format))
     {
         format.DumpString(args);
     }
     using (var dmsg = zmsg.Duplicate())
         foreach (var zfrm in dmsg)
         {
             zfrm.DumpZfrm();
         }
 }
Beispiel #2
0
			public void SendToBroker(string command, string option, ZMessage msg)
			{
				using (msg = msg != null ? msg.Duplicate() : new ZMessage())
				{
					if (!string.IsNullOrEmpty(option))
						msg.Prepend(new ZFrame(option));
					msg.Prepend(new ZFrame(command));
					msg.Prepend(new ZFrame(MdpCommon.MDPW_WORKER));
					msg.Prepend(new ZFrame(string.Empty));

					if (Verbose)
						msg.DumpZmsg("I: sending '{0:X}|{0}' to broker", command.ToMdCmd());

					Worker.Send(msg);
				}
			}
Beispiel #3
0
        public void SendToBroker(string command, string option, ZMessage msg)
        {
            using (msg = msg != null ? msg.Duplicate() : new ZMessage())
            {
                if (!string.IsNullOrEmpty(option))
                {
                    msg.Prepend(new ZFrame(option));
                }
                msg.Prepend(new ZFrame(command));
                msg.Prepend(new ZFrame(MdpCommon.MDPW_WORKER));
                msg.Prepend(new ZFrame(string.Empty));

                if (Verbose)
                {
                    msg.DumpZmsg("I: sending '{0:X}|{0}' to broker", command.ToMdCmd());
                }

                Worker.Send(msg);
            }
        }
Beispiel #4
0
            public void ControlMessage(ZMessage msg)
            {
                // This method processes one message from our frontend class
                // (it's going to be CONNECT or REQUEST):

                string command;

                using (var commandFrame = msg.Pop())
                {
                    command = commandFrame.ReadString();
                }

                if (command == "CONNECT")
                {
                    string endpoint = msg[0].ReadString();
                    Console.WriteLine("I: connecting to {0}...", endpoint);

                    Router.Connect(endpoint);

                    var server = new Server(endpoint);
                    this.Servers.Add(server);
                    this.Actives.Add(server);
                }
                else if (command == "REQUEST")
                {
                    if (this.Request != null)
                    {
                        // Strict request-reply cycle
                        throw new InvalidOperationException();
                    }

                    // Prefix request with sequence number and empty envelope
                    msg.Prepend(new ZFrame(++sequence));

                    // Take ownership of request message
                    this.Request = msg.Duplicate();

                    // Request expires after global timeout
                    this.Expires = DateTime.UtcNow + GLOBAL_TIMEOUT;
                }
            }
Beispiel #5
0
        /// <summary>
        /// Based on zmsg_dump
        /// https://github.com/imatix/zguide/blob/f94e8995a5e02d843434ace904a7afc48e266b3f/articles/src/multithreading/zmsg.c
        /// </summary>
        /// <param name="zmsg"></param>
        /// <param name="format"></param>
        /// <param name="args"></param>
        public static void DumpZmsg(this ZMessage zmsg, string format, params object[] args)
        {
            format.DumpString(args);
            using (var dmsg = zmsg.Duplicate())
                foreach (var zfrm in dmsg)
                {
                    byte[] data = zfrm.Read();
                    long   size = zfrm.Length;

                    // Dump the message as text or binary
                    bool isText = true;
                    for (int i = 0; i < size; i++)
                    {
                        if (data[i] < 32 || data[i] > 127)
                        {
                            isText = false;
                        }
                    }
                    string datastr = isText ? Encoding.UTF8.GetString(data) : data.ToHexString();
                    "\tD: [{0,3:D3}]:{1}".DumpString(size, datastr);
                }
        }
Beispiel #6
0
        //  .split worker send method
        //  This method formats and sends a command to a worker. The caller may
        //  also provide a command option, and a message payload:
        public void Send(string command, string option, ZMessage msg)
        {
            msg = msg != null
                    ? msg.Duplicate()
                    : new ZMessage();

            // Stack protocol envelope to start of message
            if (!string.IsNullOrEmpty(option))
            {
                msg.Prepend(new ZFrame(option));
            }
            msg.Prepend(new ZFrame(command));
            msg.Prepend(new ZFrame(MdpCommon.MDPW_WORKER));

            // Stack routing envelope to start of message
            msg.Wrap(Identity.Duplicate());

            if (Broker.Verbose)
            {
                msg.DumpZmsg("I: sending '{0:X}|{0}' to worker", command.ToMdCmd());
            }

            Broker.Socket.Send(msg);
        }
Beispiel #7
0
            //  .split worker send method
            //  This method formats and sends a command to a worker. The caller may
            //  also provide a command option, and a message payload:
            public void Send(string command, string option, ZMessage msg)
            {
                msg = msg != null
                        ? msg.Duplicate()
                        : new ZMessage();

                // Stack protocol envelope to start of message
                if (!string.IsNullOrEmpty(option))
                    msg.Prepend(new ZFrame(option));
                msg.Prepend(new ZFrame(command));
                msg.Prepend(new ZFrame(MdpCommon.MDPW_WORKER));

                // Stack routing envelope to start of message
                msg.Wrap(Identity.Duplicate());

                if(Broker.Verbose)
                    msg.DumpZmsg("I: sending '{0:X}|{0}' to worker", command.ToMdCmd());

                Broker.Socket.Send(msg);
            }
Beispiel #8
0
            //  .split send request and wait for reply
            //  Here is the {{send}} method. It sends a request to the broker and gets
            //  a reply even if it has to retry several times. It takes ownership of
            //  the request message, and destroys it when sent. It returns the reply
            //  message, or NULL if there was no reply after multiple attempts:
            public ZMessage Send(string service, ZMessage request, CancellationTokenSource cancellor)
            {
                if (request == null)
                {
                    throw new InvalidOperationException();
                }

                //  Prefix request with protocol frames
                //  Frame 1: "MDPCxy" (six bytes, MDP/Client x.y)
                //  Frame 2: Service name (printable string)
                request.Prepend(new ZFrame(service));
                request.Prepend(new ZFrame(MdpCommon.MDPC_CLIENT));
                if (Verbose)
                {
                    request.DumpZmsg("I: send request to '{0}' service:", service);
                }

                int retriesLeft = Retries;

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

                    // Copy the Request and send on Client
                    ZMessage msgreq = request.Duplicate();

                    ZError error;
                    if (!Client.Send(msgreq, out error))
                    {
                        if (Equals(error, ZError.ETERM))
                        {
                            cancellor.Cancel();
                            break; // Interrupted
                        }
                    }

                    var      p = ZPollItem.CreateReceiver();
                    ZMessage msg;
                    //  .split body of send
                    //  On any blocking call, {{libzmq}} will return -1 if there was
                    //  an error; we could in theory check for different error codes,
                    //  but in practice it's OK to assume it was {{EINTR}} (Ctrl-C):

                    // Poll the client Message
                    if (Client.PollIn(p, out msg, out error, Timeout))
                    {
                        //  If we got a reply, process it
                        if (Verbose)
                        {
                            msg.DumpZmsg("I: received reply");
                        }

                        if (msg.Count < 3)
                        {
                            throw new InvalidOperationException();
                        }

                        using (ZFrame header = msg.Pop())
                            if (!header.ToString().Equals(MdpCommon.MDPC_CLIENT))
                            {
                                throw new InvalidOperationException();
                            }

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

                        request.Dispose();
                        return(msg);
                    }
                    else if (Equals(error, ZError.ETERM))
                    {
                        cancellor.Cancel();
                        break; // Interrupted
                    }
                    else if (Equals(error, ZError.EAGAIN))
                    {
                        if (--retriesLeft > 0)
                        {
                            if (Verbose)
                            {
                                "W: no reply, reconnecting...".DumpString();
                            }

                            ConnectToBroker();
                        }
                        else
                        {
                            if (Verbose)
                            {
                                "W: permanent error, abandoning".DumpString();
                            }
                            break; // Give up
                        }
                    }
                }
                if (cancellor.IsCancellationRequested)
                {
                    "W: interrupt received, killing client...\n".DumpString();
                }
                request.Dispose();
                return(null);
            }
Beispiel #9
0
            public ZMessage Request(ZMessage request)
            {
                // This method does the hard work. It sends a request to all
                // connected servers in parallel (for this to work, all connections
                // must be successful and completed by this time). It then waits
                // for a single successful reply, and returns that to the caller.
                // Any other replies are just dropped:

                ZMessage reply = null;

                using (request)
                {
                    // Prefix request with sequence number and empty envelope
                    this.sequence++;
                    request.Prepend(new ZFrame(this.sequence));
                    request.Prepend(new ZFrame());

                    // Blast the request to all connected servers
                    for (int server = 0; server < this.servers; ++server)
                    {
                        using (var outgoing = request.Duplicate())
                        {
                            this.socket.Send(outgoing);
                        }
                    }

                    // Wait for a matching reply to arrive from anywhere
                    // Since we can poll several times, calculate each one
                    ZError   error;
                    DateTime endtime = DateTime.UtcNow + GLOBAL_TIMEOUT;
                    var      poll    = ZPollItem.CreateReceiver();
                    while (endtime > DateTime.UtcNow)
                    {
                        if (this.socket.PollIn(poll, out reply, out error, endtime - DateTime.UtcNow))
                        {
                            // Reply is [empty][sequence][OK]
                            if (reply.Count < 3)
                            {
                                throw new InvalidOperationException();
                            }

                            reply.RemoveAt(0);

                            using (ZFrame sequenceFrame = reply.RemoveAt(0, false))
                            {
                                int sequence = sequenceFrame.ReadInt32();

                                if (sequence == this.sequence)
                                {
                                    break;                                      // Reply is ok
                                }
                            }

                            reply.Dispose();
                        }
                        else
                        {
                            if (error == ZError.ETERM)
                            {
                                break;                                  // Interrupted
                            }
                            if (error != ZError.EAGAIN)
                            {
                                throw new ZException(error);
                            }
                        }
                    }
                }
                return(reply);
            }
Beispiel #10
0
            //  .split send request and wait for reply
            //  Here is the {{send}} method. It sends a request to the broker and gets
            //  a reply even if it has to retry several times. It takes ownership of 
            //  the request message, and destroys it when sent. It returns the reply
            //  message, or NULL if there was no reply after multiple attempts:
            public ZMessage Send(string service, ZMessage request, CancellationTokenSource cancellor)
            {
                if (request == null)
                    throw new InvalidOperationException();

                //  Prefix request with protocol frames
                //  Frame 1: "MDPCxy" (six bytes, MDP/Client x.y)
                //  Frame 2: Service name (printable string)
                request.Prepend(new ZFrame(service));
                request.Prepend(new ZFrame(MdpCommon.MDPC_CLIENT));
                if (Verbose)
                    request.DumpZmsg("I: send request to '{0}' service:", service);

                int retriesLeft = Retries;
                while (retriesLeft > 0 && !cancellor.IsCancellationRequested)
                {
                    if (cancellor.IsCancellationRequested
                        || (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape))
                        _context.Shutdown();

                    // Copy the Request and send on Client
                    ZMessage msgreq = request.Duplicate();

                    ZError error;
                    if (!Client.Send(msgreq, out error))
                    {
                        if (Equals(error, ZError.ETERM))
                        {
                            cancellor.Cancel();
                            break; // Interrupted
                        }
                    }

                    var p = ZPollItem.CreateReceiver();
                    ZMessage msg;
                    //  .split body of send 
                    //  On any blocking call, {{libzmq}} will return -1 if there was
                    //  an error; we could in theory check for different error codes,
                    //  but in practice it's OK to assume it was {{EINTR}} (Ctrl-C):

                    // Poll the client Message
                    if (Client.PollIn(p, out msg, out error, Timeout))
                    {
                        //  If we got a reply, process it
                        if (Verbose)
                            msg.DumpZmsg("I: received reply");

                        if(msg.Count < 3)
                            throw new InvalidOperationException();

                        using (ZFrame header = msg.Pop())
                            if (!header.ToString().Equals(MdpCommon.MDPC_CLIENT))
                                throw new InvalidOperationException();

                        using (ZFrame replyService = msg.Pop())
                            if(!replyService.ToString().Equals(service))
                                throw new InvalidOperationException();

                        request.Dispose();
                        return msg;
                    }
                    else if (Equals(error, ZError.ETERM))
                    {
                        cancellor.Cancel();
                        break; // Interrupted
                    }
                    else if (Equals(error, ZError.EAGAIN))
                    {
                        if (--retriesLeft > 0)
                        {
                            if (Verbose)
                                "W: no reply, reconnecting...".DumpString();

                            ConnectToBroker();
                        }
                        else
                        {
                            if (Verbose)
                                "W: permanent error, abandoning".DumpString();
                            break; // Give up
                        }
                    }
                }
                if (cancellor.IsCancellationRequested)
                {
                    "W: interrupt received, killing client...\n".DumpString();
                }
                request.Dispose();
                return null;
            }
Beispiel #11
0
			public ZMessage Request(ZMessage request)
			{
				// This method does the hard work. It sends a request to all
				// connected servers in parallel (for this to work, all connections
				// must be successful and completed by this time). It then waits
				// for a single successful reply, and returns that to the caller.
				// Any other replies are just dropped:

				ZMessage reply = null;
				using (request)
				{
					// Prefix request with sequence number and empty envelope
					this.sequence++;
					request.Prepend(new ZFrame(this.sequence));
					request.Prepend(new ZFrame());

					// Blast the request to all connected servers
					for (int server = 0; server < this.servers; ++server)
					{
						using (var outgoing = request.Duplicate())
						{
							this.socket.Send(outgoing);
						}
					}

					// Wait for a matching reply to arrive from anywhere
					// Since we can poll several times, calculate each one
					ZError error;
					DateTime endtime = DateTime.UtcNow + GLOBAL_TIMEOUT;
					var poll = ZPollItem.CreateReceiver();
					while (endtime > DateTime.UtcNow)
					{
						if (this.socket.PollIn(poll, out reply, out error, endtime - DateTime.UtcNow))
						{
							// Reply is [empty][sequence][OK]
							if (reply.Count < 3)
							{
								throw new InvalidOperationException();
							}

							reply.RemoveAt(0);

							using (ZFrame sequenceFrame = reply.RemoveAt(0, false))
							{
								int sequence = sequenceFrame.ReadInt32();

								if (sequence == this.sequence)
								{
									break;	// Reply is ok
								}
							}

							reply.Dispose();
						}
						else
						{
							if (error == ZError.ETERM)
								break;	// Interrupted
							if (error != ZError.EAGAIN)
								throw new ZException(error);
						}
					}
				}
				return reply;
			}
Beispiel #12
0
			public void ControlMessage(ZMessage msg)
			{
				// This method processes one message from our frontend class
				// (it's going to be CONNECT or REQUEST):

				string command = msg.PopString();

				if (command == "CONNECT")
				{
					string endpoint = msg.PopString();
					Console.WriteLine("I: connecting to {0}...", endpoint);

					this.Router.Connect(endpoint);

					var server = new Server(endpoint);
					this.Servers.Add(server);
					this.Actives.Add(server);
				}
				else if (command == "REQUEST")
				{
					if (this.Request != null)
					{
						// Strict request-reply cycle
						throw new InvalidOperationException();
					}

					// Prefix request with sequence number and empty envelope
					msg.Prepend(new ZFrame(++sequence));

					// Take ownership of request message
					this.Request = msg.Duplicate();

					// Request expires after global timeout
					this.Expires = DateTime.UtcNow + GLOBAL_TIMEOUT;
				}
			}