From 2f8993995b365e73c96e36447af121da76460dfd Mon Sep 17 00:00:00 2001 From: jrandom Date: Tue, 17 Aug 2004 05:20:17 +0000 Subject: [PATCH] enforce diversification of tunnel participants. when picking peers to participate in a tunnel, we still select from the 'fast' tier, except now we pick the ones that have least recently agreed to participate in a tunnel. (they're already in the fast tier, so they're reliable [ish]). the diversification has been pretty good so far, but i'm going to leave 'er running and monitor it overnight --- .../i2p/router/peermanager/PeerManager.java | 40 +++++++++++++++++-- .../peermanager/PeerManagerFacadeImpl.java | 2 +- .../i2p/router/peermanager/PeerTestJob.java | 2 +- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/router/java/src/net/i2p/router/peermanager/PeerManager.java b/router/java/src/net/i2p/router/peermanager/PeerManager.java index 5777848ac..1bf119be5 100644 --- a/router/java/src/net/i2p/router/peermanager/PeerManager.java +++ b/router/java/src/net/i2p/router/peermanager/PeerManager.java @@ -10,8 +10,11 @@ package net.i2p.router.peermanager; import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; +import java.util.List; +import java.util.TreeMap; import java.util.Set; import net.i2p.data.Hash; @@ -72,9 +75,9 @@ class PeerManager { * Find some peers that meet the criteria and we have the netDb info for locally * */ - Set selectPeers(PeerSelectionCriteria criteria) { + List selectPeers(PeerSelectionCriteria criteria) { int numPasses = 0; - Set rv = new HashSet(criteria.getMinimumRequired()); + List rv = new ArrayList(criteria.getMinimumRequired()); Set exclude = new HashSet(1); exclude.add(_context.routerHash()); while (rv.size() < criteria.getMinimumRequired()) { @@ -86,7 +89,12 @@ class PeerManager { _organizer.selectHighCapacityPeers(criteria.getMinimumRequired(), exclude, curVals); break; case PeerSelectionCriteria.PURPOSE_TUNNEL: - _organizer.selectFastPeers(criteria.getMinimumRequired(), exclude, curVals); + // 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); break; case PeerSelectionCriteria.PURPOSE_SOURCE_ROUTE: _organizer.selectHighCapacityPeers(criteria.getMinimumRequired(), exclude, curVals); @@ -111,7 +119,8 @@ class PeerManager { 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"); - rv.add(peer); + 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"); @@ -123,6 +132,29 @@ class PeerManager { } 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); + } return rv; } diff --git a/router/java/src/net/i2p/router/peermanager/PeerManagerFacadeImpl.java b/router/java/src/net/i2p/router/peermanager/PeerManagerFacadeImpl.java index 0c806a625..a8bbee491 100644 --- a/router/java/src/net/i2p/router/peermanager/PeerManagerFacadeImpl.java +++ b/router/java/src/net/i2p/router/peermanager/PeerManagerFacadeImpl.java @@ -56,7 +56,7 @@ public class PeerManagerFacadeImpl implements PeerManagerFacade { } public List selectPeers(PeerSelectionCriteria criteria) { - return new ArrayList(_manager.selectPeers(criteria)); + return _manager.selectPeers(criteria); } public void renderStatusHTML(OutputStream out) throws IOException { diff --git a/router/java/src/net/i2p/router/peermanager/PeerTestJob.java b/router/java/src/net/i2p/router/peermanager/PeerTestJob.java index 970f30204..964eddc9a 100644 --- a/router/java/src/net/i2p/router/peermanager/PeerTestJob.java +++ b/router/java/src/net/i2p/router/peermanager/PeerTestJob.java @@ -89,7 +89,7 @@ public class PeerTestJob extends JobImpl { criteria.setMinimumRequired(getTestConcurrency()); criteria.setMaximumRequired(getTestConcurrency()); criteria.setPurpose(PeerSelectionCriteria.PURPOSE_TEST); - Set peerHashes = _manager.selectPeers(criteria); + List peerHashes = _manager.selectPeers(criteria); if (_log.shouldLog(Log.DEBUG)) _log.debug("Peer selection found " + peerHashes.size() + " peers");