Request pieces in rarest-first order, instead of randomly.

This commit is contained in:
ragnarok
2005-10-20 22:05:51 +00:00
committed by zzz
parent 13bda1f6d7
commit 05e2da7c22
2 changed files with 68 additions and 22 deletions

View File

@ -69,13 +69,12 @@ public class PeerCoordinator implements PeerListener
this.storage = storage; this.storage = storage;
this.listener = listener; this.listener = listener;
// Make a random list of piece numbers // Make a list of pieces
wantedPieces = new ArrayList(); wantedPieces = new ArrayList();
BitField bitfield = storage.getBitField(); BitField bitfield = storage.getBitField();
for(int i = 0; i < metainfo.getPieces(); i++) for(int i = 0; i < metainfo.getPieces(); i++)
if (!bitfield.get(i)) if (!bitfield.get(i))
wantedPieces.add(new Integer(i)); wantedPieces.add(new Piece(i));
Collections.shuffle(wantedPieces);
// Install a timer to check the uploaders. // Install a timer to check the uploaders.
timer.schedule(new PeerCheckerTask(this), CHECK_PERIOD, CHECK_PERIOD); timer.schedule(new PeerCheckerTask(this), CHECK_PERIOD, CHECK_PERIOD);
@ -288,7 +287,7 @@ public class PeerCoordinator implements PeerListener
synchronized(wantedPieces) 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(); Iterator it = wantedPieces.iterator();
while (it.hasNext()) while (it.hasNext())
{ {
int i = ((Integer)it.next()).intValue(); Piece p = (Piece)it.next();
int i = p.getId();
if (bitfield.get(i)) if (bitfield.get(i))
p.addPeer(peer);
return true; return true;
} }
} }
@ -325,28 +326,38 @@ public class PeerCoordinator implements PeerListener
synchronized(wantedPieces) 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(); Iterator it = wantedPieces.iterator();
while (piece == null && it.hasNext()) while (piece == null && it.hasNext())
{ {
Integer i = (Integer)it.next(); Piece p = (Piece)it.next();
if (havePieces.get(i.intValue())) if (havePieces.get(p.getId()) && !p.isRequested())
{ {
it.remove(); piece = p;
piece = i;
} }
else if (p.isRequested())
{
requested.add(p);
}
} }
if (piece == null) //Only request a piece we've requested before if there's no other choice.
return -1; if (piece == null) {
Iterator it2 = requested.iterator();
// We add it back at the back of the list. It will be removed while (piece == null && it2.hasNext())
// if gotPiece is called later. This means that the last {
// couple of pieces might very well be asked from multiple Piece p = (Piece)it2.next();
// peers but that is OK. if (havePieces.get(p.getId()))
wantedPieces.add(piece); {
piece = p;
return piece.intValue(); }
}
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) synchronized(wantedPieces)
{ {
Integer p = new Integer(piece); Piece p = new Piece(piece);
if (!wantedPieces.contains(p)) if (!wantedPieces.contains(p))
{ {
if (Snark.debug >= Snark.INFO) if (Snark.debug >= Snark.INFO)

View File

@ -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; }
}