Example #1
0
        /// <summary>
        /// Looks for a route to the given peer address.
        /// </summary>
        /// <param name="peerAddresses">Nodes that should be asked first for a route.</param>
        /// <param name="routingBuilder"></param>
        /// <param name="type"></param>
        /// <param name="cc"></param>
        /// <returns>A task object that is set to complete if the route has been found.</returns>
        private TcsRouting Routing(ICollection <PeerAddress> peerAddresses, RoutingBuilder routingBuilder,
                                   Message.Message.MessageType type, ChannelCreator cc)
        {
            try
            {
                if (peerAddresses == null)
                {
                    throw new ArgumentException("Some nodes/addresses need to be specified.");
                }
                bool randomSearch = routingBuilder.LocationKey == null;
                IComparer <PeerAddress> comparer;
                if (randomSearch)
                {
                    comparer = _peerBean.PeerMap.CreateComparer();
                }
                else
                {
                    comparer = PeerMap.CreateComparer(routingBuilder.LocationKey);
                }
                var queueToAsk   = new SortedSet <PeerAddress>(comparer);
                var alreadyAsked = new SortedSet <PeerAddress>(comparer);

                // As presented by Kazuyuki Shudo at AIMS 2009, it is better to ask random
                // peers with the data than ask peers that are ordered by distance.
                // -> this balances load
                var directHits    = new SortedDictionary <PeerAddress, DigestInfo>(comparer);
                var potentialHits = new SortedSet <PeerAddress>(comparer);

                // fill initially
                queueToAsk.AddAll(peerAddresses);
                alreadyAsked.Add(_peerBean.ServerPeerAddress);
                potentialHits.Add(_peerBean.ServerPeerAddress);

                // domain key can be null if we bootstrap
                if (type == Message.Message.MessageType.Request2 &&
                    routingBuilder.DomainKey != null &&
                    !randomSearch &&
                    _peerBean.DigestStorage != null)
                {
                    Number640 from;
                    Number640 to;
                    if (routingBuilder.From != null && routingBuilder.To != null)
                    {
                        from = routingBuilder.From;
                        to   = routingBuilder.To;
                    }
                    else if (routingBuilder.ContentKey == null)
                    {
                        from = new Number640(routingBuilder.LocationKey, routingBuilder.DomainKey, Number160.Zero, Number160.Zero);
                        to   = new Number640(routingBuilder.LocationKey, routingBuilder.DomainKey, Number160.MaxValue, Number160.MaxValue);
                    }
                    else
                    {
                        from = new Number640(routingBuilder.LocationKey, routingBuilder.DomainKey, routingBuilder.ContentKey, Number160.Zero);
                        to   = new Number640(routingBuilder.LocationKey, routingBuilder.DomainKey, routingBuilder.ContentKey, Number160.MaxValue);
                    }

                    var digestBean = _peerBean.DigestStorage.Digest(from, to, -1, true);
                    if (digestBean.Size > 0)
                    {
                        directHits.Add(_peerBean.ServerPeerAddress, digestBean);
                    }
                }
                else if (type == Message.Message.MessageType.Request3 &&
                         !randomSearch &&
                         _peerBean.DigestTracker != null)
                {
                    var digestInfo = _peerBean.DigestTracker.Digest(routingBuilder.LocationKey, routingBuilder.DomainKey,
                                                                    routingBuilder.ContentKey);
                    // we always put ourselfs to the tracker list, so we need to check
                    // if we know also other peers on our trackers
                    if (digestInfo.Size > 0)
                    {
                        directHits.Add(_peerBean.ServerPeerAddress, digestInfo);
                    }
                }

                var tcsRouting = new TcsRouting();
                if (peerAddresses.Count == 0)
                {
                    tcsRouting.SetNeighbors(directHits, potentialHits, alreadyAsked, routingBuilder.IsBootstrap, false);
                }
                else
                {
                    // If a peer bootstraps to itself, then the size of peer addresses is 1
                    // and it contains itself. Check for that because we need to know if we
                    // are routing, bootstrapping and bootstrapping to ourselfs, to return
                    // the correct status for the task.
                    var isRoutingOnlyToSelf = peerAddresses.Count == 1 &&
                                              peerAddresses.First().Equals(_peerBean.ServerPeerAddress);

                    var routingMechanism = routingBuilder.CreateRoutingMechanism(tcsRouting);
                    routingMechanism.SetQueueToAsk(queueToAsk);
                    routingMechanism.SetPotentialHits(potentialHits);
                    routingMechanism.SetDirectHits(directHits);
                    routingMechanism.SetAlreadyAsked(alreadyAsked);

                    routingBuilder.SetIsRoutingOnlyToSelf(isRoutingOnlyToSelf);
                    RoutingRec(routingBuilder, routingMechanism, type, cc);
                }
                return(tcsRouting);
            }
            catch (Exception ex)
            {
                Logger.Error("An exception occurred during routing.", ex);
                throw;
            }
        }