diff --git a/router/java/src/net/i2p/router/peermanager/PeerManager.java b/router/java/src/net/i2p/router/peermanager/PeerManager.java
index c4f47b072493602caba546b35b355c5df49ec15b..9dd2a4ac5f4a9fb30270662418601acc3bf029e9 100644
--- a/router/java/src/net/i2p/router/peermanager/PeerManager.java
+++ b/router/java/src/net/i2p/router/peermanager/PeerManager.java
@@ -76,89 +76,44 @@ class PeerManager {
      *
      */
     List selectPeers(PeerSelectionCriteria criteria) {
-        int numPasses = 0;
-        List rv = new ArrayList(criteria.getMinimumRequired());
+        Set peers = new HashSet(criteria.getMinimumRequired());
         Set exclude = new HashSet(1);
         exclude.add(_context.routerHash());
-        while (rv.size() < criteria.getMinimumRequired()) {
-            Set curVals = new HashSet(criteria.getMinimumRequired());
-            switch (criteria.getPurpose()) {
-                case PeerSelectionCriteria.PURPOSE_TEST:
-                    // for now, the peers we test will be the reliable ones
-                    //_organizer.selectWellIntegratedPeers(criteria.getMinimumRequired(), exclude, curVals);
-                    _organizer.selectHighCapacityPeers(criteria.getMinimumRequired(), exclude, curVals);
-                    break;
-                case PeerSelectionCriteria.PURPOSE_TUNNEL:
-                    // pull all of the fast ones, regardless of how many we 
-                    // want - we'll whittle them down later (40 lines from now)
-                    // int num = _organizer.countFastPeers();
-                    // if (num <= 0) 
-                    //    num = criteria.getMaximumRequired();
-                    // _organizer.selectFastPeers(num, exclude, curVals);
-                    _organizer.selectFastPeers(criteria.getMaximumRequired(), exclude, curVals);
-                    break;
-                case PeerSelectionCriteria.PURPOSE_SOURCE_ROUTE:
-                    _organizer.selectHighCapacityPeers(criteria.getMinimumRequired(), exclude, curVals);
-                    break;
-                case PeerSelectionCriteria.PURPOSE_GARLIC:
-                    _organizer.selectHighCapacityPeers(criteria.getMinimumRequired(), exclude, curVals);
-                    break;
-                default:
-                    break;
-            }
-            if (curVals.size() <= 0) {
-                if (_log.shouldLog(Log.WARN))
-                    _log.warn("We ran out of peers when looking for reachable ones after finding " 
-                              + rv.size() + " with "
-                              + _organizer.countWellIntegratedPeers() + "/" 
-                              + _organizer.countHighCapacityPeers() + "/" 
-                              + _organizer.countFastPeers() + " integrated/high capacity/fast peers");
+        switch (criteria.getPurpose()) {
+            case PeerSelectionCriteria.PURPOSE_TEST:
+                // for now, the peers we test will be the reliable ones
+                //_organizer.selectWellIntegratedPeers(criteria.getMinimumRequired(), exclude, curVals);
+                _organizer.selectHighCapacityPeers(criteria.getMinimumRequired(), exclude, peers);
+                break;
+            case PeerSelectionCriteria.PURPOSE_TUNNEL:
+                // pull all of the fast ones, regardless of how many we 
+                // want - we'll whittle them down later (40 lines from now)
+                // int num = _organizer.countFastPeers();
+                // if (num <= 0) 
+                //    num = criteria.getMaximumRequired();
+                // _organizer.selectFastPeers(num, exclude, curVals);
+                _organizer.selectFastPeers(criteria.getMaximumRequired(), exclude, peers);
+                break;
+            case PeerSelectionCriteria.PURPOSE_SOURCE_ROUTE:
+                _organizer.selectHighCapacityPeers(criteria.getMinimumRequired(), exclude, peers);
+                break;
+            case PeerSelectionCriteria.PURPOSE_GARLIC:
+                _organizer.selectHighCapacityPeers(criteria.getMinimumRequired(), exclude, peers);
+                break;
+            default:
                 break;
-            } else {
-                for (Iterator iter = curVals.iterator(); iter.hasNext(); ) {
-                    Hash peer = (Hash)iter.next();
-                    if (null != _context.netDb().lookupRouterInfoLocally(peer)) {
-                        if (_log.shouldLog(Log.DEBUG))
-                            _log.debug("Peer " + peer.toBase64() + " is locally known, so we'll allow its selection");
-                        if (!rv.contains(peer))
-                            rv.add(peer);
-                    } else {
-                        if (_log.shouldLog(Log.DEBUG))
-                            _log.debug("Peer " + peer.toBase64() + " is NOT locally known, disallowing its selection");
-                    }
-                }
-                exclude.addAll(curVals);
-            }
-            numPasses++;
         }
-        if (_log.shouldLog(Log.INFO))
-            _log.info("Peers selected after " + numPasses + ": " + rv);
-        
-        /*
-        if (criteria.getPurpose() == PeerSelectionCriteria.PURPOSE_TUNNEL) {
-            // we selected extra peers above.  now lets strip that down to the 
-            // minimum requested, ordering it by the least recently agreed to
-            // first
-            TreeMap ordered = new TreeMap();
-            for (Iterator iter = rv.iterator(); iter.hasNext(); ) {
-                Hash peer = (Hash)iter.next();
-                PeerProfile prof = _organizer.getProfile(peer);
-                long when = prof.getTunnelHistory().getLastAgreedTo();
-                while (ordered.containsKey(new Long(when)))
-                    when++;
-                ordered.put(new Long(when), peer);
-            }
-            rv.clear();
-            for (Iterator iter = ordered.values().iterator(); iter.hasNext(); ) {
-                if (rv.size() >= criteria.getMaximumRequired()) break;
-                Hash peer = (Hash)iter.next();
-                rv.add(peer);
-            }
-            if (_log.shouldLog(Log.INFO))
-                _log.info("Peers selected after " + numPasses + ", sorted for a tunnel: " + rv);
+        if (peers.size() <= 0) {
+            if (_log.shouldLog(Log.WARN))
+                _log.warn("We ran out of peers when looking for reachable ones after finding " 
+                          + peers.size() + " with "
+                          + _organizer.countWellIntegratedPeers() + "/" 
+                          + _organizer.countHighCapacityPeers() + "/" 
+                          + _organizer.countFastPeers() + " integrated/high capacity/fast peers");
         }
-         */
-        return rv;
+        if (_log.shouldLog(Log.INFO))
+            _log.info("Peers selected: " + peers);
+        return new ArrayList(peers);
     }
     
     public void renderStatusHTML(OutputStream out) throws IOException { 
diff --git a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java
index 73ae5a7d564e720f9a430e62e6d64919a15deb09..a749c28b1c29ee1841618428e794e8fe8706020e 100644
--- a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java
+++ b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java
@@ -21,6 +21,7 @@ import java.util.TreeSet;
 import net.i2p.data.DataHelper;
 import net.i2p.data.Hash;
 import net.i2p.router.RouterContext;
+import net.i2p.router.NetworkDatabaseFacade;
 import net.i2p.stat.Rate;
 import net.i2p.stat.RateStat;
 import net.i2p.util.Log;
@@ -251,8 +252,14 @@ public class ProfileOrganizer {
         synchronized (_reorganizeLock) {
             locked_selectPeers(_fastPeers, howMany, exclude, matches);
         }
-        if (matches.size() < howMany)
+        if (matches.size() < howMany) {
+            if (_log.shouldLog(Log.DEBUG))
+                _log.debug("selectFastPeers("+howMany+"), not enough fast (" + matches.size() + ") going on to highCap");
             selectHighCapacityPeers(howMany, exclude, matches);
+        } else {
+            if (_log.shouldLog(Log.DEBUG))
+                _log.debug("selectFastPeers("+howMany+"), found enough fast (" + matches.size() + ")");
+        }
         return;
     }
     
@@ -271,8 +278,14 @@ public class ProfileOrganizer {
                 exclude.addAll(_fastPeers.keySet());
             locked_selectPeers(_highCapacityPeers, howMany, exclude, matches);
         }
-        if (matches.size() < howMany)
+        if (matches.size() < howMany) {
+            if (_log.shouldLog(Log.DEBUG))
+                _log.debug("selectHighCap("+howMany+"), not enough fast (" + matches.size() + ") going on to notFailing");
             selectNotFailingPeers(howMany, exclude, matches);
+        } else {
+            if (_log.shouldLog(Log.DEBUG))
+                _log.debug("selectHighCap("+howMany+"), found enough highCap (" + matches.size() + ")");
+        }
         return;
     }
     /**
@@ -283,8 +296,15 @@ public class ProfileOrganizer {
         synchronized (_reorganizeLock) {
             locked_selectPeers(_wellIntegratedPeers, howMany, exclude, matches);
         }
-        if (matches.size() < howMany)
+        if (matches.size() < howMany) {
+            if (_log.shouldLog(Log.DEBUG))
+                _log.debug("selectWellIntegrated("+howMany+"), not enough integrated (" + matches.size() + ") going on to notFailing");
             selectNotFailingPeers(howMany, exclude, matches);
+        } else {            
+            if (_log.shouldLog(Log.DEBUG))
+                _log.debug("selectWellIntegrated("+howMany+"), found enough well integrated (" + matches.size() + ")");
+        }
+        
         return;
     }
     /**
@@ -340,19 +360,27 @@ public class ProfileOrganizer {
                 for (Iterator iter = _strictCapacityOrder.iterator(); selected.size() < needed && iter.hasNext(); ) {
                     PeerProfile prof = (PeerProfile)iter.next();
                     if (matches.contains(prof.getPeer()) ||
-                    (exclude != null && exclude.contains(prof.getPeer())) ||
-                    _failingPeers.containsKey(prof.getPeer()))
+                        (exclude != null && exclude.contains(prof.getPeer())) ||
+                        _failingPeers.containsKey(prof.getPeer()) ) {
                         continue;
-                    else
-                        selected.add(prof.getPeer());
+                    } else {
+                        if (isOk(prof.getPeer()))
+                            selected.add(prof.getPeer());
+                    }
                 }
             }
             if (_log.shouldLog(Log.DEBUG))
                 _log.debug("Selecting all not failing found " + (matches.size()-orig) + " new peers: " + selected);
             matches.addAll(selected);
         }
-        if (matches.size() < howMany)
+        if (matches.size() < howMany) {
+            if (_log.shouldLog(Log.DEBUG))
+                _log.debug("selectAllNotFailing("+howMany+"), not enough (" + matches.size() + ") going on to failing");
             selectFailingPeers(howMany, exclude, matches);
+        } else {
+            if (_log.shouldLog(Log.DEBUG))
+                _log.debug("selectAllNotFailing("+howMany+"), enough (" + matches.size() + ")");
+        }
         return;
     }
     /**
@@ -554,70 +582,57 @@ public class ProfileOrganizer {
     /**
      * Update the _thresholdCapacityValue by using a few simple formulas run 
      * against the specified peers.  Ideally, we set the threshold capacity to
-     * the mean, as long as that gives us enough peers and the mean is a "growth"
-     * value.  We fall back on the capacity of the top K-th capacity, or the 
-     * mean, or the base growth value, depending on various circumstances.
+     * the mean, as long as that gives us enough peers and is greater than the
+     * median.
      *
      * @param reordered ordered set of PeerProfile objects, ordered by capacity
-     *                  (highest first) for active nonfailing peers
+     *                  (highest first) for active nonfailing peers whose 
+     *                  capacity is greater than the growth factor
      */
     private void locked_calculateCapacityThreshold(double totalCapacity, Set reordered) {
         int numNotFailing = reordered.size();
         
         double meanCapacity = avg(totalCapacity, numNotFailing);
         
-        long baseline = CapacityCalculator.GROWTH_FACTOR;
         int minHighCapacityPeers = getMinimumHighCapacityPeers();
         
         int numExceedingMean = 0;
-        int numExceedingBaseline = 0;
         double thresholdAtMedian = 0;
         double thresholdAtMinHighCap = 0;
+        double thresholdAtLowest = CapacityCalculator.GROWTH_FACTOR;
         int cur = 0;
         for (Iterator iter = reordered.iterator(); iter.hasNext(); ) {
             PeerProfile profile = (PeerProfile)iter.next();
             double val = profile.getCapacityValue();
             if (val > meanCapacity)
                 numExceedingMean++;
-            if (val > baseline)
-                numExceedingBaseline++;
             if (cur == reordered.size()/2)
                 thresholdAtMedian = val;
             if (cur == minHighCapacityPeers)
                 thresholdAtMinHighCap = val;
+            if (cur == reordered.size() -1)
+                thresholdAtLowest = val;
             cur++;
         }
         
-        if (meanCapacity > baseline) {
+        if (numExceedingMean >= minHighCapacityPeers) {
             // our average is doing well (growing, not recovering from failures)
-            if (numExceedingMean > minHighCapacityPeers) {
-                if (_log.shouldLog(Log.INFO))
-                    _log.info("Our average capacity is doing well [" + meanCapacity 
-                              + "], and includes " + numExceedingMean);
-                _thresholdCapacityValue = meanCapacity;
-            } else {
-                if (_log.shouldLog(Log.INFO))
-                    _log.info("Our average capacity is doing well [" + meanCapacity 
-                              + "], but it is skewed to only have " + numExceedingMean
-                              + " so falling back on the top few to " + thresholdAtMinHighCap);
-                _thresholdCapacityValue = thresholdAtMinHighCap;
-            }
+            if (_log.shouldLog(Log.INFO))
+                _log.info("Our average capacity is doing well [" + meanCapacity 
+                          + "], and includes " + numExceedingMean);
+            _thresholdCapacityValue = meanCapacity;
+        } else if (reordered.size()/2 >= minHighCapacityPeers) {
+            // ok mean is skewed low, but we still have enough to use the median
+            if (_log.shouldLog(Log.INFO))
+                _log.info("Our average capacity is skewed under the median [" + meanCapacity 
+                          + "], so use the median threshold " + thresholdAtMedian);
+            _thresholdCapacityValue = thresholdAtMedian;
         } else {
-            // our average isn't doing well (its recovering from failures)
-            _thresholdCapacityValue = baseline + 0.0000001;
-            /*if (numExceedingBaseline > minHighCapacityPeers) {
-                if (_log.shouldLog(Log.INFO))
-                    _log.info("Our average capacity isn't doing well [" + meanCapacity 
-                              + "], but the baseline has " + numExceedingBaseline);
-                _thresholdCapacityValue = baseline+.0001;
-            } else {
-                if (_log.shouldLog(Log.INFO))
-                    _log.info("Our average capacity isn't doing well [" + meanCapacity 
-                              + "], and the baseline has " + numExceedingBaseline 
-                              + " so falling back on the median of " + thresholdAtMedian);
-                _thresholdCapacityValue = thresholdAtMedian;
-            }
-             */
+            // our average is doing well, but not enough peers
+            if (_log.shouldLog(Log.INFO))
+                _log.info("Our average capacity is doing well [" + meanCapacity 
+                          + "], but there aren't enough of them " + numExceedingMean);
+            _thresholdCapacityValue = Math.max(thresholdAtMinHighCap, thresholdAtLowest);
         }
     }
     
@@ -681,12 +696,32 @@ public class ProfileOrganizer {
         List all = new ArrayList(peers.keySet());
         if (toExclude != null)
             all.removeAll(toExclude);
+        
         all.removeAll(matches);
         all.remove(_us);
-        howMany -= matches.size();
         Collections.shuffle(all, _random);
-        for (int i = 0; i < howMany && i < all.size(); i++) {
-            matches.add(all.get(i));
+        for (int i = 0; (matches.size() < howMany) && (i < all.size()); i++) {
+            Hash peer = (Hash)all.get(i);
+            boolean ok = isOk(peer);
+            if (ok)
+                matches.add(peer);
+            else
+                matches.remove(peer);
+        }
+    }
+    
+    private boolean isOk(Hash peer) {
+        NetworkDatabaseFacade netDb = _context.netDb();
+        // the CLI shouldn't depend upon the netDb
+        if (netDb == null) return true;
+        if (null != netDb.lookupRouterInfoLocally(peer)) {
+            if (_log.shouldLog(Log.INFO))
+                _log.info("Peer " + peer.toBase64() + " is locally known, selecting");
+            return true;
+        } else {
+            if (_log.shouldLog(Log.WARN))
+                _log.warn("Peer " + peer.toBase64() + " is NOT locally known, disallowing its selection");
+            return false;
         }
     }