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; } } } }
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; }
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; } }
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; } }
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); } }
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)); }
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 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); } } }
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; } }
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); } }
public NextHopResponse(Key sender, ushort senderTcpPort, bool isRootCandidate, NodeHandle[] nextHops) { _sender = sender; _tcpPort = senderTcpPort; _isRootCandidate = isRootCandidate; _nextHops = nextHops; }
public CloseNodeResponse(Key sender, ushort senderTcpPort, NodeHandle[] closeNodes) { _sender = sender; _tcpPort = senderTcpPort; _closeNodes = closeNodes; }