* i2psnark:
- Prevent dup requests during end game (ticket 331 - thanks sponge and Oct!)
This commit is contained in:
@ -261,11 +261,16 @@ class PeerState implements DataLoader
|
|||||||
|
|
||||||
// This is used to flag that we have to back up from the firstOutstandingRequest
|
// This is used to flag that we have to back up from the firstOutstandingRequest
|
||||||
// when calculating how far we've gotten
|
// when calculating how far we've gotten
|
||||||
Request pendingRequest = null;
|
private Request pendingRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a partial piece request has been handled by
|
* Called when a full chunk (i.e. a piece message) has been received by
|
||||||
* PeerConnectionIn.
|
* PeerConnectionIn.
|
||||||
|
*
|
||||||
|
* This may block quite a while if it is the last chunk for a piece,
|
||||||
|
* as it calls the listener, who stores the piece and then calls
|
||||||
|
* havePiece for every peer on the torrent (including us).
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
void pieceMessage(Request req)
|
void pieceMessage(Request req)
|
||||||
{
|
{
|
||||||
@ -273,11 +278,15 @@ class PeerState implements DataLoader
|
|||||||
downloaded += size;
|
downloaded += size;
|
||||||
listener.downloaded(peer, size);
|
listener.downloaded(peer, size);
|
||||||
|
|
||||||
pendingRequest = null;
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("got end of Chunk("
|
||||||
|
+ req.piece + "," + req.off + "," + req.len + ") from "
|
||||||
|
+ peer);
|
||||||
|
|
||||||
// Last chunk needed for this piece?
|
// Last chunk needed for this piece?
|
||||||
if (getFirstOutstandingRequest(req.piece) == -1)
|
if (getFirstOutstandingRequest(req.piece) == -1)
|
||||||
{
|
{
|
||||||
|
// warning - may block here for a while
|
||||||
if (listener.gotPiece(peer, req.piece, req.bs))
|
if (listener.gotPiece(peer, req.piece, req.bs))
|
||||||
{
|
{
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
@ -288,9 +297,15 @@ class PeerState implements DataLoader
|
|||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("Got BAD " + req.piece + " from " + peer);
|
_log.warn("Got BAD " + req.piece + " from " + peer);
|
||||||
// XXX ARGH What now !?!
|
// XXX ARGH What now !?!
|
||||||
|
// FIXME Why would we set downloaded to 0?
|
||||||
downloaded = 0;
|
downloaded = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ok done with this one
|
||||||
|
synchronized(this) {
|
||||||
|
pendingRequest = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized private int getFirstOutstandingRequest(int piece)
|
synchronized private int getFirstOutstandingRequest(int piece)
|
||||||
@ -303,15 +318,16 @@ class PeerState implements DataLoader
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a piece message is being processed by the incoming
|
* Called when a piece message is being processed by the incoming
|
||||||
* connection. Returns null when there was no such request. It also
|
* connection. That is, when the header of the piece message was received.
|
||||||
|
* Returns null when there was no such request. It also
|
||||||
* requeues/sends requests when it thinks that they must have been
|
* requeues/sends requests when it thinks that they must have been
|
||||||
* lost.
|
* lost.
|
||||||
*/
|
*/
|
||||||
Request getOutstandingRequest(int piece, int begin, int length)
|
Request getOutstandingRequest(int piece, int begin, int length)
|
||||||
{
|
{
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("getChunk("
|
_log.debug("got start of Chunk("
|
||||||
+ piece + "," + begin + "," + length + ") "
|
+ piece + "," + begin + "," + length + ") from "
|
||||||
+ peer);
|
+ peer);
|
||||||
|
|
||||||
int r = getFirstOutstandingRequest(piece);
|
int r = getFirstOutstandingRequest(piece);
|
||||||
@ -351,6 +367,9 @@ class PeerState implements DataLoader
|
|||||||
downloaded = 0; // XXX - punishment?
|
downloaded = 0; // XXX - punishment?
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// note that this request is being read
|
||||||
|
pendingRequest = req;
|
||||||
|
|
||||||
// Report missing requests.
|
// Report missing requests.
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
@ -374,13 +393,12 @@ class PeerState implements DataLoader
|
|||||||
// Request more if necessary to keep the pipeline filled.
|
// Request more if necessary to keep the pipeline filled.
|
||||||
addRequest();
|
addRequest();
|
||||||
|
|
||||||
pendingRequest = req;
|
|
||||||
return req;
|
return req;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get longest partial piece
|
// get longest partial piece
|
||||||
Request getPartialRequest()
|
synchronized Request getPartialRequest()
|
||||||
{
|
{
|
||||||
Request req = null;
|
Request req = null;
|
||||||
for (int i = 0; i < outstandingRequests.size(); i++) {
|
for (int i = 0; i < outstandingRequests.size(); i++) {
|
||||||
@ -401,10 +419,13 @@ class PeerState implements DataLoader
|
|||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return array of pieces terminated by -1
|
/**
|
||||||
// remove most duplicates
|
* return array of pieces terminated by -1
|
||||||
// but still could be some duplicates, not guaranteed
|
* remove most duplicates
|
||||||
int[] getRequestedPieces()
|
* but still could be some duplicates, not guaranteed
|
||||||
|
* TODO rework this Java-style to return a Set or a List
|
||||||
|
*/
|
||||||
|
synchronized int[] getRequestedPieces()
|
||||||
{
|
{
|
||||||
int size = outstandingRequests.size();
|
int size = outstandingRequests.size();
|
||||||
int[] arr = new int[size+2];
|
int[] arr = new int[size+2];
|
||||||
@ -514,6 +535,8 @@ class PeerState implements DataLoader
|
|||||||
* @since 0.8.1
|
* @since 0.8.1
|
||||||
*/
|
*/
|
||||||
synchronized boolean isRequesting(int piece) {
|
synchronized boolean isRequesting(int piece) {
|
||||||
|
if (pendingRequest != null && pendingRequest.piece == piece)
|
||||||
|
return true;
|
||||||
for (Request req : outstandingRequests) {
|
for (Request req : outstandingRequests) {
|
||||||
if (req.piece == piece)
|
if (req.piece == piece)
|
||||||
return true;
|
return true;
|
||||||
@ -616,6 +639,10 @@ class PeerState implements DataLoader
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note that in addition to the bitfield, PeerCoordinator uses
|
||||||
|
// its request tracking and isRequesting() to determine
|
||||||
|
// what piece to give us next.
|
||||||
int nextPiece = listener.wantPiece(peer, bitfield);
|
int nextPiece = listener.wantPiece(peer, bitfield);
|
||||||
if (nextPiece != -1
|
if (nextPiece != -1
|
||||||
&& (lastRequest == null || lastRequest.piece != nextPiece)) {
|
&& (lastRequest == null || lastRequest.piece != nextPiece)) {
|
||||||
|
Reference in New Issue
Block a user