* I2PSnark:

- Fix (again) partial piece avoidance for seeds
   - Fix several partial piece (temp file) leaks,
     some uncovered by previous rarest-first fixes, some in end game
   - Don't lose all DHT peers if we stop quickly (backport from update branch)
   - Explore a kbucket if it's less than 3/4 full (backport from update branch)
This commit is contained in:
zzz
2012-10-24 17:38:20 +00:00
parent 211128f128
commit 97da508df5
7 changed files with 43 additions and 8 deletions

View File

@ -518,6 +518,7 @@ public class KBucketSet<T extends SimpleDataStructure> {
/** /**
* For every bucket that hasn't been updated in this long, * For every bucket that hasn't been updated in this long,
* or isn't close to full,
* generate a random key that would be a member of that bucket. * generate a random key that would be a member of that bucket.
* The returned keys may be searched for to "refresh" the buckets. * The returned keys may be searched for to "refresh" the buckets.
* @return non-null, closest first * @return non-null, closest first
@ -528,7 +529,7 @@ public class KBucketSet<T extends SimpleDataStructure> {
getReadLock(); getReadLock();
try { try {
for (KBucket b : _buckets) { for (KBucket b : _buckets) {
if (b.getLastChanged() < old) if (b.getLastChanged() < old || b.getKeyCount() < BUCKET_SIZE * 3 / 4)
rv.add(generateRandomKey(b)); rv.add(generateRandomKey(b));
} }
} finally { releaseReadLock(); } } finally { releaseReadLock(); }

View File

@ -741,7 +741,19 @@ class PeerCoordinator implements PeerListener
break; break;
if (havePieces.get(p.getId()) && !p.isRequested()) if (havePieces.get(p.getId()) && !p.isRequested())
{ {
piece = p; // never ever choose one that's in partialPieces, or we
// will create a second one and leak
boolean hasPartial = false;
for (PartialPiece pp : partialPieces) {
if (pp.getPiece() == p.getId()) {
if (_log.shouldLog(Log.INFO))
_log.info("wantPiece() skipping partial for " + peer + ": piece = " + pp);
hasPartial = true;
break;
}
}
if (!hasPartial)
piece = p;
} }
else if (p.isRequested()) else if (p.isRequested())
{ {
@ -943,11 +955,14 @@ class PeerCoordinator implements PeerListener
*/ */
public boolean gotPiece(Peer peer, PartialPiece pp) public boolean gotPiece(Peer peer, PartialPiece pp)
{ {
if (metainfo == null || storage == null) if (metainfo == null || storage == null) {
pp.release();
return true; return true;
}
int piece = pp.getPiece(); int piece = pp.getPiece();
if (halted) { if (halted) {
_log.info("Got while-halted piece " + piece + "/" + metainfo.getPieces() +" from " + peer + " for " + metainfo.getName()); _log.info("Got while-halted piece " + piece + "/" + metainfo.getPieces() +" from " + peer + " for " + metainfo.getName());
pp.release();
return true; // We don't actually care anymore. return true; // We don't actually care anymore.
} }
@ -962,8 +977,10 @@ class PeerCoordinator implements PeerListener
// Assume we got a good piece, we don't really care anymore. // Assume we got a good piece, we don't really care anymore.
// Well, this could be caused by a change in priorities, so // Well, this could be caused by a change in priorities, so
// only return true if we already have it, otherwise might as well keep it. // only return true if we already have it, otherwise might as well keep it.
if (storage.getBitField().get(piece)) if (storage.getBitField().get(piece)) {
pp.release();
return true; return true;
}
} }
try try
@ -1277,6 +1294,7 @@ class PeerCoordinator implements PeerListener
PartialPiece pp = iter.next(); PartialPiece pp = iter.next();
if (pp.getPiece() == piece) { if (pp.getPiece() == piece) {
iter.remove(); iter.remove();
pp.release();
// there should be only one but keep going to be sure // there should be only one but keep going to be sure
} }
} }

View File

@ -592,6 +592,7 @@ class PeerState implements DataLoader
// Send cancel even when we are choked to make sure that it is // Send cancel even when we are choked to make sure that it is
// really never ever send. // really never ever send.
out.sendCancel(req); out.sendCancel(req);
req.getPartialPiece().release();
} }
} }
} }
@ -741,6 +742,10 @@ class PeerState implements DataLoader
out.sendRequest(r); out.sendRequest(r);
lastRequest = r; lastRequest = r;
return true; return true;
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("Got dup from coord: " + pp);
pp.release();
} }
} }

View File

@ -572,7 +572,9 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
_session.removeListener(I2PSession.PROTO_DATAGRAM_RAW, _rPort); _session.removeListener(I2PSession.PROTO_DATAGRAM_RAW, _rPort);
// clear the DHT and tracker // clear the DHT and tracker
_tracker.stop(); _tracker.stop();
PersistDHT.saveDHT(_knownNodes, _dhtFile); // don't lose all our peers if we didn't have time to check them
boolean saveAll = _context.clock().now() - _started < 20*60*1000;
PersistDHT.saveDHT(_knownNodes, saveAll, _dhtFile);
_knownNodes.stop(); _knownNodes.stop();
for (Iterator<ReplyWaiter> iter = _sentQueries.values().iterator(); iter.hasNext(); ) { for (Iterator<ReplyWaiter> iter = _sentQueries.values().iterator(); iter.hasNext(); ) {
ReplyWaiter waiter = iter.next(); ReplyWaiter waiter = iter.next();

View File

@ -56,12 +56,15 @@ abstract class PersistDHT {
log.info("Loaded " + count + " nodes from " + file); log.info("Loaded " + count + " nodes from " + file);
} }
public static synchronized void saveDHT(DHTNodes nodes, File file) { /**
* @param saveAll if true, don't check last seen time
*/
public static synchronized void saveDHT(DHTNodes nodes, boolean saveAll, File file) {
if (nodes.size() <= 0) if (nodes.size() <= 0)
return; return;
Log log = I2PAppContext.getGlobalContext().logManager().getLog(PersistDHT.class); Log log = I2PAppContext.getGlobalContext().logManager().getLog(PersistDHT.class);
int count = 0; int count = 0;
long maxAge = I2PAppContext.getGlobalContext().clock().now() - MAX_AGE; long maxAge = saveAll ? 0 : I2PAppContext.getGlobalContext().clock().now() - MAX_AGE;
PrintWriter out = null; PrintWriter out = null;
try { try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(file), "ISO-8859-1"))); out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(file), "ISO-8859-1")));

View File

@ -1,3 +1,9 @@
2012-10-24 zzz
* I2PSnark:
- Fix several partial piece (temp file) leaks
- Don't lose all DHT peers if we stop quickly
- Explore a kbucket if it's less than 3/4 full
2012-10-24 str4d 2012-10-24 str4d
* i2ptunnel: Truncate long client destinations (ticket #581) * i2ptunnel: Truncate long client destinations (ticket #581)

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */ /** deprecated */
public final static String ID = "Monotone"; public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION; public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 18; public final static long BUILD = 19;
/** for example "-test" */ /** for example "-test" */
public final static String EXTRA = "-rc"; public final static String EXTRA = "-rc";