/** * Adds a new request to the outstanding requests list. Then send interested if we weren't. Then * send new requests if not choked. If nothing to request, send not interested if we were. * * <p>This is called from several places: * * <pre> * By getOustandingRequest() when the first part of a chunk comes in * By havePiece() when somebody got a new piece completed * By chokeMessage() when we receive an unchoke * By setInteresting() when we are now interested * By PeerCoordinator.updatePiecePriorities() * </pre> */ synchronized void addRequest() { // no bitfield yet? nothing to request then. if (bitfield == null) return; if (metainfo == null) return; boolean more_pieces = true; while (more_pieces) { more_pieces = outstandingRequests.size() < MAX_PIPELINE; // We want something and we don't have outstanding requests? if (more_pieces && lastRequest == null) { // we have nothing in the queue right now if (!interesting) { // If we need something, set interesting but delay pulling // a request from the PeerCoordinator until unchoked. if (listener.needPiece(this.peer, bitfield)) { setInteresting(true); if (_log.shouldLog(Log.DEBUG)) _log.debug( peer + " addRequest() we need something, setting interesting, delaying requestNextPiece()"); } else { if (_log.shouldLog(Log.DEBUG)) _log.debug(peer + " addRequest() needs nothing"); } return; } if (choked) { // If choked, delay pulling // a request from the PeerCoordinator until unchoked. if (_log.shouldLog(Log.DEBUG)) _log.debug(peer + " addRequest() we are choked, delaying requestNextPiece()"); return; } // huh? rv unused more_pieces = requestNextPiece(); } else if (more_pieces) // We want something { int pieceLength; boolean isLastChunk; pieceLength = metainfo.getPieceLength(lastRequest.getPiece()); isLastChunk = lastRequest.off + lastRequest.len == pieceLength; // Last part of a piece? if (isLastChunk) more_pieces = requestNextPiece(); else { PartialPiece nextPiece = lastRequest.getPartialPiece(); int nextBegin = lastRequest.off + PARTSIZE; int maxLength = pieceLength - nextBegin; int nextLength = maxLength > PARTSIZE ? PARTSIZE : maxLength; Request req = new Request(nextPiece, nextBegin, nextLength); outstandingRequests.add(req); if (!choked) out.sendRequest(req); lastRequest = req; } } } // failsafe // However this is bad as it thrashes the peer when we change our mind // Ticket 691 cause here? if (interesting && lastRequest == null && outstandingRequests.isEmpty()) setInteresting(false); if (_log.shouldLog(Log.DEBUG)) _log.debug(peer + " requests " + outstandingRequests); }