diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java index ced568f47..2a45b0937 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java @@ -65,7 +65,7 @@ public class PeerCoordinator implements PeerListener private final byte[] id; // Some random wanted pieces - private final List wantedPieces; + private List wantedPieces; private boolean halted = false; @@ -83,6 +83,15 @@ public class PeerCoordinator implements PeerListener this.listener = listener; this.snark = torrent; + setWantedPieces(); + + // Install a timer to check the uploaders. + timer.schedule(new PeerCheckerTask(this), CHECK_PERIOD, CHECK_PERIOD); + } + + // only called externally from Storage after the double-check fails + public void setWantedPieces() + { // Make a list of pieces wantedPieces = new ArrayList(); BitField bitfield = storage.getBitField(); @@ -90,11 +99,8 @@ public class PeerCoordinator implements PeerListener if (!bitfield.get(i)) wantedPieces.add(new Piece(i)); Collections.shuffle(wantedPieces); - - // Install a timer to check the uploaders. - timer.schedule(new PeerCheckerTask(this), CHECK_PERIOD, CHECK_PERIOD); } - + public Storage getStorage() { return storage; } public CoordinatorListener getListener() { return listener; } diff --git a/apps/i2psnark/java/src/org/klomp/snark/Snark.java b/apps/i2psnark/java/src/org/klomp/snark/Snark.java index 8b8d202e9..85cbd82e2 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Snark.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Snark.java @@ -693,6 +693,11 @@ public class Snark completeListener.torrentComplete(this); } + public void setWantedPieces(Storage storage) + { + coordinator.setWantedPieces(); + } + public void shutdown() { // Should not be necessary since all non-deamon threads should diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index c7d1eb94e..bd484279e 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -39,7 +39,7 @@ public class Storage private final StorageListener listener; - private final BitField bitfield; // BitField to represent the pieces + private BitField bitfield; // BitField to represent the pieces private int needed; // Number of pieces needed // XXX - Not always set correctly @@ -483,10 +483,11 @@ public class Storage * matches), otherwise false. * @exception IOException when some storage related error occurs. */ - public boolean putPiece(int piece, byte[] bs) throws IOException + public boolean putPiece(int piece, byte[] ba) throws IOException { // First check if the piece is correct. - // If we were paranoia we could copy the array first. + // Copy the array first to be paranoid. + byte[] bs = (byte[]) ba.clone(); int length = bs.length; boolean correctHash = metainfo.checkPiece(piece, bs, 0, length); if (listener != null) @@ -505,6 +506,7 @@ public class Storage needed--; complete = needed == 0; } + } // Early typecast, avoid possibly overflowing a temp integer @@ -539,9 +541,25 @@ public class Storage } if (complete) { - listener.storageCompleted(this); +// listener.storageCompleted(this); // do we also need to close all of the files and reopen // them readonly? + + // Do a complete check to be sure. + // Temporarily resets the 'needed' variable and 'bitfield', then call + // checkCreateFiles() which will set 'needed' and 'bitfield' + // and also call listener.storageCompleted() if the double-check + // was successful. + // Todo: set a listener variable so the web shows "checking" and don't + // have the user panic when completed amount goes to zero temporarily? + needed = metainfo.getPieces(); + bitfield = new BitField(needed); + checkCreateFiles(); + if (needed > 0) { + listener.setWantedPieces(this); + Snark.debug("WARNING: Not really done, missing " + needed + + " pieces", Snark.WARNING); + } } return true; diff --git a/apps/i2psnark/java/src/org/klomp/snark/StorageListener.java b/apps/i2psnark/java/src/org/klomp/snark/StorageListener.java index c9fcf5ae6..8e520d41f 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/StorageListener.java +++ b/apps/i2psnark/java/src/org/klomp/snark/StorageListener.java @@ -55,4 +55,11 @@ public interface StorageListener * */ void storageCompleted(Storage storage); + + /** Reset the peer's wanted pieces table + * Call after the storage double-check fails + * + * @param peer the peer + */ + void setWantedPieces(Storage storage); } diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java index 6b8135f1f..764f69111 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java +++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java @@ -175,8 +175,10 @@ public class TrackerClient extends I2PThread { // Sleep some minutes... int delay; - if(coordinator.trackerProblems != null) { + if(coordinator.trackerProblems != null && !completed) { delay = 60*1000; + } else if(completed) { + delay = 3*SLEEP*60*1000 + r.nextInt(120*1000); } else { delay = SLEEP*60*1000 + r.nextInt(120*1000); delay -= sleptTime; @@ -209,6 +211,7 @@ public class TrackerClient extends I2PThread event = NO_EVENT; // Only do a request when necessary. + sleptTime = 0; if (event == COMPLETED_EVENT || coordinator.needPeers() || System.currentTimeMillis() > lastRequestTime + interval) @@ -220,7 +223,6 @@ public class TrackerClient extends I2PThread event); coordinator.trackerProblems = null; - sleptTime = 0; Set peers = info.getPeers(); coordinator.trackerSeenPeers = peers.size(); if ( (left > 0) && (!completed) ) { diff --git a/history.txt b/history.txt index 8ad8d7c3e..b9be476f9 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,9 @@ -$Id: history.txt,v 1.523 2006-09-20 17:39:26 zzz Exp $ +$Id: history.txt,v 1.524 2006-09-24 13:30:23 zzz Exp $ + +2006-09-25 zzz + * i2psnark: Paranoid copy before writing pieces, + recheck files on completion, redownload bad pieces + * i2psnark: Don't contact tracker as often when seeding 2006-09-24 zzz * i2psnark: Add some synchronization to prevent rare problem diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index f274de973..1629a20e1 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -15,9 +15,9 @@ import net.i2p.CoreVersion; * */ public class RouterVersion { - public final static String ID = "$Revision: 1.460 $ $Date: 2006-09-20 17:39:24 $"; + public final static String ID = "$Revision: 1.461 $ $Date: 2006-09-24 13:30:22 $"; public final static String VERSION = "0.6.1.25"; - public final static long BUILD = 7; + public final static long BUILD = 8; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("Router ID: " + RouterVersion.ID);