📄 piecepickerimpl.java
字号:
timeAvailRebuild -=errors;
} else
timeAvailRebuild++;
}
availabilityAsynch = new_availability;
availabilityDrift =0;
availabilityChange++;
} finally {availabilityMon.exit();}
} else if (availabilityComputeChange >=availabilityChange){
return;
}
try
{ availabilityMon.enter();
time_last_avail =now;
availabilityComputeChange =availabilityChange;
// take a snapshot of availabilityAsynch
if ( availabilityAsynch != null ){
availability = availabilityAsynch;
availabilityAsynch = null;
}
} finally {availabilityMon.exit();}
int i;
int allMin =Integer.MAX_VALUE;
int rarestMin =Integer.MAX_VALUE;
for (i =0; i <nbPieces; i++)
{
final int avail =availability[i];
final DiskManagerPiece dmPiece =dmPieces[i];
final PEPiece pePiece = pePieces[i];
if (avail >0 &&avail <rarestMin && dmPiece.isDownloadable() && (pePiece == null || pePiece.isRequestable()))
rarestMin =avail; // most important targets for near future requests from others
if (avail <allMin)
allMin =avail;
}
// copy updated local variables into globals
globalMin =allMin;
globalMinOthers =rarestMin;
int total =0;
int rarestActive =0;
long totalAvail =0;
for (i =0; i <nbPieces; i++ )
{
final int avail =availability[i];
final DiskManagerPiece dmPiece =dmPieces[i];
final PEPiece pePiece = pePieces[i];
if (avail >0)
{
if (avail >allMin)
total++;
if (avail <=rarestMin &&dmPiece.isDownloadable() && pePiece != null && !pePiece.isRequested())
rarestActive++;
totalAvail +=avail;
}
}
// copy updated local variables into globals
globalAvail =(total /(float) nbPieces) +allMin;
nbRarestActive =rarestActive;
globalAvgAvail =totalAvail /(float)(nbPieces)
/(1 +peerControl.getNbSeeds() +peerControl.getNbPeers());
}
private final int[] recomputeAvailability()
{
if (availabilityDrift >0 &&availabilityDrift !=nbPieces &&Logger.isEnabled())
Logger.log(new LogEvent(diskManager.getTorrent(), LOGID, LogEvent.LT_INFORMATION,
"Recomputing availabiliy. Drift=" +availabilityDrift +":" +peerControl.getDisplayName()));
final List peers =peerControl.getPeers();
final int[] newAvailability = new int[nbPieces];
int j;
int i;
// first our pieces
for (j =0; j <nbPieces; j++)
newAvailability[j] =dmPieces[j].isDone() ?1 :0;
//for all peers
final int peersSize =peers.size();
for (i =0; i <peersSize; i++)
{ //get the peer connection
final PEPeer peer =(PEPeerTransport)peers.get(i);
if (peer !=null &&peer.getPeerState() ==PEPeer.TRANSFERING)
{
//cycle trhough the pieces they actually have
final BitFlags peerHavePieces =peer.getAvailable();
if (peerHavePieces !=null &&peerHavePieces.nbSet >0)
{
for (j =peerHavePieces.start; j <=peerHavePieces.end; j++)
{
if (peerHavePieces.flags[j])
++newAvailability[j];
}
}
}
}
return newAvailability;
}
public int
getNumberOfPieces()
{
return( nbPieces );
}
public final int[] getAvailability()
{
return availability;
}
public final int getAvailability(final int pieceNumber)
{
return availability[pieceNumber];
}
//this only gets called when the My Torrents view is displayed
public final float getMinAvailability()
{
return globalAvail;
}
public final float getAvgAvail()
{
return globalAvgAvail;
}
/**
* Early-outs when finds a downloadable piece
* Either way sets hasNeededUndonePiece and neededUndonePieceChange if necessary
*/
protected final void checkDownloadablePiece()
{
for (int i =0; i <nbPieces; i++)
{
if (dmPieces[i].isInteresting())
{
if (!hasNeededUndonePiece)
{
hasNeededUndonePiece =true;
neededUndonePieceChange++;
}
return;
}
}
if (hasNeededUndonePiece)
{
hasNeededUndonePiece =false;
neededUndonePieceChange++;
}
}
/**
* one reason requests don't stem from the individual peers is so the connections can be
* sorted by best uploaders, providing some ooprtunity to download the most important
* (ie; rarest and/or highest priority) pieces faster and more reliably
*/
public final void allocateRequests()
{
if (!hasNeededUndonePiece){
return;
}
allocate_request_loop_count++;
final List peers =peerControl.getPeers();
final int peersSize =peers.size();
final long[] upRates =new long[peersSize];
final ArrayList bestUploaders =new ArrayList( peersSize );
for (int i =0; i <peersSize; i++){
final PEPeerTransport peer =(PEPeerTransport) peers.get(i);
if ( peer.isDownloadPossible()){
int no_req_count = peer.getConsecutiveNoRequestCount();
if ( no_req_count == 0 ||
allocate_request_loop_count % ( no_req_count + 1 ) == 0 ){
final long upRate = peer.getStats().getSmoothDataReceiveRate();
UnchokerUtil.updateLargestValueFirstSort(upRate, upRates, peer, bestUploaders, 0);
}
}
}
final int uploadersSize = bestUploaders.size();
if ( uploadersSize == 0 ){
// no usable peers, bail out early
return;
}
boolean done_priorities = false;
if ( priorityRTAexists ){
LinkedList block_time_order_peers = new LinkedList();
block_time_order_peers.addAll( bestUploaders );
Collections.sort(
block_time_order_peers,
new Comparator()
{
public int
compare(
Object arg1,
Object arg2)
{
PEPeerTransport pt1 = (PEPeerTransport)arg1;
PEPeerTransport pt2 = (PEPeerTransport)arg2;
return( getNextBlockETAFromNow( pt1 ) - getNextBlockETAFromNow( pt2 ));
}
});
PEPeerTransport best_uploader = (PEPeerTransport)bestUploaders.get(0);
// give priority pieces the first look-in
// we need to sort by how quickly the peer can get a block, not just its base speed
boolean allocated_request = true;
Set allocations_started = new HashSet();
try{
while( allocated_request && priorityRTAexists ){
allocated_request = false;
Iterator it = block_time_order_peers.iterator();
while( it.hasNext()){
final PEPeerTransport pt =(PEPeerTransport)it.next();
if ( !pt.isDownloadPossible() || pt.isSnubbed()){
it.remove();
continue;
}
// ignore request number advice from peers in RTA mode, we gotta do what we can
int maxRequests = REQUESTS_MIN +(int)( pt.getStats().getDataReceiveRate() /SLOPE_REQUESTS );
if ( maxRequests > REQUESTS_MAX || maxRequests < 0 ){
maxRequests = REQUESTS_MAX;
}
if ( pt.getNbRequests() <= maxRequests ){
if ( !done_priorities ){
done_priorities = true;
computeBasePriorities();
if ( !priorityRTAexists ){
// might have stopped RTA as this is calculated in computeBasePriorities
break;
}
}
if ( !allocations_started.contains( pt )){
pt.requestAllocationStarts( startPriorities );
allocations_started.add( pt );
}
if ( findRTAPieceToDownload( pt, pt == best_uploader )){
allocated_request = true;
}else{
it.remove();
}
}else{
it.remove();
}
}
}
}finally{
Iterator it = allocations_started.iterator();
while( it.hasNext()){
((PEPeerTransport)it.next()).requestAllocationComplete();
}
}
}
checkEndGameMode();
for (int i =0; i <uploadersSize; i++){
final PEPeerTransport pt =(PEPeerTransport) bestUploaders.get(i);
// can we transfer something?
if ( pt.isDownloadPossible()){
int peer_request_num = pt.getMaxNbRequests();
// If request queue is too low, enqueue another request
int maxRequests;
if ( peer_request_num != -1 ){
maxRequests = peer_request_num;
}else{
if (!pt.isSnubbed()){
if (!endGameMode){
maxRequests =REQUESTS_MIN +(int) (pt.getStats().getDataReceiveRate() /SLOPE_REQUESTS);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -