public synchronized RemoteFileDesc getBest() throws NoSuchElementException { if (!hasMore()) return null; RemoteFileDesc ret; // try a verified host if (!verifiedHosts.isEmpty()) { LOG.debug("getting a verified host"); ret = (RemoteFileDesc) verifiedHosts.first(); verifiedHosts.remove(ret); } else { LOG.debug("getting a non-verified host"); // use the legacy ranking logic to select a non-verified host Iterator dual = new DualIterator(testedLocations.iterator(), newHosts.iterator()); ret = LegacyRanker.getBest(dual); newHosts.remove(ret); testedLocations.remove(ret); if (ret.needsPush()) { for (Iterator iter = ret.getPushProxies().iterator(); iter.hasNext(); ) pingedHosts.remove(iter.next()); } else pingedHosts.remove(ret); } pingNewHosts(); if (LOG.isDebugEnabled()) LOG.debug("the best host we came up with is " + ret + " " + ret.getPushAddr()); return ret; }
private boolean addInternal(RemoteFileDesc host) { // initialize the sha1 if we don't have one if (sha1 == null) { if (host.getSHA1Urn() != null) sha1 = host.getSHA1Urn(); else // BUGFIX: We can't discard sources w/out a SHA1 when we dont' have // a SHA1 for the download, or else it won't be possible to download a // file from a query hit without a SHA1, if we can received UDP pings return testedLocations.add(host); // we can't do anything yet } // do not allow duplicate hosts if (running && knowsAboutHost(host)) return false; if (LOG.isDebugEnabled()) LOG.debug("adding new host " + host + " " + host.getPushAddr()); boolean ret = false; // don't bother ranking multicasts if (host.isReplyToMulticast()) ret = verifiedHosts.add(host); else ret = newHosts.add(host); // rank // make sure that if we were stopped, we return true ret = ret | !running; // initialize the guid if we don't have one if (myGUID == null && meshHandler != null) { myGUID = new GUID(GUID.makeGuid()); RouterService.getMessageRouter().registerMessageListener(myGUID.bytes(), this); } return ret; }
/** Informs the Ranker that a host has replied with a HeadPing */ public void processMessage(Message m, ReplyHandler handler) { MeshHandler mesh; RemoteFileDesc rfd; Collection alts = null; // this -> meshHandler NOT ok synchronized (this) { if (!running) return; if (!(m instanceof HeadPong)) return; HeadPong pong = (HeadPong) m; if (!pingedHosts.containsKey(handler)) return; rfd = (RemoteFileDesc) pingedHosts.remove(handler); testedLocations.remove(rfd); if (LOG.isDebugEnabled()) { LOG.debug( "received a pong " + pong + " from " + handler + " for rfd " + rfd + " with PE " + rfd.getPushAddr()); } // older push proxies do not route but respond directly, we want to get responses // from other push proxies if (!pong.hasFile() && !pong.isGGEPPong() && rfd.needsPush()) return; // if the pong is firewalled, remove the other proxies from the // pinged set if (pong.isFirewalled()) { for (Iterator iter = rfd.getPushProxies().iterator(); iter.hasNext(); ) pingedHosts.remove(iter.next()); } mesh = meshHandler; if (pong.hasFile()) { // update the rfd with information from the pong pong.updateRFD(rfd); // if the remote host is busy, re-add him for later ranking if (rfd.isBusy()) newHosts.add(rfd); else verifiedHosts.add(rfd); alts = pong.getAllLocsRFD(rfd); } } // if the pong didn't have the file, drop it // otherwise add any altlocs the pong had to our known hosts if (alts == null) mesh.informMesh(rfd, false); else mesh.addPossibleSources(alts); }
/** schedules a push ping to each proxy of the given host */ private void pingProxies(RemoteFileDesc rfd) { if (RouterService.acceptedIncomingConnection() || (RouterService.getUdpService().canDoFWT() && rfd.supportsFWTransfer())) { HeadPing pushPing = new HeadPing( myGUID, rfd.getSHA1Urn(), new GUID(rfd.getPushAddr().getClientGUID()), getPingFlags()); for (Iterator iter = rfd.getPushProxies().iterator(); iter.hasNext(); ) pingedHosts.put(iter.next(), rfd); if (LOG.isDebugEnabled()) LOG.debug("pinging push location " + rfd.getPushAddr()); pinger.rank(rfd.getPushProxies(), null, this, pushPing); } }