Sfoglia il codice sorgente

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.
Tatsuhiro Tsujikawa 19 anni fa
parent
commit
b8737b0e7c

+ 58 - 0
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:

+ 1 - 2
src/DownloadEngineFactory.cc

@@ -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(),

+ 158 - 0
src/TorrentMan.cc

@@ -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());
+}

+ 17 - 0
src/TorrentMan.h

@@ -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,

+ 15 - 70
src/TrackerUpdateCommand.cc

@@ -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);
-      }
-    }
-    if(!peersEntry) {
-      logger->info("CUID#%d - No peer list received.", cuid);
+    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);
     }
-    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);

+ 1 - 1
src/TrackerUpdateCommand.h

@@ -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();

+ 26 - 81
src/TrackerWatcherCommand.cc

@@ -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() {
+  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->commands.push_back(this);
+  return false;
+}
+
+Command* TrackerWatcherCommand::createCommand() {
   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();
+  if(e->torrentMan->isAnnounceReady()) {
+    command = createRequestCommand(e->torrentMan->getAnnounceUrl());
+    e->torrentMan->announceStart(); // inside it, trackers++.
   } 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->torrentMan->announceFailure(); // inside it, 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 {
+    if(e->torrentMan->isAllAnnounceFailed()) {
+      e->torrentMan->resetAnnounce();
       // sleep a few seconds.
       command =
 	new SleepCommand(cuid, e,
-			 createRequestCommand(),
+			 createRequestCommand(e->torrentMan->getAnnounceUrl()),
 			 e->option->getAsInt(PREF_RETRY_WAIT));
     }
   }
-
-  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;
+  return command;
 }
 
-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::createRequestCommand(const string& url) {
   RequestHandle req;
   req->setUrl(url);
   req->isTorrent = true;

+ 8 - 5
src/TrackerWatcherCommand.h

@@ -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();
 };
 

+ 5 - 2
test/Makefile.am

@@ -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@

+ 7 - 3
test/Makefile.in

@@ -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@

+ 1 - 1
test/ShaVisitorTest.cc

@@ -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);
 }

+ 68 - 0
test/TrackerWatcherCommandTest.cc

@@ -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
test/test.torrent

@@ -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