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

📄 pepieceimpl.java

📁 基于JXTA开发平台的下载软件开发源代码
💻 JAVA
字号:
/*
 * File    : PEPieceImpl.java
 * Created : 15-Oct-2003
 * By      : Olivier
 * 
 * Azureus - a Java Bittorrent client
 *
 * 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.
 *
 * 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 ( see the LICENSE file ).
 *
 * 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
 */

package org.gudy.azureus2.core3.peer.impl;

/**
 * @author parg
 * @author MjrTom
 *			2005/Oct/08: numerous changes for new piece-picking
 *			2006/Jan/02: refactoring piece picking to elsewhere, and consolidations
 */

import java.util.*;

import org.gudy.azureus2.core3.disk.*;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.peer.*;
import org.gudy.azureus2.core3.util.*;

public class 
PEPieceImpl
implements PEPiece
{
	private static final LogIDs LOGID = LogIDs.PIECES;
	
	final private DiskManagerPiece	dmPiece;
	final private PEPeerManager		manager;
	
    final private int       nbBlocks;       // number of blocks in this piece
    private long            creationTime;
    
	private final String[]	requested;
	private final boolean[]	downloaded;
	private final String[] 	writers;
	private List 			writes;
	
	private String			reservedBy;	// using address for when they send bad/disconnect/reconnect
	
	//In end game mode, this limitation isn't used
    private int             speed;      //slower peers dont slow down fast pieces too much
    
    private long            resumePriority;
    
	// experimental class level lock
	protected static AEMonitor 	class_mon	= new AEMonitor( "PEPiece:class");
	
    /** piece for tracking partially downloaded pieces
     * @param _manager the PEPeerManager
     * @param _dm_piece the backing dmPiece
     * @param _pieceSpeed the speed threshold for potential new requesters
     */
	public PEPieceImpl(
		PEPeerManager 		_manager, 
		DiskManagerPiece	_dm_piece,
        int                 _pieceSpeed)
	{
        creationTime =SystemTime.getCurrentTime();
		manager =_manager;
		dmPiece =_dm_piece;
        speed =_pieceSpeed;

		nbBlocks =dmPiece.getNbBlocks();

		requested =new String[nbBlocks];
        
        final boolean[] written =dmPiece.getWritten();
		if (written ==null)
			downloaded =new boolean[nbBlocks];
		else
			downloaded =(boolean[])written.clone();

        writers =new String[nbBlocks];
		writes =new ArrayList(0);
	}

    public DiskManagerPiece getDMPiece()
    {
        return dmPiece;
    }

    public long getCreationTime()
    {
        long now =SystemTime.getCurrentTime();
        if (now >=creationTime &&creationTime >0)
            return creationTime;
        creationTime =now;
        return now;
    }
    
    public long getTimeSinceLastActivity()
    {
        final long now =SystemTime.getCurrentTime();
        long lastWriteTime =dmPiece.getLastWriteTime();
        if (lastWriteTime >0 &&now >=lastWriteTime)
            return now -lastWriteTime;
        if (creationTime >0 &&now >=creationTime)
            return now -creationTime;
        creationTime =now;
        return 0;
    }

	/** Tells if a block has been requested
	 * @param blockNumber the block in question
	 * @return true if the block is Requested already
	 */
	public boolean isRequested(int blockNumber)
	{
		return requested[blockNumber] !=null;
	}

	/** Tells if a block has been downloaded
	 * @param blockNumber the block in question
	 * @return true if the block is downloaded already
	 */
	public boolean isDownloaded(int blockNumber)
	{
		return downloaded[blockNumber];
	}

	/** This flags the block at the given offset as having been downloaded
     * If all blocks are now downloaed, sets the dmPiece as downloaded
	 * @param blockNumber
	 */
	public void setDownloaded(int offset)
	{
		downloaded[offset /DiskManager.BLOCK_SIZE] =true;
        for (int i =0; i <nbBlocks; i++)
        {
            if (!downloaded[i])
                return;
        }
        dmPiece.setDownloaded();
        dmPiece.clearRequested();
	}

    /** This flags the block at the given offset as NOT having been downloaded
     * and the whole piece as not having been fully downloaded
     * @param blockNumber
     */
    public void clearDownloaded(int offset)
    {
        downloaded[offset /DiskManager.BLOCK_SIZE] =false;
        dmPiece.clearDownloaded();
    }

	/** This marks a given block as having been written by the given peer
	 * @param peer the PEPeer that sent the data
	 * @param blockNumber the block we're operating on
	 */
	public void setWritten(PEPeer peer, int blockNumber)
	{
		writers[blockNumber] =peer.getIp();
		dmPiece.setWritten(blockNumber);
	}
	
	/** This method clears the requested information for the given block
     * unless the block has already been downloaded, in which case the writer's
     * IP is recorded as a request for the block.
	 */
	public void clearRequested(int blockNumber)
	{
		requested[blockNumber] =downloaded[blockNumber] ?writers[blockNumber] :null;
	}

    /** @deprecated
     * This method is safe in a multi-threaded situation as the worst that it can do is mark a block as not requested even
     * though its downloaded which may lead to it being downloaded again
     */
    public void unmarkBlock(int blockNumber)
    {
        requested[blockNumber] =downloaded[blockNumber] ?writers[blockNumber] :null;
    }

//	/** This will scan each block looking for requested blocks. For each one, it'll verify
//	 * if the PEPeer for it still exists and is still willing and able to upload data.
//	 * If not, it'll unmark the block as requested. This should probably only be called
//	 * after a piece has timed out, and not during end game mode
//	 * @return int of how many were cleared (0 to nbBlocks)
//	 */
//	public int checkRequests()
//	{
//		int cleared =0;
//		boolean nullPeer =false;
//		for (int i =0; i <nbBlocks; i++)
//		{
//			if (!downloaded[i] &&!dmPiece.isWritten(i))
//			{
//				final String			requester =requested[i];
//				final PEPeerTransport	pt;
//				if (requester !=null)
//				{
//					pt =manager.getTransportFromAddress(requester);
//					if (pt !=null)
//					{
//						pt.setSnubbed(true);
//						if (!pt.isDownloadPossible())
//						{
//							requested[i] =null;
//							cleared++;
//						}
//					} else
//					{
//						nullPeer =true;
//						requested[i] =null;
//						cleared++;
//					}
//				}
//			}
//		}
//		if (cleared >0)
//		{
//			dmPiece.clearRequested();
////			manager.getPiecePicker().addEndGameBlocks(this);
//            if (Logger.isEnabled())
//                Logger.log(new LogEvent(dmPiece.getManager().getTorrent(), LOGID, LogEvent.LT_WARNING,
//                        "Piece:"+getPieceNumber()+" cleared "+cleared+" requests."
//                        + (nullPeer ?" Null peer was detected." :" ")));
//		}
//		return cleared;
//	}

	/** @return true if the piece has any blocks that are not;
	 *  Downloaded, Requested, or Written
	 */
	public boolean hasUnrequestedBlock()
	{
		final boolean[] written =dmPiece.getWritten();
		for (int i =0; i <nbBlocks; i++ )
		{
			if (!downloaded[i] &&requested[i] ==null &&(written ==null ||!written[i]))
				return true;
		}
		return false;
	}

	/**
	 * This method scans a piece for the first unrequested block.  Upon finding it,
	 * it counts how many are unrequested up to nbWanted.
	 * The blocks are marked as requested by the PEPeer
	 * Assumption - single threaded access to this
	 * TODO: this should return the largest span equal or smaller than nbWanted
	 * OR, probably a different method should do that, so this one can support 'more sequential' picking
	 */
	public int[] getAndMarkBlocks(PEPeer peer, int nbWanted)
	{
		final String ip =peer.getIp();
        final boolean[] written =dmPiece.getWritten();
		int blocksFound =0;
		// scan piece to find first free block
		for (int i =0; i <nbBlocks; i++)
		{
			while (blocksFound <nbWanted &&(i +blocksFound) <nbBlocks &&!downloaded[i +blocksFound]
			    &&requested[i +blocksFound] ==null &&(written ==null ||!written[i]))
			{
				requested[i +blocksFound] =ip;
				blocksFound++;
			}
			if (blocksFound >0)
				return new int[] {i, blocksFound};
		}
		return new int[] {-1, 0};
	}

    public int getNbRequests()
    {
        int result =0;
        for (int i =0; i <nbBlocks; i++)
        {
            if (!downloaded[i] &&requested[i] !=null)
                result++;
        }
        return result;
    }

    public int getNbUnrequested()
    {
        int result =0;
        final boolean[] written =dmPiece.getWritten();
        for (int i =0; i <nbBlocks; i++ )
        {
            if (!downloaded[i] &&requested[i] ==null &&(written ==null ||!written[i]))
                result++;
        }
        return result;
    }

	/**
	 * Assumption - single threaded with getAndMarkBlock
	 */
	public boolean setRequested(PEPeer peer, int blockNumber)
	{
		if (!downloaded[blockNumber])
		{
			requested[blockNumber] =peer.getIp();
			return true;
		}
		return false;
	}
	
	public int 
	getBlockSize(
		int blockNumber) 
	{
		if ( blockNumber == (nbBlocks - 1)){
			
			int	length = dmPiece.getLength();
			
			if ((length % DiskManager.BLOCK_SIZE) != 0){
				
				return( length % DiskManager.BLOCK_SIZE );
			}
		}
		
		return DiskManager.BLOCK_SIZE;
	}
    
    public int getBlockNumber(int offset)
    {
        return offset /DiskManager.BLOCK_SIZE;
    }
	
	public int getNbBlocks()
	{
		return nbBlocks;
	}

	public List getPieceWrites()
	{
		List result;
		try{
			class_mon.enter();
			
			result = new ArrayList(writes);
		}finally{
			
			class_mon.exit();
		}
		return result;
	}
	
	
	public List getPieceWrites(int blockNumber) {
		List result;
		try{
			class_mon.enter();
			
			result = new ArrayList(writes);
			
		}finally{
			
			class_mon.exit();
		}
		Iterator iter = result.iterator();
		while(iter.hasNext()) {
			PEPieceWriteImpl write = (PEPieceWriteImpl) iter.next();
			if(write.getBlockNumber() != blockNumber)
				iter.remove();
		}
		return result;
	}
	
	
	public List getPieceWrites(PEPeer peer) {
		List result;
		try{
			class_mon.enter();
			
			result = new ArrayList(writes);
		}finally{
			class_mon.exit();
		}
		Iterator iter = result.iterator();
		while(iter.hasNext()) {
			PEPieceWriteImpl write = (PEPieceWriteImpl) iter.next();
			if(peer == null || ! peer.equals(write.getSender()))
				iter.remove();
		}
		return result;
	}
	
	public List 
	getPieceWrites( 
		String	ip ) 
	{
		List result;
		
		try{
			class_mon.enter();
			
			result = new ArrayList(writes);
			
		}finally{
			
			class_mon.exit();
		}
		
		Iterator iter = result.iterator();
		
		while(iter.hasNext()) {
			
			PEPieceWriteImpl write = (PEPieceWriteImpl) iter.next();
			
			if ( !write.getSender().equals( ip )){
				
				iter.remove();
			}
		}
		
		return result;
	}

	public void reset()
	{
		dmPiece.reset();
		for (int i =0; i <nbBlocks; i++)
		{
            requested[i] =null;
			downloaded[i] =false;
			writers[i] =null;
		}
		reservedBy =null;
	}

	protected void addWrite(PEPieceWriteImpl write) {
		try{
			class_mon.enter();
			
			writes.add(write);
			
		}finally{
			
			class_mon.exit();
		}
	}
	
	public void 
	addWrite(
		int blockNumber,
		String sender, 
		byte[] hash,
		boolean correct	)
	{
		addWrite( new PEPieceWriteImpl( blockNumber, sender, hash, correct ));
	}

	public String[] getWriters()
	{
		return writers;
	}

	public int getSpeed()
	{
		return speed;
	}

	public void setSpeed(int newSpeed)
	{
		speed =newSpeed;
	}

	/** @deprecated
	*/
	public void decSpeed()
	{
		if (speed >0)
			speed--;
	}

	public void incSpeed()
	{
		speed++;
	}

	/**
	 * @return Returns the manager.
	 */
	public PEPeerManager getManager()
	{
		return manager;
	}

	public void setReservedBy(String peer)
	{
		reservedBy =peer;
	}

	public String getReservedBy()
	{
		return reservedBy;
	}

	/** for a block that's already downloadedt, mark up the piece
	 * so that the block will get downloaded again.  This is used
	 * when the piece fails hash-checking.
	 */
	public void reDownloadBlock(int blockNumber)
	{
		downloaded[blockNumber] =false;
		requested[blockNumber] =null;
		dmPiece.reDownloadBlock(blockNumber);
	}

	/** finds all blocks downloaded by the given address
	 * and marks them up for re-downloading 
	 * @param address String
	 */
	public void reDownloadBlocks(String address)
	{
		for (int i =0; i <writers.length; i++ )
		{
			String writer =writers[i];

			if (writer !=null &&writer.equals(address))
				reDownloadBlock(i);
		}
	}

	public void setResumePriority(long p)
	{
		resumePriority =p;
	}

	public long getResumePriority()
	{
		return resumePriority;
	}

    /**
     * @return int of availability in the swarm for this piece
     * @see org.gudy.azureus2.core3.peer.PEPeerManager.getAvailability(int pieceNumber)
     */
    public int getAvailability()
    {
        return manager.getAvailability(dmPiece.getPieceNumber());
    }

    /** This support method returns how many blocks have already been
     * written from the dmPiece
     * @return int from dmPiece.getNbWritten()
     * @see org.gudy.azureus2.core3.disk.DiskManagerPiece.getNbWritten()
     */
    public int getNbWritten()
    {
        return dmPiece.getNbWritten();
    }
    
    /** This support method returns the dmPiece's written array
     * @return boolean[] from the dmPiece
     * @see org.gudy.azureus2.core3.disk.DiskManagerPiece.getWritten()
     */
    public boolean[] getWritten()
    {
        return dmPiece.getWritten();
    }

	public int getPieceNumber()
	{
		return dmPiece.getPieceNumber();
	}

	public int getLength()
	{
		return dmPiece.getLength();
	}

    /**
     * @see DiskManagerPiece.isWritten()
     */
	public boolean isWritten()
	{
		return dmPiece.isWritten();
	}

	public void setRequestable()
	{
		dmPiece.setRequestable();
	}
	
	public boolean isChecking()
	{
		return dmPiece.isChecking();
	}

/*
    public void clearChecking()
    {
        dmPiece.clearChecking();
    }

	public int getNbWritten()
	{
		return dmPiece.getNbWritten();
	}
	
	public boolean isRequestable()
	{
		return dmPiece.isRequestable();
	}

	public void setChecking(boolean b)
	{
		dmPiece.setChecking(b);
	}

	public boolean isNeeded()
	{
		return dmPiece.isNeeded();
	}
*/
}

⌨️ 快捷键说明

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