From 523d39b3bbbe00dd10d4c5e620966a3477eb340a Mon Sep 17 00:00:00 2001 From: zzz Date: Wed, 15 Aug 2012 12:44:46 +0000 Subject: [PATCH] * i2psnark: - Fix bug preventing completion announcement, broken in 0.9.1 - Fix setting short retry time after initial announce failure - Fix DHT announce and getPeers - Fix DHT warning message - log tweaks --- .../src/org/klomp/snark/SnarkManager.java | 2 +- .../src/org/klomp/snark/TrackerClient.java | 41 +++++++++--------- .../java/src/org/klomp/snark/dht/DHT.java | 6 +-- .../java/src/org/klomp/snark/dht/KRPC.java | 42 +++++++++++-------- history.txt | 7 ++++ .../src/net/i2p/router/RouterVersion.java | 2 +- 6 files changed, 56 insertions(+), 44 deletions(-) diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index 94609432fa..e755fcc7a7 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -828,7 +828,7 @@ public class SnarkManager implements Snark.CompleteListener { } else if (_util.shouldUseOpenTrackers() && _util.getOpenTrackers() != null) { addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName())); //addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers only.", info.getName())); - } else if (_util.getDHT() != null) { + } else if (_util.shouldUseDHT()) { addMessage(_("Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will announce to DHT only.", info.getName())); } else { addMessage(_("Warning - No I2P trackers in \"{0}\", and DHT and open trackers are disabled, you should enable open trackers or DHT before starting the torrent.", info.getName())); diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java index 826b659650..4f08e7bb26 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java +++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java @@ -27,6 +27,7 @@ import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Iterator; @@ -100,6 +101,7 @@ public class TrackerClient implements Runnable { // these 2 used in loop() private volatile boolean runStarted; private volatile int consecutiveFails; + private boolean completed; private volatile boolean _fastUnannounce; private final List trackers; @@ -218,11 +220,16 @@ public class TrackerClient implements Runnable { try { if (!_initialized) { setup(); - // FIXME dht - if (trackers.isEmpty()) { - stop = true; - return; - } + } + if (trackers.isEmpty() && _util.getDHT() == null) { + stop = true; + this.snark.addMessage(_util.getString("No valid trackers for {0} - enable opentrackers or DHT?", + this.snark.getBaseName())); + _log.error("No valid trackers for " + this.snark.getBaseName()); + this.snark.stopTorrent(); + return; + } + if (!_initialized) { _initialized = true; // FIXME only when starting everybody at once, not for a single torrent long delay = I2PAppContext.getGlobalContext().random().nextInt(30*1000); @@ -296,15 +303,7 @@ public class TrackerClient implements Runnable { _log.debug("Additional announce: [" + url + "] for infoHash: " + infoHash); } } - - if (trackers.isEmpty() && _util.getDHT() == null) { - stop = true; - this.snark.addMessage(_util.getString("No valid trackers for {0} - enable opentrackers or DHT?", - this.snark.getBaseName())); - _log.error("No valid trackers for " + this.snark.getBaseName()); - this.snark.stopTorrent(); - return; - } + this.completed = coordinator.getLeft() == 0; } /** @@ -331,7 +330,6 @@ public class TrackerClient implements Runnable { long uploaded = coordinator.getUploaded(); long downloaded = coordinator.getDownloaded(); long left = coordinator.getLeft(); // -1 in magnet mode - boolean completed = (left == 0); // First time we got a complete download? String event; @@ -345,8 +343,7 @@ public class TrackerClient implements Runnable { // *** loop once for each tracker int maxSeenPeers = 0; - for (Iterator iter = trackers.iterator(); iter.hasNext(); ) { - Tracker tr = (Tracker)iter.next(); + for (Tracker tr : trackers) { if ((!stop) && (!tr.stop) && (completed || coordinator.needOutboundPeers() || !tr.started) && (event.equals(COMPLETED_EVENT) || System.currentTimeMillis() > tr.lastRequestTime + tr.interval)) @@ -468,7 +465,9 @@ public class TrackerClient implements Runnable { numwant = 1; else numwant = _util.getMaxConnections(); - List hashes = dht.getPeers(snark.getInfoHash(), numwant, 2*60*1000); + Collection hashes = dht.getPeers(snark.getInfoHash(), numwant, 2*60*1000); + if (!hashes.isEmpty()) + runStarted = true; if (_log.shouldLog(Log.INFO)) _log.info("Got " + hashes + " from DHT"); // announce ourselves while the token is still good @@ -509,10 +508,6 @@ public class TrackerClient implements Runnable { if (stop) return; - if (!runStarted) - if (_log.shouldLog(Log.DEBUG)) - _log.debug(" Retrying in one minute..."); - try { // Sleep some minutes... // Sleep the minimum interval for all the trackers, but 60s minimum @@ -522,6 +517,8 @@ public class TrackerClient implements Runnable { delay = 3*SLEEP*60*1000 + random; else if (snark.getTrackerProblems() != null && ++consecutiveFails < MAX_CONSEC_FAILS) delay = INITIAL_SLEEP; + else if ((!runStarted) && _runCount < MAX_CONSEC_FAILS) + delay = INITIAL_SLEEP; else // sleep a while, when we wake up we will contact only the trackers whose intervals have passed delay = SLEEP*60*1000 + random; diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/DHT.java b/apps/i2psnark/java/src/org/klomp/snark/dht/DHT.java index d5b8913ffd..9e629415b4 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/dht/DHT.java +++ b/apps/i2psnark/java/src/org/klomp/snark/dht/DHT.java @@ -4,7 +4,7 @@ package org.klomp.snark.dht; * GPLv2 */ -import java.util.List; +import java.util.Collection; import net.i2p.data.Destination; import net.i2p.data.Hash; @@ -42,9 +42,9 @@ public interface DHT { * @param ih the Info Hash (torrent) * @param max maximum number of peers to return * @param maxWait the maximum time to wait (ms) must be > 0 - * @return list or empty list (never null) + * @return possibly empty (never null) */ - public List getPeers(byte[] ih, int max, long maxWait); + public Collection getPeers(byte[] ih, int max, long maxWait); /** * Announce to ourselves. diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java b/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java index 01364a3968..0bec326d34 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java +++ b/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java @@ -299,25 +299,28 @@ public class KRPC implements I2PSessionMuxedListener, DHT { * @param ih the Info Hash (torrent) * @param max maximum number of peers to return * @param maxWait the maximum time to wait (ms) must be > 0 - * @return list or empty list (never null) + * @return possibly empty (never null) */ - public List getPeers(byte[] ih, int max, long maxWait) { + public Collection getPeers(byte[] ih, int max, long maxWait) { // check local tracker first InfoHash iHash = new InfoHash(ih); - List rv = _tracker.getPeers(iHash, max); + Collection rv = _tracker.getPeers(iHash, max); rv.remove(_myNodeInfo.getHash()); - if (!rv.isEmpty()) - return rv; // TODO get DHT too? + if (rv.size() >= max) + return rv; + rv = new HashSet(rv); + long endTime = _context.clock().now() + maxWait; // Initial set to try, will get added to as we go - List nodes = _knownNodes.findClosest(iHash, max); + int maxNodes = 12; + List nodes = _knownNodes.findClosest(iHash, maxNodes); SortedSet toTry = new TreeSet(new NodeInfoComparator(iHash)); toTry.addAll(nodes); Set tried = new HashSet(); if (_log.shouldLog(Log.INFO)) - _log.info("Starting getPeers with " + nodes.size() + " to try"); - for (int i = 0; i < max; i++) { + _log.info("Starting getPeers for " + iHash + " with " + nodes.size() + " to try"); + for (int i = 0; i < maxNodes; i++) { if (!_isRunning) break; NodeInfo nInfo; @@ -334,7 +337,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT { continue; synchronized(waiter) { try { - waiter.wait(maxWait); + waiter.wait(Math.max(20*1000, (Math.min(40*1000, endTime - _context.clock().now())))); } catch (InterruptedException ie) {} } @@ -350,9 +353,12 @@ public class KRPC implements I2PSessionMuxedListener, DHT { _log.info("Got peers"); List reply = (List) waiter.getReplyObject(); if (!reply.isEmpty()) { + for (int j = 0; j < reply.size() && rv.size() < max; j++) { + rv.add(reply.get(j)); + } if (_log.shouldLog(Log.INFO)) - _log.info("Finished get Peers, returning " + reply.size()); - return reply; + _log.info("Finished get Peers, got " + rv.size() + " from DHT, returning " + reply.size()); + return rv; } } else if (replyType == REPLY_NODES) { List reply = (List) waiter.getReplyObject(); @@ -366,10 +372,12 @@ public class KRPC implements I2PSessionMuxedListener, DHT { if (_log.shouldLog(Log.INFO)) _log.info("Got unexpected reply " + replyType + ": " + waiter.getReplyObject()); } + if (_context.clock().now() > endTime) + break; } if (_log.shouldLog(Log.INFO)) - _log.info("Finished get Peers, fail"); - return Collections.EMPTY_LIST; + _log.info("Finished get Peers, " + rv.size() + " from local and none from DHT"); + return rv; } /** @@ -465,7 +473,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT { if (maxWait <= 0) return false; if (_log.shouldLog(Log.INFO)) - _log.info("No token for announce to " + nInfo + " sending get_peers first"); + _log.info("No token for announce to " + nInfo + ", sending get_peers first"); ReplyWaiter waiter = sendGetPeers(nInfo, iHash); if (waiter == null) return false; @@ -478,20 +486,20 @@ public class KRPC implements I2PSessionMuxedListener, DHT { int replyType = waiter.getReplyCode(); if (!(replyType == REPLY_PEERS || replyType == REPLY_NODES)) { if (_log.shouldLog(Log.INFO)) - _log.info("Get_peers failed to " + nInfo); + _log.info("Get_peers in announce() failed to " + nInfo); return false; } // we should have a token now token = _incomingTokens.get(nInfo.getNID()); if (token == null) { if (_log.shouldLog(Log.INFO)) - _log.info("Huh? no token after get_peers succeeded to " + nInfo); + _log.info("Huh? no token after get_peers in announce() succeeded to " + nInfo); return false; } maxWait -= _context.clock().now() - start; if (maxWait < 1000) { if (_log.shouldLog(Log.INFO)) - _log.info("Ran out of time after get_peers succeeded to " + nInfo); + _log.info("Ran out of time after get_peers in announce() succeeded to " + nInfo); return false; } } diff --git a/history.txt b/history.txt index 55ab9e5902..a7ca76565a 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,10 @@ +2012-08-15 zzz + * i2psnark: + - Fix bug preventing completion announcement, broken in 0.9.1 + - Fix setting short retry time after initial announce failure + - Fix DHT announce and getPeers + - Fix DHT warning message + 2012-08-13 zzz * SSU EstablishmentManager: - Remove use of outbound timers in EstablishmentManager; drive all events in Establisher thread diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index f2522cd4ed..7ca1a3ec2c 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 9; + public final static long BUILD = 10; /** for example "-test" */ public final static String EXTRA = "";