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

📄 piecepickerimpl.java

📁 基于JXTA开发平台的下载软件开发源代码
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
     * 3. If it can't find any piece, this means all pieces are
     *  already downloaded/full requested
     * 4. Returns int[] pieceNumber, blockNumber if a request to be made is found,
     *  or null if none could be found
     * @param pc PEPeerTransport to work with
     * 
     * @return int with pieceNumberto be requested or -1 if no request could be found
     */
    private int getRequestCandidate(final PEPeerTransport pt)
    {
        if (pt ==null ||pt.getPeerState() !=PEPeer.TRANSFERING)
            return -1;
        final BitFlags  peerHavePieces =pt.getAvailable();
        if (peerHavePieces ==null ||peerHavePieces.nbSet <=0)
            return -1;
        
        // piece number and its block number that we'll try to DL
        int pieceNumber;                // will be set to the piece # we want to resume
        DiskManagerPiece    dmPiece;    // the DiskManagerPiece backing the PEPiece under inspection

        if (FORCE_PIECE >=0 &&FORCE_PIECE <nbPieces)
            pieceNumber =FORCE_PIECE;
        else
            pieceNumber =pt.getReservedPieceNumber();

        // If there's a piece Reserved to this peer or a FORCE_PIECE, start/resume it and only it (if possible)
        if (pieceNumber >=0)
        {
            dmPiece =dmPieces[pieceNumber];
            if (peerHavePieces.flags[pieceNumber] &&dmPiece.isRequestable())
                return pieceNumber;
            return -1; // this is an odd case that maybe should be handled better, but checkers might fully handle it
        }

        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   rarestOverride =getRarestOverride();

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

        BitFlags    startCandidates =null;
        long        startMaxPriority =Long.MIN_VALUE;
        int         startMinAvail =Integer.MAX_VALUE;
        boolean     startIsRarest =false;

        PEPiece     pePiece;    // the PEPiece under inspection 
        long        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
        int         freeReqs;   // the number of unrequested (free) blocks in the piece under inspection
        int         pieceSpeed; // the current speed rating of the PEPiece under inspection
        long        staleness;  // how long since there's been a write to the resume 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 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])
            {
                dmPiece =dmPieces[i];
                // is the piece: Needed, not fully: Requested, Downloaded, Written, hash-Checking or Done?
                if (dmPiece.isRequestable())
                {
                    priority =startPriorities[i];
                    if (priority >=0)
                    {
                        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
                        pePiece =peerControl.getPiece(i);
                        if (pePiece !=null)
                        {
                            // How many requests can still be made on this piece?
                            freeReqs =pePiece.getNbUnrequested();
                            if (freeReqs <=0)
                            {
                                dmPiece.setRequested();
                                continue;
                            }
                            
                            // Don't touch pieces reserved for others
                            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, but we located it
                                pt.setReservedPieceNumber(i);
                                return i;
                            }
                            
                            pieceSpeed =pePiece.getSpeed();
                            // peers allowed to continue same piece as last requested from them
                            // or pieces only they have
                            // or pieces with 0 speed
                            if (pieceSpeed >0 &&i !=lastPiece)
                            {
                                // if the peer is snubbed, only request on slow pieces
                                if (peerSpeed <pieceSpeed ||pt.isSnubbed())
                                {
                                    // peer allowed when free blocks is >= 3 and enough to not slow piece down too much
                                    if (avail >1 &&(freeReqs <3 ||pieceSpeed -1 >=freeReqs *peerSpeed))
                                        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 +=pePiece.getTimeSinceLastActivity() /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);  // this is only for display
                                
                                if (avail <resumeMinAvail &&(!rarestOverride ||priority >=resumeMaxPriority)
                                    ||(priority >resumeMaxPriority &&(!resumeIsRarest ||rarestOverride)))
                                {   // 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
                                        pieceNumber =i;
                                        resumeMinAvail =avail;
                                        resumeMaxPriority =priority;
                                        resumeIsRarest =avail <=globalMinOthers; // only going to try to resume one
                                    }
                                }
                            }
                        } else if (avail <=globalMinOthers &&!rarestOverride) 
                        {   // 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 ||rarestOverride)
                        {   // 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);
                                }
                            }
                        }
                    }
                }
            }
        }

        // Didnt find anything to do
        if (pieceNumber <0 &&(startCandidates ==null ||startCandidates.nbSet <1))
            return -1;

        // See if have found a valid (piece;block) to request from a piece in progress
        boolean resumeIsBetter =false;
        if (pieceNumber >=0)
        {
            resumeIsBetter =startCandidates ==null ||startCandidates.nbSet <1
                ||resumeIsRarest ||!startIsRarest ||rarestOverride 
                ||(resumeMaxPriority /resumeMinAvail) >(startMaxPriority /globalMinOthers);
            if (resumeIsBetter)
                return pieceNumber;
        }
        
        if (Logger.isEnabled())
            Logger.log(new LogEvent(pt, LOGID, "Starting Piece. "
                +"resume piece #= " +pieceNumber +" globalMinOthers=" +globalMinOthers
                +" startMaxPriority=" +startMaxPriority +" startMinAvail=" +startMinAvail +" startIsRarest=" +startIsRarest
                +(pieceNumber >0
                    ?" resumeMaxPriority=" +resumeMaxPriority +" resumeMinAvail=" +resumeMinAvail +" resumeIsRarest=" +resumeIsRarest
                 :"") 
                +"  " +peerControl.getDisplayName()));
        
        // Gets here when no resume piece choice was made
        return getPieceToStart(pt, startCandidates); // pick piece from candidates bitfield
    }
    
    
    /** @return int the piece number that should be started, according to selection criteria
     * 
     * @param pt PEPeer the piece would be started for
     * @param startCandidates BitFlags of potential candidates to choose from
     * @return int the piece number that was chosen to be started
     */
	protected int getPieceToStart(final PEPeerTransport pt, final BitFlags startCandidates)
	{
		if (startCandidates ==null ||startCandidates.nbSet <=0)
		{	// cant do anything if no pieces to startup
			return -1;
		}

		int startI;
		int direction;
		
		if (startCandidates.nbSet ==1)
		{
			startI =startCandidates.start;
			direction =1;
		} else
		{
			// Mix it up!
			startI =RandomUtils.generateRandomIntBetween(startCandidates.start,
					startCandidates.end);
			direction =RandomUtils.generateRandomPlusMinus1();
		}

        final PEPiece[] pePieces =pt.getControl().getPieces();
		// For every Priority piece
		for (int i =startI; i >=startCandidates.start &&i <=startCandidates.end; i +=direction)
		{
			// is piece flagged and confirmed not in progress
			if (pePieces[i] ==null &&startCandidates.flags[i])
			{
				// This should be a piece we want to start
				return i;
			}
		}
		return -1;
	}

	public boolean hasDownloadablePiece()
	{
		return hasNeededUndonePiece;
	}

	public long getNeededUndonePieceChange()
	{
		return neededUndonePieceChange;
	}

    
    private 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.isEGMIgnored())
                continue;
            // If the piece is being downloaded (fully requested), count it and continue
            if (dmPiece.isEGMActive())
            {
                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)
        {
            timeEndGameModeEntered =now;
            endGameMode =true;
            computeEndGameModeChunks();
            if (Logger.isEnabled())
                Logger.log(new LogEvent(diskManager.getTorrent(), LOGID, "Entering end-game mode: "
                    +peerControl.getDisplayName()));
            // System.out.println("End-Game Mode activated");
        }
    }
    
    private void computeEndGameModeChunks()
    {
        PEPiece[] _pieces =peerControl.getPieces();
        if (_pieces ==null)
            return;

        endGameModeChunks =new ArrayList();
        try
        {
            endGameModeChunks_mon.enter();

            for (int i =0; i <nbPieces; i++ )
            {
                DiskManagerPiece dmPiece =dmPieces[i];
                // Pieces not Needed or not needing more downloading are of no interest
                if (!dmPiece.isInteresting())
                    continue;
                
                PEPiece pePiece =_pieces[i];
                if (pePiece ==null)
                    continue;

                boolean written[] =dmPiece.getWritten();
                if (written ==null)
                {

⌨️ 快捷键说明

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