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); } } }
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); }
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; } }