예제 #1
0
        public void Fail(NodeHandle node)
        {
            if (node.NodeID == null) {
                Fail (node.EndPoint);
                return;
            }
            List<NodeHandle> list = LookupNodeList (node.NodeID);
            if (list == null)
                return;

            lock (_routingTable) {
                for (int i = 0; i < list.Count; i++) {
                    if (list[i].NodeID.Equals (node.NodeID)) {
                        _flatList.Remove (list[i]);
                        list.RemoveAt (i);
                        return;
                    }
                }
            }
        }
예제 #2
0
        public NodeHandle[] GetCloseNodes(Key target, int maxNum, Key exclude)
        {
            List<NodeHandle> nodes;
            lock (_routingTable) {
                nodes = new List<NodeHandle> (_flatList.ToArray ());
            }
            if (exclude != null) {
                for (int i = 0; i < nodes.Count; i ++) {
                    if (exclude.Equals (nodes[i].NodeID)) {
                        nodes.RemoveAt (i);
                        break;
                    }
                }
            }
            nodes.Sort (delegate (NodeHandle x, NodeHandle y) {
                Key diffX = target ^ x.NodeID;
                Key diffY = target ^ y.NodeID;
                return diffX.CompareTo (diffY);
            });

            NodeHandle[] results = new NodeHandle[Math.Min (nodes.Count, maxNum)];
            nodes.CopyTo (0, results, 0, results.Length);
            return results;
        }
예제 #3
0
        public void Touch(NodeHandle node)
        {
            if (node.NodeID == null)
                return;
            List<NodeHandle> list = LookupNodeList (node.NodeID);
            if (list == null)
                return;

            lock (_routingTable) {
                if (list.Count >= BucketSize)
                    return;
                for (int i = 0; i < list.Count; i ++) {
                    if (list[i].NodeID.Equals (node.NodeID))
                        return;
                }
                //Logger.Log (LogLevel.Trace, this, "{0}: add routing-table entry to {1}", _selfNodeId, node.NodeID);
                list.Add (node);
                _flatList.Add (node);
                _epMapping[node.EndPoint] = node;
            }
        }
예제 #4
0
 public HopSlotEntry(NodeHandle node, int hop)
 {
     _node = node;
     _start = DateTime.Now;
     _hop = hop;
     if (node.EndPoint == null) {
         // self
         _isInquiryStarted = true;
         _fail = false;
         _hop = 0;
         _time = TimeSpan.Zero;
     }
 }
예제 #5
0
 public void Responsed(Key key, ushort tcpPort, Dictionary<Key, HopSlotEntry> map)
 {
     _time = DateTime.Now.Subtract (_start);
     if (_node.NodeID == null) {
         _node = new NodeHandle (key, _node.EndPoint, tcpPort);
         map.Add (key, this);
     }
 }
예제 #6
0
 void Success(NodeHandle[] resultNodes, int hops)
 {
     Done (new RoutingResult (resultNodes, hops));
     _router.InvokeStatisticsNotice (StatisticsNoticeEventArgs.CreateSuccess ());
     _router.InvokeStatisticsNotice (StatisticsNoticeEventArgs.CreateRTT (DateTime.Now.Subtract (_startTime)));
     _router.InvokeStatisticsNotice (StatisticsNoticeEventArgs.CreateHops (hops));
 }
예제 #7
0
                public void AddEntry(NodeHandle node, int hop, Dictionary<Key, HopSlotEntry> map)
                {
                    if (node.NodeID != null && map.ContainsKey (node.NodeID))
                        return;

                    HopSlotEntry entry = new HopSlotEntry (node, hop);
                    _minHop = Math.Min (_minHop, hop);
                    _entries.Add (entry);
                    if (node.NodeID != null)
                        map.Add (node.NodeID, entry);
                }
예제 #8
0
            void FillSlot(HopSlotEntry sender, NodeHandle[] nextHops, bool isRootCandidates, int current_inquiring)
            {
                int nextHopIndex = (sender == null ? 1 : sender.Hop + 1);

                if (isRootCandidates) {
                    if (_strictLookup) {
                        FillRootCandidateSlot (sender, true, nextHops, current_inquiring);
                        return;
                    } else {
                        lock (_rootCandidates) {
                            _rootCandidates.Add (sender);
                        }
                        NodeHandle[] result;
                        if (sender != null) {
                            result = new NodeHandle[nextHops == null ? 1 : nextHops.Length + 1];
                            result[0] = sender.NodeHandle;
                            for (int i = 0; i < nextHops.Length; i ++)
                                result[i + 1] = nextHops[i];
                        } else {
                            result = nextHops;
                        }
                        Success (result, nextHopIndex - 1);
                        return;
                    }
                }
                if (_rootCandidates.Count > 0) {
                    if (_strictLookup) {
                        // 厳密なルックアップの場合、すでにルート候補が選出されているので
                        // ルート候補となったノードと同じスロットに入っているノードへの問い合わせのみを行う #1
                    } else {
                        // ルート候補の選出は終了している
                        return;
                    }
                }

                if (_timeout < DateTime.Now) {
                    Fail (FailReason.Timeout, nextHopIndex - 1);
                    return;
                }

                // Fill slots
                if (nextHops != null) {
                    for (int i = 0; i < nextHops.Length; i++) {
                        int level = (nextHops[i].NodeID == null ? 0 : _router.RoutingAlgorithm.ComputeRoutingLevel (_dest, nextHops[i].NodeID));
                        if (_slots[level] == null)
                            _slots[level] = new HopSlot (_numOfSimultaneous);
                        _slots[level].AddEntry (nextHops[i], nextHopIndex, _keyMap);
                    }
                }

                // Start NextHop Inquire
                int free_inq = Math.Max (0, _numOfSimultaneous - current_inquiring);
                int inquiried = 0, inquiry_failed = 0;
                for (int i = _slots.Length - 1; free_inq > 0 && i >= 0; i--) {
                    if (_slots[i] == null) continue;
                    for (int q = 0; free_inq > 0 && q < _slots[i].Count; q++) {
                        if (_slots[i][q].IsInquiryStarted) {
                            inquiried ++;
                            if (_slots[i][q].IsFailed)
                                inquiry_failed ++;
                            continue;
                        }
                        _slots[i][q].StartInquiry ();
                        _router.MessagingSocket.BeginInquire (_query1, _slots[i][q].NodeHandle.EndPoint, NextHopQuery_Callback, _slots[i][q]);
                        current_inquiring = Interlocked.Increment (ref _inquiring);
                        free_inq--;
                    }

                    // 問い合わせ中のものがあれば、同時問い合わせ数未満だったとしても
                    // 最長一致スロットのみをチェックして、ループから抜ける
                    if (inquiried != inquiry_failed)
                        break;
                    inquiried = int.MinValue;
                }

                if (current_inquiring == 0) {
                    // 問い合わせ中のものがない場合、
                    // 厳密なルックアップを行っていて、かつルート候補リストが1つ以上埋まっていれば
                    // ルート候補選定に入り、そうでない場合は失敗とする
                    if (_strictLookup && _rootCandidates.Count > 0) {
                        FillRootCandidateSlot (sender, false, null, current_inquiring);
                    } else {
                        Fail (FailReason.NoRoot, nextHopIndex - 1);
                    }
                }
            }
예제 #9
0
            void FillRootCandidateSlot(HopSlotEntry sender, bool senderIsRoot, NodeHandle[] closeNodes, int current_inquiring)
            {
                NodeHandle[] resultNodes = null;
                int resultHops = 0;

                if (_rootCandidates.Count == 0 && _dest.Equals (_router.SelftNodeId)) {
                    // 自分自身が宛先と同じなので候補に追加する
                    _rootCandidates.Add (new HopSlotEntry (new NodeHandle (_router.SelftNodeId, null, _router.SelfTcpPort), 0));
                }
                if (senderIsRoot && sender != null) {
                    // senderがルート候補なので追加する
                    if (!_rootCandidates.Exists (delegate (HopSlotEntry entry) {
                        return Key.Equals (sender.NodeHandle.NodeID, entry.NodeHandle.NodeID);
                    })) {
                        _rootCandidates.Add (sender);
                    }
                    if (closeNodes == null)
                        closeNodes = new NodeHandle[0]; // ソートのためにダミーの空配列を代入
                }
                if (closeNodes != null) {
                    // closeNodesを候補一覧に追加し、ソート
                    int nextHopIndex = (sender == null ? 1 : sender.Hop + 1);
                    for (int i = 0; i < closeNodes.Length; i ++) {
                        if (_rootCandidates.Exists (delegate (HopSlotEntry entry) {
                            return Key.Equals (closeNodes[i].NodeID, entry.NodeHandle.NodeID);
                        })) continue;
                        HopSlotEntry hopSlotEntry;
                        if (!_keyMap.TryGetValue (closeNodes[i].NodeID, out hopSlotEntry))
                            hopSlotEntry = new HopSlotEntry (closeNodes[i], nextHopIndex);
                        _rootCandidates.Add (hopSlotEntry);
                    }
                    _rootCandidates.Sort (delegate (HopSlotEntry x, HopSlotEntry y) {
                        Key diffX = _router.RoutingAlgorithm.ComputeDistance (_dest, x.NodeHandle.NodeID);
                        Key diffY = _router.RoutingAlgorithm.ComputeDistance (_dest, y.NodeHandle.NodeID);
                        return diffX.CompareTo (diffY);
                    });
                }

                // ルート候補が確定しているか確認
                int decided_candidates = 0;
                for (int i = 0; i < _rootCandidates.Count; i ++) {
                    if (_rootCandidates[i].IsFailed) continue;
                    if (_rootCandidates[i].IsResponsed) {
                        decided_candidates ++;
                        if (decided_candidates == _numOfCandidates)
                            break;
                    } else {
                        break;
                    }
                }
                if (decided_candidates >= _numOfCandidates) {
                    // 問い合わせ完了!
                    resultNodes = new NodeHandle[decided_candidates];
                    for (int i = 0, q = 0; i < _rootCandidates.Count; i ++) {
                        if (_rootCandidates[i].IsResponsed) {
                            resultNodes[q ++] = _rootCandidates[i].NodeHandle;
                            resultHops = Math.Max (resultHops, _rootCandidates[i].Hop);
                            if (q == decided_candidates)
                                break;
                        }
                    }
                    Success (resultNodes, resultHops);
                    return;
                }

                if (_timeout <= DateTime.Now) {
                    Fail (FailReason.Timeout, sender == null ? 0 : sender.Hop);
                    return;
                }

                // Start CloseNode Inquire
                int free_inq = Math.Max (0, _numOfSimultaneous - current_inquiring);
                for (int i = 0; i < _rootCandidates.Count && free_inq > 0; i ++, free_inq --) {
                    if (_rootCandidates[i].IsInquiryStarted) continue;
                    _rootCandidates[i].StartInquiry ();
                    _router.MessagingSocket.BeginInquire (_query2, _rootCandidates[i].NodeHandle.EndPoint, CloseNodeQuery_Callback, _rootCandidates[i]);
                    current_inquiring = Interlocked.Increment (ref _inquiring);
                }

                if (current_inquiring == 0) {
                    // 指定された数だけルート候補がそろわなかったが、
                    // Failよりはましなので、Successとする
                    List<NodeHandle> temp = new List<NodeHandle> ();
                    for (int i = 0; i < _rootCandidates.Count; i++) {
                        if (_rootCandidates[i].IsResponsed) {
                            temp.Add (_rootCandidates[i].NodeHandle);
                            resultHops = Math.Max (resultHops, _rootCandidates[i].Hop);
                            if (temp.Count == _numOfCandidates)
                                break;
                        }
                    }
                    Success (temp.ToArray (), resultHops);
                    return;
                }
            }
예제 #10
0
 public void Start(EndPoint[] firstHops)
 {
     NodeHandle[] nodes;
     bool isRoot = false;
     if (firstHops == null || firstHops.Length == 0) {
         if (_router.SelftNodeId.Equals (_dest)) {
             nodes = _router.RoutingAlgorithm.GetRandomNodes (_numOfSimultaneous);
             if (nodes == null || nodes.Length == 0)
                 isRoot = true;
         } else {
             nodes = _router.RoutingAlgorithm.GetNextHopNodes (_dest, _numOfSimultaneous, null);
             if (nodes == null || nodes.Length == 0) {
                 isRoot = true;
                 List<NodeHandle> list = new List<NodeHandle> (_numOfCandidates + 1);
                 list.Add (new NodeHandle (_router.SelftNodeId, null, _router.SelfTcpPort));
                 list.AddRange (_router.RoutingAlgorithm.GetCloseNodes (_dest, _numOfCandidates, null));
                 nodes = list.ToArray ();
             }
         }
     } else {
         nodes = new NodeHandle [firstHops.Length];
         for (int i = 0; i < firstHops.Length; i ++)
             nodes[i] = new NodeHandle (null, firstHops[i], 0);
     }
     lock (_fillLock) {
         FillSlot (null, nodes, isRoot, 0);
     }
 }
예제 #11
0
 public NextHopResponse(Key sender, ushort senderTcpPort, bool isRootCandidate, NodeHandle[] nextHops)
 {
     _sender = sender;
     _tcpPort = senderTcpPort;
     _isRootCandidate = isRootCandidate;
     _nextHops = nextHops;
 }
예제 #12
0
 public CloseNodeResponse(Key sender, ushort senderTcpPort, NodeHandle[] closeNodes)
 {
     _sender = sender;
     _tcpPort = senderTcpPort;
     _closeNodes = closeNodes;
 }