Exemplo n.º 1
0
        public static void Main(string[] args)
        {
            using (var context = new Context(1))
            {
                //  Connect to task ventilator and weather server
                using (Socket receiver = context.Socket(SocketType.PULL), subscriber = context.Socket(SocketType.SUB))
                {
                    receiver.Connect("tcp://localhost:5557");
                    subscriber.Connect("tcp://localhost:5556");
                    subscriber.Subscribe("10001 ", Encoding.Unicode);

                    var items = new PollItem[2];
                    items[0] = receiver.CreatePollItem(IOMultiPlex.POLLIN);
                    items[0].PollInHandler += ReceiverPollInHandler;
                    items[1] = subscriber.CreatePollItem(IOMultiPlex.POLLIN);
                    items[1].PollInHandler += SubscriberPollInHandler;

                    //  Process messages from both sockets
                    while (true)
                    {
                        context.Poll(items, -1);
                    }
                }
            }
        }
Exemplo n.º 2
0
        static void Main(string[] args)
        {
            using (var context = new Context(1))
              using (var receiver = context.Socket(SocketType.PULL))
              {
            receiver.Connect("tcp://localhost:5557");

            using (var sender = context.Socket(SocketType.PUSH))
            {
              sender.Connect("tcp://localhost:5558");

              using (var controller = context.Socket(SocketType.SUB))
              {
            controller.Connect("tcp://localhost:5559");
            controller.Subscribe(string.Empty, Encoding.Unicode);

            bool run = true;
            PollItem[] items = new PollItem[2];
            items[0] = receiver.CreatePollItem(IOMultiPlex.POLLIN);
            items[0].PollInHandler += (socket, revents) => ReceiverPollInHandler(socket, sender);
            items[1] = controller.CreatePollItem(IOMultiPlex.POLLIN);
            items[1].PollInHandler += delegate { run = false; };

            //  Process tasks as long as the controller does not signal the end.
            while (run)
            {
              context.Poll(items);
            }
              }
            }
              }
        }
Exemplo n.º 3
0
 public void Broker()
 {
     //  Initialize poll set
     PollItem[] pollItems = new PollItem[2];
     pollItems[0] = frontend.CreatePollItem(IOMultiPlex.POLLIN);
     pollItems[0].PollInHandler += new PollHandler(FrontendPollInHandler);
     pollItems[1] = backend.CreatePollItem(IOMultiPlex.POLLIN);
     pollItems[1].PollInHandler += new PollHandler(BackendPollInHandler);
     //  Switch messages between sockets
     while (true) {
         context.Poll(pollItems, -1);
     }
 }
Exemplo n.º 4
0
        public void Run()
        {
            using (var context = new Context(1))
            {
                using (var pub = context.Socket(SocketType.PUB))
                using (var control = context.Socket(SocketType.SUB))
                {
                    pub.Bind("inproc://workers");

                    var step2 = new Thread(() => Worker(context));
                    step2.Start();
                    Thread.Sleep(100);

                    control.Connect("inproc://control");
                    control.Subscribe("", Encoding.Unicode);

                    var count = 0;
                    var message = string.Empty;
                    var controlItems = new PollItem[2];

                    controlItems[0] = control.CreatePollItem(IOMultiPlex.POLLIN);
                    controlItems[0].PollInHandler += (x, y) =>
                        {
                            message = x.Recv(Encoding.Unicode);
                            Console.WriteLine("A message: {0}", message);
                        };

                    controlItems[1] = pub.CreatePollItem(IOMultiPlex.POLLOUT);
                    controlItems[1].PollOutHandler += (z, y) =>
                        {
                            Console.WriteLine(string.Format("About to send {0}", count));
                            z.Send(count++.ToString(), Encoding.Unicode);
                        };

                    //Console.WriteLine("Recieved the {0} signal",control.Recv(Encoding.Unicode));

                    while (string.IsNullOrEmpty(message) || !message.Equals("Stop"))
                    {
                        context.Poll(controlItems, -1);
                        Thread.Sleep(500);
                    }
                }
            }
        }
Exemplo n.º 5
0
        public static void Main(string[] args)
        {
            using (var context = new Context(1))
            {
                using (Socket frontend = context.Socket(SocketType.ROUTER), backend = context.Socket(SocketType.DEALER))
                {
                    frontend.Bind("tcp://*:5559");
                    backend.Bind("tcp://*:5560");

                    var pollItems = new PollItem[2];
                    pollItems[0] = frontend.CreatePollItem(IOMultiPlex.POLLIN);
                    pollItems[0].PollInHandler += (socket, revents) => FrontendPollInHandler(socket, backend);
                    pollItems[1] = backend.CreatePollItem(IOMultiPlex.POLLIN);
                    pollItems[1].PollInHandler += (socket, revents) => BackendPollInHandler(socket, frontend);

                    while (true)
                    {
                        context.Poll(pollItems, -1);
                    }
                }
            }
        }
Exemplo n.º 6
0
        public void Worker(object things)
        {
            {
                var context = (Context)things;
                using (var control = context.Socket(SocketType.PUB))
                using (var sub = context.Socket(SocketType.SUB))
                {
                    Console.WriteLine("Worker started");
                    control.Bind("inproc://control");

                    sub.Subscribe("", Encoding.Unicode);
                    sub.Connect("inproc://workers");

                    var count = 0;

                    var items = new PollItem[1];

                    items[0] = sub.CreatePollItem(IOMultiPlex.POLLIN);
                    items[0].PollInHandler += (x, y) =>
                        {
                            Console.WriteLine("Received : {0}",x.Recv(Encoding.Unicode));
                            count++;
                        };

                    control.Send("Go", Encoding.Unicode);

                    while (count < 10)
                    {
                        context.Poll(items, -1);
                    }

                    control.Send("Stop", Encoding.Unicode);

                }
            }
        }
Exemplo n.º 7
0
 private void CommonInit(bool local)
 {
     _msg = Marshal.AllocHGlobal(ZMQ_MSG_T_SIZE);
     _localSocket = local;
     _pollItem = new PollItem(new ZMQPollItem(Ptr, 0, 0), this);
 }
Exemplo n.º 8
0
 /// <summary>
 /// Polls the supplied items for events, with infinite timeout.
 /// </summary>
 /// <param name="items">Items to Poll</param>
 /// <returns>Number of Poll items with events</returns>
 public int Poll(PollItem[] items)
 {
     return Poll(items, -1);
 }
Exemplo n.º 9
0
 /// <summary>
 /// Polls the supplied items for events.
 /// </summary>
 /// <param name="items">Items to Poll</param>
 /// <param name="timeout">Timeout(micro seconds)</param>
 /// <returns>Number of Poll items with events</returns>
 public int Poll(PollItem[] items, long timeout)
 {
     return Poller(items, timeout);
 }
Exemplo n.º 10
0
 /// <summary>
 /// Polls the supplied items for events, with infinite timeout.
 /// Static method
 /// </summary>
 /// <param name="items">Items to Poll</param>
 /// <returns>Number of Poll items with events</returns>
 public static int Poller(PollItem[] items)
 {
     return Poller(items, -1);
 }
Exemplo n.º 11
0
 /// <summary>
 /// Polls the supplied items for events. Static method.
 /// </summary>
 /// <param name="items">Items to Poll</param>
 /// <param name="timeout">Timeout(micro seconds)</param>
 /// <returns>Number of Poll items with events</returns>
 public static int Poller(PollItem[] items, long timeout)
 {
     var spentTimeout = new Stopwatch();
     int rc = -1;
     if (timeout >= 0) {
         spentTimeout.Start();
     }
     while (rc != 0) {
         var zitems = new ZMQPollItem[items.Length];
         int index = 0;
         foreach (PollItem item in items) {
             item.ZMQPollItem.ResetRevents();
             zitems[index] = item.ZMQPollItem;
             index++;
         }
         rc = C.zmq_poll(zitems, items.Length, timeout);
         if (rc > 0) {
             for (index = 0; index < items.Length; index++) {
                 items[index].ZMQPollItem = zitems[index];
                 items[index].FireEvents();
             }
             break;
         }
         if (rc < 0) {
             if (C.zmq_errno() == 4) {
                 if (spentTimeout.IsRunning) {
                     long elapsed = spentTimeout.ElapsedMilliseconds * 1000;
                     if (timeout < elapsed) {
                         break;
                     }
                     timeout -= elapsed;
                     continue;
                 }
                 continue;
             }
             throw new Exception();
         }
     }
     return rc;
 }
Exemplo n.º 12
0
            public void Run(object threadContext)
            {
                object[] thrContextObjects = (object[])threadContext;
                Context ctx = (Context)thrContextObjects[0];

                using (Socket ctl = ctx.Socket(SocketType.REP))
                {
                    // Bind the control reply socket:
                    ctl.SndBuf = 1048576 * 20;
                    if (host.tsp == Transport.TCP)
                    {
                        ctl.Bind(Transport.TCP, host.device, (host.port + 1));
                    }
                    else
                    {
                        ctl.Bind(Transport.TCP, "*", (host.port + 1));
                    }

                    // Wait for the sockets to bind:
                    Thread.Sleep(500);

                    // Create a poller on the control socket to handle client requests:
                    PollItem[] pollItems = new PollItem[1];
                    pollItems[0] = ctl.CreatePollItem(IOMultiPlex.POLLIN);
                    pollItems[0].PollInHandler += new PollHandler((Socket sock, IOMultiPlex mp) =>
                    {
                        Queue<byte[]> request = sock.RecvAll();

                        // Bad message?
                        if (request.Count == 0) return;

                        Guid clientIdentity = new Guid(request.Dequeue().Skip(1).ToArray());
                        ClientState client;
                        bool newClient = false;

                        lock (host.clientLock)
                        {
                            if (!host.clients.ContainsKey(clientIdentity))
                            {
                                client = new ClientState(clientIdentity);
                                host.clients.Add(clientIdentity, client);
                                newClient = true;
                            }
                            else
                            {
                                client = host.clients[clientIdentity];
                            }

                            // Update last message received time to now:
                            client.LastMessageTime = DateTimeOffset.UtcNow;
                        }

                        string cmd = Encoding.Unicode.GetString(request.Dequeue());

                        // Process the client command:
                        trace("{0}: Client sent '{1}'", clientIdentity.ToString(), cmd);
                        switch (cmd)
                        {
                            case "JOIN":
                                sock.SendMore("JOINED", Encoding.Unicode);

                                ReadOnlyCollection<FileInfo> files = host.tarball.Files;

                                sock.SendMore(BitConverter.GetBytes(host.numChunks));
                                sock.SendMore(BitConverter.GetBytes(host.chunkSize));
                                sock.SendMore(BitConverter.GetBytes(host.tarball.Files.Count));

                                foreach (var fi in files)
                                {
                                    string fiName = fi.FullName.Substring(host.basePath.Length);
                                    sock.SendMore(fiName, Encoding.Unicode);
                                    sock.SendMore(BitConverter.GetBytes(fi.Length));
                                    sock.SendMore(new byte[16]);
                                }

                                sock.Send("", Encoding.Unicode);
                                trace("{0}: Sent JOINED response", clientIdentity.ToString());
                                if (host.ClientJoined != null) host.ClientJoined(host, clientIdentity);
                                break;

                            case "NAKS":
                                // Receive the client's current NAK:
                                byte[] tmp = request.Dequeue();
                                if (tmp.Length != host.numBitArrayBytes)
                                {
                                    trace("{0}: Bad NAKs", clientIdentity.ToString());
                                    sock.Send("BADNAKS", Encoding.Unicode);
                                    break;
                                }
                                sock.Send("", Encoding.Unicode);

                                lock (host.clientLock)
                                {
                                    BitArray newNAKs = new BitArray(tmp);
                                    // Add to the running ACK count the number of chunks turned from NAK to ACK in this update:
                                    if (client.HasNAKs)
                                    {
                                        client.RunningACKCount += (
                                            from i in Enumerable.Range(0, host.numChunks)
                                            where (client.NAK[i] == true) && (newNAKs[i] == false)
                                            select i
                                        ).Count();
                                    }
                                    else
                                    {
                                        client.RunningACKCount += newNAKs.Cast<bool>().Take(host.numChunks).Count(b => !b);
                                    }
                                    // Update to the new NAK state:
                                    client.NAK = newNAKs;

                                    // Inform the server to update the program:
                                    host.haveNewNAKs = true;
                                }

                                trace("{0}: NAKs received", clientIdentity.ToString());
                                if (host.ChunksACKed != null) host.ChunksACKed(host);
                                break;

                            case "LEAVE":
                                sock.Send("LEFT", Encoding.Unicode);

                                lock (host.clientLock)
                                {
                                    // Remove the client's state record:
                                    host.clients.Remove(clientIdentity);
                                }

                                if (host.ClientLeft != null) host.ClientLeft(host, clientIdentity, ClientLeaveReason.Left);

                                trace("{0}: Client left", clientIdentity.ToString());
                                break;

                            case "ALIVE":
                                if (newClient)
                                {
                                    trace("{0}: WHOAREYOU", clientIdentity.ToString());
                                    byte[] sendIdentity = new byte[1] { (byte)'@' }.Concat(clientIdentity.ToByteArray()).ToArray();
                                    sock.Send("WHOAREYOU", Encoding.Unicode);
                                    break;
                                }

                                // Fantastic.
                                sock.Send("", Encoding.Unicode);
                                break;

                            default:
                                // Unknown command.
                                sock.Send("UNKNOWN", Encoding.Unicode);
                                trace("{0}: Unknown request", clientIdentity.ToString());
                                break;
                        }

                        request = null;
                    });

                    while (host.isRunning)
                    {
                        while (ctx.Poll(pollItems, 100000L) == 1)
                        {
                        }
                    }
                }
            }
Exemplo n.º 13
0
        private void DiskWriterThread(object threadContext)
        {
            try
            {
                Context ctx = (Context)threadContext;

                using (Socket
                    disk = new Socket(SocketType.PULL),
                    diskACK = new Socket(SocketType.PUSH)
                )
                {
                    if (diskHWM > 0) disk.RCVHWM = diskHWM;
                    //disk.RcvBuf = 1048576 * diskHWM * 4;
                    disk.Connect("inproc://disk");
                    diskACK.Connect("inproc://diskack");

                    // 'inproc://' connections are immediate. No need to sleep.
                    //Thread.Sleep(500);

                    bool done = false;

                    PollItem[] pollItems = new PollItem[1];
                    pollItems[0] = disk.CreatePollItem(IOMultiPlex.POLLIN);
                    pollItems[0].PollInHandler += new PollHandler((Socket sock, IOMultiPlex revents) =>
                    {
                        Queue<byte[]> packet = sock.RecvAll();

                        // Determine the action to take:
                        byte[] cmd = packet.Dequeue();

                        int chunkIdx;
                        byte[] chunkIdxPkt;
                        byte[] chunk;

                        switch (cmd[0])
                        {
                            // Write to disk
                            case (byte)'W':
                                chunkIdx = BitConverter.ToInt32(chunkIdxPkt = packet.Dequeue(), 0);
                                chunk = packet.Dequeue();
                                if (!testMode)
                                {
                                    lock (tarballLock)
                                    {
                                        tarball.Seek((long)chunkIdx * chunkSize, SeekOrigin.Begin);
                                        tarball.Write(chunk, 0, chunk.Length);
                                    }
                                }

                                // Notify the host that a chunk was written:
                                if (ChunkWritten != null) ChunkWritten(this, chunkIdx);

                                // Send the acknowledgement that this chunk was written to disk:
                                diskACK.Send(chunkIdxPkt);
                                break;

                            // Exit thread
                            case (byte)'X':
                                done = true;
                                break;

                            default:
                                break;
                        }
                    });

                    while (!done)
                    {
                        if (ctx.Poll(pollItems, 1000L) == 0)
                        {
                            Thread.Sleep(5);
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                Console.Error.WriteLine(ex.ToString());
            }
        }
Exemplo n.º 14
0
        /// <summary>
        /// Main thread to host the client process.
        /// </summary>
        /// <param name="threadContext">A ZMQ.Context instance.</param>
        public void Run(object threadContext)
        {
            try
            {
                Context ctx = (Context)threadContext;

                // This would be a using statement on data and ctl but we need to close and reopen sockets, which means
                // we have to Dispose() of a socket early and create a new instance. C#, wisely so, prevents you from
                // reassigning a using variable.
                Socket data = null, ctl = null, disk = null, diskACK = null;
                try
                {
                    data = ctx.Socket(SocketType.SUB);
                    ctl = ctx.Socket(SocketType.REQ);
                    disk = new Socket(SocketType.PUSH);
                    diskACK = new Socket(SocketType.PULL);

                    // Set the HWM for the disk PUSH so that the PUSH blocks if the PULL can't keep up writing:
                    if (diskHWM > 0) disk.SNDHWM = diskHWM;
                    //disk.SndBuf = 1048576 * diskHWM * 4;

                    // inproc:// binds are immediate.
                    disk.Bind("inproc://disk");
                    diskACK.Bind("inproc://diskack");

                    // Create the disk PULL thread:
                    Thread diskWriterThread = new Thread(new ParameterizedThreadStart(DiskWriterThread));
                    diskWriterThread.Start(ctx);

                    data.RCVHWM = networkHWM;

                    //data.RcvBuf = 1048576 * hwm * 4;
                    // NOTE: work-around for MS bug in WinXP's networking stack. See http://support.microsoft.com/kb/201213 for details.
                    data.RcvBuf = 0;

                    if (tsp == Transport.EPGM || tsp == Transport.PGM)
                    {
                        data.Rate = pgmRate;
                    }

                    string address = tsp.ToString().ToLower() + "://" + deviceData + ":" + portData;
                    Console.WriteLine("Connect(\"{0}\")", address);
                    data.Connect(address);
                    data.Subscribe(subscription, Encoding.Unicode);

                    // Connect to the control request socket:
                    ctl.RcvBuf = 1048576 * 4;
                    ctl.SndBuf = 1048576 * 4;
                    address = "tcp://" + deviceCtl + ":" + portCtl.ToString();
                    Console.WriteLine("Connect(\"{0}\")", address);
                    ctl.Connect(address);

                    Guid myIdentity = Guid.NewGuid();
                    ctl.Identity = new byte[1] { (byte)'@' }.Concat(myIdentity.ToByteArray()).ToArray();

                    Thread.Sleep(500);

                    // Begin client logic:

                    naks = null;
                    numBytes = 0;
                    int ackCount = -1;
                    byte[] nakBuf = null;

                    bool shuttingDown = false;

                    Stopwatch recvTimer = Stopwatch.StartNew();
                    long lastElapsedMilliseconds = recvTimer.ElapsedMilliseconds;
                    int msgsRecv = 0, msgsWritten = 0;

                    try
                    {
                        // Poll for incoming messages on the data SUB socket:
                        PollItem[] pollItems = new PollItem[3];
                        pollItems[0] = data.CreatePollItem(IOMultiPlex.POLLIN);
                        pollItems[1] = ctl.CreatePollItem(IOMultiPlex.POLLIN /* | IOMultiPlex.POLLOUT */);
                        pollItems[2] = diskACK.CreatePollItem(IOMultiPlex.POLLIN);

                        ZMQStateMasheen<DataSUBState> dataFSM;
                        ZMQStateMasheen<ControlREQState> controlFSM;
                        Queue<QueuedControlMessage> controlStateQueue = new Queue<QueuedControlMessage>();

                        DateTimeOffset lastSentNAKs = DateTimeOffset.UtcNow.Subtract(TimeSpan.FromSeconds(60));

                        // We create a state machine to handle our send/recv state:
                        dataFSM = new ZMQStateMasheen<DataSUBState>(
                            // Set the initial state:
                            DataSUBState.Recv,
                            // Initial state handler:
                            new ZMQStateMasheen<DataSUBState>.State(DataSUBState.Recv, (sock, revents) =>
                            {
                                Queue<byte[]> packet = sock.RecvAll();

                                if (packet.Count == 0) { trace("FAIL!"); return DataSUBState.Recv; }
                                string sub = Encoding.Unicode.GetString(packet.Dequeue());
                                if (packet.Count == 0) { trace("FAIL!"); return DataSUBState.Recv; }
                                string cmd = Encoding.Unicode.GetString(packet.Dequeue());

                                if ((naks != null) && (cmd == "DATA"))
                                {
                                    if (packet.Count == 0) { trace("FAIL!"); return DataSUBState.Recv; }
                                    int chunkIdx = BitConverter.ToInt32(packet.Dequeue(), 0);

                                    // Count the number of messages received from the network:
                                    ++msgsRecv;
                                    if (ChunkReceived != null) ChunkReceived(this, chunkIdx);

                                    // Already received this chunk?
                                    if (!naks[chunkIdx])
                                    {
                                        trace("ALREADY RECV {0}", chunkIdx);
                                        return DataSUBState.Recv;
                                    }

                                    trace("RECV {0}", chunkIdx);

                                    // Queue up the disk writes with PUSH/PULL and an HWM on a separate thread to maintain as
                                    // constant disk write throughput as we can get... The HWM will enforce the PUSHer to block
                                    // when the PULLer cannot receive yet.
                                    if (packet.Count == 0) return DataSUBState.Recv;
                                    byte[] chunk = packet.Dequeue();
                                    disk.SendMore(cmdWrite);
                                    disk.SendMore(BitConverter.GetBytes(chunkIdx));
                                    // This will block if the disk queue gets full:
                                    disk.Send(chunk);
                                    chunk = null;

                                    return DataSUBState.Recv;
                                }
                                else if (cmd == "PING")
                                {
                                    if (shuttingDown) return DataSUBState.Recv;

                                    controlStateQueue.Enqueue(new QueuedControlMessage(ControlREQState.SendALIVE, null));
                                    return DataSUBState.Recv;
                                }
                                else
                                {
                                    return DataSUBState.Recv;
                                }
                            })
                        );

                        // We create a state machine to handle our send/recv state:
                        object tmpControlState = null;
                        controlFSM = new ZMQStateMasheen<ControlREQState>(
                            ControlREQState.Nothing,
                            new ZMQStateMasheen<ControlREQState>.State(ControlREQState.Nothing, (sock, revents) =>
                            {
                                // Do nothing state.
                                return ControlREQState.Nothing;
                            }),
                            new ZMQStateMasheen<ControlREQState>.State(ControlREQState.SendALIVE, (sock, revents) =>
                            {
                                if (shuttingDown) return ControlREQState.Nothing;

                                ctl.SendMore(ctl.Identity);
                                ctl.Send("ALIVE", Encoding.Unicode);

                                return new ZMQStateMasheen<ControlREQState>.MoveOperation(ControlREQState.RecvALIVE, false);
                            }),
                            new ZMQStateMasheen<ControlREQState>.State(ControlREQState.RecvALIVE, (sock, revents) =>
                            {
                                Queue<byte[]> packet = ctl.RecvAll();

                                if (packet.Count == 0) return ControlREQState.Nothing;
                                string cmd = Encoding.Unicode.GetString(packet.Dequeue());
                                //trace("Server: '{0}'", cmd);

                                if (cmd == "") return ControlREQState.Nothing;
                                else if (cmd == "WHOAREYOU") return new ZMQStateMasheen<ControlREQState>.MoveOperation(ControlREQState.SendJOIN, true);

                                return ControlREQState.Nothing;
                            }),
                            new ZMQStateMasheen<ControlREQState>.State(ControlREQState.SendJOIN, (sock, revents) =>
                            {
                                if (shuttingDown) return ControlREQState.Nothing;

                                // Send a JOIN request:
                                ctl.SendMore(ctl.Identity);
                                ctl.Send("JOIN", Encoding.Unicode);

                                return ControlREQState.RecvJOIN;
                            }),
                            new ZMQStateMasheen<ControlREQState>.State(ControlREQState.RecvJOIN, (sock, revents) =>
                            {
                                Queue<byte[]> packet = ctl.RecvAll();
                                if (packet.Count == 0) return ControlREQState.Nothing;

                                string resp = Encoding.Unicode.GetString(packet.Dequeue());
                                if (resp != "JOINED")
                                {
                                    // TODO: handle this failure.
                                    trace("FAIL!"); return ControlREQState.Nothing;
                                }

                                // TODO: make this atomically succeed or fail without corrupting state
                                if (packet.Count == 0) { trace("FAIL!"); return ControlREQState.Nothing; }
                                numChunks = BitConverter.ToInt32(packet.Dequeue(), 0);
                                numBytes = ((numChunks + 7) & ~7) >> 3;
                                nakBuf = new byte[numBytes];
                                if (packet.Count == 0) { trace("FAIL!"); return ControlREQState.Nothing; }
                                chunkSize = BitConverter.ToInt32(packet.Dequeue(), 0);
                                if (packet.Count == 0) { trace("FAIL!"); return ControlREQState.Nothing; }
                                int numFiles = BitConverter.ToInt32(packet.Dequeue(), 0);

                                List<TarballEntry> tbes = new List<TarballEntry>(numFiles);
                                for (int i = 0; i < numFiles; ++i)
                                {
                                    if (packet.Count == 0) { trace("FAIL!"); return ControlREQState.Nothing; }
                                    string fiName = Encoding.Unicode.GetString(packet.Dequeue());
                                    if (packet.Count == 0) { trace("FAIL!"); return ControlREQState.Nothing; }
                                    long length = BitConverter.ToInt64(packet.Dequeue(), 0);
                                    if (packet.Count == 0) { trace("FAIL!"); return ControlREQState.Nothing; }
                                    byte[] hash = packet.Dequeue();

                                    TarballEntry tbe = new TarballEntry(fiName, length, hash);
                                    tbes.Add(tbe);
                                }

                                lock (tarballLock)
                                {
                                    if (tarball != null)
                                    {
                                        tarball.Close();
                                        tarball.Dispose();
                                        tarball = null;
                                    }
                                }

                                lock (tarballLock)
                                {
                                    // Create the tarball reader that writes the files locally:
                                    tarball = new TarballStreamReader(downloadDirectory, tbes);

                                    // Get our local download state:
                                    naks = getClientState(this, tarball);
                                }
                                ackCount = naks.Cast<bool>().Take(numChunks).Count(b => !b);

                                return new ZMQStateMasheen<ControlREQState>.MoveOperation(ControlREQState.SendNAKS, true);
                            }),
                            new ZMQStateMasheen<ControlREQState>.State(ControlREQState.SendNAKS, (sock, revents) =>
                            {
                                if (shuttingDown) return ControlREQState.Nothing;

                                if (nakBuf == null) return ControlREQState.Nothing;

                                // Send our NAKs:
                                ctl.SendMore(ctl.Identity);
                                ctl.SendMore("NAKS", Encoding.Unicode);
                                // TODO: RLE!
                                naks.CopyTo(nakBuf, 0);
                                trace("SEND NAK");
                                ctl.Send(nakBuf);

                                return ControlREQState.RecvNAKS;
                            }),
                            new ZMQStateMasheen<ControlREQState>.State(ControlREQState.RecvNAKS, (sock, revents) =>
                            {
                                Queue<byte[]> packet = ctl.RecvAll();
                                // Don't care what the response is for now.

                                return ControlREQState.Nothing;
                            })
                        );

                        // Disk-write acknowledgement poll input handler:
                        pollItems[2].PollInHandler += new PollHandler((Socket sock, IOMultiPlex revents) =>
                        {
                            byte[] idxPkt = sock.RecvAll().Dequeue();

                            int chunkIdx = BitConverter.ToInt32(idxPkt, 0);
                            naks[chunkIdx] = false;

                            // Count the number of messages written to disk:
                            ++msgsWritten;
                            ++ackCount;

                            // Profiled - terrible performance. Not a big surprise here.
                            //ackCount = naks.Cast<bool>().Take(numChunks).Count(b => !b);

                            // If we ran up the timer, send more ACKs:
                            if (DateTimeOffset.UtcNow.Subtract(lastSentNAKs).TotalMilliseconds >= 250d)
                            {
                                lastSentNAKs = DateTimeOffset.UtcNow;
                                controlStateQueue.Enqueue(new QueuedControlMessage(ControlREQState.SendNAKS, null));
                            }
                        });

                        pollItems[0].PollInHandler += new PollHandler(dataFSM.StateMasheen);
                        pollItems[1].PollInHandler += new PollHandler(controlFSM.StateMasheen);

                        DateTimeOffset lastRecv = DateTimeOffset.UtcNow;

                        // Start the control state machine with a JOIN:
                        controlStateQueue.Enqueue(new QueuedControlMessage(ControlREQState.SendJOIN, null));

                        // Create a socket poller for the data socket:
                        while (true)
                        {
                            // If we disposed of the previous control socket, create a new one:
                            if (ctl == null)
                            {
                                trace("Creating new CONTROL socket");
                                // Set up new socket:
                                ctl = ctx.Socket(SocketType.REQ);
                                // Connect to the control request socket:
                                ctl.Connect("tcp://" + deviceCtl + ":" + portCtl.ToString());
                                ctl.Identity = new byte[1] { (byte)'@' }.Concat(myIdentity.ToByteArray()).ToArray();
                            }

                            if (!shuttingDown && IsSendState(controlFSM.CurrentState))
                            {
                                // If we ran up the timer, send more NAKs:
                                if (DateTimeOffset.UtcNow.Subtract(lastSentNAKs).TotalMilliseconds >= 200d)
                                {
                                    lastSentNAKs = DateTimeOffset.UtcNow;
                                    controlStateQueue.Enqueue(new QueuedControlMessage(ControlREQState.SendNAKS, null));
                                }

                                if (controlStateQueue.Count > 0)
                                {
                                    var msg = controlStateQueue.Dequeue();

                                    // Roll up similar state requests:
                                    int dupes = 0;
                                    while (controlStateQueue.Count > 0)
                                    {
                                        if (controlStateQueue.Peek().NewState != msg.NewState) break;

                                        msg = controlStateQueue.Dequeue();
                                        ++dupes;
                                    }

                                    if (dupes > 0)
                                    {
                                        trace("Removed {0} redundant queued states", dupes);
                                    }

                                    tmpControlState = msg.Object;

                                    // Run the control state machine to SEND:
                                    controlFSM.CurrentState = msg.NewState;
                                    controlFSM.StateMasheen(ctl, IOMultiPlex.POLLOUT);
                                }
                            }

                            // Measure our message send rate per minute:
                            long elapsed = recvTimer.ElapsedMilliseconds - lastElapsedMilliseconds;
                            if (elapsed >= 100L)
                            {
                                NetworkRecvChunksPerMinute = (int)((msgsRecv * 60000L) / elapsed);
                                DiskWriteChunksPerMinute = (int)((msgsWritten * 60000L) / elapsed);
                                lastElapsedMilliseconds = recvTimer.ElapsedMilliseconds;
                                msgsRecv = 0;
                                msgsWritten = 0;
                            }

                            if (!recvTimer.IsRunning)
                            {
                                recvTimer.Reset();
                                recvTimer.Start();
                                lastElapsedMilliseconds = 0L;
                            }

                            if (ackCount >= numChunks)
                            {
                                disk.Send(cmdExit);
                                break;
                            }

                            if (ctx.Poll(pollItems, 100L) == 0)
                                Thread.Sleep(1);
                        }

                        // Wait for the disk writer to finish up:
                        shuttingDown = true;
                        diskWriterThread.Join();

                        // If we were last to await some response, receive it:
                        if (controlFSM.CurrentState == ControlREQState.RecvALIVE || controlFSM.CurrentState == ControlREQState.RecvJOIN || controlFSM.CurrentState == ControlREQState.RecvNAKS)
                        {
                            PollItem[] recvPoll = new PollItem[1];
                            recvPoll[0] = ctl.CreatePollItem(IOMultiPlex.POLLIN);
                            recvPoll[0].PollInHandler += new PollHandler(controlFSM.StateMasheen);

                            // Wait a bit to receive the response:
                            for (int i = 0; (i < 20) && ((ctx.Poll(recvPoll, 100) == 1) && (ctl != null)); ++i)
                            {
                            }
                        }

                        // Send the LEAVE message:
                        ctl.SendMore(ctl.Identity);
                        ctl.Send("LEAVE", Encoding.Unicode);
                        Completed = true;
                    }
                    finally
                    {
                        if (tarball != null) tarball.Dispose();
                    }
                }
                finally
                {
                    if (data != null) data.Dispose();
                    if (ctl != null) ctl.Dispose();
                }
            }
            catch (System.Exception ex)
            {
                Console.Error.WriteLine(ex.ToString());
            }
        }
Exemplo n.º 15
0
 private void CommonInit(bool local)
 {
     _msg         = Marshal.AllocHGlobal(ZMQ_MSG_T_SIZE);
     _localSocket = local;
     _pollItem    = new PollItem(new ZMQPollItem(_ptr, 0, 0), this);
 }
Exemplo n.º 16
0
        public static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                Console.WriteLine("Usage: peering2 <myself> <peer_1> … <peer_N>");
                return;
            }

            var myself = args[0];
            Console.WriteLine("Hello, I am " + myself);

            using (var context = new Context(1))
            {
                using (Socket cloudfe = context.Socket(SocketType.ROUTER), cloudbe = context.Socket(SocketType.ROUTER),
                    localfe = context.Socket(SocketType.ROUTER), localbe = context.Socket(SocketType.ROUTER))
                {
                    cloudFeAddress = "tcp://127.0.0.1:" + myself;
                    cloudfe.Identity = Encoding.Unicode.GetBytes(myself);
                    cloudfe.Bind(cloudFeAddress);

                    cloudbe.Identity = Encoding.Unicode.GetBytes(myself);
                    for (int arg = 1; arg < args.Length; arg++)
                    {
                        var endpoint = "tcp://127.0.0.1:" + args[arg];
                        peers.Add(endpoint);
                        Console.WriteLine("I: connecting to cloud frontend at " + endpoint);
                        cloudbe.Connect(endpoint);
                    }

                    localFeAddress = cloudFeAddress + "1";
                    localfe.Bind(localFeAddress);
                    localBeAddress = cloudFeAddress + "2";
                    localbe.Bind(localBeAddress);

                    Console.WriteLine("Press Enter when all brokers are started: ");
                    Console.ReadKey();

                    var workers = new List<Thread>();
                    for (int workerNumber = 0; workerNumber < numberOfWorkers; workerNumber++)
                    {
                        workers.Add(new Thread(WorkerTask));
                        workers[workerNumber].Start();
                    }

                    var clients = new List<Thread>();
                    for (int clientNumber = 0; clientNumber < numberOfClients; clientNumber++)
                    {
                        clients.Add(new Thread(ClientTask));
                        clients[clientNumber].Start();
                    }

                    var workerQueue = new Queue<byte[]>();

                    var localfeReady = false;
                    var cloudfeReady = false;

                    var backends = new PollItem[2];
                    backends[0] = localbe.CreatePollItem(IOMultiPlex.POLLIN);
                    backends[0].PollInHandler += (socket, revents) =>
                                                     {
                                                         var zmsg = new ZMessage(socket);

                                                         //  Use worker address for LRU routing
                                                         workerQueue.Enqueue(zmsg.Unwrap());

                                                         if (zmsg.BodyToString() != "READY")
                                                         {
                                                             SendReply(zmsg, cloudfe, localfe);
                                                         }
                                                     };

                    backends[1] = cloudbe.CreatePollItem(IOMultiPlex.POLLIN);
                    backends[1].PollInHandler += (socket, revents) =>
                    {
                        var zmsg = new ZMessage(socket);
                        //  We don't use peer broker address for anything
                        zmsg.Unwrap();

                        SendReply(zmsg, cloudfe, localfe);
                    };

                    var frontends = new PollItem[2];
                    frontends[0] = cloudfe.CreatePollItem(IOMultiPlex.POLLIN);
                    frontends[0].PollInHandler += (socket, revents) =>
                                                    {
                                                        cloudfeReady = true;
                                                    };

                    frontends[1] = localfe.CreatePollItem(IOMultiPlex.POLLIN);
                    frontends[1].PollInHandler += (socket, revents) =>
                                                     {
                                                         localfeReady = true;
                                                     };

                    while (true)
                    {
                        var timeout = (workerQueue.Count > 0 ? 1000000 : -1);
                        var rc = Context.Poller(backends, timeout);

                        if (rc == -1)
                            break; // Interrupted

                        while (workerQueue.Count > 0)
                        {
                            Context.Poller(frontends, 0);
                            bool reRoutable;

                            ZMessage msg;

                            if (cloudfeReady)
                            {
                                cloudfeReady = false;
                                msg = new ZMessage(cloudfe);
                                reRoutable = false;
                            }
                            else if (localfeReady)
                            {
                                localfeReady = false;
                                msg = new ZMessage(localfe);
                                reRoutable = true;
                            }
                            else
                            {
                                break;
                            }

                            //if (reRoutable && workerQueue.Count > 0 && randomizer.Next(3) == 0)
                            if (reRoutable && peers.Count > 0 && randomizer.Next(4) == 0)
                            {
                                var randomPeer = randomizer.Next(1, args.Length - 1);
                                var endpoint = "tcp://127.0.0.1:" + args[randomPeer];
                                msg.Wrap(Encoding.Unicode.GetBytes(endpoint), new byte[0]);
                                msg.Send(cloudbe);
                            }
                            else
                            {
                                msg.Wrap(workerQueue.Dequeue(), new byte[0]);
                                msg.Send(localbe);
                            }
                        }
                    }
                }
            }
        }