示例#1
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);
                    }
                }
            }
示例#2
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);
                }
示例#3
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;
                }
            }