⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 piecepickerimpl.java

📁 这是一个基于java编写的torrent的P2P源码
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
            
            if ( pePiece != null ){
            	
            	String peerReserved = pePiece.getReservedBy();
            
            	if ( peerReserved != null ){
            
            		if ( peerReserved.equals(pt.getIp())){
            			
            			pePiece.setReservedBy( null );
            		}
            	}
            }

            	// note, pieces reserved to peers that get disconnected are released in pepeercontrol
            
            reservedPieceNumber	= -1;
        }

        final int       peerSpeed =(int) pt.getStats().getDataReceiveRate() /1000;  // how many KB/s has the peer has been sending
        final int       lastPiece =pt.getLastPiece();
        final boolean   globalRarestOverride =isRarestOverride();
        final int		nbSnubbed =peerControl.getNbPeersSnubbed();

        long        resumeMinAvail =Long.MAX_VALUE;
        int         resumeMaxPriority =Integer.MIN_VALUE;
        boolean     resumeIsRarest =false; // can the peer continuea piece with lowest avail of all pieces we want

        BitFlags    startCandidates =null;
        int         startMaxPriority =Integer.MIN_VALUE;
        int         startMinAvail =Integer.MAX_VALUE;
        boolean     startIsRarest =false;
        
        int         priority;   // aggregate priority of piece under inspection (start priority or resume priority for pieces to be resumed)
        int         avail =0;   // the swarm-wide availability level of the piece under inspection
        long        pieceAge;   // how long since the PEPiece first started downloading (requesting, actually)
        
        final int	startI =peerHavePieces.start;
        final int	endI =peerHavePieces.end;
        int         i;

        final int[]		peerPriorities	= pt.getPriorityOffsets();
        
        final long  now =SystemTime.getCurrentTime();
        // Try to continue a piece already loaded, according to priority
        for (i =startI; i <=endI; i++)
        {
            // is the piece available from this peer?
            if (peerHavePieces.flags[i])
            {
                priority =startPriorities[i];
                
                if ( peerPriorities != null ){
                	
                	if ( priority >= 0 ){
                		
                		priority += peerPriorities[i];
                	}
                }
                
                final DiskManagerPiece dmPiece =dmPieces[i];

                if ( priority >=0 && dmPiece.isDownloadable()){
               
                    final PEPiece pePiece = pePieces[i];
                    
               			// if we are considering realtime pieces then don't bother with non-realtime ones
                    
                    if (( pePiece == null || pePiece.isRequestable())){
                    
                   			// if this priority exceeds the priority-override threshold then  we override rarity
                    	
                    	boolean	pieceRarestOverride = priority>=PRIORITY_OVERRIDES_RAREST?true:globalRarestOverride;
                    	    
                        	// piece is: Needed, not fully: Requested, Downloaded, Written, hash-Checking or Done
                     	
                        avail =availability[i];
                        
                        if (avail ==0 )
                        {   // maybe we didn't know we could get it before
                            availability[i] =1;    // but the peer says s/he has it
                            avail =1;
                        }
                        
                        // is the piece active
                        if (pePiece !=null)
                        {
                            // How many requests can still be made on this piece?
                            final int freeReqs =pePiece.getNbUnrequested();
                            if (freeReqs <=0)
                            {
                            	pePiece.setRequested();
                                continue;
                            }
                            
                            // Don't touch pieces reserved for others
                            final String peerReserved =pePiece.getReservedBy();
                            if (peerReserved !=null)
                            {
                                if (!peerReserved.equals(pt.getIp()))
                                    continue;   //reserved to somebody else
                                // the peer forgot this is reserved to him; re-associate it
                                pt.setReservedPieceNumber(i);
                                return i;
                            }
                            
                            final int pieceSpeed =pePiece.getSpeed();
                        	final long timeSinceLastActivity =pePiece.getTimeSinceLastActivity();
                            // Snubbed peers or peers slower than the piece can only request on the piece if;
                            // they're the sole source OR
                            // it's the same as the last piece they were on AND there's enough free blocks
                            // TODO: instead of 3, should count how many peers are snubbed and use that
                            if (avail >1 &&(freeReqs <3 ||pieceSpeed -1 >=freeReqs *peerSpeed))
                            {
                            	// unless the piece has been inactive too long,
                            	//  don't request from snubbed peers UNLESS;
                            	//   it's possible all sources for the piece are snubbed,
                            	//  don't request from slow peers UNLESS;
                            	//   it was the last piece requested from them already
                                if (timeSinceLastActivity < 10 *60*1000 
                                	&&(avail >nbSnubbed &&pt.isSnubbed()) ||(peerSpeed <pieceSpeed &&i !=lastPiece))
                                    continue;
                            }
                            if (avail <=resumeMinAvail)
                            {
                                priority +=pieceSpeed;
                                
                                priority +=(i ==lastPiece) ?PRIORITY_W_SAME_PIECE :0;
                                // Adjust priority for purpose of continuing pieces
                                // how long since last written to (if written to)
                                priority +=timeSinceLastActivity /PRIORITY_DW_STALE;
                                // how long since piece was started
                                pieceAge =now -pePiece.getCreationTime();
                                if (pieceAge >0)
                                    priority +=PRIORITY_W_AGE *pieceAge /(PRIORITY_DW_AGE *dmPiece.getNbBlocks());
                                // how much is already written to disk
                                priority +=(PRIORITY_W_PIECE_DONE *dmPiece.getNbWritten()) /dmPiece.getNbBlocks();
                                
                                pePiece.setResumePriority(priority);
                                
                                if (avail <resumeMinAvail &&(!pieceRarestOverride ||priority >=resumeMaxPriority)
                                    ||(priority >resumeMaxPriority &&(!resumeIsRarest ||pieceRarestOverride)))
                                {   // this piece seems like best choice for resuming
                                    // Verify it's still possible to get a block to request from this piece
                                    if (pePiece.hasUnrequestedBlock())
                                    {   // change the different variables to reflect interest in this block
                                        reservedPieceNumber =i;
                                        resumeMinAvail =avail;
                                        resumeMaxPriority =priority;
                                        resumeIsRarest =avail <=globalMinOthers; // only going to try to resume one
                                    }
                                }
                            }
                        } else if (avail <=globalMinOthers &&!pieceRarestOverride) 
                        {   // rarest pieces only from now on
                            if (!startIsRarest)
                            {   // 1st rarest piece
                                if (startCandidates ==null)
                                    startCandidates =new BitFlags(nbPieces);
                                startMaxPriority =priority;
                                startMinAvail =avail;
                                startIsRarest =avail <=globalMinOthers;
                                startCandidates.setOnly(i); // clear the non-rarest bits in favor of only rarest
                            } else if (priority >startMaxPriority)
                            {   // continuing rarest, higher priority level
                                if (startCandidates ==null)
                                    startCandidates =new BitFlags(nbPieces);
                                startMaxPriority =priority;
                                startCandidates.setOnly(i);
                            } else if (priority ==startMaxPriority)
                            {   // continuing rares, same priority level
                                startCandidates.setEnd(i);
                            }
                        } else if (!startIsRarest ||pieceRarestOverride)
                        {   // not doing rarest pieces
                            if (priority >startMaxPriority)
                            {   // new priority level
                                if (startCandidates ==null)
                                    startCandidates =new BitFlags(nbPieces);
                                startMaxPriority =priority;
                                startMinAvail =avail;
                                startIsRarest =avail <=globalMinOthers;
                                startCandidates.setOnly(i);
                            } else if (priority ==startMaxPriority)
                            {   // continuing same priority level
                                if (avail <startMinAvail)
                                {   // same priority, new availability level
                                    startMinAvail =avail;
                                    startIsRarest =avail <=globalMinOthers;
                                    startCandidates.setOnly(i);
                                } else if (avail ==startMinAvail)
                                {   // same priority level, same availability level
                                    startCandidates.setEnd(i);
                                }
                            }
                        }
                    }
                }
            }
        }
        
        // can & should or must resume a piece?
        if (reservedPieceNumber >=0 &&(resumeIsRarest ||!startIsRarest ||globalRarestOverride ||startCandidates ==null ||startCandidates.nbSet <=0))
            return reservedPieceNumber;

// this would allow more non-rarest pieces to be resumed so they get completed so they can be re-shared,
// which can make us intersting to more peers, and generally improve the speed of the swarm,
// however, it can sometimes be hard to get the rarest pieces, such as when a holder unchokes very infrequently
// 20060312[MjrTom] this can lead to TOO many active pieces, so do the extra check with arbitrary # of active pieces
        final boolean resumeIsBetter;
        if (reservedPieceNumber >=0 &&globalMinOthers >0 &&peerControl.getNbActivePieces() >32)	// check at arbitrary figure of 32 pieces 
        {
            resumeIsBetter =(resumeMaxPriority /resumeMinAvail) >(startMaxPriority /globalMinOthers);
            
            if (Constants.isCVSVersion() &&Logger.isEnabled())
                Logger.log(new LogEvent(new Object[] {pt, peerControl}, LOGID, 
                    "Start/resume choice; piece #:" +reservedPieceNumber +" resumeIsBetter:" +resumeIsBetter
                    +" globalMinOthers=" +globalMinOthers
                    +" startMaxPriority=" +startMaxPriority +" startMinAvail=" +startMinAvail
                    +" resumeMaxPriority=" +resumeMaxPriority +" resumeMinAvail=" +resumeMinAvail
                    +" : " +pt));
            
            if (resumeIsBetter)
                return reservedPieceNumber;
        }
        
        // start a new piece; select piece from start candidates bitfield
        return getPieceToStart(startCandidates);
    }
    
    
    /** 
     * @param startCandidates BitFlags of potential candidates to choose from
     * @return int the piece number that was chosen to be started. Note it's possible for
     * the chosen piece to have been started already (by another thread).
     * This method considers that potential to not be relevant.
     */
	protected final int getPieceToStart(final BitFlags startCandidates)
	{
		if (startCandidates ==null ||startCandidates.nbSet <=0)
			return -1;
        if (startCandidates.nbSet ==1)
            return startCandidates.start;
		
		final int direction =RandomUtils.generateRandomPlusMinus1();
        final int startI;
        if (direction ==1)
            startI =startCandidates.start;
        else
            startI =startCandidates.end;
		
		// randomly select a bit flag to be the one
        final int targetNb =RandomUtils.generateRandomIntUpto(startCandidates.nbSet);
        
        // figure out the piece number of that selected bitflag
        int foundNb =-1;
		for (int i =startI; i <=startCandidates.end &&i >=startCandidates.start; i +=direction)
		{
			// is piece flagged
			if (startCandidates.flags[i])
            {
                foundNb++;
                if (foundNb >=targetNb)
                    return i;
            }
		}
		return -1;
	}

	public final boolean hasDownloadablePiece()
	{
		return hasNeededUndonePiece;
	}

	public final long getNeededUndonePieceChange()
	{
		return neededUndonePieceChange;
	}

    
    private final void checkEndGameMode()
    {
        if (peerControl.getNbSeeds() +peerControl.getNbPeers() <3)
            return;
        final long now =SystemTime.getCurrentTime();
        // We can't come back from end-game mode
        if (endGameMode ||endGameModeAbandoned)
        {
            if (!endGameModeAbandoned)
            {
                if (now -timeEndGameModeEntered >END_GAME_MODE_TIMEOUT)
                {
                    endGameModeAbandoned =true;
                    clearEndGameChunks();
                    
                    if (Logger.isEnabled())
                        Logger.log(new LogEvent(diskManager.getTorrent(), LOGID, "Abandoning end-game mode: "
                            +peerControl.getDisplayName()));
                }
            }
            return;
        }

        int active_pieces =0;

        for (int i =0; i <nbPieces; i++)
        {
            final DiskManagerPiece dmPiece =dmPieces[i];
            // If the piece isn't even Needed, or doesn't need more downloading, simply continue
            if (!dmPiece.isDownloadable())
                continue;
            
            final PEPiece pePiece = pePieces[i];
            
            if ( pePiece != null && pePiece.isDownloaded()){
            	continue;
            }
            
            // If the piece is being downloaded (fully requested), count it and continue
            if ( pePiece != null && pePiece.isRequested() && dmPiece.isNeeded())
            {
                active_pieces++;
                continue;
            }

            // Else, some piece is Needed, not downloaded/fully requested; this isn't end game mode
            return;
        }

        // only flick into end-game mode if < trigger size left
        if (active_pieces *diskManager.getPieceLength() <=END_GAME_MODE_SIZE_TRIGGER)
        {
            endGameModeChunks =new ArrayList();

            timeEndGameModeEntered =now;
            endGameMode =true;
            computeEndGameModeChunks();
            if (Logger.isEnabled())
                Logger.log(new LogEvent(diskManage

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -