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

📄 piecepickerimpl.java

📁 基于JXTA开发平台的下载软件开发源代码
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/*
 * Created by Joseph Bridgewater
 * Created on Jan 2, 2006
 * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 
 * AELITIS, SAS au capital de 46,603.30 euros
 * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
 *
 */

package com.aelitis.azureus.core.peermanager.piecepicker.impl;

import java.util.*;

import org.gudy.azureus2.core3.config.*;
import org.gudy.azureus2.core3.disk.*;
import org.gudy.azureus2.core3.disk.impl.DiskManagerFileInfoImpl;
import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceList;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.peer.*;
import org.gudy.azureus2.core3.peer.impl.*;
import org.gudy.azureus2.core3.util.*;

import com.aelitis.azureus.core.peermanager.piecepicker.*;
import com.aelitis.azureus.core.peermanager.piecepicker.priority.PiecePriorityShaper;
import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags;
import com.aelitis.azureus.core.peermanager.unchoker.UnchokerUtil;

/**
 * @author MjrTom
 * 
 */

public class PiecePickerImpl
	implements PiecePicker
{
	private static final LogIDs LOGID = LogIDs.PIECES;

    /** min ms for recalculating availability - reducing this has serious ramifications */
    private static final long TIME_MIN_AVAILABILITY	=974;
    /** min ms for recalculating base priorities */
    private static final long TIME_MIN_PRIORITIES	=999;
    /** min ms for total availability rebuild */
    private static final long TIME_AVAIL_REBUILD	=2*60*1000; 

	// The following are added to the base User setting based priorities (for all inspected pieces)
    /** user select prioritize first/last */
	private static final long PRIORITY_W_FIRSTLAST	=1200;
    /** min # pieces in file for first/last prioritization */
    private static final long FIRST_PIECE_MIN_NB	=4;
    /** user sets file as "High" */
    private static final long PRIORITY_W_FILE		=1100;
    /** Additional boost for more completed High priority */
    private static final long PRIORITY_W_COMPLETION	=1000;

    /** Additional boost for globally rarest piece */
    private static final long PRIORITY_W_RAREST		=1300;
    /** boost for rarity */
    private static final long PRIORITY_W_RARE		=2300;

	// The following are only used when resuming already running pieces
    /** priority boost due to being too old */
    private static final long PRIORITY_W_AGE		=1000;
    /** ms a block is expected to complete in, with leeway factor */
    private static final long PRIORITY_DW_AGE		=60 *1000;
    /** ms since last write */
    private static final long PRIORITY_DW_STALE		=120 *1000;
    /** finish pieces already almost done */
    private static final long PRIORITY_W_PIECE_DONE	=900;
    /** keep working on same piece */
    private static final long PRIORITY_W_SAME_PIECE	=500;

    /** Min number of requests sent to a peer */
    private static final int REQUESTS_MIN	=2;
    /** Max number of request sent to a peer */
    private static final int REQUESTS_MAX	=256;
	/** Default number of requests sent to a peer, (for each X B/s another request will be used) */
	private static final int SLOPE_REQUESTS	=4 *1024;
	
	private static final long END_GAME_MODE_SIZE_TRIGGER	=20 *1024 *1024;
	private static final long END_GAME_MODE_TIMEOUT			=60 *END_GAME_MODE_SIZE_TRIGGER /16384;
	
	protected static volatile boolean	firstPiecePriority	=COConfigurationManager.getBooleanParameter("Prioritize First Piece", false);
	protected static volatile boolean	completionPriority	=COConfigurationManager.getBooleanParameter("Prioritize Most Completed Files", false);
    /** event # of user settings controlling priority changes */
    protected static volatile long		paramPriorityChange =Long.MIN_VALUE;

	private final DiskManager			diskManager;
	private final PEPeerControl			peerControl;
	private final PiecePriorityShaper	priorityShaper;
	
	private final DiskManagerListenerImpl	diskManagerListener;
	
	protected final Map					peerListeners;
	private final PEPeerManagerListener	peerManagerListener;
	
	protected final int			nbPieces;
	protected final DiskManagerPiece[]	dmPieces;

	protected final AEMonitor availabilityMon = new AEMonitor("PiecePicker:avail");
	private final AEMonitor endGameModeChunks_mon =new AEMonitor("PiecePicker:EGM");

	protected volatile int	nbPiecesDone;
	
    /** asyncronously updated availability */
    protected volatile int[]	availabilityAsynch;
    /** indicates availability needs to be recomputed due to detected drift */
    protected volatile long		availabilityDrift;
	
    /** periodically updated consistent view of availability for calculating */
    protected volatile int[]	availability;
	
	private long			time_last_avail;
	protected volatile long	availabilityChange;
	private volatile long	availabilityComputeChange;
	private long			time_last_rebuild;
	
	private float		globalAvail;
	private float		globalAvgAvail;
	private int			nbRarestActive;
	private int			globalMin;
	/**
	 * The rarest availability level of pieces that we affirmatively want to try to request from others soonest
	 * ie; our prime targets for requesting rarest pieces
	 */
	private volatile int		globalMinOthers;
	
    /** event # of user file priority settings changes */
    protected volatile long		filePriorityChange;
	
    /** last user parameter settings event # when priority bases were calculated */
    private volatile long		priorityParamChange;
    /** last user priority event # when priority bases were calculated */
    private volatile long		priorityFileChange;
    /** last availability event # when priority bases were calculated */
    private volatile long		priorityAvailChange;
	
    /** time that base priorities were last computed */
    private long				timeLastPriorities;
	
    /** the priority for starting each piece/base priority for resuming */
    private long[]				startPriorities;
	
	protected volatile boolean	hasNeededUndonePiece;
	protected volatile long		neededUndonePieceChange;
	
	/** A flag to indicate when we're in endgame mode */
	private volatile boolean	endGameMode;
	private volatile boolean	endGameModeAbandoned;
	private volatile long		timeEndGameModeEntered;
	/** The list of chunks needing to be downloaded (the mechanism change when entering end-game mode) */
	private List 				endGameModeChunks;
	
	static
	{
		class ParameterListenerImpl
			implements ParameterListener
		{
			public void parameterChanged(String parameterName)
			{
				if (parameterName.equals("Prioritize Most Completed Files"))
				{
					completionPriority =COConfigurationManager.getBooleanParameter(parameterName, false);
					paramPriorityChange++;	// this is a user's priority change event
				} else if (parameterName.equals("Prioritize First Piece"))
				{
					firstPiecePriority =COConfigurationManager.getBooleanParameter(parameterName, false);
					paramPriorityChange++;	// this is a user's priority change event
			    }
		    }
		}

		ParameterListenerImpl	parameterListener =new ParameterListenerImpl();;

		COConfigurationManager.addParameterListener("Prioritize Most Completed Files", parameterListener);
		COConfigurationManager.addAndFireParameterListener("Prioritize First Piece", parameterListener);

	}
	
	
	public PiecePickerImpl(final PEPeerControl pc)
	{
		// class administration first
		priorityShaper =null;	//PiecePriorityShaperFactory.create(this);
		peerControl	= pc;
		diskManager = peerControl.getDiskManager();
		dmPieces =diskManager.getPieces();

 		nbPieces =diskManager.getNbPieces();
		nbPiecesDone =0;
		
		
		// now do stuff related to availability
		availability =new int[nbPieces];  //always needed
		
		hasNeededUndonePiece =false;
		neededUndonePieceChange =Long.MIN_VALUE;
		
		// ensure all periodic calculaters perform operations at least once
		time_last_avail =Long.MIN_VALUE;
		availabilityChange =Long.MIN_VALUE +1;
		availabilityComputeChange =Long.MIN_VALUE;
		availabilityDrift =nbPieces;
		
		// initialize each piece; on going changes will use event driven tracking
		for (int i =0; i <nbPieces; i++)
		{
			if (dmPieces[i].isDone()){
				availability[i]++;
				nbPiecesDone++;
			}else{
				hasNeededUndonePiece |=dmPieces[i].calcNeeded();
			}
		}
		if (hasNeededUndonePiece)
			neededUndonePieceChange++;
		
		updateAvailability();
		
		// with availability charged and primed, ready for peer messages
		peerListeners =new HashMap();
		peerManagerListener =new PEPeerManagerListenerImpl();
		peerControl.addListener(peerManagerListener);
		
		
		// now do stuff related to starting/continuing pieces
//		startPriorities =new long[nbPieces];    //allocate on demand
		filePriorityChange =Long.MIN_VALUE;
		
		priorityParamChange =Long.MIN_VALUE;
		priorityFileChange =Long.MIN_VALUE;
		priorityAvailChange =Long.MIN_VALUE;
		
		timeLastPriorities =Long.MIN_VALUE;
		
		endGameMode =false;
		endGameModeAbandoned =false;
		timeEndGameModeEntered =0;
		
//		computeBasePriorities();
		
		// with priorities charged and primed, ready for dm messages
		diskManagerListener =new DiskManagerListenerImpl();
		diskManager.addListener(diskManagerListener);
	}
	

    public void addHavePiece(final int pieceNumber)
	{
		try
		{	availabilityMon.enter();
			if ( availabilityAsynch == null ){
				availabilityAsynch = (int[])availability.clone();
			}
			++availabilityAsynch[pieceNumber];
			availabilityChange++;
		} finally {availabilityMon.exit();}
	}
	
    /**
     * This methd will compute the pieces' overall availability (including ourself)
     * and the _globalMinOthers & _globalAvail
     */
	public void updateAvailability()
	{
		final long now =SystemTime.getCurrentTime();
		if (now >=time_last_avail &&now <time_last_avail +TIME_MIN_AVAILABILITY)
			return;
		if (availabilityDrift >0 || now < time_last_rebuild ||  now - time_last_rebuild > TIME_AVAIL_REBUILD ){
			try
			{	availabilityMon.enter();
		
				time_last_rebuild	= now;
				
				int[]	new_availability = recomputeAvailability();
				
				/*
				int[]	old_availability = availabilityAsynch==null?availability:availabilityAsynch;
				
				int	errors	= 0;
				
				for (int i=0;i<new_availability.length;i++){
					if ( new_availability[i] != old_availability[i]){
						errors++;
					}
				}
				
				System.out.println( "avail rebuild: errors = " + errors );
				*/
				
				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];
			if (avail >0 &&avail <rarestMin &&dmPiece.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];
			if (avail >0)
			{
				if (avail >allMin)
					total++;
				if (avail <=rarestMin &&dmPiece.isRequestable() &&peerControl.getPiece(i) !=null)
					rarestActive++;
				totalAvail +=avail;
			}

⌨️ 快捷键说明

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