Author: robert
Date: 2008-01-29 18:39:55 +0000 (Tue, 29 Jan 2008)
New Revision: 17398
Modified:
trunk/freenet/src/freenet/node/PeerManager.java
Log:
scan array once for finding closerPeer (with & without backoff)
Modified: trunk/freenet/src/freenet/node/PeerManager.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerManager.java 2008-01-29 18:12:09 UTC
(rev 17397)
+++ trunk/freenet/src/freenet/node/PeerManager.java 2008-01-29 18:39:55 UTC
(rev 17398)
@@ -696,55 +696,71 @@
}
/*
- * FIXME
- * This scans the same array 4 times. It would be better to scan once and
execute 4 callbacks...
- * For this reason the metrics are only updated if advanced mode is enabled
+ * Because in the past this function would scan the array four times, the
metrics are only updated if advanced mode is enabled
*/
public PeerNode closerPeer(PeerNode pn, Set routedTo, Set notIgnored,
double loc, boolean ignoreSelf, boolean calculateMisrouting, int minVersion,
Vector addUnpickedLocsTo, double maxDistance) {
- PeerNode best = closerPeerBackoff(pn, routedTo, notIgnored, loc,
ignoreSelf, minVersion, addUnpickedLocsTo, maxDistance);
-
+ CloserPeerReturn retval = _closerPeer(pn, routedTo, notIgnored, loc,
ignoreSelf, minVersion, addUnpickedLocsTo, maxDistance);
+ PeerNode best = retval.closestNotBackedOff;
+
+ if (best==null)
+ best = retval.closestBackedOff;
+
if (calculateMisrouting) {
- PeerNode nbo = _closerPeer(pn, routedTo, notIgnored, loc,
ignoreSelf, true, minVersion, null, maxDistance);
- if(nbo != null) {
+ PeerNode nbo = retval.closestNotBackedOff;
+ if (nbo != null) {
node.nodeStats.routingMissDistance.report(Location.distance(best,
nbo.getLocation()));
int numberOfConnected =
getPeerNodeStatusSize(PEER_NODE_STATUS_CONNECTED, false);
int numberOfRoutingBackedOff =
getPeerNodeStatusSize(PEER_NODE_STATUS_ROUTING_BACKED_OFF, false);
if (numberOfRoutingBackedOff + numberOfConnected > 0 ) {
node.nodeStats.backedOffPercent.report((double)
numberOfRoutingBackedOff / (double) (numberOfRoutingBackedOff +
numberOfConnected));
}
- }
+ }
}
+
+ if (best!=null && addUnpickedLocsTo!=null) {
+ //Add the location which we did not pick, if it exists.
+ if (retval.closestNotBackedOff!=null &&
retval.closestBackedOff!=null)
+ addUnpickedLocsTo.add(new
Double(retval.closestBackedOff.getLocation()));
+ }
+
return best;
}
-
- private PeerNode closerPeerBackoff(PeerNode pn, Set routedTo, Set
notIgnored, double loc, boolean ignoreSelf, int minVersion, Vector
addUnpickedLocsTo, double maxDistance) {
- PeerNode best = _closerPeer(pn, routedTo, notIgnored, loc, ignoreSelf,
false, minVersion, addUnpickedLocsTo, maxDistance);
- if(best == null) {
- best = _closerPeer(pn, routedTo, notIgnored, loc, ignoreSelf,
true, minVersion, addUnpickedLocsTo, maxDistance);
- }
- return best;
+
+ private static class CloserPeerReturn {
+ PeerNode closest;
+ double closestDistance;
+
+ PeerNode closestBackedOff;
+ double closestBackedOffDistance;
+
+ PeerNode closestNotBackedOff;
+ double closestNotBackedOffDistance;
}
/**
- * Find the peer, if any, which is closer to the target location
- * than we are, and is not included in the provided set.
+ * Find the peer, if any, which is closer to the target location than we
are, and is not included in the provided set.
+ * If ignoreSelf==false, and we are closer to the target than any
peers, this function returns null.
+ * This function returns two values, the closest such peer which is
backed off, and the same which is not backed off.
+ * It is possible for either to be null independant of the other,
'closest' is the closer of the two in either case, and
+ * will not be null if any of the other two return values is not null.
* @param addUnpickedLocsTo Add all locations we didn't choose which we
could have routed to to
* this array. Remove the location of the peer we pick from it.
* @param maxDistance If a node is further away from the target than
this distance, ignore it.
*/
- private PeerNode _closerPeer(PeerNode pn, Set routedTo, Set notIgnored,
double target, boolean ignoreSelf, boolean ignoreBackedOff, int minVersion,
Vector addUnpickedLocsTo, double maxDistance) {
+ private CloserPeerReturn _closerPeer(PeerNode pn, Set routedTo, Set
notIgnored, double target, boolean ignoreSelf, int minVersion, Vector
addUnpickedLocsTo, double maxDistance) {
PeerNode[] peers;
synchronized (this) {
peers = connectedPeers;
}
if(logMINOR) Logger.minor(this, "Choosing closest peer:
connectedPeers="+peers.length);
- double bestDiff = Double.MAX_VALUE;
- double maxDiff = 0.0;
+ double maxDiff = Double.MAX_VALUE;
if(!ignoreSelf)
maxDiff = Location.distance(node.lm.getLocation(), target);
- PeerNode best = null;
- double bestLoc = -2;
- int count = 0;
+ CloserPeerReturn ret=new CloserPeerReturn();
+ ret.closestDistance = Double.MAX_VALUE;
+ ret.closestBackedOffDistance = Double.MAX_VALUE;
+ ret.closestNotBackedOffDistance = Double.MAX_VALUE;
+ int count = 0;
for(int i=0;i<peers.length;i++) {
PeerNode p = peers[i];
if(routedTo.contains(p)) {
@@ -759,39 +775,48 @@
if(logMINOR) Logger.minor(this, "Skipping (not connected):
"+p.getPeer());
continue;
}
- if((!ignoreBackedOff) && p.isRoutingBackedOff()) {
- if(logMINOR) Logger.minor(this, "Skipping (routing backed off):
"+p.getPeer());
- continue;
- }
if(minVersion > 0 &&
Version.getArbitraryBuildNumber(p.getVersion(), -1) < minVersion) {
if(logMINOR) Logger.minor(this, "Skipping old version:
"+p.getPeer());
continue;
}
- count++;
- double diff = Location.distance(p, target);
+ //To help avoid odd race conditions, get the location
only once and use it for all calculations.
+ double loc = p.getLocation();
+ double diff = Location.distance(loc, target);
if(diff > maxDistance) continue;
- if(logMINOR) Logger.minor(this, "p.loc="+p.getLocation()+",
target="+target+", d="+Location.distance(p.getLocation(), target)+"
usedD="+diff+" for "+p.getPeer());
- if((!ignoreSelf) && (diff > maxDiff)) {
- if(logMINOR) Logger.minor(this, "Ignoring because
>maxDiff="+maxDiff);
+ if((!ignoreSelf) && (diff > maxDiff)) {
+ if(logMINOR) Logger.minor(this, "Ignoring, further than self
>maxDiff="+maxDiff);
continue;
}
- double loc = p.getLocation();
- if(diff < bestDiff) {
- bestLoc = loc;
- best = p;
- bestDiff = diff;
- if(logMINOR) Logger.minor(this, "New best: "+diff+"
("+p.getLocation()+" for "+p.getPeer());
+ count++;
+ if(logMINOR) Logger.minor(this, "p.loc="+loc+", target="+target+",
d="+Location.distance(loc, target)+" usedD="+diff+" for "+p.getPeer());
+ boolean chosen=false;
+ if(diff < ret.closestDistance) {
+ ret.closestDistance = diff;
+ ret.closest = p;
+ chosen=true;
+ if(logMINOR) Logger.minor(this, "New best: "+diff+" ("+loc+"
for "+p.getPeer());
}
- if(addUnpickedLocsTo != null) {
+ boolean backedOff=p.isRoutingBackedOff();
+ if(backedOff && (diff < ret.closestBackedOffDistance)) {
+ ret.closestBackedOffDistance = diff;
+ ret.closestBackedOff = p;
+ chosen=true;
+ if(logMINOR) Logger.minor(this, "New best-backed-off: "+diff+"
("+loc+" for "+p.getPeer());
+ }
+ if(!backedOff && (diff <
ret.closestNotBackedOffDistance)) {
+ ret.closestNotBackedOffDistance = diff;
+ ret.closestNotBackedOff = p;
+ chosen=true;
+ if(logMINOR) Logger.minor(this, "New best-not-backed-off:
"+diff+" ("+loc+" for "+p.getPeer());
+ }
+ if(addUnpickedLocsTo != null && !chosen) {
Double d = new Double(loc);
// Here we can directly compare double's because they
aren't processed in any way, and are finite and (probably) nonzero.
if(!addUnpickedLocsTo.contains(d))
addUnpickedLocsTo.add(d);
}
}
- if(addUnpickedLocsTo != null && bestLoc >= 0)
- addUnpickedLocsTo.remove(new Double(bestLoc));
- return best;
+ return ret;
}
/**