private IEnumerable <NodeIdentifier <TKey> > NodeLookUp(TKey key, IEnumerable <NodeIdentifier <TKey> > knownClosestNodes) { // convert the closest nodes to a list to prevent multiple enumerations List <NodeIdentifier <TKey> > closestNodes = knownClosestNodes.ToList(); List <NodeIdentifier <TKey> > orderedNodes = closestNodes.ToObservable() .CachedSelectMany(nodeId => { IKadNode <TKey, TValue> client = CreateClientFromNodeId(nodeId); FindNodeResult <TKey> nodes = client.FindNode(key, NodeIdentifier); return(Observable.Return(nodes)); }, maxConcurrent: Settings.Cita) .SelectMany(findNodeResult => findNodeResult.Nodes) .Merge(closestNodes.ToObservable()) .Distinct() .Do(RegisterNewNode) .Timeout(Settings.ClientTimeOut) .OnErrorResumeNext(Observable.Empty <NodeIdentifier <TKey> >()) .ToEnumerable() .OrderBy(nodeId => nodeId.NodeId, new LamdaComparer <TKey>((n1, n2) => RoutingTable.DistanceComparer(n1, n2, key))) .Take(Settings.K) .ToList(); return(orderedNodes.SequenceEqual(closestNodes) ? orderedNodes : NodeLookUp(key, orderedNodes)); }
/// <summary> /// Find the closest k closest nodes to the given key (using <see cref = "NodeLookUp" />) and stores /// the (<paramref name = "key" />,<paramref name = "value" />) pair in those nodes. /// </summary> /// <param name = "key"></param> /// <param name = "value"></param> public void StoreLookUp(TKey key, TValue value) { // the calls to Store in the nodes can be asynchronous NodeLookUp(key).ToObservable() .Subscribe(node => { try { IKadNode <TKey, TValue> client = CreateClientFromNodeId(node); client.Store(key, value, NodeIdentifier); } catch (CommunicationException e) { } }); }
/// <summary> /// This method returns the value associated with the given key. /// </summary> /// <remarks> /// It's similar to the <see cref = "NodeLookUp" /> method but using <see cref = "FindValue" />. /// </remarks> /// <param name = "key"></param> /// <returns></returns> public TValue ValueLookUp(TKey key) { // IEnumerable<NodeIdentifier<TKey>> closestNodes = NodeLookUp(key).ToList(); foreach (var nodeIdentifier in NodeLookUp(key)) { try { IKadNode <TKey, TValue> client = CreateClientFromNodeId(nodeIdentifier); FindValueResult <TKey, TValue> findValueResult = client.FindValue(key, NodeIdentifier); if (findValueResult.HasValue) { return(findValueResult.Value); } } catch (CommunicationException e) { // the service isn't working properly or doesn't contain the given key } } throw new KeyNotFoundException("The key doesn't exist in the network."); }