diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java index 3fb39ce96b9f43d6a5270dc8f7b344373fb1083d..ce4a0658ac8a7ac1b6889d0dd16df64e68a505b8 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java @@ -69,13 +69,12 @@ public class PeerCoordinator implements PeerListener this.storage = storage; this.listener = listener; - // Make a random list of piece numbers + // Make a list of pieces wantedPieces = new ArrayList(); BitField bitfield = storage.getBitField(); for(int i = 0; i < metainfo.getPieces(); i++) if (!bitfield.get(i)) - wantedPieces.add(new Integer(i)); - Collections.shuffle(wantedPieces); + wantedPieces.add(new Piece(i)); // Install a timer to check the uploaders. timer.schedule(new PeerCheckerTask(this), CHECK_PERIOD, CHECK_PERIOD); @@ -288,7 +287,7 @@ public class PeerCoordinator implements PeerListener synchronized(wantedPieces) { - return wantedPieces.contains(new Integer(piece)); + return wantedPieces.contains(new Piece(piece)); } } @@ -306,8 +305,10 @@ public class PeerCoordinator implements PeerListener Iterator it = wantedPieces.iterator(); while (it.hasNext()) { - int i = ((Integer)it.next()).intValue(); + Piece p = (Piece)it.next(); + int i = p.getId(); if (bitfield.get(i)) + p.addPeer(peer); return true; } } @@ -325,28 +326,38 @@ public class PeerCoordinator implements PeerListener synchronized(wantedPieces) { - Integer piece = null; + Piece piece = null; + Collections.sort(wantedPieces); // Sort in order of rarest first. + List requested = new ArrayList(); Iterator it = wantedPieces.iterator(); while (piece == null && it.hasNext()) { - Integer i = (Integer)it.next(); - if (havePieces.get(i.intValue())) + Piece p = (Piece)it.next(); + if (havePieces.get(p.getId()) && !p.isRequested()) { - it.remove(); - piece = i; + piece = p; } + else if (p.isRequested()) + { + requested.add(p); + } } - - if (piece == null) - return -1; - - // We add it back at the back of the list. It will be removed - // if gotPiece is called later. This means that the last - // couple of pieces might very well be asked from multiple - // peers but that is OK. - wantedPieces.add(piece); - - return piece.intValue(); + + //Only request a piece we've requested before if there's no other choice. + if (piece == null) { + Iterator it2 = requested.iterator(); + while (piece == null && it2.hasNext()) + { + Piece p = (Piece)it2.next(); + if (havePieces.get(p.getId())) + { + piece = p; + } + } + if (piece == null) return -1; //If we still can't find a piece we want, so be it. + } + piece.setRequested(true); + return piece.getId(); } } @@ -404,7 +415,7 @@ public class PeerCoordinator implements PeerListener synchronized(wantedPieces) { - Integer p = new Integer(piece); + Piece p = new Piece(piece); if (!wantedPieces.contains(p)) { if (Snark.debug >= Snark.INFO) diff --git a/apps/i2psnark/java/src/org/klomp/snark/Piece.java b/apps/i2psnark/java/src/org/klomp/snark/Piece.java new file mode 100644 index 0000000000000000000000000000000000000000..d98421b99252babe3f3564b05d10f1d65c2e738c --- /dev/null +++ b/apps/i2psnark/java/src/org/klomp/snark/Piece.java @@ -0,0 +1,35 @@ +package org.klomp.snark; + +import java.util.Set; +import java.util.HashSet; + +public class Piece implements Comparable { + + private int id; + private Set peers; + private boolean requested; + + public Piece(int id) { + this.id = id; + this.peers = new HashSet(); + } + + public int compareTo(Object o) throws ClassCastException { + return this.peers.size() - ((Piece)o).peers.size(); + } + + public boolean equals(Object o) { + if (o == null) return false; + try { + return this.id == ((Piece)o).id; + } catch (ClassCastException cce) { + return false; + } + } + + public int getId() { return this.id; } + public Set getPeers() { return this.peers; } + public boolean addPeer(Peer peer) { return this.peers.add(peer.getPeerID()); } + public boolean isRequested() { return this.requested; } + public void setRequested(boolean requested) { this.requested = requested; } +}