diff --git a/apps/i2psnark/java/src/org/klomp/snark/BitField.java b/apps/i2psnark/java/src/org/klomp/snark/BitField.java index c1c238cec..3534a8d7e 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/BitField.java +++ b/apps/i2psnark/java/src/org/klomp/snark/BitField.java @@ -170,7 +170,24 @@ public class BitField return count >= size; } - @Override + /** @since 0.9.33 */ + @Override + public int hashCode() { + return (count << 16) ^ size; + } + + /** @since 0.9.33 */ + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof BitField)) + return false; + BitField bf = (BitField) o; + return count == bf.count() && + size == bf.size() && + Arrays.equals(bitfield, bf.getFieldBytes()); + } + + @Override public String toString() { // Not very efficient diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index 11825d09f..ab181172a 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -892,9 +892,7 @@ public class Storage implements Closeable * @since 0.9.23 */ public boolean recheck() throws IOException { - int previousNeeded = needed; - checkCreateFiles(true); - boolean changed = previousNeeded != needed; + boolean changed = checkCreateFiles(true); if (listener != null && changed) listener.setWantedPieces(this); return changed; @@ -910,19 +908,23 @@ public class Storage implements Closeable * @param recheck if true, this is a check after we downloaded the * last piece, and we don't modify the global bitfield unless * the check fails. + * @return true if changed (only valid if recheck == true) */ - private void checkCreateFiles(boolean recheck) throws IOException { + private boolean checkCreateFiles(boolean recheck) throws IOException { synchronized(this) { _isChecking = true; try { - locked_checkCreateFiles(recheck); + return locked_checkCreateFiles(recheck); } finally { _isChecking = false; } } } - private void locked_checkCreateFiles(boolean recheck) throws IOException + /** + * @return true if changed (only valid if recheck == true) + */ + private boolean locked_checkCreateFiles(boolean recheck) throws IOException { _checkProgress.set(0); // Whether we are resuming or not, @@ -1033,9 +1035,11 @@ public class Storage implements Closeable // do this here so we don't confuse the user during checking needed = need; - if (recheck && need > 0) { - // whoops, recheck failed + boolean rv = false; + if (recheck) { + // FIXME bogus synch synchronized(bitfield) { + rv = !bfield.equals(bitfield); bitfield = bfield; } } @@ -1045,6 +1049,7 @@ public class Storage implements Closeable if (needed <= 0) listener.storageCompleted(this); } + return rv; } /** diff --git a/history.txt b/history.txt index a4478327f..d7b21a8b5 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,7 @@ +2017-11-16 zzz + * i2psnark: Fix bad completion status after recheck (ticket #2046) + * Jetty 9.2.22 + 2017-11-07 zzz * Utils: Constant-time password check diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 87e5bffca..282c18b42 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 = 1; + public final static long BUILD = 2; /** for example "-test" */ public final static String EXTRA = "";