mirror of https://github.com/aria2/aria2
				
				
				
			2006-05-20 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
To add the ability to download several pieces in mix in a command and increase the number of request slots according to request-cancel latency: * src/PeerInteractionCommand.cc (executeInternal): The number of messages to be received at a time is increased from 10 to 50. * src/LogFactory (getInstance): Added NullLogger. * src/NullLogger.h: New class. * src/BitfieldMan.h (getMissingIndex): New function. * src/BitfieldMan.cc (getMissingIndex): New function. * src/TorrentMan.h (checkOutPiece): New function. (getMissingPieceIndex): New function. (getMissingFastPieceIndex): New function. (getMissingFastPiece): New function. * src/TorrentMan.cc (updatePiece): Rewritten using STL. (syncPiece): Rewritten using STL. (getMissingPiece): Rewritten using getMissingPieceIndex() and checkOutPiece(). (getMissingPieceIndex): New function. (getMissingFastPieceIndex): New function. (getMissingFastPiece): New function. (checkOutPiece): New function. * src/PeerInteraction.h (Pieces): New type definition. (piece): Removed. (pieces): New variable. (getNewPieceAndSendInterest): Added the "piece" argument. (abortPiece): Added the "piece" argument. (abortAllPieces): New function. (isInRequestSlot): New function. (hasDownloadPiece): Added the "index" argument. (setDownloadPiece): Removed. (getDownloadPiece): Added the "index" argument. (updatePiece): New function. (createRequestMessage): Added the "index" argument. * src/PeerInteraction.cc (onChoked): Rewritten. (abortPiece): Rewirtten. (abortAllPieces): New function. (deleteTimeoutRequestSlot): Rewritten. Clarified code a little bit. (deleteCompletedRequestSlot): Rewritten. (isInRequestSlot): New function. (syncPiece): Rewritten. (updatePiece): New function. (getNewPieceAndSendInterest): Rewritten. (addRequests): Rewritten. (getDownloadPiece): Rewritten. (hasDownloadPiece): Rewritten. (createRequestMessage): Added the "index" argument. * src/common.h (BITFIELD_LEN_FROM_PIECES): Enclosed the variable in parentheses. (DIV_FLOOR): New definition. * src/PieceMessage.cc (receivedAction): Update request-piece latency here. * src/RequestSlot.h (getLatencyInMillis): New function. * src/RequestSlot.cc (isTimeout): Rewritten using getLatencyInMillis. (getLatencyInMillis): New function. * src/Piece.h (operator==): New function. (getMissingBlockIndex): New function. * src/Piece.cc (operator==): New function. (getMissingBlockIndex): New function. * src/Peer.h (DEFAULT_LATENCY): New definition. (latency): New variable. (updateLatency): New function. (getLatency): New function. * src/Peer.cc (resetStatus): Reset latecy. (updateLatency): New function.pull/1/head
							parent
							
								
									6497ed63d4
								
							
						
					
					
						commit
						896ca193e0
					
				
							
								
								
									
										83
									
								
								ChangeLog
								
								
								
								
							
							
						
						
									
										83
									
								
								ChangeLog
								
								
								
								
							| 
						 | 
				
			
			@ -1,3 +1,86 @@
 | 
			
		|||
2006-05-20  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 | 
			
		||||
 | 
			
		||||
	To add the ability to download several pieces in mix in a command and
 | 
			
		||||
	increase the number of request slots according to request-cancel
 | 
			
		||||
	latency:
 | 
			
		||||
	
 | 
			
		||||
	* src/PeerInteractionCommand.cc
 | 
			
		||||
	(executeInternal): The number of messages to be received at a time
 | 
			
		||||
	is increased from 10 to 50.
 | 
			
		||||
	* src/LogFactory
 | 
			
		||||
	(getInstance): Added NullLogger.
 | 
			
		||||
	* src/NullLogger.h: New class.
 | 
			
		||||
	* src/BitfieldMan.h
 | 
			
		||||
	(getMissingIndex): New function.
 | 
			
		||||
	* src/BitfieldMan.cc
 | 
			
		||||
	(getMissingIndex): New function.
 | 
			
		||||
	* src/TorrentMan.h
 | 
			
		||||
	(checkOutPiece): New function.
 | 
			
		||||
	(getMissingPieceIndex): New function.
 | 
			
		||||
	(getMissingFastPieceIndex): New function.
 | 
			
		||||
	(getMissingFastPiece): New function.
 | 
			
		||||
	* src/TorrentMan.cc
 | 
			
		||||
	(updatePiece): Rewritten using STL.
 | 
			
		||||
	(syncPiece): Rewritten using STL.
 | 
			
		||||
	(getMissingPiece): Rewritten using getMissingPieceIndex() and
 | 
			
		||||
	checkOutPiece().
 | 
			
		||||
	(getMissingPieceIndex): New function.
 | 
			
		||||
	(getMissingFastPieceIndex): New function.
 | 
			
		||||
	(getMissingFastPiece): New function.
 | 
			
		||||
	(checkOutPiece): New function.
 | 
			
		||||
	* src/PeerInteraction.h
 | 
			
		||||
	(Pieces): New type definition.
 | 
			
		||||
	(piece): Removed.
 | 
			
		||||
	(pieces): New variable.
 | 
			
		||||
	(getNewPieceAndSendInterest): Added the "piece" argument.
 | 
			
		||||
	(abortPiece): Added the "piece" argument.
 | 
			
		||||
	(abortAllPieces): New function.
 | 
			
		||||
	(isInRequestSlot): New function.
 | 
			
		||||
	(hasDownloadPiece): Added the "index" argument.
 | 
			
		||||
	(setDownloadPiece): Removed.
 | 
			
		||||
	(getDownloadPiece): Added the "index" argument.
 | 
			
		||||
	(updatePiece): New function.
 | 
			
		||||
	(createRequestMessage): Added the "index" argument.
 | 
			
		||||
	* src/PeerInteraction.cc
 | 
			
		||||
	(onChoked): Rewritten.
 | 
			
		||||
	(abortPiece): Rewirtten.
 | 
			
		||||
	(abortAllPieces): New function.
 | 
			
		||||
	(deleteTimeoutRequestSlot): Rewritten.
 | 
			
		||||
	Clarified code a little bit.
 | 
			
		||||
	(deleteCompletedRequestSlot): Rewritten.
 | 
			
		||||
	(isInRequestSlot): New function.
 | 
			
		||||
	(syncPiece): Rewritten.
 | 
			
		||||
	(updatePiece): New function.
 | 
			
		||||
	(getNewPieceAndSendInterest): Rewritten.
 | 
			
		||||
	(addRequests):  Rewritten.
 | 
			
		||||
	(getDownloadPiece): Rewritten.
 | 
			
		||||
	(hasDownloadPiece): Rewritten.
 | 
			
		||||
	(createRequestMessage): Added the "index" argument.
 | 
			
		||||
	* src/common.h
 | 
			
		||||
	(BITFIELD_LEN_FROM_PIECES): Enclosed the variable in parentheses.
 | 
			
		||||
	(DIV_FLOOR): New definition.
 | 
			
		||||
	* src/PieceMessage.cc
 | 
			
		||||
	(receivedAction): Update request-piece latency here.
 | 
			
		||||
	* src/RequestSlot.h
 | 
			
		||||
	(getLatencyInMillis): New function.
 | 
			
		||||
	* src/RequestSlot.cc
 | 
			
		||||
	(isTimeout): Rewritten using getLatencyInMillis.
 | 
			
		||||
	(getLatencyInMillis): New function.
 | 
			
		||||
	* src/Piece.h
 | 
			
		||||
	(operator==): New function.
 | 
			
		||||
	(getMissingBlockIndex): New function.
 | 
			
		||||
	* src/Piece.cc
 | 
			
		||||
	(operator==): New function.
 | 
			
		||||
	(getMissingBlockIndex): New function.
 | 
			
		||||
	* src/Peer.h
 | 
			
		||||
	(DEFAULT_LATENCY): New definition.
 | 
			
		||||
	(latency): New variable.
 | 
			
		||||
	(updateLatency): New function.
 | 
			
		||||
	(getLatency): New function.
 | 
			
		||||
	* src/Peer.cc
 | 
			
		||||
	(resetStatus): Reset latecy.
 | 
			
		||||
	(updateLatency): New function.
 | 
			
		||||
	
 | 
			
		||||
2006-05-20  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 | 
			
		||||
 | 
			
		||||
	* src/SocketCore.cc
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -192,6 +192,20 @@ int BitfieldMan::getFirstMissingUnusedIndex() const {
 | 
			
		|||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int BitfieldMan::getMissingIndex() const {
 | 
			
		||||
  unsigned char* tempBitfield = new unsigned char[bitfieldLength];
 | 
			
		||||
  for(int i = 0; i < bitfieldLength; i++) {
 | 
			
		||||
    tempBitfield[i] = ~bitfield[i];
 | 
			
		||||
    if(filterEnabled) {
 | 
			
		||||
      tempBitfield[i] &= filterBitfield[i];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  int max = countSetBit(tempBitfield, bitfieldLength);
 | 
			
		||||
  int index = getMissingIndexRandomly(tempBitfield, bitfieldLength, max);
 | 
			
		||||
  delete [] tempBitfield;
 | 
			
		||||
  return index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BlockIndexes BitfieldMan::getAllMissingIndexes() const {
 | 
			
		||||
  BlockIndexes missingIndexes;
 | 
			
		||||
  for(int i = 0; i < bitfieldLength; i++) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,6 +68,10 @@ public:
 | 
			
		|||
   * affected by filter
 | 
			
		||||
   */
 | 
			
		||||
  int getMissingIndex(const unsigned char* bitfield, int len) const;
 | 
			
		||||
  /**
 | 
			
		||||
   * affected by filter
 | 
			
		||||
   */
 | 
			
		||||
  int getMissingIndex() const;
 | 
			
		||||
  /**
 | 
			
		||||
   * affected by filter
 | 
			
		||||
   */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,19 +21,20 @@
 | 
			
		|||
/* copyright --> */
 | 
			
		||||
#include "LogFactory.h"
 | 
			
		||||
#include "SimpleLogger.h"
 | 
			
		||||
#include "NullLogger.h"
 | 
			
		||||
 | 
			
		||||
string LogFactory::filename;
 | 
			
		||||
Logger* LogFactory::logger = NULL;
 | 
			
		||||
 | 
			
		||||
Logger* LogFactory::getInstance() {
 | 
			
		||||
  if(logger == NULL) {
 | 
			
		||||
    SimpleLogger* slogger = new SimpleLogger();
 | 
			
		||||
    if(filename.empty()) {
 | 
			
		||||
      slogger->openFile("/dev/null");
 | 
			
		||||
      logger = new NullLogger();
 | 
			
		||||
    } else {
 | 
			
		||||
      SimpleLogger* slogger = new SimpleLogger();
 | 
			
		||||
      slogger->openFile(filename);
 | 
			
		||||
      logger = slogger;
 | 
			
		||||
    }
 | 
			
		||||
    logger = slogger;
 | 
			
		||||
  }
 | 
			
		||||
  return logger;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -100,7 +100,8 @@ SRCS =  Socket.cc Socket.h\
 | 
			
		|||
	RejectMessage.cc RejectMessage.h\
 | 
			
		||||
	AllowedFastMessage.cc AllowedFastMessage.h\
 | 
			
		||||
	SuggestPieceMessage.cc SuggestPieceMessage.h\
 | 
			
		||||
	SimplePeerMessage.cc SimplePeerMessage.h
 | 
			
		||||
	SimplePeerMessage.cc SimplePeerMessage.h\
 | 
			
		||||
	NullLogger.h
 | 
			
		||||
noinst_LIBRARIES = libaria2c.a
 | 
			
		||||
libaria2c_a_SOURCES = $(SRCS)
 | 
			
		||||
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -359,7 +359,8 @@ SRCS = Socket.cc Socket.h\
 | 
			
		|||
	RejectMessage.cc RejectMessage.h\
 | 
			
		||||
	AllowedFastMessage.cc AllowedFastMessage.h\
 | 
			
		||||
	SuggestPieceMessage.cc SuggestPieceMessage.h\
 | 
			
		||||
	SimplePeerMessage.cc SimplePeerMessage.h
 | 
			
		||||
	SimplePeerMessage.cc SimplePeerMessage.h\
 | 
			
		||||
	NullLogger.h
 | 
			
		||||
 | 
			
		||||
noinst_LIBRARIES = libaria2c.a
 | 
			
		||||
libaria2c_a_SOURCES = $(SRCS)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
/* <!-- copyright */
 | 
			
		||||
/*
 | 
			
		||||
 * aria2 - a simple utility for downloading files faster
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2006 Tatsuhiro Tsujikawa
 | 
			
		||||
 *
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
/* copyright --> */
 | 
			
		||||
#ifndef _D_NULL_LOGGER_H_
 | 
			
		||||
#define _D_NULL_LOGGER_H_
 | 
			
		||||
 | 
			
		||||
#include "Logger.h"
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
class NullLogger : public Logger {
 | 
			
		||||
public:
 | 
			
		||||
  NullLogger() {}
 | 
			
		||||
  virtual ~NullLogger() {}
 | 
			
		||||
  virtual void debug(const char* msg, ...) const {}
 | 
			
		||||
  virtual void debug(const char* msg, Exception* ex, ...) const {}
 | 
			
		||||
  virtual void info(const char* msg, ...) const {}
 | 
			
		||||
  virtual void info(const char* msg, Exception* ex, ...) const {}
 | 
			
		||||
  virtual void warn(const char* msg, ...) const {}
 | 
			
		||||
  virtual void warn(const char* msg, Exception* ex, ...) const {}
 | 
			
		||||
  virtual void error(const char*  msg, ...) const {}
 | 
			
		||||
  virtual void error(const char* msg, Exception* ex, ...) const {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // _D_NULL_LOGGER_H_
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +60,7 @@ void Peer::resetStatus() {
 | 
			
		|||
  chokingRequired = true;
 | 
			
		||||
  optUnchoking = false;
 | 
			
		||||
  fastExtensionEnabled = false;
 | 
			
		||||
  latency = DEFAULT_LATENCY;
 | 
			
		||||
  fastSet.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -76,3 +77,7 @@ void Peer::addFastSetIndex(int index) {
 | 
			
		|||
void Peer::setAllBitfield() {
 | 
			
		||||
  bitfield->setAllBit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Peer::updateLatency(int latency) {
 | 
			
		||||
  this->latency = (this->latency*80+latency*20)/200;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
 | 
			
		||||
#define PEER_ID_LENGTH 20
 | 
			
		||||
#define DEFAULT_LATENCY 1000
 | 
			
		||||
 | 
			
		||||
class Peer {
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			@ -57,6 +58,7 @@ private:
 | 
			
		|||
  long long int totalLength;
 | 
			
		||||
  int deltaUpload;
 | 
			
		||||
  int deltaDownload;
 | 
			
		||||
  int latency;
 | 
			
		||||
public:
 | 
			
		||||
  Peer(string ipaddr, int port, int pieceLength, long long int totalLength):
 | 
			
		||||
    entryId(0), ipaddr(ipaddr), port(port),
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +70,8 @@ public:
 | 
			
		|||
    fastExtensionEnabled(false),
 | 
			
		||||
    peerUpload(0), peerDownload(0),
 | 
			
		||||
    pieceLength(pieceLength), totalLength(totalLength),
 | 
			
		||||
    deltaUpload(0), deltaDownload(0) {
 | 
			
		||||
    deltaUpload(0), deltaDownload(0),
 | 
			
		||||
    latency(DEFAULT_LATENCY) {
 | 
			
		||||
    this->bitfield = new BitfieldMan(pieceLength, totalLength);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -140,6 +143,9 @@ public:
 | 
			
		|||
 | 
			
		||||
  bool isSeeder() const;
 | 
			
		||||
 | 
			
		||||
  void updateLatency(int latency);
 | 
			
		||||
  int getLatency() const { return latency; }
 | 
			
		||||
 | 
			
		||||
  static Peer* nullPeer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,8 +35,7 @@ PeerInteraction::PeerInteraction(int cuid,
 | 
			
		|||
  :cuid(cuid),
 | 
			
		||||
   uploadLimit(0),
 | 
			
		||||
   torrentMan(torrentMan),
 | 
			
		||||
   peer(peer),
 | 
			
		||||
   piece(Piece::nullPiece) {
 | 
			
		||||
   peer(peer) {
 | 
			
		||||
  peerConnection = new PeerConnection(cuid, socket, op);
 | 
			
		||||
  logger = LogFactory::getInstance();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -163,34 +162,51 @@ void PeerInteraction::rejectPieceMessageInQueue(int index, int begin, int length
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void PeerInteraction::onChoked() {
 | 
			
		||||
  if(!Piece::isNull(piece) && !peer->isInFastSet(piece.getIndex())) {
 | 
			
		||||
    abortPiece();
 | 
			
		||||
  for(Pieces::iterator itr = pieces.begin(); itr != pieces.end();) {
 | 
			
		||||
    Piece& piece = *itr;
 | 
			
		||||
    if(!peer->isInFastSet(piece.getIndex())) {
 | 
			
		||||
      abortPiece(piece);
 | 
			
		||||
      itr = pieces.erase(itr);
 | 
			
		||||
    } else {
 | 
			
		||||
      itr++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PeerInteraction::abortPiece() {
 | 
			
		||||
void PeerInteraction::abortAllPieces() {
 | 
			
		||||
  for(Pieces::iterator itr = pieces.begin(); itr != pieces.end();) {
 | 
			
		||||
    abortPiece(*itr);
 | 
			
		||||
    itr = pieces.erase(itr);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PeerInteraction::abortPiece(Piece& piece) {
 | 
			
		||||
  if(!Piece::isNull(piece)) {
 | 
			
		||||
    for(MessageQueue::iterator itr = messageQueue.begin();
 | 
			
		||||
	itr != messageQueue.end();) {
 | 
			
		||||
      if((*itr)->getId() == RequestMessage::ID
 | 
			
		||||
	 && !(*itr)->isInProgress()) {
 | 
			
		||||
      if((*itr)->getId() == RequestMessage::ID &&
 | 
			
		||||
	!(*itr)->isInProgress() &&
 | 
			
		||||
	 ((RequestMessage*)*itr)->getIndex() == piece.getIndex()) {
 | 
			
		||||
	delete *itr;
 | 
			
		||||
	itr = messageQueue.erase(itr);
 | 
			
		||||
      } else {
 | 
			
		||||
	itr++;
 | 
			
		||||
      }
 | 
			
		||||
    }  
 | 
			
		||||
    for(RequestSlots::const_iterator itr = requestSlots.begin();
 | 
			
		||||
	itr != requestSlots.end(); itr++) {
 | 
			
		||||
      logger->debug("CUID#%d - Deleting request slot blockIndex=%d"
 | 
			
		||||
		    " because piece was canceled",
 | 
			
		||||
		    cuid,
 | 
			
		||||
		    itr->getBlockIndex());
 | 
			
		||||
      piece.cancelBlock(itr->getBlockIndex());
 | 
			
		||||
    for(RequestSlots::iterator itr = requestSlots.begin();
 | 
			
		||||
	itr != requestSlots.end();) {
 | 
			
		||||
      if(itr->getIndex() == piece.getIndex()) {
 | 
			
		||||
	logger->debug("CUID#%d - Deleting request slot blockIndex=%d"
 | 
			
		||||
		      " because piece was canceled",
 | 
			
		||||
		      cuid,
 | 
			
		||||
		      itr->getBlockIndex());
 | 
			
		||||
	piece.cancelBlock(itr->getBlockIndex());
 | 
			
		||||
	itr = requestSlots.erase(itr);
 | 
			
		||||
      } else {
 | 
			
		||||
	itr++;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    requestSlots.clear();
 | 
			
		||||
    torrentMan->cancelPiece(piece);
 | 
			
		||||
    piece = Piece::nullPiece;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -206,31 +222,35 @@ void PeerInteraction::deleteRequestSlot(const RequestSlot& requestSlot) {
 | 
			
		|||
void PeerInteraction::deleteTimeoutRequestSlot() {
 | 
			
		||||
  for(RequestSlots::iterator itr = requestSlots.begin();
 | 
			
		||||
      itr != requestSlots.end();) {
 | 
			
		||||
    if(itr->isTimeout(REQUEST_TIME_OUT)) {
 | 
			
		||||
    RequestSlot& slot = *itr;
 | 
			
		||||
    if(slot.isTimeout(REQUEST_TIME_OUT)) {
 | 
			
		||||
      logger->debug("CUID#%d - Deleting request slot blockIndex=%d"
 | 
			
		||||
		    " because of time out",
 | 
			
		||||
		    cuid,
 | 
			
		||||
		    itr->getBlockIndex());
 | 
			
		||||
      if(!Piece::isNull(piece)) {
 | 
			
		||||
	piece.cancelBlock(itr->getBlockIndex());
 | 
			
		||||
      }
 | 
			
		||||
		    slot.getBlockIndex());
 | 
			
		||||
      Piece& piece = getDownloadPiece(slot.getIndex());
 | 
			
		||||
      piece.cancelBlock(slot.getBlockIndex());
 | 
			
		||||
      itr = requestSlots.erase(itr);
 | 
			
		||||
    } else {
 | 
			
		||||
      itr++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  torrentMan->updatePiece(piece);
 | 
			
		||||
  updatePiece();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PeerInteraction::deleteCompletedRequestSlot() {
 | 
			
		||||
  for(RequestSlots::iterator itr = requestSlots.begin();
 | 
			
		||||
      itr != requestSlots.end();) {
 | 
			
		||||
    if(Piece::isNull(piece) || piece.hasBlock(itr->getBlockIndex()) ||
 | 
			
		||||
    RequestSlot& slot = *itr;
 | 
			
		||||
    Piece piece = getDownloadPiece(slot.getIndex());
 | 
			
		||||
    if(piece.hasBlock(slot.getBlockIndex()) ||
 | 
			
		||||
       torrentMan->hasPiece(piece.getIndex())) {
 | 
			
		||||
      logger->debug("CUID#%d - Deleting request slot blockIndex=%d because"
 | 
			
		||||
		    " the block has been acquired.", cuid,
 | 
			
		||||
		    itr->getBlockIndex());
 | 
			
		||||
      addMessage(createCancelMessage(itr->getIndex(), itr->getBegin(), itr->getLength()));
 | 
			
		||||
		    slot.getBlockIndex());
 | 
			
		||||
      addMessage(createCancelMessage(slot.getIndex(),
 | 
			
		||||
				     slot.getBegin(),
 | 
			
		||||
				     slot.getLength()));
 | 
			
		||||
      itr = requestSlots.erase(itr);
 | 
			
		||||
    } else {
 | 
			
		||||
      itr++;
 | 
			
		||||
| 
						 | 
				
			
			@ -238,6 +258,17 @@ void PeerInteraction::deleteCompletedRequestSlot() {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool PeerInteraction::isInRequestSlot(int index, int blockIndex) const {
 | 
			
		||||
  for(RequestSlots::const_iterator itr = requestSlots.begin();
 | 
			
		||||
      itr != requestSlots.end(); itr++) {
 | 
			
		||||
    const RequestSlot& slot = *itr;
 | 
			
		||||
    if(slot.getIndex() == index && slot.getBlockIndex() == blockIndex) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RequestSlot PeerInteraction::getCorrespondingRequestSlot(int index,
 | 
			
		||||
							 int begin,
 | 
			
		||||
							 int length) const {
 | 
			
		||||
| 
						 | 
				
			
			@ -379,62 +410,112 @@ PeerMessage* PeerInteraction::createPeerMessage(const char* msg, int msgLength)
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
void PeerInteraction::syncPiece() {
 | 
			
		||||
  if(Piece::isNull(piece)) {
 | 
			
		||||
    return;
 | 
			
		||||
  for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
 | 
			
		||||
    torrentMan->syncPiece(*itr);
 | 
			
		||||
  }
 | 
			
		||||
  torrentMan->syncPiece(piece);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PeerInteraction::getNewPieceAndSendInterest() {
 | 
			
		||||
  piece = torrentMan->getMissingPiece(peer);
 | 
			
		||||
  if(Piece::isNull(piece)) {
 | 
			
		||||
    logger->debug("CUID#%d - Not interested in the peer", cuid);
 | 
			
		||||
    addMessage(createNotInterestedMessage());
 | 
			
		||||
  } else {
 | 
			
		||||
    if(peer->peerChoking && !peer->isInFastSet(piece.getIndex())) {
 | 
			
		||||
      abortPiece();
 | 
			
		||||
    } else {
 | 
			
		||||
      logger->info("CUID#%d - Starting download for piece index=%d (%d/%d completed)",
 | 
			
		||||
		    cuid, piece.getIndex(), piece.countCompleteBlock(),
 | 
			
		||||
		    piece.countBlock());
 | 
			
		||||
void PeerInteraction::updatePiece() {
 | 
			
		||||
  for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
 | 
			
		||||
    torrentMan->updatePiece(*itr);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PeerInteraction::getNewPieceAndSendInterest(int pieceNum) {
 | 
			
		||||
  int index = torrentMan->getMissingPieceIndex(peer);
 | 
			
		||||
  if(pieces.empty() && index == -1) {
 | 
			
		||||
    if(peer->amInterested) {
 | 
			
		||||
      logger->debug("CUID#%d - Not interested in the peer", cuid);
 | 
			
		||||
      addMessage(createNotInterestedMessage());
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    if(peer->peerChoking) {
 | 
			
		||||
      onChoked();
 | 
			
		||||
      if(peer->isFastExtensionEnabled()) {
 | 
			
		||||
	while((int)pieces.size() < pieceNum) {
 | 
			
		||||
	  Piece piece = torrentMan->getMissingFastPiece(peer);
 | 
			
		||||
	  if(Piece::isNull(piece)) {
 | 
			
		||||
	    break;
 | 
			
		||||
	  } else {
 | 
			
		||||
	    pieces.push_back(piece);
 | 
			
		||||
	  }
 | 
			
		||||
	}
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      while((int)pieces.size() < pieceNum) {
 | 
			
		||||
	Piece piece = torrentMan->getMissingPiece(peer);
 | 
			
		||||
	if(Piece::isNull(piece)) {
 | 
			
		||||
	  break;
 | 
			
		||||
	} else {
 | 
			
		||||
	  pieces.push_back(piece);
 | 
			
		||||
	}
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if(!peer->amInterested) {
 | 
			
		||||
      logger->debug("CUID#%d - Interested in the peer", cuid);
 | 
			
		||||
      addMessage(createInterestedMessage());
 | 
			
		||||
    }
 | 
			
		||||
    logger->debug("CUID#%d - Interested in the peer", cuid);
 | 
			
		||||
    addMessage(createInterestedMessage());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PeerInteraction::addRequests() {
 | 
			
		||||
  if(Piece::isNull(piece)) {
 | 
			
		||||
    // retrive new piece from TorrentMan
 | 
			
		||||
    getNewPieceAndSendInterest();
 | 
			
		||||
  } else if(peer->peerChoking && !peer->isInFastSet(piece.getIndex())) {
 | 
			
		||||
    onChoked();
 | 
			
		||||
  } else if(piece.pieceComplete()) {
 | 
			
		||||
    abortPiece();
 | 
			
		||||
    getNewPieceAndSendInterest();
 | 
			
		||||
  // Abort downloading of completed piece.
 | 
			
		||||
  for(Pieces::iterator itr = pieces.begin(); itr != pieces.end();) {
 | 
			
		||||
    Piece& piece = *itr;
 | 
			
		||||
    if(piece.pieceComplete()) {
 | 
			
		||||
      abortPiece(piece);
 | 
			
		||||
      itr = pieces.erase(itr);
 | 
			
		||||
    } else {
 | 
			
		||||
      itr++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if(!Piece::isNull(piece)) {
 | 
			
		||||
  int MAX_PENDING_REQUEST;
 | 
			
		||||
  if(peer->getLatency() < 300) {
 | 
			
		||||
    MAX_PENDING_REQUEST = 24;
 | 
			
		||||
  } else if(peer->getLatency() < 600) {
 | 
			
		||||
    MAX_PENDING_REQUEST = 18;
 | 
			
		||||
  } else if(peer->getLatency() < 1000) {
 | 
			
		||||
    MAX_PENDING_REQUEST = 12;
 | 
			
		||||
  } else {
 | 
			
		||||
    MAX_PENDING_REQUEST = 6;
 | 
			
		||||
  }
 | 
			
		||||
  int pieceNum;
 | 
			
		||||
  if(torrentMan->isEndGame()) {
 | 
			
		||||
    pieceNum = 1;
 | 
			
		||||
  } else {
 | 
			
		||||
    int blocks = DIV_FLOOR(torrentMan->pieceLength, BLOCK_LENGTH);
 | 
			
		||||
    pieceNum = DIV_FLOOR(MAX_PENDING_REQUEST, blocks);
 | 
			
		||||
  }
 | 
			
		||||
  getNewPieceAndSendInterest(pieceNum);
 | 
			
		||||
  for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
 | 
			
		||||
    Piece& piece = *itr;
 | 
			
		||||
    if(torrentMan->isEndGame()) {
 | 
			
		||||
      BlockIndexes missingBlockIndexes = piece.getAllMissingBlockIndexes();
 | 
			
		||||
      if(countRequestSlot() == 0) {
 | 
			
		||||
	random_shuffle(missingBlockIndexes.begin(), missingBlockIndexes.end());
 | 
			
		||||
	int count = 0;
 | 
			
		||||
	for(BlockIndexes::const_iterator itr = missingBlockIndexes.begin();
 | 
			
		||||
	    itr != missingBlockIndexes.end() && count < 6; itr++, count++) {
 | 
			
		||||
	  addMessage(createRequestMessage(*itr));
 | 
			
		||||
      random_shuffle(missingBlockIndexes.begin(), missingBlockIndexes.end());
 | 
			
		||||
      int count = countRequestSlot();
 | 
			
		||||
      for(BlockIndexes::const_iterator bitr = missingBlockIndexes.begin();
 | 
			
		||||
	  bitr != missingBlockIndexes.end() && count < MAX_PENDING_REQUEST;
 | 
			
		||||
	  bitr++) {
 | 
			
		||||
	int blockIndex = *bitr;
 | 
			
		||||
	if(!isInRequestSlot(piece.getIndex(), blockIndex)) {
 | 
			
		||||
	  addMessage(createRequestMessage(piece.getIndex(), blockIndex));
 | 
			
		||||
	  count++;
 | 
			
		||||
	}
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      for(int i = countRequestSlot(); i < 6; i++) {
 | 
			
		||||
      while(countRequestSlot() < MAX_PENDING_REQUEST) {
 | 
			
		||||
	int blockIndex = piece.getMissingUnusedBlockIndex();
 | 
			
		||||
	if(blockIndex == -1) {
 | 
			
		||||
	  break;
 | 
			
		||||
	}
 | 
			
		||||
	torrentMan->updatePiece(piece);
 | 
			
		||||
	addMessage(createRequestMessage(blockIndex));
 | 
			
		||||
	addMessage(createRequestMessage(piece.getIndex(), blockIndex));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if(countRequestSlot() >= MAX_PENDING_REQUEST) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  updatePiece();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PeerInteraction::sendHandshake() {
 | 
			
		||||
| 
						 | 
				
			
			@ -474,11 +555,22 @@ void PeerInteraction::sendAllowedFast() {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Piece& PeerInteraction::getDownloadPiece() {
 | 
			
		||||
  if(Piece::isNull(piece)) {
 | 
			
		||||
    throw new DlAbortEx("current piece is null");
 | 
			
		||||
Piece& PeerInteraction::getDownloadPiece(int index) {
 | 
			
		||||
  for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
 | 
			
		||||
    if(itr->getIndex() == index) {
 | 
			
		||||
      return *itr;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return piece;
 | 
			
		||||
  throw new DlAbortEx("No such piece index=%d", index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool PeerInteraction::hasDownloadPiece(int index) const {
 | 
			
		||||
  for(Pieces::const_iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
 | 
			
		||||
    if(itr->getIndex() == index) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool PeerInteraction::isInFastSet(int index) const {
 | 
			
		||||
| 
						 | 
				
			
			@ -497,8 +589,9 @@ void PeerInteraction::setPeerMessageCommonProperty(PeerMessage* peerMessage) {
 | 
			
		|||
  peerMessage->setPeerInteraction(this);  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RequestMessage* PeerInteraction::createRequestMessage(int blockIndex) {
 | 
			
		||||
RequestMessage* PeerInteraction::createRequestMessage(int index, int blockIndex) {
 | 
			
		||||
  RequestMessage* msg = new RequestMessage();
 | 
			
		||||
  Piece piece = getDownloadPiece(index);
 | 
			
		||||
  msg->setIndex(piece.getIndex());
 | 
			
		||||
  msg->setBegin(blockIndex*piece.getBlockLength());
 | 
			
		||||
  msg->setLength(piece.getBlockLength(blockIndex));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,6 +48,7 @@
 | 
			
		|||
 | 
			
		||||
typedef deque<RequestSlot> RequestSlots;
 | 
			
		||||
typedef deque<PeerMessage*> MessageQueue;
 | 
			
		||||
typedef deque<Piece> Pieces;
 | 
			
		||||
 | 
			
		||||
class PeerInteraction {
 | 
			
		||||
private:
 | 
			
		||||
| 
						 | 
				
			
			@ -59,12 +60,12 @@ private:
 | 
			
		|||
  TorrentMan* torrentMan;
 | 
			
		||||
  PeerConnection* peerConnection;
 | 
			
		||||
  Peer* peer;
 | 
			
		||||
  Piece piece;
 | 
			
		||||
  Pieces pieces;
 | 
			
		||||
  // allowed fast piece indexes that local client has sent
 | 
			
		||||
  Integers fastSet;
 | 
			
		||||
  const Logger* logger;
 | 
			
		||||
  
 | 
			
		||||
  void getNewPieceAndSendInterest();
 | 
			
		||||
  void getNewPieceAndSendInterest(int pieceNum);
 | 
			
		||||
  PeerMessage* createPeerMessage(const char* msg, int msgLength);
 | 
			
		||||
  HandshakeMessage* createHandshakeMessage(const char* msg, int msgLength);
 | 
			
		||||
  void setPeerMessageCommonProperty(PeerMessage* peerMessage);
 | 
			
		||||
| 
						 | 
				
			
			@ -81,13 +82,15 @@ public:
 | 
			
		|||
  void rejectPieceMessageInQueue(int index, int begin, int length);
 | 
			
		||||
  void rejectAllPieceMessageInQueue();
 | 
			
		||||
  void onChoked();
 | 
			
		||||
  void abortPiece();
 | 
			
		||||
  void abortPiece(Piece& piece);
 | 
			
		||||
  void abortAllPieces();
 | 
			
		||||
 | 
			
		||||
  bool isSendingMessageInProgress() const;
 | 
			
		||||
  void deleteRequestSlot(const RequestSlot& requestSlot);
 | 
			
		||||
  void deleteTimeoutRequestSlot();
 | 
			
		||||
  void deleteCompletedRequestSlot();
 | 
			
		||||
  RequestSlot getCorrespondingRequestSlot(int index, int begin, int length) const;
 | 
			
		||||
  bool isInRequestSlot(int index, int blockIndex) const;
 | 
			
		||||
 | 
			
		||||
  int countMessageInQueue() const;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -97,21 +100,17 @@ public:
 | 
			
		|||
  TorrentMan* getTorrentMan() const { return torrentMan; }
 | 
			
		||||
  PeerConnection* getPeerConnection() const { return peerConnection; }
 | 
			
		||||
  // If this object has nullPiece, then return false, otherwise true
 | 
			
		||||
  bool hasDownloadPiece() const {
 | 
			
		||||
    return !Piece::isNull(piece);
 | 
			
		||||
  }
 | 
			
		||||
  bool hasDownloadPiece(int index) const;
 | 
			
		||||
  // If the piece which this object has is nullPiece, then throws an exception.
 | 
			
		||||
  // So before calling this function, call hasDownloadPiece and make sure
 | 
			
		||||
  // this has valid piece, not nullPiece.
 | 
			
		||||
  Piece& getDownloadPiece();
 | 
			
		||||
  void setDownloadPiece(const Piece& piece) {
 | 
			
		||||
    this->piece = piece;
 | 
			
		||||
  }
 | 
			
		||||
  Piece& getDownloadPiece(int index);
 | 
			
		||||
  
 | 
			
		||||
  bool isInFastSet(int index) const;
 | 
			
		||||
  void addFastSetIndex(int index);
 | 
			
		||||
 | 
			
		||||
  void syncPiece();
 | 
			
		||||
  void updatePiece();
 | 
			
		||||
  void addRequests();
 | 
			
		||||
  void sendMessages(int currentUploadSpeed);
 | 
			
		||||
  void sendHandshake();
 | 
			
		||||
| 
						 | 
				
			
			@ -121,7 +120,7 @@ public:
 | 
			
		|||
  PeerMessage* receiveMessage();
 | 
			
		||||
  HandshakeMessage* receiveHandshake();
 | 
			
		||||
 | 
			
		||||
  RequestMessage* createRequestMessage(int blockIndex);
 | 
			
		||||
  RequestMessage* createRequestMessage(int index, int blockIndex);
 | 
			
		||||
  CancelMessage* createCancelMessage(int index, int begin, int length);
 | 
			
		||||
  PieceMessage* createPieceMessage(int index, int begin, int length);
 | 
			
		||||
  HaveMessage* createHaveMessage(int index);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -113,7 +113,7 @@ bool PeerInteractionCommand::executeInternal() {
 | 
			
		|||
  case WIRED:
 | 
			
		||||
    peerInteraction->syncPiece();
 | 
			
		||||
    decideChoking();
 | 
			
		||||
    for(int i = 0; i < 10; i++) {
 | 
			
		||||
    for(int i = 0; i < 50; i++) {
 | 
			
		||||
      if(!socket->isReadable(0)) {
 | 
			
		||||
	break;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -245,7 +245,7 @@ bool PeerInteractionCommand::prepareForRetry(int wait) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void PeerInteractionCommand::onAbort(Exception* ex) {
 | 
			
		||||
  peerInteraction->abortPiece();
 | 
			
		||||
  peerInteraction->abortAllPieces();
 | 
			
		||||
  PeerAbstractCommand::onAbort(ex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								src/Piece.cc
								
								
								
								
							
							
						
						
									
										13
									
								
								src/Piece.cc
								
								
								
								
							| 
						 | 
				
			
			@ -49,6 +49,10 @@ Piece& Piece::operator=(const Piece& piece) {
 | 
			
		|||
  return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Piece::operator==(const Piece& piece) const {
 | 
			
		||||
  return index == piece.index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Piece::completeBlock(int blockIndex) {
 | 
			
		||||
  bitfield->setBit(blockIndex);
 | 
			
		||||
  bitfield->unsetUseBit(blockIndex);
 | 
			
		||||
| 
						 | 
				
			
			@ -79,6 +83,15 @@ int Piece::getMissingUnusedBlockIndex() const {
 | 
			
		|||
  return blockIndex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Piece::getMissingBlockIndex() const {
 | 
			
		||||
  int blockIndex = bitfield->getMissingIndex();
 | 
			
		||||
  if(blockIndex == -1) {
 | 
			
		||||
    return blockIndex;
 | 
			
		||||
  }
 | 
			
		||||
  bitfield->setUseBit(blockIndex);
 | 
			
		||||
  return blockIndex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BlockIndexes Piece::getAllMissingBlockIndexes() const {
 | 
			
		||||
  return bitfield->getAllMissingIndexes();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,8 +43,10 @@ public:
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  Piece& operator=(const Piece& piece);
 | 
			
		||||
  bool operator==(const Piece& piece) const;
 | 
			
		||||
 | 
			
		||||
  int getMissingUnusedBlockIndex() const;
 | 
			
		||||
  int getMissingBlockIndex() const;
 | 
			
		||||
  BlockIndexes getAllMissingBlockIndexes() const;
 | 
			
		||||
  void completeBlock(int blockIndex);
 | 
			
		||||
  void cancelBlock(int blockIndex);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,9 +57,11 @@ void PieceMessage::receivedAction() {
 | 
			
		|||
								  begin,
 | 
			
		||||
								  blockLength);
 | 
			
		||||
  peer->addPeerUpload(blockLength);
 | 
			
		||||
  if(peerInteraction->hasDownloadPiece() &&
 | 
			
		||||
     !RequestSlot::isNull(slot)) {
 | 
			
		||||
    Piece& piece = peerInteraction->getDownloadPiece();
 | 
			
		||||
  if(!RequestSlot::isNull(slot) &&
 | 
			
		||||
     peerInteraction->hasDownloadPiece(slot.getIndex())) {
 | 
			
		||||
    //logger->debug("CUID#%d - Latency=%d", cuid, slot.getLatencyInMillis());
 | 
			
		||||
    peer->updateLatency(slot.getLatencyInMillis());
 | 
			
		||||
    Piece& piece = peerInteraction->getDownloadPiece(slot.getIndex());
 | 
			
		||||
    long long int offset =
 | 
			
		||||
      ((long long int)index)*torrentMan->pieceLength+begin;
 | 
			
		||||
    logger->debug("CUID#%d - Writing the block length=%d, offset=%lld",
 | 
			
		||||
| 
						 | 
				
			
			@ -197,7 +199,6 @@ void PieceMessage::onGotNewPiece(Piece& piece) {
 | 
			
		|||
  logger->info(MSG_GOT_NEW_PIECE, cuid, piece.getIndex());
 | 
			
		||||
  torrentMan->completePiece(piece);
 | 
			
		||||
  torrentMan->advertisePiece(cuid, piece.getIndex());
 | 
			
		||||
  piece = Piece::nullPiece;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PieceMessage::onGotWrongPiece(Piece& piece) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,9 +53,13 @@ void RequestSlot::setDispatchedTime() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
bool RequestSlot::isTimeout(int timeoutSec) const {
 | 
			
		||||
  return getLatencyInMillis() > timeoutSec*1000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int RequestSlot::getLatencyInMillis() const {
 | 
			
		||||
  struct timeval now;
 | 
			
		||||
  gettimeofday(&now, NULL);
 | 
			
		||||
  return Util::difftv(now, dispatchedTime) > ((long long int)timeoutSec)*1000000;
 | 
			
		||||
  return Util::difftv(now, dispatchedTime)/1000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RequestSlot::isNull(const RequestSlot& requestSlot) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,6 +43,7 @@ public:
 | 
			
		|||
  void setDispatchedTime();
 | 
			
		||||
 | 
			
		||||
  bool isTimeout(int timeoutSec) const;
 | 
			
		||||
  int getLatencyInMillis() const;
 | 
			
		||||
 | 
			
		||||
  bool operator==(const RequestSlot& requestSlot) const;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -145,7 +145,19 @@ bool TorrentMan::isEndGame() const {
 | 
			
		|||
  return bitfield->countMissingBlock() <= END_GAME_PIECE_NUM;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Piece TorrentMan::getMissingPiece(const Peer* peer) {
 | 
			
		||||
int TorrentMan::getMissingPieceIndex(const Peer* peer) const {
 | 
			
		||||
  int index = -1;
 | 
			
		||||
  if(isEndGame()) {
 | 
			
		||||
    index = bitfield->getMissingIndex(peer->getBitfield(),
 | 
			
		||||
				      peer->getBitfieldLength());
 | 
			
		||||
  } else {
 | 
			
		||||
    index = bitfield->getMissingUnusedIndex(peer->getBitfield(),
 | 
			
		||||
					    peer->getBitfieldLength());
 | 
			
		||||
  }
 | 
			
		||||
  return index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TorrentMan::getMissingFastPieceIndex(const Peer* peer) const {
 | 
			
		||||
  int index = -1;
 | 
			
		||||
  if(peer->isFastExtensionEnabled() && peer->countFastSet() > 0) {
 | 
			
		||||
    BitfieldMan tempBitfield(pieceLength, totalLength);
 | 
			
		||||
| 
						 | 
				
			
			@ -163,15 +175,20 @@ Piece TorrentMan::getMissingPiece(const Peer* peer) {
 | 
			
		|||
					      tempBitfield.getBitfieldLength());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if(index == -1) {
 | 
			
		||||
    if(isEndGame()) {
 | 
			
		||||
      index = bitfield->getMissingIndex(peer->getBitfield(),
 | 
			
		||||
					peer->getBitfieldLength());
 | 
			
		||||
    } else {
 | 
			
		||||
      index = bitfield->getMissingUnusedIndex(peer->getBitfield(),
 | 
			
		||||
					      peer->getBitfieldLength());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Piece TorrentMan::getMissingFastPiece(const Peer* peer) {
 | 
			
		||||
  int index = getMissingFastPieceIndex(peer);
 | 
			
		||||
  return checkOutPiece(index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Piece TorrentMan::getMissingPiece(const Peer* peer) {
 | 
			
		||||
  int index = getMissingPieceIndex(peer);
 | 
			
		||||
  return checkOutPiece(index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Piece TorrentMan::checkOutPiece(int index) {
 | 
			
		||||
  if(index == -1) {
 | 
			
		||||
    return Piece::nullPiece;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -281,11 +298,10 @@ void TorrentMan::updatePiece(const Piece& piece) {
 | 
			
		|||
  if(Piece::isNull(piece)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  for(UsedPieces::iterator itr = usedPieces.begin(); itr != usedPieces.end(); itr++) {
 | 
			
		||||
    if(itr->getIndex() == piece.getIndex()) {
 | 
			
		||||
      *itr = piece;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  UsedPieces::iterator itr = find(usedPieces.begin(), usedPieces.end(),
 | 
			
		||||
				  piece);
 | 
			
		||||
  if(itr != usedPieces.end()) {
 | 
			
		||||
    *itr = piece;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -293,17 +309,18 @@ void TorrentMan::syncPiece(Piece& piece) {
 | 
			
		|||
  if(Piece::isNull(piece)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  for(UsedPieces::iterator itr = usedPieces.begin(); itr != usedPieces.end(); itr++) {
 | 
			
		||||
    if(itr->getIndex() == piece.getIndex()) {
 | 
			
		||||
      piece = *itr;
 | 
			
		||||
      return;
 | 
			
		||||
  UsedPieces::iterator itr = find(usedPieces.begin(), usedPieces.end(),
 | 
			
		||||
				  piece);
 | 
			
		||||
  if(itr != usedPieces.end()) {
 | 
			
		||||
    piece = *itr;
 | 
			
		||||
    return;
 | 
			
		||||
  } else {
 | 
			
		||||
    // hasPiece(piece.getIndex()) is true, then set all bit of
 | 
			
		||||
    // piece.bitfield to 1
 | 
			
		||||
    if(hasPiece(piece.getIndex())) {
 | 
			
		||||
      piece.setAllBlock();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  // hasPiece(piece.getIndex()) is true, then set all bit of
 | 
			
		||||
  // piece.bitfield to 1
 | 
			
		||||
  if(hasPiece(piece.getIndex())) {
 | 
			
		||||
    piece.setAllBlock();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TorrentMan::initBitfield() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -91,6 +91,7 @@ private:
 | 
			
		|||
  void setFileFilter(const Strings& filePaths);
 | 
			
		||||
  void setupInternal1(const string& metaInfoFile);
 | 
			
		||||
  void setupInternal2();
 | 
			
		||||
  Piece checkOutPiece(int index);
 | 
			
		||||
public:
 | 
			
		||||
  int pieceLength;
 | 
			
		||||
  int pieces;
 | 
			
		||||
| 
						 | 
				
			
			@ -126,7 +127,10 @@ public:
 | 
			
		|||
  bool isPeerAvailable() const;
 | 
			
		||||
  int deleteOldErrorPeers(int maxNum);
 | 
			
		||||
 | 
			
		||||
  int getMissingPieceIndex(const Peer* peer) const;
 | 
			
		||||
  int getMissingFastPieceIndex(const Peer* peer) const;
 | 
			
		||||
  Piece getMissingPiece(const Peer* peer);
 | 
			
		||||
  Piece getMissingFastPiece(const Peer* peer);
 | 
			
		||||
  void completePiece(const Piece& piece);
 | 
			
		||||
  void cancelPiece(const Piece& piece);
 | 
			
		||||
  void updatePiece(const Piece& piece);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,9 @@
 | 
			
		|||
 | 
			
		||||
#define USER_AGENT "aria2"
 | 
			
		||||
 | 
			
		||||
#define BITFIELD_LEN_FROM_PIECES(X) (X/8+(X%8? 1 : 0))
 | 
			
		||||
#define BITFIELD_LEN_FROM_PIECES(X) ((X)/8+((X)%8? 1 : 0))
 | 
			
		||||
 | 
			
		||||
#define DIV_FLOOR(X,Y) ((X)/(Y)+((X)%(Y)? 1:0))
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue