mirror of https://github.com/aria2/aria2
				
				
				
			2006-10-20 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
To simplify TrackerWatherCommand, TrackerUpdateCommand and make the process of announce request testable. * src/TrackerWatcherCommand.h (TimeA2.h): Removed. (interval): Removed. (checkPoint): Removed. (createRequestCommand): Added an argument 'url'. (TrackerWatherCommand): Removed interval. (createCommand): New function. * src/DownloadEngineFactory.cc (newTorrentConsoleEngine): Updated according to the changes in TrackerWatherCommand. * src/TorrentMan.cc (DelegatingPeerListProcessor.h): New includes. (TorrentMan): Added the initialization of announceInterval. (isStoppedAnnounceReady): New function. (isCompletedAnnounceReady): New function. (isDefaultAnnounceReady): New function. (isAnnounceReady): New function. (getAnnounceUrl): New function. (announceStart): New function. (announceFailure): New function. (announceSuccess): New function. (isAllAnnounceFailed): New function. (resetAnnounce): New function. (processAnnounceResponse): New function. (needMorePeerConnection): New function. (noMoreAnnounce): New function. * src/TrackerUpdateCommand.h (getTrackerResponse): int->size_t * src/TorrentMan.h (isStoppedAnnounceReady): New function. (isCompletedAnnounceReady): New function. (isDefaultAnnounceReady): New function. (announceInterval): New variable. (isAnnounceReady): New function. (getAnnounceUrl): New function. (announceStart): New function. (announceFailure): New function. (announceSuccess): New function. (isAllAnnounceFailed): New function. (resetAnnounce): New function. (processAnnounceResponse): New function. (needMorePeerConnection): New function. (noMoreAnnounce): New function. * src/TrackerWatcherCommand.cc (TrackerWatherCommand): Removed interval and checkPoint. (execute): Rewritten. (createCommand): New function. (createRequestCommand): Rewritten. * src/TrackerUpdateCommand.cc (MetaFileUtil.h): Removed. (DelegatingPeerListProcessor.h): Removed. (getTrackerResponse): int->size_t. Use torrentMan's new functions.pull/1/head
							parent
							
								
									c0fd1fff2a
								
							
						
					
					
						commit
						b8737b0e7c
					
				
							
								
								
									
										58
									
								
								ChangeLog
								
								
								
								
							
							
						
						
									
										58
									
								
								ChangeLog
								
								
								
								
							|  | @ -1,3 +1,61 @@ | |||
| 2006-10-20  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com> | ||||
| 
 | ||||
| 	To simplify TrackerWatherCommand, TrackerUpdateCommand and | ||||
| 	make the process of announce request testable. | ||||
| 	 | ||||
| 	* src/TrackerWatcherCommand.h | ||||
| 	(TimeA2.h): Removed. | ||||
| 	(interval): Removed. | ||||
| 	(checkPoint): Removed. | ||||
| 	(createRequestCommand): Added an argument 'url'. | ||||
| 	(TrackerWatherCommand): Removed interval. | ||||
| 	(createCommand): New function. | ||||
| 	* src/DownloadEngineFactory.cc | ||||
| 	(newTorrentConsoleEngine): Updated according to the changes in | ||||
| 	TrackerWatherCommand. | ||||
| 	* src/TorrentMan.cc | ||||
| 	(DelegatingPeerListProcessor.h): New includes. | ||||
| 	(TorrentMan): Added the initialization of announceInterval. | ||||
| 	(isStoppedAnnounceReady): New function. | ||||
| 	(isCompletedAnnounceReady): New function. | ||||
| 	(isDefaultAnnounceReady): New function. | ||||
| 	(isAnnounceReady): New function. | ||||
| 	(getAnnounceUrl): New function. | ||||
| 	(announceStart): New function. | ||||
| 	(announceFailure): New function. | ||||
| 	(announceSuccess): New function. | ||||
| 	(isAllAnnounceFailed): New function. | ||||
| 	(resetAnnounce): New function. | ||||
| 	(processAnnounceResponse): New function. | ||||
| 	(needMorePeerConnection): New function. | ||||
| 	(noMoreAnnounce): New function. | ||||
| 	* src/TrackerUpdateCommand.h | ||||
| 	(getTrackerResponse): int->size_t | ||||
| 	* src/TorrentMan.h | ||||
| 	(isStoppedAnnounceReady): New function. | ||||
| 	(isCompletedAnnounceReady): New function. | ||||
| 	(isDefaultAnnounceReady): New function. | ||||
| 	(announceInterval): New variable. | ||||
| 	(isAnnounceReady): New function. | ||||
| 	(getAnnounceUrl): New function. | ||||
| 	(announceStart): New function. | ||||
| 	(announceFailure): New function. | ||||
| 	(announceSuccess): New function. | ||||
| 	(isAllAnnounceFailed): New function. | ||||
| 	(resetAnnounce): New function. | ||||
| 	(processAnnounceResponse): New function. | ||||
| 	(needMorePeerConnection): New function. | ||||
| 	(noMoreAnnounce): New function. | ||||
| 	* src/TrackerWatcherCommand.cc | ||||
| 	(TrackerWatherCommand): Removed interval and checkPoint. | ||||
| 	(execute): Rewritten. | ||||
| 	(createCommand): New function. | ||||
| 	(createRequestCommand): Rewritten. | ||||
| 	* src/TrackerUpdateCommand.cc | ||||
| 	(MetaFileUtil.h): Removed. | ||||
| 	(DelegatingPeerListProcessor.h): Removed. | ||||
| 	(getTrackerResponse): int->size_t. Use torrentMan's new functions. | ||||
| 	 | ||||
| 2006-10-18  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com> | ||||
| 
 | ||||
| 	Request -> RequestHandle: | ||||
|  |  | |||
|  | @ -114,8 +114,7 @@ DownloadEngineFactory::newTorrentConsoleEngine(const Option* op, | |||
|   te->commands.push_back(listenCommand); | ||||
|    | ||||
|   te->commands.push_back(new TrackerWatcherCommand(te->torrentMan->getNewCuid(), | ||||
| 						   te, | ||||
| 						   te->torrentMan->minInterval)); | ||||
| 						   te)); | ||||
|   te->commands.push_back(new TrackerUpdateCommand(te->torrentMan->getNewCuid(), | ||||
| 						  te)); | ||||
|   te->commands.push_back(new TorrentAutoSaveCommand(te->torrentMan->getNewCuid(), | ||||
|  |  | |||
|  | @ -49,6 +49,7 @@ | |||
| #include "DirectDiskAdaptor.h" | ||||
| #include "MultiDiskAdaptor.h" | ||||
| #include "LogFactory.h" | ||||
| #include "DelegatingPeerListProcessor.h" | ||||
| #include <errno.h> | ||||
| #include <libgen.h> | ||||
| #include <string.h> | ||||
|  | @ -76,6 +77,8 @@ TorrentMan::TorrentMan():bitfield(0), | |||
| 			 diskAdaptor(0) | ||||
| { | ||||
|   logger = LogFactory::getInstance(); | ||||
|   // to force requesting to a tracker first time.
 | ||||
|   announceInterval.setTimeInSec(0); | ||||
| } | ||||
| 
 | ||||
| TorrentMan::~TorrentMan() { | ||||
|  | @ -751,3 +754,158 @@ TransferStat TorrentMan::calculateStat() { | |||
|   } | ||||
|   return stat; | ||||
| } | ||||
| 
 | ||||
| bool TorrentMan::isStoppedAnnounceReady() const { | ||||
|   return (trackers == 0 && | ||||
| 	  isHalt() && | ||||
| 	  announceList.countStoppedAllowedTier()); | ||||
| } | ||||
| 
 | ||||
| bool TorrentMan::isCompletedAnnounceReady() const { | ||||
|   return (trackers == 0 && | ||||
| 	  downloadComplete() && | ||||
| 	  announceList.countCompletedAllowedTier()); | ||||
| } | ||||
| 
 | ||||
| bool TorrentMan::isDefaultAnnounceReady() const { | ||||
|   return (trackers == 0 && | ||||
| 	  announceInterval.elapsed(minInterval)); | ||||
| } | ||||
| 
 | ||||
| bool TorrentMan::isAnnounceReady() const { | ||||
|   return | ||||
|     isStoppedAnnounceReady() || | ||||
|     isCompletedAnnounceReady() || | ||||
|     isDefaultAnnounceReady(); | ||||
| } | ||||
| 
 | ||||
| string TorrentMan::getAnnounceUrl() { | ||||
|   if(isStoppedAnnounceReady()) { | ||||
|     announceList.moveToStoppedAllowedTier(); | ||||
|     announceList.setEvent(AnnounceTier::STOPPED); | ||||
|   } else if(isCompletedAnnounceReady()) { | ||||
|     announceList.moveToCompletedAllowedTier(); | ||||
|     announceList.setEvent(AnnounceTier::COMPLETED); | ||||
|   } else if(isDefaultAnnounceReady()) { | ||||
|     // If download completed before "started" event is sent to a tracker,
 | ||||
|     // we change the event to something else to prevent us from
 | ||||
|     // sending "completed" event.
 | ||||
|     if(downloadComplete() && | ||||
|        announceList.getEvent() == AnnounceTier::STARTED) { | ||||
|       announceList.setEvent(AnnounceTier::STARTED_AFTER_COMPLETION); | ||||
|     } | ||||
|   } | ||||
|   int numWant = 50; | ||||
|   if(connections >= MIN_PEERS || isHalt()) { | ||||
|     numWant = 0; | ||||
|   } | ||||
|   string url = announceList.getAnnounce()+"?"+ | ||||
|     "info_hash="+Util::torrentUrlencode(getInfoHash(), 20)+"&"+ | ||||
|     "peer_id="+peerId+"&"+ | ||||
|     "port="+Util::itos(getPort())+"&"+ | ||||
|     "uploaded="+Util::llitos(getSessionUploadLength())+"&"+ | ||||
|     "downloaded="+Util::llitos(getSessionDownloadLength())+"&"+ | ||||
|     "left="+(getTotalLength()-getDownloadLength() <= 0 | ||||
| 	     ? "0" : Util::llitos(getTotalLength()-getDownloadLength()))+"&"+ | ||||
|     "compact=1"+"&"+ | ||||
|     "key="+key+"&"+ | ||||
|     "numwant="+Util::itos(numWant)+"&"+ | ||||
|     "no_peer_id=1"; | ||||
|   string event = announceList.getEventString(); | ||||
|   if(!event.empty()) { | ||||
|     url += string("&")+"event="+event; | ||||
|   } | ||||
|   if(!trackerId.empty()) { | ||||
|     url += string("&")+"trackerid="+trackerId; | ||||
|   } | ||||
|   return url; | ||||
| } | ||||
| 
 | ||||
| void TorrentMan::announceStart() { | ||||
|   trackers++; | ||||
| } | ||||
| 
 | ||||
| void TorrentMan::announceFailure() { | ||||
|   trackers = 0; | ||||
|   trackerNumTry++; | ||||
|   announceList.announceFailure(); | ||||
| } | ||||
| 
 | ||||
| void TorrentMan::announceSuccess() { | ||||
|   trackers = 0; | ||||
|   announceList.announceSuccess(); | ||||
| } | ||||
| 
 | ||||
| bool TorrentMan::isAllAnnounceFailed() const { | ||||
|   return  | ||||
|     trackerNumTry >= option->getAsInt(PREF_TRACKER_MAX_TRIES); | ||||
| } | ||||
| 
 | ||||
| void TorrentMan::resetAnnounce() { | ||||
|   announceInterval.reset(); | ||||
|   trackerNumTry = 0; | ||||
| } | ||||
| 
 | ||||
| void TorrentMan::processAnnounceResponse(const char* trackerResponse, | ||||
| 					 size_t trackerResponseLength) { | ||||
|   SharedHandle<MetaEntry> entry(MetaFileUtil::bdecoding(trackerResponse, | ||||
| 							trackerResponseLength)); | ||||
|   Dictionary* response = (Dictionary*)entry.get(); | ||||
|   Data* failureReasonData = (Data*)response->get("failure reason"); | ||||
|   if(failureReasonData) { | ||||
|     throw new DlAbortEx("Tracker returned failure reason: %s", | ||||
| 			failureReasonData->toString().c_str()); | ||||
|   } | ||||
|   Data* warningMessageData = (Data*)response->get("warning message"); | ||||
|   if(warningMessageData) { | ||||
|     logger->warn(MSG_TRACKER_WARNING_MESSAGE, | ||||
| 		 warningMessageData->toString().c_str()); | ||||
|   } | ||||
|   Data* trackerIdData = (Data*)response->get("tracker id"); | ||||
|   if(trackerIdData) { | ||||
|     trackerId = trackerIdData->toString(); | ||||
|     logger->debug("Tracker ID:%s", trackerId.c_str()); | ||||
|   } | ||||
|   Data* intervalData = (Data*)response->get("interval"); | ||||
|   if(intervalData) { | ||||
|     interval = intervalData->toInt(); | ||||
|     logger->debug("Interval:%d", interval); | ||||
|   } | ||||
|   Data* minIntervalData = (Data*)response->get("min interval"); | ||||
|   if(minIntervalData) { | ||||
|     minInterval = minIntervalData->toInt(); | ||||
|     logger->debug("Min interval:%d", minInterval); | ||||
|   } | ||||
|   if(minInterval > interval) { | ||||
|     minInterval = interval; | ||||
|   } | ||||
|   Data* completeData = (Data*)response->get("complete"); | ||||
|   if(completeData) { | ||||
|     complete = completeData->toInt(); | ||||
|     logger->debug("Complete:%d", complete); | ||||
|   } | ||||
|   Data* incompleteData = (Data*)response->get("incomplete"); | ||||
|   if(incompleteData) { | ||||
|     incomplete = incompleteData->toInt(); | ||||
|     logger->debug("Incomplete:%d", incomplete); | ||||
|   } | ||||
|   const MetaEntry* peersEntry = response->get("peers"); | ||||
|   if(peersEntry && !isHalt() && connections < MIN_PEERS) { | ||||
|     DelegatingPeerListProcessor proc(pieceLength, getTotalLength()); | ||||
|     Peers peers = proc.extractPeer(peersEntry); | ||||
|     addPeer(peers); | ||||
|   } | ||||
|   if(!peersEntry) { | ||||
|     logger->info("No peer list received."); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| bool TorrentMan::needMorePeerConnection() const { | ||||
|   return isPeerAvailable() && connections < MIN_PEERS; | ||||
| } | ||||
| 
 | ||||
| bool TorrentMan::noMoreAnnounce() const { | ||||
|   return (trackers == 0 && | ||||
| 	  isHalt() && | ||||
| 	  !announceList.countStoppedAllowedTier()); | ||||
| } | ||||
|  |  | |||
|  | @ -126,6 +126,10 @@ private: | |||
|   void setupInternal1(const string& metaInfoFile); | ||||
|   void setupInternal2(); | ||||
|   Piece checkOutPiece(int index); | ||||
|   bool isStoppedAnnounceReady() const; | ||||
|   bool isCompletedAnnounceReady() const; | ||||
|   bool isDefaultAnnounceReady() const; | ||||
| 
 | ||||
| public: | ||||
|   int pieceLength; | ||||
|   int pieces; | ||||
|  | @ -143,6 +147,7 @@ public: | |||
|   // The number of tracker request command currently in the command queue.
 | ||||
|   int trackers; | ||||
|   int trackerNumTry; | ||||
|   Time announceInterval; | ||||
|   // tracker request
 | ||||
|   AnnounceList announceList; | ||||
| public: | ||||
|  | @ -297,6 +302,18 @@ public: | |||
|   void setHalt(bool halt) { | ||||
|     this->halt = halt; | ||||
|   } | ||||
|   // announce related methods.
 | ||||
|   bool isAnnounceReady() const; | ||||
|   string getAnnounceUrl(); | ||||
|   void announceStart(); | ||||
|   void announceSuccess(); | ||||
|   void announceFailure(); | ||||
|   bool isAllAnnounceFailed() const; | ||||
|   void resetAnnounce(); | ||||
|   void processAnnounceResponse(const char* trackerResponse, | ||||
| 			       size_t trackerResponseLength); | ||||
|   bool needMorePeerConnection() const; | ||||
|   bool noMoreAnnounce() const; | ||||
| 
 | ||||
|   enum FILE_MODE { | ||||
|     SINGLE, | ||||
|  |  | |||
|  | @ -34,15 +34,13 @@ | |||
| /* copyright --> */ | ||||
| #include "TrackerUpdateCommand.h" | ||||
| #include "LogFactory.h" | ||||
| #include "MetaFileUtil.h" | ||||
| #include "DlAbortEx.h" | ||||
| #include "message.h" | ||||
| #include "PeerInitiateConnectionCommand.h" | ||||
| #include "SleepCommand.h" | ||||
| #include "Util.h" | ||||
| #include "DelegatingPeerListProcessor.h" | ||||
| 
 | ||||
| TrackerUpdateCommand::TrackerUpdateCommand(int cuid, TorrentDownloadEngine*e):Command(cuid), e(e) { | ||||
| TrackerUpdateCommand::TrackerUpdateCommand(int cuid, TorrentDownloadEngine* e):Command(cuid), e(e) { | ||||
|   logger = LogFactory::getInstance(); | ||||
| } | ||||
| 
 | ||||
|  | @ -53,7 +51,7 @@ bool TrackerUpdateCommand::prepareForRetry() { | |||
|   return false; | ||||
| } | ||||
| 
 | ||||
| char* TrackerUpdateCommand::getTrackerResponse(int& trackerResponseLength) { | ||||
| char* TrackerUpdateCommand::getTrackerResponse(size_t& trackerResponseLength) { | ||||
|   int maxBufLength = 2048; | ||||
|   char* buf = new char[maxBufLength]; | ||||
|   int bufLength = 0; | ||||
|  | @ -86,77 +84,24 @@ bool TrackerUpdateCommand::execute() { | |||
|     return prepareForRetry(); | ||||
|   } | ||||
|   char* trackerResponse = NULL; | ||||
|   int trackerResponseLength = 0; | ||||
|   size_t trackerResponseLength = 0; | ||||
| 
 | ||||
|   try { | ||||
|     trackerResponse = getTrackerResponse(trackerResponseLength); | ||||
|     SharedHandle<MetaEntry> entry(MetaFileUtil::bdecoding(trackerResponse, | ||||
| 							  trackerResponseLength)); | ||||
|     Dictionary* response = (Dictionary*)entry.get(); | ||||
|     Data* failureReason = (Data*)response->get("failure reason"); | ||||
|     if(failureReason != NULL) { | ||||
|       throw new DlAbortEx("Tracker returned failure reason: %s", failureReason->toString().c_str()); | ||||
|     } | ||||
|     Data* warningMessage = (Data*)response->get("warning message"); | ||||
|     if(warningMessage != NULL) { | ||||
|       logger->warn(MSG_TRACKER_WARNING_MESSAGE, warningMessage->toString().c_str()); | ||||
|     } | ||||
|     Data* trackerId = (Data*)response->get("tracker id"); | ||||
|     if(trackerId != NULL) { | ||||
|       e->torrentMan->trackerId = trackerId->toString(); | ||||
|       logger->debug("CUID#%d - Tracker ID:%s", | ||||
| 		    cuid, e->torrentMan->trackerId.c_str()); | ||||
|     } | ||||
|     Data* interval = (Data*)response->get("interval"); | ||||
|     if(interval != NULL) { | ||||
|       e->torrentMan->interval = interval->toInt(); | ||||
|       logger->debug("CUID#%d - Interval:%d", cuid, e->torrentMan->interval); | ||||
|     } | ||||
|     Data* minInterval = (Data*)response->get("min interval"); | ||||
|     if(minInterval != NULL) { | ||||
|       e->torrentMan->minInterval = minInterval->toInt(); | ||||
|       logger->debug("CUID#%d - Min interval:%d", | ||||
| 		    cuid, e->torrentMan->minInterval); | ||||
|     } | ||||
|     if(e->torrentMan->minInterval > e->torrentMan->interval) { | ||||
|       e->torrentMan->minInterval = e->torrentMan->interval; | ||||
|     } | ||||
|     Data* complete = (Data*)response->get("complete"); | ||||
|     if(complete != NULL) { | ||||
|       e->torrentMan->complete = complete->toInt(); | ||||
|       logger->debug("CUID#%d - Complete:%d", cuid, e->torrentMan->complete); | ||||
|     } | ||||
|     Data* incomplete = (Data*)response->get("incomplete"); | ||||
|     if(incomplete != NULL) { | ||||
|       e->torrentMan->incomplete = incomplete->toInt(); | ||||
|       logger->debug("CUID#%d - Incomplete:%d", | ||||
| 		    cuid, e->torrentMan->incomplete); | ||||
|     } | ||||
|     const MetaEntry* peersEntry = response->get("peers"); | ||||
|     if(!e->torrentMan->isHalt() && | ||||
|        e->torrentMan->connections < MIN_PEERS && | ||||
|        peersEntry) { | ||||
|       DelegatingPeerListProcessor proc(e->torrentMan->pieceLength, | ||||
| 				       e->torrentMan->getTotalLength()); | ||||
|       Peers peers = proc.extractPeer(peersEntry); | ||||
|       e->torrentMan->addPeer(peers); | ||||
| 
 | ||||
|       while(e->torrentMan->isPeerAvailable() && | ||||
| 	    e->torrentMan->connections < MIN_PEERS) { | ||||
| 	PeerHandle peer = e->torrentMan->getPeer(); | ||||
| 	int newCuid =  e->torrentMan->getNewCuid(); | ||||
| 	peer->cuid = newCuid; | ||||
| 	PeerInitiateConnectionCommand* command = | ||||
| 	  new PeerInitiateConnectionCommand(newCuid, peer, e); | ||||
| 	e->commands.push_back(command); | ||||
| 	logger->debug("CUID#%d - Adding new command CUID#%d", cuid, newCuid); | ||||
|       } | ||||
|     e->torrentMan->processAnnounceResponse(trackerResponse, | ||||
| 					   trackerResponseLength); | ||||
|     while(e->torrentMan->needMorePeerConnection()) { | ||||
|       PeerHandle peer = e->torrentMan->getPeer(); | ||||
|       int newCuid =  e->torrentMan->getNewCuid(); | ||||
|       peer->cuid = newCuid; | ||||
|       PeerInitiateConnectionCommand* command = | ||||
| 	new PeerInitiateConnectionCommand(newCuid, peer, e); | ||||
|       e->commands.push_back(command); | ||||
|       logger->debug("CUID#%d - Adding new command CUID#%d", cuid, newCuid); | ||||
|     } | ||||
|     if(!peersEntry) { | ||||
|       logger->info("CUID#%d - No peer list received.", cuid); | ||||
|     } | ||||
|     e->torrentMan->announceList.announceSuccess(); | ||||
|     e->torrentMan->trackers = 0; | ||||
|     e->torrentMan->announceSuccess(); | ||||
|     e->torrentMan->resetAnnounce(); | ||||
|     e->segmentMan->init(); | ||||
|   } catch(Exception* err) { | ||||
|     logger->error("CUID#%d - Error occurred while processing tracker response.", cuid, err); | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ private: | |||
|   TorrentDownloadEngine* e; | ||||
|   const Logger* logger; | ||||
|   bool prepareForRetry(); | ||||
|   char* getTrackerResponse(int& trackerResponseLength); | ||||
|   char* getTrackerResponse(size_t& trackerResponseLength); | ||||
| public: | ||||
|   TrackerUpdateCommand(int cuid, TorrentDownloadEngine* e); | ||||
|   virtual ~TrackerUpdateCommand(); | ||||
|  |  | |||
|  | @ -39,103 +39,48 @@ | |||
| #include "prefs.h" | ||||
| 
 | ||||
| TrackerWatcherCommand::TrackerWatcherCommand(int cuid, | ||||
| 					     TorrentDownloadEngine* e, | ||||
| 					     int interval): | ||||
|   Command(cuid), e(e), interval(interval) { | ||||
|   // to force requesting to a tracker first time.
 | ||||
|   checkPoint.setTimeInSec(0); | ||||
| 					     TorrentDownloadEngine* e): | ||||
|   Command(cuid), e(e) { | ||||
| } | ||||
| 
 | ||||
| TrackerWatcherCommand::~TrackerWatcherCommand() {} | ||||
| 
 | ||||
| bool TrackerWatcherCommand::execute() { | ||||
|   Command* command = 0; | ||||
|   if(e->torrentMan->trackers == 0 && e->torrentMan->isHalt()) { | ||||
|     // Download is going to halt.
 | ||||
|     // Check whether there are at least one tracker which can receive
 | ||||
|     // "stopped" event.
 | ||||
|     if(e->torrentMan->announceList.countStoppedAllowedTier()) { | ||||
|       e->torrentMan->announceList.moveToStoppedAllowedTier(); | ||||
|       e->torrentMan->announceList.setEvent(AnnounceTier::STOPPED); | ||||
|       command = createRequestCommand(); | ||||
|     } else { | ||||
|       // We don't send "stopped" event since no tracker cares about it.
 | ||||
|       return true; | ||||
|     } | ||||
|   } else if(e->torrentMan->trackers == 0 && | ||||
| 	    e->torrentMan->downloadComplete() && | ||||
| 	    e->torrentMan->announceList.countCompletedAllowedTier()) { | ||||
|     // Send "completed" event to all trackers which can accept it.
 | ||||
|     e->torrentMan->announceList.moveToCompletedAllowedTier(); | ||||
|     e->torrentMan->announceList.setEvent(AnnounceTier::COMPLETED); | ||||
|     command = createRequestCommand(); | ||||
|   } else if(e->torrentMan->trackers == 0 && | ||||
| 	    checkPoint.elapsed(interval)) { | ||||
|     checkPoint.reset(); | ||||
|     // If download completed before "started" event is sent to a tracker,
 | ||||
|     // we change the event to something else to prevent us from
 | ||||
|     // sending "completed" event.
 | ||||
|     if(e->torrentMan->downloadComplete() && | ||||
|        e->torrentMan->announceList.getEvent() == AnnounceTier::STARTED) { | ||||
|       e->torrentMan->announceList.setEvent(AnnounceTier::STARTED_AFTER_COMPLETION); | ||||
|     } | ||||
|     command = createRequestCommand(); | ||||
|   } else if(e->segmentMan->errors > 0) { | ||||
|     e->torrentMan->trackerNumTry++; | ||||
|     checkPoint.reset(); | ||||
|     // we assume the tracker request has failed.
 | ||||
|     e->torrentMan->announceList.announceFailure(); | ||||
|     e->torrentMan->trackers = 0; | ||||
|     e->segmentMan->init(); | ||||
|     if(e->torrentMan->trackerNumTry >= e->option->getAsInt(PREF_TRACKER_MAX_TRIES)) { | ||||
|       // abort tracker request
 | ||||
|       e->torrentMan->trackerNumTry = 0; | ||||
|       if(e->torrentMan->isHalt()) { | ||||
| 	return true; | ||||
|       } | ||||
|     } else { | ||||
|       // sleep a few seconds.
 | ||||
|       command = | ||||
| 	new SleepCommand(cuid, e, | ||||
| 			 createRequestCommand(), | ||||
| 			 e->option->getAsInt(PREF_RETRY_WAIT)); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| bool TrackerWatcherCommand::execute() { | ||||
|   if(e->torrentMan->isHalt() && | ||||
|      e->segmentMan->errors > 0 && e->torrentMan->isAllAnnounceFailed() || | ||||
|      e->torrentMan->noMoreAnnounce()) { | ||||
|     return true; | ||||
|   } | ||||
|   Command* command = createCommand(); | ||||
|   if(command) { | ||||
|     e->commands.push_back(command); | ||||
|     e->torrentMan->trackers++; | ||||
|   } | ||||
|   // updates interval with newest minInterval
 | ||||
|   interval = e->torrentMan->minInterval; | ||||
|   e->commands.push_back(this); | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| Command* TrackerWatcherCommand::createRequestCommand() { | ||||
|   int numWant = 50; | ||||
|   if(e->torrentMan->connections >= MIN_PEERS || e->torrentMan->isHalt()) { | ||||
|     numWant = 0; | ||||
|   } | ||||
|   string url = e->torrentMan->announceList.getAnnounce()+"?"+ | ||||
|     "info_hash="+Util::torrentUrlencode(e->torrentMan->getInfoHash(), 20)+"&"+ | ||||
|     "peer_id="+e->torrentMan->peerId+"&"+ | ||||
|     "port="+Util::itos(e->torrentMan->getPort())+"&"+ | ||||
|     "uploaded="+Util::llitos(e->torrentMan->getSessionUploadLength())+"&"+ | ||||
|     "downloaded="+Util::llitos(e->torrentMan->getSessionDownloadLength())+"&"+ | ||||
|     "left="+(e->torrentMan->getTotalLength()-e->torrentMan->getDownloadLength() <= 0 | ||||
| 	     ? "0" : Util::llitos(e->torrentMan->getTotalLength()-e->torrentMan->getDownloadLength()))+"&"+ | ||||
|     "compact=1"+"&"+ | ||||
|     "key="+e->torrentMan->key+"&"+ | ||||
|     "numwant="+Util::itos(numWant)+"&"+ | ||||
|     "no_peer_id=1"; | ||||
|   string event = e->torrentMan->announceList.getEventString(); | ||||
|   if(!event.empty()) { | ||||
|     url += string("&")+"event="+event; | ||||
|   } | ||||
|   if(!e->torrentMan->trackerId.empty()) { | ||||
|     url += string("&")+"trackerid="+e->torrentMan->trackerId; | ||||
| Command* TrackerWatcherCommand::createCommand() { | ||||
|   Command* command = 0; | ||||
|   if(e->torrentMan->isAnnounceReady()) { | ||||
|     command = createRequestCommand(e->torrentMan->getAnnounceUrl()); | ||||
|     e->torrentMan->announceStart(); // inside it, trackers++.
 | ||||
|   } else if(e->segmentMan->errors > 0) { | ||||
|     e->torrentMan->announceFailure(); // inside it, trackers = 0.
 | ||||
|     e->segmentMan->init(); | ||||
|     if(e->torrentMan->isAllAnnounceFailed()) { | ||||
|       e->torrentMan->resetAnnounce(); | ||||
|       // sleep a few seconds.
 | ||||
|       command = | ||||
| 	new SleepCommand(cuid, e, | ||||
| 			 createRequestCommand(e->torrentMan->getAnnounceUrl()), | ||||
| 			 e->option->getAsInt(PREF_RETRY_WAIT)); | ||||
|     } | ||||
|   } | ||||
|   return command; | ||||
| } | ||||
| 
 | ||||
| Command* TrackerWatcherCommand::createRequestCommand(const string& url) { | ||||
|   RequestHandle req; | ||||
|   req->setUrl(url); | ||||
|   req->isTorrent = true; | ||||
|  |  | |||
|  | @ -37,19 +37,22 @@ | |||
| 
 | ||||
| #include "Command.h" | ||||
| #include "TorrentDownloadEngine.h" | ||||
| #include "TimeA2.h" | ||||
| 
 | ||||
| class TrackerWatcherCommand : public Command { | ||||
| private: | ||||
|   TorrentDownloadEngine* e; | ||||
|   int interval; | ||||
|   Time checkPoint; | ||||
| 
 | ||||
|   Command* createRequestCommand(); | ||||
|   /**
 | ||||
|    * Returns a command for announce request. Returns 0 if no announce request | ||||
|    * is needed. | ||||
|    */ | ||||
|   Command* createRequestCommand(const string& url); | ||||
| public: | ||||
|   TrackerWatcherCommand(int cuid, TorrentDownloadEngine* e, int interval); | ||||
|   TrackerWatcherCommand(int cuid, TorrentDownloadEngine* e); | ||||
|   ~TrackerWatcherCommand(); | ||||
| 
 | ||||
|   Command* createCommand(); | ||||
| 
 | ||||
|   bool execute(); | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,16 +41,19 @@ aria2c_SOURCES = AllTest.cc\ | |||
| 	SegmentManTest.cc\
 | ||||
| 	SpeedCalcTest.cc\
 | ||||
| 	DefaultPeerListProcessorTest.cc\
 | ||||
| 	AnnounceListTest.cc | ||||
| 	AnnounceListTest.cc\
 | ||||
| 	TrackerWatcherCommandTest.cc | ||||
| #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
 | ||||
| #aria2c_LDFLAGS = ${CPPUNIT_LIBS}
 | ||||
| 
 | ||||
| aria2c_LDADD = ../src/libaria2c.a\
 | ||||
| 	 ${CPPUNIT_LIBS} @LIBGNUTLS_LIBS@\
 | ||||
| 	@LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@ | ||||
| 	@LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@\
 | ||||
| 	@LIBARES_LIBS@ @LIBCARES_LIBS@ | ||||
| AM_CPPFLAGS =  -Wall\
 | ||||
| 	${CPPUNIT_CFLAGS}\
 | ||||
| 	-I ../src\
 | ||||
| 	-I../lib -I../intl -I$(top_srcdir)/intl\
 | ||||
| 	@LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\
 | ||||
| 	@LIBARES_CPPFLAGS@ @LIBCARES_CPPFLAGS@\
 | ||||
| 	-D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ | ||||
|  |  | |||
|  | @ -78,7 +78,7 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) RequestTest.$(OBJEXT) \ | |||
| 	ShareRatioSeedCriteriaTest.$(OBJEXT) \
 | ||||
| 	TimeSeedCriteriaTest.$(OBJEXT) SegmentManTest.$(OBJEXT) \
 | ||||
| 	SpeedCalcTest.$(OBJEXT) DefaultPeerListProcessorTest.$(OBJEXT) \
 | ||||
| 	AnnounceListTest.$(OBJEXT) | ||||
| 	AnnounceListTest.$(OBJEXT) TrackerWatcherCommandTest.$(OBJEXT) | ||||
| aria2c_OBJECTS = $(am_aria2c_OBJECTS) | ||||
| am__DEPENDENCIES_1 = | ||||
| aria2c_DEPENDENCIES = ../src/libaria2c.a $(am__DEPENDENCIES_1) | ||||
|  | @ -279,19 +279,22 @@ aria2c_SOURCES = AllTest.cc\ | |||
| 	SegmentManTest.cc\
 | ||||
| 	SpeedCalcTest.cc\
 | ||||
| 	DefaultPeerListProcessorTest.cc\
 | ||||
| 	AnnounceListTest.cc | ||||
| 	AnnounceListTest.cc\
 | ||||
| 	TrackerWatcherCommandTest.cc | ||||
| 
 | ||||
| #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
 | ||||
| #aria2c_LDFLAGS = ${CPPUNIT_LIBS}
 | ||||
| aria2c_LDADD = ../src/libaria2c.a\
 | ||||
| 	 ${CPPUNIT_LIBS} @LIBGNUTLS_LIBS@\
 | ||||
| 	@LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@ | ||||
| 	@LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@\
 | ||||
| 	@LIBARES_LIBS@ @LIBCARES_LIBS@ | ||||
| 
 | ||||
| AM_CPPFLAGS = -Wall\
 | ||||
| 	${CPPUNIT_CFLAGS}\
 | ||||
| 	-I ../src\
 | ||||
| 	-I../lib -I../intl -I$(top_srcdir)/intl\
 | ||||
| 	@LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\
 | ||||
| 	@LIBARES_CPPFLAGS@ @LIBCARES_CPPFLAGS@\
 | ||||
| 	-D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ | ||||
| 
 | ||||
| all: all-am | ||||
|  | @ -379,6 +382,7 @@ distclean-compile: | |||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SuggestPieceMessageTest.Po@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeSeedCriteriaTest.Po@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentManTest.Po@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerWatcherCommandTest.Po@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UnchokeMessageTest.Po@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UtilTest.Po@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xml2MetalinkProcessorTest.Po@am__quote@ | ||||
|  |  | |||
|  | @ -55,6 +55,6 @@ void ShaVisitorTest::testVisitCompound() { | |||
|   int len = 0; | ||||
|   v.getHash(md, len); | ||||
|   string hashHex = hexHash(md, len); | ||||
|   CPPUNIT_ASSERT_EQUAL(string("9d33ba293924df85f6067a81c65b484de04e8efd"), | ||||
|   CPPUNIT_ASSERT_EQUAL(string("0815f9b8137fbca179c8f560e20849174e9ede8b"), | ||||
| 		       hashHex); | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,68 @@ | |||
| #include "TrackerWatcherCommand.h" | ||||
| #include "TorrentConsoleDownloadEngine.h" | ||||
| #include "MetaFileUtil.h" | ||||
| #include "Exception.h" | ||||
| #include "prefs.h" | ||||
| #include "HttpInitiateConnectionCommand.h" | ||||
| #include "ByteArrayDiskWriter.h" | ||||
| #include <cppunit/extensions/HelperMacros.h> | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| class TrackerWatcherCommandTest:public CppUnit::TestFixture { | ||||
| 
 | ||||
|   CPPUNIT_TEST_SUITE(TrackerWatcherCommandTest); | ||||
|   CPPUNIT_TEST(testCreateCommand); | ||||
|   CPPUNIT_TEST_SUITE_END(); | ||||
| private: | ||||
| 
 | ||||
| public: | ||||
|   void setUp() { | ||||
|   } | ||||
| 
 | ||||
|   void testCreateCommand(); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| CPPUNIT_TEST_SUITE_REGISTRATION( TrackerWatcherCommandTest ); | ||||
| 
 | ||||
| void TrackerWatcherCommandTest::testCreateCommand() { | ||||
|   try { | ||||
|   Option* op = new Option(); | ||||
|   op->put(PREF_TRACKER_MAX_TRIES, "10"); | ||||
| 
 | ||||
|   TorrentConsoleDownloadEngine* te = new TorrentConsoleDownloadEngine(); | ||||
|   te->option = op; | ||||
|   te->segmentMan = new SegmentMan(); | ||||
|   te->segmentMan->option = op; | ||||
|   ByteArrayDiskWriter* byteArrayDiskWriter = new ByteArrayDiskWriter(); | ||||
|   te->segmentMan->diskWriter = byteArrayDiskWriter; | ||||
|   te->torrentMan = new TorrentMan(); | ||||
|   te->torrentMan->option = op; | ||||
|   te->torrentMan->setup("test.torrent", Strings()); | ||||
| 
 | ||||
|   TrackerWatcherCommand command(1, te); | ||||
| 
 | ||||
|   CPPUNIT_ASSERT(dynamic_cast<HttpInitiateConnectionCommand*>(command.createCommand())); | ||||
|   cerr << te->torrentMan->getAnnounceUrl() << endl; | ||||
| 
 | ||||
|   te->torrentMan->announceSuccess(); | ||||
|   te->torrentMan->resetAnnounce(); | ||||
|   te->segmentMan->init(); | ||||
| 
 | ||||
|   te->torrentMan->setHalt(true); | ||||
| 
 | ||||
|   CPPUNIT_ASSERT(dynamic_cast<HttpInitiateConnectionCommand*>(command.createCommand())); | ||||
|   cerr << te->torrentMan->getAnnounceUrl() << endl; | ||||
| 
 | ||||
|   te->torrentMan->announceSuccess(); | ||||
|   te->torrentMan->resetAnnounce(); | ||||
|   te->segmentMan->init(); | ||||
| 
 | ||||
|   CPPUNIT_ASSERT(te->torrentMan->noMoreAnnounce()); | ||||
| 
 | ||||
|   } catch(Exception* e) { | ||||
|     cerr << e->getMsg() << endl; | ||||
|     delete e; | ||||
|   } | ||||
| } | ||||
|  | @ -1 +1 @@ | |||
| d8:announce36:http://aria.rednoah.com/announce.php7:comment17:REDNOAH.COM RULES13:creation datei1123456789e4:infod5:filesld6:lengthi256000e4:pathl5:aria23:src6:aria2ceed6:lengthi128900e4:pathl19:aria2-0.2.2.tar.bz2eee4:name10:aria2-test12:piece lengthi128e6:pieces60:AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCee | ||||
| d8:announce36:http://aria.rednoah.com/announce.php13:announce-listll15:http://tracker1el15:http://tracker2el15:http://tracker3ee7:comment17:REDNOAH.COM RULES13:creation datei1123456789e4:infod5:filesld6:lengthi284e4:pathl5:aria23:src6:aria2ceed6:lengthi100e4:pathl19:aria2-0.2.2.tar.bz2eee4:name10:aria2-test12:piece lengthi128e6:pieces60:AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCee | ||||
		Loading…
	
		Reference in New Issue
	
	 Tatsuhiro Tsujikawa
						Tatsuhiro Tsujikawa