static void Main(string[] args) { if(args.Length < 1) return; string user = args[0]; string broadcast = ""; List<int> selectedVideos = new List<int>(); bool downloadReplayOnly = false; bool isReverseOrder = false; var p = new OptionSet { {"b|broadcast=", "the name of broadcast.", v => broadcast = v}, {"ds|downloadselected=", "only selected videos downloaded, seperate with comma (e.g. 1,2,7), start index is 0", v => selectedVideos = v.Split(',').Select(int.Parse).ToList()}, {"ro|replayonly", "download only replay videos", v => downloadReplayOnly = v != null}, {"r|reverse", "download reverse order", v => isReverseOrder = v != null} }; p.Parse(args); if(string.IsNullOrEmpty(user)) return; bool downloadSingle = !string.IsNullOrEmpty(broadcast); bool downloadSelectedVideos = selectedVideos.Any(); if(downloadSelectedVideos && downloadSingle) return; PDownload pDownload = new PDownload { User = user, Broadcast = broadcast, SelectedVideos = selectedVideos, DownloadLiveStream = !downloadReplayOnly, IsReverseOrder = isReverseOrder }; using (VideoDownloader videoDownloader = new VideoDownloader()) { if (downloadSingle) videoDownloader.DownloadVideos(pDownload); else videoDownloader.DownloadAllVideos(pDownload); } }
private void ConnectionsManagerThread() { Stopwatch connectionCheckStopwatch = new Stopwatch(); connectionCheckStopwatch.Start(); Stopwatch refreshStopwatch = new Stopwatch(); Stopwatch pushBlockDiffusionStopwatch = new Stopwatch(); pushBlockDiffusionStopwatch.Start(); Stopwatch pushBlockUploadStopwatch = new Stopwatch(); pushBlockUploadStopwatch.Start(); Stopwatch pushBlockDownloadStopwatch = new Stopwatch(); pushBlockDownloadStopwatch.Start(); Stopwatch pushMetadataUploadStopwatch = new Stopwatch(); pushMetadataUploadStopwatch.Start(); Stopwatch pushMetadataDownloadStopwatch = new Stopwatch(); pushMetadataDownloadStopwatch.Start(); for (; ; ) { Thread.Sleep(1000); if (this.State == ManagerState.Stop) return; var connectionCount = 0; lock (this.ThisLock) { connectionCount = _connectionManagers.Count; } if (connectionCount > ((this.ConnectionCountLimit / 3) * 1) && connectionCheckStopwatch.Elapsed.TotalMinutes >= 5) { connectionCheckStopwatch.Restart(); var nodeSortItems = new List<NodeSortItem>(); lock (this.ThisLock) { foreach (var connectionManager in _connectionManagers) { nodeSortItems.Add(new NodeSortItem() { Node = connectionManager.Node, Priority = _messagesManager[connectionManager.Node].Priority, LastPullTime = _messagesManager[connectionManager.Node].LastPullTime, }); } } nodeSortItems.Sort((x, y) => { int c = x.Priority.CompareTo(y.Priority); if (c != 0) return c; return x.LastPullTime.CompareTo(y.LastPullTime); }); foreach (var node in nodeSortItems.Select(n => n.Node).Take(1)) { ConnectionManager connectionManager = null; lock (this.ThisLock) { connectionManager = _connectionManagers.FirstOrDefault(n => n.Node == node); } if (connectionManager != null) { try { lock (this.ThisLock) { this.RemoveNode(connectionManager.Node); } connectionManager.PushCancel(); Debug.WriteLine("ConnectionManager: Push Cancel"); } catch (Exception) { } this.RemoveConnectionManager(connectionManager); } } } if (!refreshStopwatch.IsRunning || refreshStopwatch.Elapsed.TotalSeconds >= 30) { refreshStopwatch.Restart(); // トラストにより必要なMetadataを選択し、不要なMetadataを削除する。 ThreadPool.QueueUserWorkItem((object wstate) => { if (_refreshThreadRunning) return; _refreshThreadRunning = true; try { var lockSignatures = this.OnLockSignaturesEvent(); if (lockSignatures == null) return; var lockWikis = this.OnLockWikisEvent(); if (lockWikis == null) return; var lockChats = this.OnLockChatsEvent(); if (lockChats == null) return; // Broadcast { // Signature { var removeSignatures = new HashSet<string>(); removeSignatures.UnionWith(_settings.MetadataManager.GetBroadcastSignatures()); removeSignatures.ExceptWith(lockSignatures); var sortList = removeSignatures .OrderBy(n => { DateTime t; _broadcastSignatureLastAccessTimes.TryGetValue(n, out t); return t; }).ToList(); _settings.MetadataManager.RemoveBroadcastSignatures(sortList.Take(sortList.Count - 1024)); var liveSignatures = new HashSet<string>(_settings.MetadataManager.GetBroadcastSignatures()); foreach (var signature in _broadcastSignatureLastAccessTimes.Keys.ToArray()) { if (liveSignatures.Contains(signature)) continue; _broadcastSignatureLastAccessTimes.Remove(signature); } } } // Unicast { // Signature { var removeSignatures = new HashSet<string>(); removeSignatures.UnionWith(_settings.MetadataManager.GetUnicastSignatures()); removeSignatures.ExceptWith(lockSignatures); var sortList = removeSignatures .OrderBy(n => { DateTime t; _unicastSignatureLastAccessTimes.TryGetValue(n, out t); return t; }).ToList(); _settings.MetadataManager.RemoveUnicastSignatures(sortList.Take(sortList.Count - 1024)); var liveSignatures = new HashSet<string>(_settings.MetadataManager.GetUnicastSignatures()); foreach (var signature in _unicastSignatureLastAccessTimes.Keys.ToArray()) { if (liveSignatures.Contains(signature)) continue; _unicastSignatureLastAccessTimes.Remove(signature); } } } // Multicast { // Wiki { var removeWikis = new HashSet<Wiki>(); removeWikis.UnionWith(_settings.MetadataManager.GetMulticastWikis()); removeWikis.ExceptWith(lockWikis); var sortList = removeWikis .OrderBy(n => { DateTime t; _multicastWikiLastAccessTimes.TryGetValue(n, out t); return t; }).ToList(); _settings.MetadataManager.RemoveMulticastWikis(sortList.Take(sortList.Count - 1024)); var liveWikis = new HashSet<Wiki>(_settings.MetadataManager.GetMulticastWikis()); foreach (var tag in _multicastWikiLastAccessTimes.Keys.ToArray()) { if (liveWikis.Contains(tag)) continue; _multicastWikiLastAccessTimes.Remove(tag); } } // Chat { var removeChats = new HashSet<Chat>(); removeChats.UnionWith(_settings.MetadataManager.GetMulticastChats()); removeChats.ExceptWith(lockChats); var sortList = removeChats .OrderBy(n => { DateTime t; _multicastChatLastAccessTimes.TryGetValue(n, out t); return t; }).ToList(); _settings.MetadataManager.RemoveMulticastChats(sortList.Take(sortList.Count - 1024)); var liveChats = new HashSet<Chat>(_settings.MetadataManager.GetMulticastChats()); foreach (var tag in _multicastChatLastAccessTimes.Keys.ToArray()) { if (liveChats.Contains(tag)) continue; _multicastChatLastAccessTimes.Remove(tag); } } } // Unicast { var trustSignature = new HashSet<string>(lockSignatures); { var now = DateTime.UtcNow; var removeSignatureMessageMetadatas = new HashSet<SignatureMessageMetadata>(); foreach (var targetSignature in _settings.MetadataManager.GetUnicastSignatures()) { // SignatureMessage { var trustMetadatas = new Dictionary<string, List<SignatureMessageMetadata>>(); var untrustMetadatas = new Dictionary<string, List<SignatureMessageMetadata>>(); foreach (var metadata in _settings.MetadataManager.GetSignatureMessageMetadatas(targetSignature)) { var signature = metadata.Certificate.ToString(); if (trustSignature.Contains(signature)) { List<SignatureMessageMetadata> list; if (!trustMetadatas.TryGetValue(signature, out list)) { list = new List<SignatureMessageMetadata>(); trustMetadatas[signature] = list; } list.Add(metadata); } else { List<SignatureMessageMetadata> list; if (!untrustMetadatas.TryGetValue(signature, out list)) { list = new List<SignatureMessageMetadata>(); untrustMetadatas[signature] = list; } list.Add(metadata); } } removeSignatureMessageMetadatas.UnionWith(untrustMetadatas.Randomize().Skip(256).SelectMany(n => n.Value)); foreach (var list in CollectionUtilities.Unite(trustMetadatas.Values, untrustMetadatas.Values)) { if (list.Count <= 32) continue; list.Sort((x, y) => x.CreationTime.CompareTo(y.CreationTime)); removeSignatureMessageMetadatas.UnionWith(list.Take(list.Count - 32)); } } } foreach (var metadata in removeSignatureMessageMetadatas) { _settings.MetadataManager.RemoveMetadata(metadata); } } } // Multicast { var trustSignature = new HashSet<string>(lockSignatures); { var now = DateTime.UtcNow; var removeWikiDocumentMetadatas = new HashSet<WikiDocumentMetadata>(); foreach (var wiki in _settings.MetadataManager.GetMulticastWikis()) { // WikiDocument { var trustMetadatas = new Dictionary<string, List<WikiDocumentMetadata>>(); var untrustMetadatas = new Dictionary<string, List<WikiDocumentMetadata>>(); foreach (var metadata in _settings.MetadataManager.GetWikiDocumentMetadatas(wiki)) { var signature = metadata.Certificate.ToString(); if (trustSignature.Contains(signature)) { List<WikiDocumentMetadata> list; if (!trustMetadatas.TryGetValue(signature, out list)) { list = new List<WikiDocumentMetadata>(); trustMetadatas[signature] = list; } list.Add(metadata); } else { List<WikiDocumentMetadata> list; if (!untrustMetadatas.TryGetValue(signature, out list)) { list = new List<WikiDocumentMetadata>(); untrustMetadatas[signature] = list; } list.Add(metadata); } } removeWikiDocumentMetadatas.UnionWith(untrustMetadatas.Randomize().Skip(256).SelectMany(n => n.Value)); foreach (var list in CollectionUtilities.Unite(trustMetadatas.Values, untrustMetadatas.Values)) { if (list.Count <= 32) continue; list.Sort((x, y) => x.CreationTime.CompareTo(y.CreationTime)); removeWikiDocumentMetadatas.UnionWith(list.Take(list.Count - 32)); } } } foreach (var metadata in removeWikiDocumentMetadatas) { _settings.MetadataManager.RemoveMetadata(metadata); } } { var now = DateTime.UtcNow; var removeChatMessageMetadatas = new HashSet<ChatMessageMetadata>(); foreach (var chat in _settings.MetadataManager.GetMulticastChats()) { // ChatMessage { var trustMetadatas = new Dictionary<string, List<ChatMessageMetadata>>(); var untrustMetadatas = new Dictionary<string, List<ChatMessageMetadata>>(); foreach (var metadata in _settings.MetadataManager.GetChatMessageMetadatas(chat)) { var signature = metadata.Certificate.ToString(); if (trustSignature.Contains(signature)) { List<ChatMessageMetadata> list; if (!trustMetadatas.TryGetValue(signature, out list)) { list = new List<ChatMessageMetadata>(); trustMetadatas[signature] = list; } list.Add(metadata); } else { List<ChatMessageMetadata> list; if (!untrustMetadatas.TryGetValue(signature, out list)) { list = new List<ChatMessageMetadata>(); untrustMetadatas[signature] = list; } list.Add(metadata); } } removeChatMessageMetadatas.UnionWith(untrustMetadatas.Randomize().Skip(256).SelectMany(n => n.Value)); foreach (var list in CollectionUtilities.Unite(trustMetadatas.Values, untrustMetadatas.Values)) { if (list.Count <= 32) continue; list.Sort((x, y) => x.CreationTime.CompareTo(y.CreationTime)); removeChatMessageMetadatas.UnionWith(list.Take(list.Count - 32)); } } } foreach (var metadata in removeChatMessageMetadatas) { _settings.MetadataManager.RemoveMetadata(metadata); } } } } catch (Exception e) { Log.Error(e); } finally { _refreshThreadRunning = false; } }); } // 拡散アップロード if (connectionCount > _diffusionConnectionCountLowerLimit && pushBlockDiffusionStopwatch.Elapsed.TotalSeconds >= 60) { pushBlockDiffusionStopwatch.Restart(); // 拡散アップロードするブロック数を10000以下に抑える。 lock (this.ThisLock) { lock (_settings.DiffusionBlocksRequest.ThisLock) { if (_settings.DiffusionBlocksRequest.Count > 10000) { foreach (var key in _settings.DiffusionBlocksRequest.ToArray().Randomize() .Take(_settings.DiffusionBlocksRequest.Count - 10000).ToList()) { _settings.DiffusionBlocksRequest.Remove(key); } } } } // 存在しないブロックのKeyをRemoveする。 lock (this.ThisLock) { lock (_settings.DiffusionBlocksRequest.ThisLock) { foreach (var key in _cacheManager.ExceptFrom(_settings.DiffusionBlocksRequest.ToArray()).ToArray()) { _settings.DiffusionBlocksRequest.Remove(key); } } lock (_settings.UploadBlocksRequest.ThisLock) { foreach (var key in _cacheManager.ExceptFrom(_settings.UploadBlocksRequest.ToArray()).ToArray()) { _settings.UploadBlocksRequest.Remove(key); } } } var baseNode = this.BaseNode; var otherNodes = new List<Node>(); lock (this.ThisLock) { otherNodes.AddRange(_connectionManagers.Select(n => n.Node)); } var messageManagers = new Dictionary<Node, MessageManager>(); foreach (var node in otherNodes) { messageManagers[node] = _messagesManager[node]; } var diffusionBlocksList = new List<Key>(); { { var array = _settings.UploadBlocksRequest.ToArray(); _random.Shuffle(array); int count = 256; for (int i = 0; i < count && i < array.Length; i++) { diffusionBlocksList.Add(array[i]); } } { var array = _settings.DiffusionBlocksRequest.ToArray(); _random.Shuffle(array); int count = 256; for (int i = 0; i < count && i < array.Length; i++) { diffusionBlocksList.Add(array[i]); } } } _random.Shuffle(diffusionBlocksList); { var diffusionBlocksDictionary = new Dictionary<Node, HashSet<Key>>(); foreach (var key in diffusionBlocksList) { try { var requestNodes = new List<Node>(); // 自分より距離が遠いノードにもアップロードを試みる。 foreach (var node in Kademlia<Node>.Search(key.Hash, otherNodes, 3)) { requestNodes.Add(node); } if (requestNodes.Any(n => _messagesManager[n].StockBlocks.Contains(key))) { _settings.UploadBlocksRequest.Remove(key); _settings.DiffusionBlocksRequest.Remove(key); continue; } for (int i = 0; i < requestNodes.Count; i++) { HashSet<Key> collection; if (!diffusionBlocksDictionary.TryGetValue(requestNodes[i], out collection)) { collection = new HashSet<Key>(); diffusionBlocksDictionary[requestNodes[i]] = collection; } collection.Add(key); } } catch (Exception e) { Log.Error(e); } } lock (_diffusionBlocksDictionary.ThisLock) { _diffusionBlocksDictionary.Clear(); foreach (var pair in diffusionBlocksDictionary) { var node = pair.Key; var targets = pair.Value; _diffusionBlocksDictionary.Add(node, new Queue<Key>(targets.Randomize())); } } } } // アップロード if (connectionCount >= _uploadingConnectionCountLowerLimit && pushBlockUploadStopwatch.Elapsed.TotalSeconds >= 10) { pushBlockUploadStopwatch.Restart(); var baseNode = this.BaseNode; var otherNodes = new List<Node>(); lock (this.ThisLock) { otherNodes.AddRange(_connectionManagers.Select(n => n.Node)); } var messageManagers = new Dictionary<Node, MessageManager>(); foreach (var node in otherNodes) { messageManagers[node] = _messagesManager[node]; } { var uploadBlocksDictionary = new Dictionary<Node, List<Key>>(); foreach (var pair in messageManagers) { var node = pair.Key; var messageManager = pair.Value; uploadBlocksDictionary.Add(node, _cacheManager.IntersectFrom(messageManager.PullBlocksRequest.ToArray().Randomize()).Take(128).ToList()); } lock (_uploadBlocksDictionary.ThisLock) { _uploadBlocksDictionary.Clear(); foreach (var pair in uploadBlocksDictionary) { var node = pair.Key; var targets = pair.Value; _uploadBlocksDictionary.Add(node, new Queue<Key>(targets.Randomize())); } } } } // ダウンロード if (connectionCount >= _downloadingConnectionCountLowerLimit && pushBlockDownloadStopwatch.Elapsed.TotalSeconds >= 60) { pushBlockDownloadStopwatch.Restart(); var baseNode = this.BaseNode; var otherNodes = new List<Node>(); lock (this.ThisLock) { otherNodes.AddRange(_connectionManagers.Select(n => n.Node)); } var messageManagers = new Dictionary<Node, MessageManager>(); foreach (var node in otherNodes) { messageManagers[node] = _messagesManager[node]; } var pushBlocksLinkList = new List<Key>(); var pushBlocksRequestList = new List<Key>(); { { var array = _cacheManager.ToArray(); _random.Shuffle(array); int count = _maxBlockLinkCount; for (int i = 0; count > 0 && i < array.Length; i++) { if (!messageManagers.Values.Any(n => n.PushBlocksLink.Contains(array[i]))) { pushBlocksLinkList.Add(array[i]); count--; } } } foreach (var pair in messageManagers) { var node = pair.Key; var messageManager = pair.Value; { var array = messageManager.PullBlocksLink.ToArray(); _random.Shuffle(array); int count = (int)(_maxBlockLinkCount * ((double)12 / otherNodes.Count)); for (int i = 0; count > 0 && i < array.Length; i++) { if (!messageManagers.Values.Any(n => n.PushBlocksLink.Contains(array[i]))) { pushBlocksLinkList.Add(array[i]); count--; } } } } { var array = _cacheManager.ExceptFrom(_downloadBlocks.ToArray()).ToArray(); _random.Shuffle(array); int count = _maxBlockRequestCount; for (int i = 0; count > 0 && i < array.Length; i++) { if (!messageManagers.Values.Any(n => n.PushBlocksRequest.Contains(array[i]))) { pushBlocksRequestList.Add(array[i]); count--; } } } foreach (var pair in messageManagers) { var node = pair.Key; var messageManager = pair.Value; { var array = _cacheManager.ExceptFrom(messageManager.PullBlocksRequest.ToArray()).ToArray(); _random.Shuffle(array); int count = (int)(_maxBlockRequestCount * ((double)12 / otherNodes.Count)); for (int i = 0; count > 0 && i < array.Length; i++) { if (!messageManagers.Values.Any(n => n.PushBlocksRequest.Contains(array[i]))) { pushBlocksRequestList.Add(array[i]); count--; } } } } } _random.Shuffle(pushBlocksLinkList); _random.Shuffle(pushBlocksRequestList); { var pushBlocksLinkDictionary = new Dictionary<Node, HashSet<Key>>(); foreach (var key in pushBlocksLinkList) { try { var requestNodes = new List<Node>(); foreach (var node in Kademlia<Node>.Search(key.Hash, baseNode.Id, otherNodes, 1)) { requestNodes.Add(node); } for (int i = 0; i < requestNodes.Count; i++) { HashSet<Key> collection; if (!pushBlocksLinkDictionary.TryGetValue(requestNodes[i], out collection)) { collection = new HashSet<Key>(); pushBlocksLinkDictionary[requestNodes[i]] = collection; } if (collection.Count < _maxBlockLinkCount) { collection.Add(key); } } } catch (Exception e) { Log.Error(e); } } lock (_pushBlocksLinkDictionary.ThisLock) { _pushBlocksLinkDictionary.Clear(); foreach (var pair in pushBlocksLinkDictionary) { var node = pair.Key; var targets = pair.Value; _pushBlocksLinkDictionary.Add(node, new List<Key>(targets.Randomize())); } } } { var pushBlocksRequestDictionary = new Dictionary<Node, HashSet<Key>>(); foreach (var key in pushBlocksRequestList) { try { List<Node> requestNodes = new List<Node>(); foreach (var node in Kademlia<Node>.Search(key.Hash, baseNode.Id, otherNodes, 2)) { requestNodes.Add(node); } foreach (var pair in messageManagers) { var node = pair.Key; var messageManager = pair.Value; if (messageManager.PullBlocksLink.Contains(key)) { requestNodes.Add(node); } } for (int i = 0; i < requestNodes.Count; i++) { HashSet<Key> collection; if (!pushBlocksRequestDictionary.TryGetValue(requestNodes[i], out collection)) { collection = new HashSet<Key>(); pushBlocksRequestDictionary[requestNodes[i]] = collection; } if (collection.Count < _maxBlockRequestCount) { collection.Add(key); } } } catch (Exception e) { Log.Error(e); } } lock (_pushBlocksRequestDictionary.ThisLock) { _pushBlocksRequestDictionary.Clear(); foreach (var pair in pushBlocksRequestDictionary) { var node = pair.Key; var targets = pair.Value; _pushBlocksRequestDictionary.Add(node, new List<Key>(targets.Randomize())); } } } } // Metadataのアップロード if (connectionCount >= _uploadingConnectionCountLowerLimit && pushMetadataUploadStopwatch.Elapsed.TotalMinutes >= 3) { pushMetadataUploadStopwatch.Restart(); var baseNode = this.BaseNode; var otherNodes = new List<Node>(); lock (this.ThisLock) { otherNodes.AddRange(_connectionManagers.Select(n => n.Node)); } var messageManagers = new Dictionary<Node, MessageManager>(); foreach (var node in otherNodes) { messageManagers[node] = _messagesManager[node]; } // Broadcast foreach (var signature in _settings.MetadataManager.GetBroadcastSignatures()) { try { var requestNodes = new List<Node>(); foreach (var node in Kademlia<Node>.Search(Signature.GetHash(signature), baseNode.Id, otherNodes, 2)) { requestNodes.Add(node); } for (int i = 0; i < requestNodes.Count; i++) { messageManagers[requestNodes[i]].PullBroadcastSignaturesRequest.Add(signature); } } catch (Exception e) { Log.Error(e); } } // Unicast foreach (var signature in _settings.MetadataManager.GetUnicastSignatures()) { try { var requestNodes = new List<Node>(); foreach (var node in Kademlia<Node>.Search(Signature.GetHash(signature), baseNode.Id, otherNodes, 2)) { requestNodes.Add(node); } for (int i = 0; i < requestNodes.Count; i++) { messageManagers[requestNodes[i]].PullUnicastSignaturesRequest.Add(signature); } } catch (Exception e) { Log.Error(e); } } // Multicast { foreach (var tag in _settings.MetadataManager.GetMulticastWikis()) { try { var requestNodes = new List<Node>(); foreach (var node in Kademlia<Node>.Search(tag.Id, baseNode.Id, otherNodes, 2)) { requestNodes.Add(node); } for (int i = 0; i < requestNodes.Count; i++) { messageManagers[requestNodes[i]].PullMulticastWikisRequest.Add(tag); } } catch (Exception e) { Log.Error(e); } } foreach (var tag in _settings.MetadataManager.GetMulticastChats()) { try { var requestNodes = new List<Node>(); foreach (var node in Kademlia<Node>.Search(tag.Id, baseNode.Id, otherNodes, 2)) { requestNodes.Add(node); } for (int i = 0; i < requestNodes.Count; i++) { messageManagers[requestNodes[i]].PullMulticastChatsRequest.Add(tag); } } catch (Exception e) { Log.Error(e); } } } } // Metadataのダウンロード if (connectionCount >= _downloadingConnectionCountLowerLimit && pushMetadataDownloadStopwatch.Elapsed.TotalSeconds >= 60) { pushMetadataDownloadStopwatch.Restart(); var baseNode = this.BaseNode; var otherNodes = new List<Node>(); lock (this.ThisLock) { otherNodes.AddRange(_connectionManagers.Select(n => n.Node)); } var messageManagers = new Dictionary<Node, MessageManager>(); foreach (var node in otherNodes) { messageManagers[node] = _messagesManager[node]; } var pushBroadcastSignaturesRequestList = new List<string>(); var pushUnicastSignaturesRequestList = new List<string>(); var pushMulticastWikisRequestList = new List<Wiki>(); var pushMulticastChatsRequestList = new List<Chat>(); // Broadcast { { var array = _pushBroadcastSignaturesRequestList.ToArray(); _random.Shuffle(array); int count = _maxMetadataRequestCount; for (int i = 0; count > 0 && i < array.Length; i++) { if (!messageManagers.Values.Any(n => n.PushBroadcastSignaturesRequest.Contains(array[i]))) { pushBroadcastSignaturesRequestList.Add(array[i]); count--; } } } foreach (var pair in messageManagers) { var node = pair.Key; var messageManager = pair.Value; { var array = messageManager.PullBroadcastSignaturesRequest.ToArray(); _random.Shuffle(array); int count = _maxMetadataRequestCount; for (int i = 0; count > 0 && i < array.Length; i++) { if (!messageManagers.Values.Any(n => n.PushBroadcastSignaturesRequest.Contains(array[i]))) { pushBroadcastSignaturesRequestList.Add(array[i]); count--; } } } } } // Unicast { { var array = _pushUnicastSignaturesRequestList.ToArray(); _random.Shuffle(array); int count = _maxMetadataRequestCount; for (int i = 0; count > 0 && i < array.Length; i++) { if (!messageManagers.Values.Any(n => n.PushUnicastSignaturesRequest.Contains(array[i]))) { pushUnicastSignaturesRequestList.Add(array[i]); count--; } } } foreach (var pair in messageManagers) { var node = pair.Key; var messageManager = pair.Value; { var array = messageManager.PullUnicastSignaturesRequest.ToArray(); _random.Shuffle(array); int count = _maxMetadataRequestCount; for (int i = 0; count > 0 && i < array.Length; i++) { if (!messageManagers.Values.Any(n => n.PushUnicastSignaturesRequest.Contains(array[i]))) { pushUnicastSignaturesRequestList.Add(array[i]); count--; } } } } } // Multicast { { { var array = _pushMulticastWikisRequestList.ToArray(); _random.Shuffle(array); int count = _maxMetadataRequestCount; for (int i = 0; count > 0 && i < array.Length; i++) { if (!messageManagers.Values.Any(n => n.PushMulticastWikisRequest.Contains(array[i]))) { pushMulticastWikisRequestList.Add(array[i]); count--; } } } { var array = _pushMulticastChatsRequestList.ToArray(); _random.Shuffle(array); int count = _maxMetadataRequestCount; for (int i = 0; count > 0 && i < array.Length; i++) { if (!messageManagers.Values.Any(n => n.PushMulticastChatsRequest.Contains(array[i]))) { pushMulticastChatsRequestList.Add(array[i]); count--; } } } } foreach (var pair in messageManagers) { var node = pair.Key; var messageManager = pair.Value; { var array = messageManager.PullMulticastWikisRequest.ToArray(); _random.Shuffle(array); int count = _maxMetadataRequestCount; for (int i = 0; count > 0 && i < array.Length; i++) { if (!messageManagers.Values.Any(n => n.PushMulticastWikisRequest.Contains(array[i]))) { pushMulticastWikisRequestList.Add(array[i]); count--; } } } { var array = messageManager.PullMulticastChatsRequest.ToArray(); _random.Shuffle(array); int count = _maxMetadataRequestCount; for (int i = 0; count > 0 && i < array.Length; i++) { if (!messageManagers.Values.Any(n => n.PushMulticastChatsRequest.Contains(array[i]))) { pushMulticastChatsRequestList.Add(array[i]); count--; } } } } } _random.Shuffle(pushBroadcastSignaturesRequestList); _random.Shuffle(pushUnicastSignaturesRequestList); _random.Shuffle(pushMulticastWikisRequestList); _random.Shuffle(pushMulticastChatsRequestList); // Broadcast { var pushBroadcastSignaturesRequestDictionary = new Dictionary<Node, HashSet<string>>(); foreach (var signature in pushBroadcastSignaturesRequestList) { try { var requestNodes = new List<Node>(); foreach (var node in Kademlia<Node>.Search(Signature.GetHash(signature), baseNode.Id, otherNodes, 2)) { requestNodes.Add(node); } for (int i = 0; i < requestNodes.Count; i++) { HashSet<string> collection; if (!pushBroadcastSignaturesRequestDictionary.TryGetValue(requestNodes[i], out collection)) { collection = new HashSet<string>(); pushBroadcastSignaturesRequestDictionary[requestNodes[i]] = collection; } if (collection.Count < _maxMetadataRequestCount) { collection.Add(signature); } } } catch (Exception e) { Log.Error(e); } } lock (_pushBroadcastSignaturesRequestDictionary.ThisLock) { _pushBroadcastSignaturesRequestDictionary.Clear(); foreach (var pair in pushBroadcastSignaturesRequestDictionary) { var node = pair.Key; var targets = pair.Value; _pushBroadcastSignaturesRequestDictionary.Add(node, new List<string>(targets.Randomize())); } } } // Unicast { var pushUnicastSignaturesRequestDictionary = new Dictionary<Node, HashSet<string>>(); foreach (var signature in pushUnicastSignaturesRequestList) { try { var requestNodes = new List<Node>(); foreach (var node in Kademlia<Node>.Search(Signature.GetHash(signature), baseNode.Id, otherNodes, 2)) { requestNodes.Add(node); } for (int i = 0; i < requestNodes.Count; i++) { HashSet<string> collection; if (!pushUnicastSignaturesRequestDictionary.TryGetValue(requestNodes[i], out collection)) { collection = new HashSet<string>(); pushUnicastSignaturesRequestDictionary[requestNodes[i]] = collection; } if (collection.Count < _maxMetadataRequestCount) { collection.Add(signature); } } } catch (Exception e) { Log.Error(e); } } lock (_pushUnicastSignaturesRequestDictionary.ThisLock) { _pushUnicastSignaturesRequestDictionary.Clear(); foreach (var pair in pushUnicastSignaturesRequestDictionary) { var node = pair.Key; var targets = pair.Value; _pushUnicastSignaturesRequestDictionary.Add(node, new List<string>(targets.Randomize())); } } } // Multicast { var pushMulticastWikisRequestDictionary = new Dictionary<Node, HashSet<Wiki>>(); var pushMulticastChatsRequestDictionary = new Dictionary<Node, HashSet<Chat>>(); foreach (var tag in pushMulticastWikisRequestList) { try { var requestNodes = new List<Node>(); foreach (var node in Kademlia<Node>.Search(tag.Id, baseNode.Id, otherNodes, 2)) { requestNodes.Add(node); } for (int i = 0; i < requestNodes.Count; i++) { HashSet<Wiki> collection; if (!pushMulticastWikisRequestDictionary.TryGetValue(requestNodes[i], out collection)) { collection = new HashSet<Wiki>(); pushMulticastWikisRequestDictionary[requestNodes[i]] = collection; } if (collection.Count < _maxMetadataRequestCount) { collection.Add(tag); } } } catch (Exception e) { Log.Error(e); } } foreach (var tag in pushMulticastChatsRequestList) { try { var requestNodes = new List<Node>(); foreach (var node in Kademlia<Node>.Search(tag.Id, baseNode.Id, otherNodes, 2)) { requestNodes.Add(node); } for (int i = 0; i < requestNodes.Count; i++) { HashSet<Chat> collection; if (!pushMulticastChatsRequestDictionary.TryGetValue(requestNodes[i], out collection)) { collection = new HashSet<Chat>(); pushMulticastChatsRequestDictionary[requestNodes[i]] = collection; } if (collection.Count < _maxMetadataRequestCount) { collection.Add(tag); } } } catch (Exception e) { Log.Error(e); } } lock (_pushMulticastWikisRequestDictionary.ThisLock) { _pushMulticastWikisRequestDictionary.Clear(); foreach (var pair in pushMulticastWikisRequestDictionary) { var node = pair.Key; var targets = pair.Value; _pushMulticastWikisRequestDictionary.Add(node, new List<Wiki>(targets.Randomize())); } } lock (_pushMulticastChatsRequestDictionary.ThisLock) { _pushMulticastChatsRequestDictionary.Clear(); foreach (var pair in pushMulticastChatsRequestDictionary) { var node = pair.Key; var targets = pair.Value; _pushMulticastChatsRequestDictionary.Add(node, new List<Chat>(targets.Randomize())); } } } } } }