📄 piecepickerimpl.java
字号:
if (maxRequests >REQUESTS_MAX ||maxRequests <0)
maxRequests =REQUESTS_MAX;
}else{
maxRequests =2;
}
}else{
maxRequests =1;
}
}
// Only loop when 3/5 of the queue is empty, in order to make more consecutive requests,
// and improve cache efficiency
if ( pt.getNbRequests() <=(maxRequests *3) /5){
if ( !done_priorities ){
done_priorities = true;
computeBasePriorities();
}
int total_allocated = 0;
try{
boolean peer_managing_requests = pt.requestAllocationStarts( startPriorities );
while ( pt.isDownloadPossible() && pt.getNbRequests() < maxRequests ){
// is there anything else to download?
int allocated;
if ( peer_managing_requests || !endGameMode ){
allocated = findPieceToDownload(pt, maxRequests );
}else{
allocated = findPieceInEndGameMode(pt, maxRequests);
}
if ( allocated == 0 ){
break;
}else{
total_allocated += allocated;
}
}
}finally{
pt.requestAllocationComplete();
}
if ( total_allocated == 0 ){
// there are various reasons that we might not allocate any requests to a peer
// such as them not having any pieces we're interested in. Keep track of the
// number of consecutive "no requests" outcomes so we can reduce the scheduling
// frequency of such peers
int no_req_count = pt.getConsecutiveNoRequestCount();
if ( no_req_count < NO_REQUEST_BACKOFF_MAX_LOOPS ){
pt.setConsecutiveNoRequestCount( no_req_count + 2 );
}
// System.out.println( pt.getIp() + ": nb=" + pt.getNbRequests() + ",max=" + maxRequests + ",nrc=" + no_req_count +",loop=" + allocate_request_loop_count);
}else{
pt.setConsecutiveNoRequestCount( 0 );
}
}
}
}
}
protected int
getNextBlockETAFromNow(
PEPeerTransport pt )
{
long upRate = pt.getStats().getDataReceiveRate();
if ( upRate < 1 ){
upRate = 1;
}
int next_block_bytes = ( pt.getNbRequests() + 1 ) * DiskManager.BLOCK_SIZE;
return((int)(( next_block_bytes * 1000 )/ upRate));
}
/** This computes the base priority for all pieces that need requesting if there's
* been any availability change or user priority setting changes since the last
* call, which will be most of the time since availability changes so dynamicaly
* It will change startPriorities[] (unless there was nothing to do)
*/
private final void
computeBasePriorities()
{
final long now = SystemTime.getCurrentTime();
if ( now < lastProviderRecalcTime || now - lastProviderRecalcTime > 1000 ){
lastProviderRecalcTime = now;
priorityRTAexists = computeProviderPriorities();
}
if ( !priorityRTAexists ){
if (startPriorities !=null &&((now >timeLastPriorities &&now <time_last_avail +TIME_MIN_PRIORITIES)
||(priorityParamChange >=paramPriorityChange &&priorityFileChange >=filePriorityChange
&&priorityAvailChange >=availabilityChange)))
return; // *somehow* nothing changed, so nothing to do
}
// store the latest change indicators before we start making dependent calculations so that a
// further change while computing stuff doesn't get lost
timeLastPriorities =now;
priorityParamChange =paramPriorityChange;
priorityFileChange =filePriorityChange;
priorityAvailChange =availabilityChange;
boolean foundPieceToDownload =false;
final int[] newPriorities =new int[nbPieces];
// locals are a tiny bit faster
final boolean firstPiecePriorityL =firstPiecePriority;
final boolean completionPriorityL =completionPriority;
try
{
final boolean rarestOverride =isRarestOverride();
// calculate all base (starting) priorities for all pieces needing requesting
final int nbConnects =peerControl.getNbPeers() +peerControl.getNbSeeds();
for (int i =0; i <nbPieces; i++)
{
final DiskManagerPiece dmPiece =dmPieces[i];
if (dmPiece.isDone())
continue; // nothing to do for pieces not needing requesting
int priority =Integer.MIN_VALUE;
int startPriority =Integer.MIN_VALUE;
final DMPieceList pieceList =diskManager.getPieceList(dmPiece.getPieceNumber());
final int pieceListSize =pieceList.size();
for (int j =0; j <pieceListSize; j++)
{
final DiskManagerFileInfoImpl fileInfo =pieceList.get(j).getFile();
final long downloaded =fileInfo.getDownloaded();
final long length =fileInfo.getLength();
if (length >0 &&downloaded <length &&!fileInfo.isSkipped())
{
priority =0;
// user option "prioritize first and last piece"
// TODO: should prioritize ~10% from edges of file
if (firstPiecePriorityL &&fileInfo.getNbPieces() >FIRST_PIECE_MIN_NB)
{
/* backed out for the moment - reverting to old first/last piece only
int lastFirstPiece = fileInfo.getFirstPieceNumber() + FIRST_PIECE_RANGE_PERCENT * (fileInfo.getLastPieceNumber() - fileInfo.getFirstPieceNumber()) / 100;
if ( (i >=fileInfo.getFirstPieceNumber() && i<= lastFirstPiece ) ) {
priority +=PRIORITY_W_FIRSTLAST + 10 * (lastFirstPiece - i) ;
}
if( i ==fileInfo.getLastPieceNumber() ) {
priority +=PRIORITY_W_FIRSTLAST;
}
*/
if (i == fileInfo.getFirstPieceNumber() ||i == fileInfo.getLastPieceNumber())
priority +=PRIORITY_W_FIRSTLAST;
}
// if the file is high-priority
// startPriority +=(1000 *fileInfo.getPriority()) /255;
if (fileInfo.isPriority())
{
priority +=PRIORITY_W_FILE;
if (completionPriorityL)
{
final long percent =(1000 *downloaded) /length;
if (percent >=900)
priority +=(PRIORITY_W_COMPLETION *downloaded) /diskManager.getTotalLength();
}
}
if (priority >startPriority)
startPriority =priority;
}
}
if (startPriority >=0)
{
dmPiece.setNeeded();
foundPieceToDownload =true;
final int avail =availability[i];
// nbconnects is async calculate so may be wrong - make sure we don't decrease pri by accident
if (avail >0 && nbConnects > avail )
{ // boost priority for rarity
startPriority +=nbConnects -avail;
// startPriority +=(PRIORITY_W_RARE +peerControl.getNbPeers()) /avail;
// Boost priority even a little more if it's a globally rarest piece
if (!rarestOverride &&avail <=globalMinOthers)
startPriority +=nbConnects /avail;
}
if ( provider_piece_rtas != null ){
if ( provider_piece_rtas[i] > 0 ){
startPriority = PRIORITY_REALTIME;
}
}else if ( provider_piece_priorities != null ){
startPriority += provider_piece_priorities[i];
}
}else{
dmPiece.clearNeeded();
}
newPriorities[i] =startPriority;
}
} catch (Throwable e)
{
Debug.printStackTrace(e);
}
if (foundPieceToDownload !=hasNeededUndonePiece)
{
hasNeededUndonePiece =foundPieceToDownload;
neededUndonePieceChange++;
}
startPriorities = newPriorities;
}
private final boolean isRarestOverride()
{
final int nbSeeds =peerControl.getNbSeeds();
final int nbPeers =peerControl.getNbPeers();
final int nbMost =(nbPeers >nbSeeds ?nbPeers :nbSeeds);
final int nbActive =peerControl.getNbActivePieces();
// Dont seek rarest under a few circumstances, so that other factors work better
// never seek rarest when bootstrapping torrent
boolean rarestOverride =nbPiecesDone <4 ||endGameMode
||(globalMinOthers >1 &&(nbRarestActive >=nbMost ||nbActive >=nbMost));
if (!rarestOverride &&nbRarestActive >1 &&globalMinOthers >1)
{
// if already getting some rarest, dont get more if swarm is healthy or too many pieces running
rarestOverride =globalMinOthers >globalMin
||(globalMinOthers >=(2 *nbSeeds) &&(2 *globalMinOthers) >=nbPeers);
// Interest in Rarest pieces (compared to user priority settings) could be influenced by several factors;
// less demand closer to 0% and 100% of torrent completion/farther from 50% of torrent completion
// less demand closer to 0% and 100% of peers interestd in us/farther from 50% of peers interested in us
// less demand the more pieces are in progress (compared to swarm size)
// less demand the farther ahead from absolute global minimum we're at already
// less demand the healthier a swarm is (rarity compared to # seeds and # peers)
}
return rarestOverride;
}
/**
* @param pt the PEPeerTransport we're working on
* @return int # of blocks that were requested (0 if no requests were made)
*/
protected final int findPieceToDownload(PEPeerTransport pt, final int nbWanted)
{
final int pieceNumber =getRequestCandidate(pt);
if (pieceNumber <0)
{ // probaly should have found something since chose to try; probably not interested anymore
// (or maybe Needed but not Done pieces are otherwise not requestable)
// pt.checkInterested();
return 0;
}
final int peerSpeed =(int) pt.getStats().getDataReceiveRate() /1000;
PEPiece pePiece = pePieces[pieceNumber];
if ( pePiece==null ){
int[] peer_priority_offsets = pt.getPriorityOffsets();
int this_offset = peer_priority_offsets==null?0:peer_priority_offsets[pieceNumber];
//create piece manually
pePiece =new PEPieceImpl(pt.getManager(), dmPieces[pieceNumber], peerSpeed >>1);
// Assign the created piece to the pieces array.
peerControl.addPiece(pePiece, pieceNumber);
if (startPriorities !=null){
pePiece.setResumePriority(startPriorities[pieceNumber] + this_offset);
}else{
pePiece.setResumePriority( this_offset );
}
if (availability[pieceNumber] <=globalMinOthers)
nbRarestActive++;
}
final int[] blocksFound =pePiece.getAndMarkBlocks(pt, nbWanted );
final int blockNumber =blocksFound[0];
final int nbBlocks =blocksFound[1];
if (nbBlocks <=0)
return 0;
int requested =0;
// really try to send the request to the peer
for (int i =0; i <nbBlocks; i++)
{
final int thisBlock =blockNumber +i;
if (pt.request(pieceNumber, thisBlock *DiskManager.BLOCK_SIZE, pePiece.getBlockSize(thisBlock)) != null )
{
requested++;
pt.setLastPiece(pieceNumber);
pePiece.setLastRequestedPeerSpeed( peerSpeed );
// have requested a block
}
}
return requested;
}
protected final boolean
findRTAPieceToDownload(
PEPeerTransport pt,
boolean best_uploader )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -