package com.limegroup.gnutella.downloader; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.limegroup.gnutella.Assert; import com.limegroup.gnutella.RemoteFileDesc; /** * A ranker which uses the legacy logic for selecting from available * sources. */ public class LegacyRanker extends SourceRanker { private static final Log LOG = LogFactory.getLog(LegacyRanker.class); private final Set rfds; public LegacyRanker() { rfds = new HashSet(); } public synchronized boolean addToPool(RemoteFileDesc host) { if (LOG.isDebugEnabled()) LOG.debug("adding host "+host+" to be ranked"); return rfds.add(host); } /** * Removes and returns the RemoteFileDesc with the highest quality in * filesLeft. If two or more entries have the same quality, returns the * entry with the highest speed. * * @param filesLeft the list of file/locations to choose from, which MUST * have length of at least one. Each entry MUST be an instance of * RemoteFileDesc. The assumption is that all are "same", though this * isn't strictly needed. * @return the best file/endpoint location */ public synchronized RemoteFileDesc getBest() { if (!hasMore()) return null; RemoteFileDesc ret = getBest(rfds.iterator()); //The best rfd found so far boolean removed = rfds.remove(ret); Assert.that(removed == true, "unable to remove RFD."); if (LOG.isDebugEnabled()) LOG.debug("the best we came with is "+ret); return ret; } static RemoteFileDesc getBest(Iterator iter) { RemoteFileDesc ret=(RemoteFileDesc)iter.next(); long now = System.currentTimeMillis(); //Find max of each (remaining) element, storing in max. //Follows the following logic: //1) Find a non-busy host (make connections) //2) Find a host that uses hashes (avoid corruptions) //3) Find a better quality host (avoid dud locations) //4) Find a speedier host (avoid slow downloads) while (iter.hasNext()) { RemoteFileDesc rfd=(RemoteFileDesc)iter.next(); // 1. if (rfd.isBusy(now)) continue; if (ret.isBusy(now)) ret=rfd; // 2. else if (rfd.getSHA1Urn()!=null && ret.getSHA1Urn()==null) ret=rfd; // 3 & 4. // (note the use of == so that the comparison is only done // if both rfd & ret either had or didn't have a SHA1) else if ((rfd.getSHA1Urn()==null) == (ret.getSHA1Urn()==null)) { // 3. if (rfd.getQuality() > ret.getQuality()) ret=rfd; else if (rfd.getQuality() == ret.getQuality()) { // 4. if (rfd.getSpeed() > ret.getSpeed()) ret=rfd; } } } return ret; } public boolean hasMore() { return !rfds.isEmpty(); } protected Collection getShareableHosts() { return rfds; } protected Collection getPotentiallyBusyHosts() { return rfds; } public int getNumKnownHosts() { return rfds.size(); } }