示例#1
0
        public NodeRecvModule()
        {
            var config = Node.config;

            //var adjNodes = new ArraySegment<string>(args, 2, args.Length - 2);

            Get("/{msg}", x =>
            {
                lock (Node.nodeLock)
                {
                    Message msg = new Message(x.msg);
                    List <Message> msgsToSend = new List <Message>();

                    // Print received message
                    Console.WriteLine(string.Format("... {0} {1} < {2} {3} {4} {5}", msg.time, Node.nodeId, msg.from, msg.to, (byte)msg.token, msg.payload));

                    // Terminate condition
                    if (Node.nodeId == "1" && msg.token == TokenType.Return)
                    {
                        Console.WriteLine(string.Format("... {0} {1} > {2} {3} {4} {5}", msg.time, "1", "1", "0", (byte)msg.token, msg.payload + 1));
                    }

                    // Mark incoming link as father if this is the first time we've received a token
                    if (msg.token != TokenType.Vis && !Node.hasHadToken && msg.from != Node.netNodeId)
                    {
                        Node.links[msg.from].marker = MarkerType.Father;
                    }

                    // Handle receiving forward token if we've already had one
                    if (msg.token == TokenType.Forward && Node.hasHadToken)
                    {
                        Node.links[msg.from].marker = MarkerType.Visited;
                    }

                    // Handle receiving visited token
                    bool skipSendVisit = false;
                    if (msg.token == TokenType.Vis && msg.from != Node.netNodeId)
                    {
                        Node.links[msg.from].marker = MarkerType.Visited;
                        // Regerate last token / message conditions if we sent a forward token to a visited node
                        if (msg.from == Node.lastNodeSentTokenTo)
                        {
                            msg = Node.savedMessage;
                            Node.hasHadToken = false;
                            skipSendVisit    = true;
                        }
                    }

                    // Handle receiving forward token
                    if ((msg.token == TokenType.Forward && !Node.hasHadToken) || msg.token == TokenType.Return)
                    {
                        bool foundUnvisited = false;
                        var nodeIds         = new List <string>(Node.links.Keys);
                        var fatherNodeId    = "";
                        foreach (string nodeId in nodeIds)
                        {
                            // Find father node
                            if (fatherNodeId == "" && Node.links[nodeId].marker == MarkerType.Father)
                            {
                                fatherNodeId = nodeId;
                            }

                            if (Node.links[nodeId].marker == MarkerType.Unvisited)
                            {
                                // Find first unvisited node
                                if (!foundUnvisited)
                                {
                                    // If we found one, then send a forward token and mark the link as a son
                                    foundUnvisited = true;
                                    msgsToSend.Add(new Message(msg.time, Node.nodeId, nodeId, TokenType.Forward, msg.payload));
                                    Node.links[nodeId].marker = MarkerType.Son;

                                    // Save the forward token / messge in case we need to regenerate it later
                                    Node.savedMessage        = msg;
                                    Node.lastNodeSentTokenTo = nodeId;
                                }
                                // Send vis token on all other unvisited nodes.
                                // Skip this if token is a return token
                                else if (msg.token != TokenType.Return && !skipSendVisit)
                                {
                                    msgsToSend.Add(new Message(msg.time, Node.nodeId, nodeId, TokenType.Vis, 0));
                                }
                            }

                            // Send visited token over all visited links to inform neighbors that they should mark this node visited
                            if (Node.links[nodeId].marker == MarkerType.Visited && msg.token != TokenType.Return && !skipSendVisit)
                            {
                                msgsToSend.Add(new Message(msg.time, Node.nodeId, nodeId, TokenType.Vis, 0));
                            }
                        }

                        // If we have no unvisited nodes, then send a return token on the father link
                        if (!foundUnvisited && fatherNodeId != "")
                        {
                            msgsToSend.Add(new Message(msg.time, Node.nodeId, fatherNodeId, TokenType.Return, msg.payload + 1));
                        }

                        // Print sent messages
                        foreach (Message msgToSend in msgsToSend)
                        {
                            Console.WriteLine(string.Format("... {0} {1} > {2} {3} {4} {5}", msg.time, Node.nodeId, msgToSend.from, msgToSend.to, (byte)msgToSend.token, msgToSend.payload));
                        }

                        // Record that we have seen the token already in case it gets returned to us
                        Node.hasHadToken = true;

                        // Send messages as bundle to net node
                        if (msgsToSend.Count > 0)
                        {
                            var msgBundle    = new MsgBundle(msgsToSend);
                            var bundleClient = new WebClient();
                            bundleClient.DownloadStringAsync(new Uri("http://localhost:" + Node.netNodePort + "/" + msgBundle.Serialize()));
                        }
                    }
                }

                return("");
            });
        }
示例#2
0
文件: Net.cs 项目: LEChaney/Cidon-DFS
        public NetRecvModule()
        {
            Get("/{msg}", x =>
            {
                var msgBundle = new MsgBundle(x.msg);

                // Add messages to queue along with their time-to-send
                foreach (var msg in msgBundle.msgList)
                {
                    // Print received messages
                    Console.WriteLine(string.Format("... {0} {1} < {2} {3} {4} {5}", Net.time, Net.nodeId, msg.from, msg.to, (byte)msg.token, msg.payload));

                    // Get message delay
                    var delayConfigKey = msg.from + "-" + msg.to;
                    uint delay;
                    if (Net.config.ContainsKey(delayConfigKey))
                    {
                        delay = UInt32.Parse(Net.config[delayConfigKey]);
                    }
                    else
                    {
                        delay = UInt32.Parse(Net.config["-"]);
                    }
                    var timeToSend = Net.time + delay;

                    // Add message to queue and sort
                    Net.msgSendQueue.Enqueue(Tuple.Create(msg, timeToSend));
                    Net.msgSendQueue = new Queue <Tuple <Message, uint> >(Net.msgSendQueue.OrderBy(elem => elem.Item2));
                }

                // Until we've sent a forward or return token, or the queue is empty
                bool shouldStopSending = false;
                var msgsToSend         = new List <Message>();
                while (Net.msgSendQueue.Count > 0 && !shouldStopSending)
                {
                    // Update current time from top of message queue
                    Net.time = Net.msgSendQueue.Peek().Item2;
                    // Pop all messages to be sent at this timepoint
                    while (Net.msgSendQueue.Count > 0 && Net.msgSendQueue.Peek().Item2 == Net.time)
                    {
                        var msgTimePair = Net.msgSendQueue.Dequeue();
                        var msgToSend   = msgTimePair.Item1;
                        msgToSend.time  = msgTimePair.Item2;
                        msgsToSend.Add(msgToSend);

                        // Check if we should stop sending messages and wait for new messages to arrive
                        if (msgToSend.token == TokenType.Forward || msgToSend.token == TokenType.Return)
                        {
                            // flush queue if we're returning the token back to the initiator (hard coded to id 1)
                            if (msgToSend.to == "1")
                            {
                                shouldStopSending = false;
                            }
                            else
                            {
                                shouldStopSending = true;
                                // Need to handle case where a node has sent a token to a node that should have been marked as visited by the sender.
                                // But due to network delays, the node is still marked as unvisited by the sending node.
                                // Search for matching visited token in the queue going in reverse direction to the main token.
                                foreach (var queuedMsgTimePair in Net.msgSendQueue)
                                {
                                    var queuedMsg = queuedMsgTimePair.Item1;
                                    if (queuedMsg.token == TokenType.Vis && queuedMsg.from == msgToSend.to && queuedMsg.to == msgToSend.from)
                                    {
                                        shouldStopSending = false;
                                    }
                                }
                            }
                        }


                        // Print sent messages
                        Console.WriteLine(string.Format("... {0} {1} > {2} {3} {4} {5}", Net.time, Net.nodeId, msgToSend.from, msgToSend.to, (byte)msgToSend.token, msgToSend.payload));

                        // Terminate condition
                        if (msgToSend.to == "1" && msgToSend.token == TokenType.Return)
                        {
                            Console.WriteLine(string.Format("... {0} {1} < {2} {3} {4} {5}", msgToSend.time, "0", "1", "0", (byte)msgToSend.token, msgToSend.payload + 1));
                        }
                    }
                }
                // Send after popping from queue to avoid ping back forward tokens potentially concurrently modifying the queue
                foreach (var msgToSend in msgsToSend)
                {
                    var sendPort   = Net.config[msgToSend.to];
                    var sendClient = new WebClient();
                    sendClient.DownloadStringAsync(new Uri("http://localhost:" + sendPort + "/" + msgToSend.Serialize()));
                }

                return("");
            });
        }