📄 pepieceimpl.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;
private final DiskManagerPiece dmPiece;
private final PEPeerManager manager;
private final int nbBlocks; // number of blocks in this piece
private long creationTime;
private final String[] requested;
private boolean fully_requested;
private final boolean[] downloaded;
private boolean fully_downloaded;
private long time_last_download;
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 int resumePriority;
private Object real_time_data;
// experimental class level lock
protected static final 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()
{
final long now =SystemTime.getCurrentTime();
if (now >=creationTime &&creationTime >0)
return creationTime;
creationTime =now;
return now;
}
public long getTimeSinceLastActivity()
{
final long now =SystemTime.getCurrentTime();
final long lastWriteTime =getLastDownloadTime(now);
if (time_last_download >0 &&now >=time_last_download)
return now -time_last_download;
if (creationTime >0 &&now >=creationTime)
return now -creationTime;
creationTime =now;
return 0;
}
public long getLastDownloadTime(final long now)
{
if (time_last_download <=now)
return time_last_download;
return time_last_download =now;
}
/** 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)
{
time_last_download =SystemTime.getCurrentTime();
downloaded[offset /DiskManager.BLOCK_SIZE] =true;
for (int i =0; i <nbBlocks; i++)
{
if (!downloaded[i])
return;
}
fully_downloaded = true;
fully_requested = false;
}
/** 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;
fully_downloaded = false;
}
public boolean
isDownloaded()
{
return( fully_downloaded );
}
public boolean[]
getDownloaded()
{
return( downloaded );
}
public boolean
hasUndownloadedBlock()
{
for (int i =0; i <nbBlocks; i++ ){
if (!downloaded[i]){
return( true );
}
}
return( false );
}
/** 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;
fully_requested = false;
}
public boolean
isRequested()
{
return( fully_requested );
}
public void
setRequested()
{
fully_requested = true;
}
/** 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.
* @return int of how many were cleared (0 to nbBlocks)
*/
/*
public int checkRequests()
{
if (getTimeSinceLastActivity() <30 *1000)
return 0;
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())
{
clearRequested(i);
cleared++;
}
} else
{
nullPeer =true;
clearRequested(i);
cleared++;
}
}
}
}
if (cleared >0)
{
dmPiece.clearRequested();
if (Logger.isEnabled())
Logger.log(new LogEvent(dmPiece.getManager().getTorrent(), LOGID, LogEvent.LT_WARNING,
"checkRequests(): 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 void getAndMarkBlock(PEPeer peer, int index )
{
requested[index] = peer.getIp();
if ( getNbUnrequested() <= 0 ){
setRequested();
}
}
public int getNbRequests()
{
int result =0;
for (int i =0; i <nbBlocks; i++)
{
if (!downloaded[i] &&requested[i] !=null)
result++;
}
return result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -