public KadValue FindValue(KadId valueId) { if (Owner.Storage.Contains(valueId)) { var storageVal = Owner.Storage.Get(valueId); if (Owner.IsValueExpired(storageVal)) { Owner.Storage.Remove(valueId); } else { return(storageVal); } } SortedSet <KadContactNode> shortList; Tuple <KadContactNode, KadValue> value = LookupValue(valueId, out shortList); if (value != null) { if (shortList.Min.Id != value.Item1.Id) { Owner.StoreValue(shortList.Min, value.Item2); } Owner.Storage.Put(value.Item2); } return(value.Item2); }
private Tuple <KadContactNode, KadValue> LookupValue(KadId valueId, out SortedSet <KadContactNode> retSortList) { var closestNodes = Owner.BucketList.GetClosestNodes(valueId, MaxConcurrentThreads); SortedSet <KadContactNode> shortList = new SortedSet <KadContactNode>(closestNodes, new KadId.KadIdToBaseComparator(valueId)); retSortList = shortList; if (shortList.Count == 0) { return(null); } SortedSet <KadId> queriedNodes = new SortedSet <KadId>(new KadId.KadIdToIdComparator()); KadId closestId = shortList.Min.Id; SemaphoreSlim tasksSemaphore = new SemaphoreSlim(MaxConcurrentThreads); KadContactNode returnedNode = null; KadValue value = null; //Should do fine for small alpha List <Task> tasks = new List <Task>(); while (queriedNodes.Count < ReplicationCount) { var shortListSnapshot = shortList.Where((n) => !queriedNodes.Contains(n.Id)).ToList(); foreach (var node in shortListSnapshot) { tasks.Add(Task.Run(() => { var response = Owner.FindValue(node, valueId); if (response != null) { if (response.Type == MessageType.FindNode) { foreach (var contact in response.Contacts) { shortList.Add(contact); } } else if (response.Type == MessageType.FindValue) { value = new KadValue(valueId, DateTime.Now, response.Payload); returnedNode = node; } } tasksSemaphore.Release(); })); queriedNodes.Add(node.Id); tasksSemaphore.Wait(); } Task.WaitAll(tasks.ToArray()); tasks.Clear(); if ((shortList.Min.Id ^ closestId) >= closestId) { break; } closestId = shortList.Min.Id; } return(value != null ? new Tuple <KadContactNode, KadValue>(returnedNode, value) : null); }
/// <summary> /// Retrives value from other node /// </summary> /// <param name="node">Node to query</param> /// <param name="valId">Value id</param> /// <returns>Value if queried node has value, otherwise closest nodes to id</returns> public NodeMessage FindValue(KadContactNode node, KadId valId) { NodeMessage findValMsg = new NodeMessage.Builder() .SetType(MessageType.FindValue) .SetOriginator(Id) .SetIsRequest(true) .SetPayload(valId.Value) .Build(); findValMsg.AddCallback(UpdateLastSeen); return(_server.SendMessageSync(node.EndPoint, findValMsg, TimeoutInMSec).Response); }
private IEnumerable <KadContactNode> LookupNode(KadId nodeId) { var closestNodes = Owner.BucketList.GetClosestNodes(nodeId, MaxConcurrentThreads); SortedSet <KadContactNode> shortList = new SortedSet <KadContactNode>(closestNodes, new KadId.KadIdToBaseComparator(nodeId)); if (shortList.Count == 0) { return(shortList); } SortedSet <KadId> queriedNodes = new SortedSet <KadId>(new KadId.KadIdToIdComparator()); KadId closestId = shortList.Min.Id; SemaphoreSlim tasksSemaphore = new SemaphoreSlim(MaxConcurrentThreads); List <Task> tasks = new List <Task>(); while (queriedNodes.Count < ReplicationCount) { var shortListSnapshot = shortList.Where((n) => !queriedNodes.Contains(n.Id)).ToList(); foreach (var node in shortListSnapshot) { tasks.Add(Task.Run(() => { var contacts = Owner.FindNode(node, nodeId); foreach (var contact in contacts) { shortList.Add(contact); } tasksSemaphore.Release(); })); tasksSemaphore.Wait(); } Task.WaitAll(tasks.ToArray()); tasks.Clear(); if ((shortList.Min.Id ^ closestId) >= closestId) { break; } closestId = shortList.Min.Id; } return(shortList.Take(ReplicationCount).ToList()); }
public void RefreshBucket(KadId id) { var closestNodes = LookupNode(id); foreach (var contactNode in closestNodes) { switch (Owner.BucketList.Put(contactNode)) { case Buckets.BucketList.BucketPutResult.BucketIsFull: TryReplaceLeastSeenContactFromBucket(contactNode); break; case Buckets.BucketList.BucketPutResult.Updated: case Buckets.BucketList.BucketPutResult.Success: //Nothing to do here. break; } } }
/// <summary> /// Find contact's closest nodes to id /// </summary> /// <param name="node">Node to query</param> /// <param name="id">Id to compare</param> /// <returns>Closest nodes to id</returns> public IEnumerable <KadContactNode> FindNode(KadContactNode node, KadId id) { NodeMessage msg = new NodeMessage.Builder() .SetType(MessageType.FindNode) .SetOriginator(Id) .SetIsRequest(true) .SetPayload(id.Value) .Build(); NodeMessage response = _server.SendMessageSync(node.EndPoint, msg, TimeoutInMSec).Response; msg.AddCallback(UpdateLastSeen); if (response != null) { return(new List <KadContactNode>(response.Contacts)); } return(new List <KadContactNode>()); }
public void RefreshUnaccessedBuckets() { SortedSet <Buckets.Bucket> sortedBuckets = new SortedSet <Buckets.Bucket>(Owner.BucketList.Buckets, new Buckets.Bucket.ByLastUpdatedComparer()); foreach (var bucket in sortedBuckets) { if ((DateTime.UtcNow - bucket.LastUpdated).TotalSeconds > BucketsRefreshInSecs) { byte[] intBytes = BitConverter.GetBytes(bucket.Id); byte[] idBytes = new byte[ReplicationCount]; Buffer.BlockCopy(intBytes, 0, idBytes, 0, intBytes.Length); KadId bucketId = new KadId(idBytes); RefreshBucket(bucketId); } else { break; } } }
public KadContactNode(KadId id, IPEndPoint endPoint) { Id = id; EndPoint = endPoint; }
/// <summary> /// Pings other node /// </summary> /// <param name="id">Node id to ping</param> /// <returns></returns> public NodeMessage Ping(KadId id) { var bucket = BucketList.GetBucket(id); return(Ping(bucket.GetNode(id))); }
public KadNode(IPEndPoint ipEndpoint, KadId id) { Id = id; InitNode(ipEndpoint); }
public KadNode(IPEndPoint ipEndpoint) { Id = KadId.GenerateRandom(); InitNode(ipEndpoint); }
/// <summary> /// Processes request from other node. Used by NodeServer class /// </summary> /// <param name="msg">Request to process</param> /// <param name="origAddress">Request originator adress</param> public void ProcessRequest(NodeMessage msg, IPEndPoint origAddress) { switch (msg.Type) { case MessageType.Ping: { //TODO: handle cases when bucket is full, etc NodeMessage respMsg = new NodeMessage.Builder() .SetType(MessageType.Ping) .SetOriginator(Id) .SetSeq(msg.Seq) .SetIsRequest(false) .Build(); _server.SendMessage(origAddress, respMsg); break; } case MessageType.FindNode: { var closestNodes = BucketList.GetClosestNodes(new KadId(msg.Payload), 20); NodeMessage respMsg = new NodeMessage.Builder() .SetType(MessageType.FindNode) .SetSeq(msg.Seq) .SetOriginator(Id) .SetContacts(closestNodes) .Build(); _server.SendMessage(origAddress, respMsg); break; } case MessageType.FindValue: { KadId valueId = new KadId(msg.Payload); NodeMessage.Builder msgBuilder = new NodeMessage.Builder() .SetType(MessageType.FindValue) .SetSeq(msg.Seq) .SetOriginator(Id); if (Storage.Contains(valueId)) { msgBuilder.SetKadValueAsPayload(Storage.Get(valueId)); } else { var closestNodes = BucketList.GetClosestNodes(valueId, 20); msgBuilder.SetContacts(closestNodes) .SetType(MessageType.FindNode); } _server.SendMessage(origAddress, msgBuilder.Build()); break; } case MessageType.CanStoreValue: { NodeMessage respMsg = new NodeMessage.Builder() .SetType(MessageType.CanStoreValue) .SetSeq(msg.Seq) .SetOriginator(Id) .SetIsRequest(false) .SetFlagAsPayload(!Storage.IsFull()) .Build(); _server.SendMessage(origAddress, respMsg); break; } case MessageType.StoreValue: { NodeMessage.Builder msgBuilder = new NodeMessage.Builder() .SetSeq(msg.Seq) .SetOriginator(Id) .SetIsRequest(false) .SetType(MessageType.CanStoreValue); if (Storage.IsFull()) { msgBuilder.SetFlagAsPayload(false); } else { msgBuilder.SetFlagAsPayload(true); Storage.Put(msg.Value); } _server.SendMessage(origAddress, msgBuilder.Build()); break; } } UpdateLastSeen(msg); }
/// <summary> /// Retrives value from other node /// </summary> /// <param name="node">Node to query</param> /// <param name="valId">Value id</param> /// <returns>Value if queried node has value, otherwise closest nodes to id</returns> public NodeMessage FindValue(KadId id, KadId valId) { var bucket = BucketList.GetBucket(id); return(FindValue(bucket.GetNode(id), valId)); }
/// <summary> /// Store value in contact /// </summary> /// <param name="node">Contact node</param> /// <param name="value">Value to store</param> /// <returns>true, if node stored value</returns> public bool StoreValue(KadId id, KadValue value) { var bucket = BucketList.GetBucket(id); return(StoreValue(bucket.GetNode(id), value)); }
/// <summary> /// Find contact's closest nodes to id /// </summary> /// <param name="node">Node to query</param> /// <param name="id">Id to compare</param> /// <returns>Closest nodes to id</returns> public IEnumerable <KadContactNode> FindNode(KadId id, KadId idToFind) { var bucket = BucketList.GetBucket(id); return(FindNode(bucket.GetNode(id), idToFind)); }
public KadIdToBaseComparator(KadId baseId) { _base = baseId; }