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

📄 piecepickerimpl.java

📁 基于JXTA开发平台的下载软件开发源代码
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
		}
		// copy updated local variables into globals
		globalAvail =(total /(float) nbPieces) +allMin;
		nbRarestActive =rarestActive;
		globalAvgAvail =totalAvail /(float)(nbPieces)
            /(1 +peerControl.getNbSeeds() +peerControl.getNbPeers());
	}
	
	private 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	peerTransports =peerControl.getPeers();
	    
	    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
	    for (i =0; i <peerTransports.size(); i++)
	    {	//get the peer connection
	        final PEPeerTransport pt =(PEPeerTransport)peerTransports.get(i);
	        if (pt !=null &&pt.getPeerState() ==PEPeer.TRANSFERING)
	        {
	            //cycle trhough the pieces they actually have
	            final BitFlags peerHavePieces =pt.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[] getAvailability()
	{
		return availability;
	}

	public int getAvailability(final int pieceNumber)
	{
		return availability[pieceNumber];
	}
	
	//this only gets called when the My Torrents view is displayed
	public float getMinAvailability()
	{
		return globalAvail;
	}

	public float getAvgAvail()
	{
		return globalAvgAvail;
	}


	/**
	 * Early-outs when finds a downloadable piece
	 * Either way sets hasNeededUndonePiece and neededUndonePieceChange if necessary 
	 */
	protected 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 boolean checkDownloadPossible()
	{
		if (!hasNeededUndonePiece)
			return false;

		final List bestUploaders =new ArrayList();
		final List peer_transports =peerControl.getPeers();

		final long[] upRates =new long[peer_transports.size()];
		Arrays.fill(upRates, -1);

		for (int i =0; i <peer_transports.size(); i++)
		{
			final PEPeerTransport pt =(PEPeerTransport) peer_transports.get(i);
			if (pt.getPeerState() <PEPeer.CLOSING)
			{
				final long upRate =pt.getStats().getSmoothDataReceiveRate();
				UnchokerUtil.updateLargestValueFirstSort(upRate, upRates, pt, bestUploaders, 0);
			}
		}

		checkEndGameMode();

		computeBasePriorities();
		
		for (int i =0; i <bestUploaders.size(); i++)
		{
			// get a connection
			final PEPeerTransport pt =(PEPeerTransport) bestUploaders.get(i);
			// can we transfer something?
			if (pt.isDownloadPossible())
			{
				// If queue is too low, we will enqueue another request
				int found =0;
				int maxRequests =REQUESTS_MIN +(int) (pt.getStats().getDataReceiveRate() /SLOPE_REQUESTS);
				if (maxRequests >REQUESTS_MAX ||maxRequests <0)
					maxRequests =REQUESTS_MAX;

				if (endGameMode)
					maxRequests =2;
				if (pt.isSnubbed())
					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)
				{
					while (pt.isDownloadPossible() &&pt.getNbRequests() <maxRequests)
					{
						// is there anything else to download?
						if (!endGameMode)
							found =findPieceToDownload(pt, maxRequests);
						else
							found =findPieceInEndGameMode(pt, maxRequests);
						if (found <=0)
							break;
					}
				}
			}
		}
		return true;
	}
	
    /** 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 void computeBasePriorities()
    {
        final long now =SystemTime.getCurrentTime();
        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
        
        priorityParamChange =paramPriorityChange;
        priorityFileChange =filePriorityChange;
        priorityAvailChange =availabilityChange;
        timeLastPriorities =now;
        
        boolean         changedPriority =false;
        boolean         foundPieceToDownload =false;
        long[]          newPriorities   =new long[nbPieces];
        try
        {
            final boolean rarestOverride =getRarestOverride();
            // calculate all base (starting) priorities for all pieces needing requesting
            for (int i =0; i <nbPieces; i++)
            {
                final int avail =availability[i];
                DiskManagerPiece dmPiece =dmPieces[i];
                if (dmPiece.isDone())
                    continue;   // nothing to do for pieces not needing requesting
                
                long startPriority =Long.MIN_VALUE;
                long priority =Long.MIN_VALUE;
                
                final DMPieceList pieceList =diskManager.getPieceList(dmPiece.getPieceNumber());
                for (int j =0; j <pieceList.size(); j++)
                {
                    final DiskManagerFileInfoImpl fileInfo =pieceList.get(j).getFile();
                    final long length =fileInfo.getLength();
                    final long downloaded =fileInfo.getDownloaded();
                    if (length >0 &&downloaded <length &&!fileInfo.isSkipped())
                    {
                        priority =0;
                        // user option "prioritize first and last piece"
                        // TODO: should prioritize ~10% to ~%25 from edges of file
                        if (firstPiecePriority &&fileInfo.getNbPieces() >FIRST_PIECE_MIN_NB)
                        {
                            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 (completionPriority)
                            {
                                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;
//                    if (avail >0)
//                    {
//                        // boost priority for rarity
//                        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 +=PRIORITY_W_RAREST /avail;
//                    }
                } else
                {
                    dmPiece.clearNeeded();
                }
                
                newPriorities[i] =startPriority;
                changedPriority =true;
            }
        } catch (Throwable e)
        {
            Debug.printStackTrace(e);
        }
                
        if (foundPieceToDownload)
        {
            if (!hasNeededUndonePiece)
            {
                hasNeededUndonePiece =true;
                neededUndonePieceChange++;
            }
        } else if (hasNeededUndonePiece)
        {
            hasNeededUndonePiece =false;
            neededUndonePieceChange++;
        }
        
        if (changedPriority)
            startPriorities =newPriorities;
    }
    
    private boolean getRarestOverride()
    {
        final int nbSeeds =peerControl.getNbSeeds();
        final int nbPeers =peerControl.getNbPeers();
        // Dont seek rarest this time around under a few circumstances, so that other factors work better
        // never seek rarest when bootstrapping torrent
        boolean rarestOverride =nbPiecesDone <4 ||endGameMode ||nbRarestActive >=(nbSeeds +nbPeers);
        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 the torrent/farther from 50% of the torrent
            // 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 pc
	 *            the PeerConnection we're working on
	 * @return true if a request was assigned, false otherwise
	 */
	protected int findPieceToDownload(final PEPeerTransport pt, final int nbWanted)
	{
		final int pieceNumber =getRequestCandidate(pt);
		if (pieceNumber <0)
			return 0;

		int peerSpeed =(int) pt.getStats().getDataReceiveRate() /1000;

		PEPeerControl pc =pt.getControl();
		PEPiece pePiece =pc.getPiece(pieceNumber);
		if (pePiece ==null)
        {   //create piece manually
			pePiece =new PEPieceImpl(pt.getManager(), dmPieces[pieceNumber], peerSpeed >>1);

			// Assign the created piece to the pieces array.
			pc.addPiece(pePiece, pieceNumber);
            if (startPriorities !=null)
                pePiece.setResumePriority(startPriorities[pieceNumber]);
			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)))
			{
				requested++;
				pt.setLastPiece(pieceNumber);
				// Up the speed on this piece?
				if (peerSpeed >pePiece.getSpeed())
					pePiece.incSpeed();
				// have requested a block
			}
		}
		return requested;
	}

    // set FORCE_PIECE if trying to diagnose piece problems and only want to d/l a specific piece from a torrent
    private static final int    FORCE_PIECE =-1;

    /**
     * This method is the downloading core. It decides, for a given peer,
     * which block should be requested. Here is the overall algorithm :
     * 0. If there a FORCED_PIECE or reserved piece, that will be started/resumed if possible
     * 1. Scan all the active pieces and find the rarest piece (and highest priority among equally rarest)
     *  that can possibly be continued by this peer, if any
     * 2. While scanning the active pieces, develop a list of equally highest priority pieces
     *  (and equally rarest among those) as candidates for starting a new piece

⌨️ 快捷键说明

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