Explorar o código

2010-03-06 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Added Time global::wallclock to cache "current time" to reduce the
	call gettimeofday(). Global variables are now in namespace global.
	* src/AbstractCommand.cc
	* src/ActivePeerConnectionCommand.cc
	* src/AdaptiveURISelector.cc
	* src/BtLeecherStateChoke.cc
	* src/BtLeecherStateChoke.h
	* src/BtSeederStateChoke.cc
	* src/BtSeederStateChoke.h
	* src/BtStopDownloadCommand.cc
	* src/ConsoleStatCalc.cc
	* src/DHTBucket.cc
	* src/DHTGetPeersCommand.cc
	* src/DHTMessageTrackerEntry.cc
	* src/DHTNode.cc
	* src/DHTPeerAnnounceEntry.cc
	* src/DHTPeerAnnounceStorage.cc
	* src/DHTSetup.cc
	* src/DefaultBtAnnounce.cc
	* src/DefaultBtInteractive.cc
	* src/DefaultBtMessageDispatcher.cc
	* src/DefaultPeerStorage.cc
	* src/DefaultPieceStorage.cc
	* src/DownloadCommand.cc
	* src/DownloadEngine.cc
	* src/FileEntry.cc
	* src/HttpServerBodyCommand.cc
	* src/HttpServerCommand.cc
	* src/HttpServerResponseCommand.cc
	* src/LpdMessageDispatcher.cc
	* src/MultiUrlRequestInfo.cc
	* src/Peer.cc
	* src/Peer.h
	* src/PeerAbstractCommand.cc
	* src/PeerStat.h
	* src/RequestSlot.cc
	* src/RequestSlot.h
	* src/SegmentMan.cc
	* src/ServerStatMan.cc
	* src/SleepCommand.cc
	* src/SpeedCalc.cc
	* src/SpeedCalc.h
	* src/TimeA2.cc
	* src/TimeA2.h
	* src/TimeBasedCommand.cc
	* src/TimeSeedCriteria.h
	* src/UTMetadataRequestTracker.h
	* src/UTPexExtensionMessage.cc
	* src/wallclock.h
Tatsuhiro Tsujikawa %!s(int64=15) %!d(string=hai) anos
pai
achega
8d09b069e2
Modificáronse 50 ficheiros con 314 adicións e 213 borrados
  1. 52 0
      ChangeLog
  2. 3 2
      src/AbstractCommand.cc
  3. 3 2
      src/ActivePeerConnectionCommand.cc
  4. 2 1
      src/AdaptiveURISelector.cc
  5. 7 16
      src/BtLeecherStateChoke.cc
  6. 1 1
      src/BtLeecherStateChoke.h
  7. 5 11
      src/BtSeederStateChoke.cc
  8. 1 1
      src/BtSeederStateChoke.h
  9. 3 2
      src/BtStopDownloadCommand.cc
  10. 5 4
      src/ConsoleStatCalc.cc
  11. 4 2
      src/DHTBucket.cc
  12. 5 3
      src/DHTGetPeersCommand.cc
  13. 2 1
      src/DHTMessageTrackerEntry.cc
  14. 4 2
      src/DHTNode.cc
  15. 3 2
      src/DHTPeerAnnounceEntry.cc
  16. 3 1
      src/DHTPeerAnnounceStorage.cc
  17. 4 1
      src/DHTSetup.cc
  18. 8 5
      src/DefaultBtAnnounce.cc
  19. 20 16
      src/DefaultBtInteractive.cc
  20. 2 13
      src/DefaultBtMessageDispatcher.cc
  21. 11 12
      src/DefaultPeerStorage.cc
  22. 2 1
      src/DefaultPieceStorage.cc
  23. 3 1
      src/DownloadCommand.cc
  24. 18 9
      src/DownloadEngine.cc
  25. 3 1
      src/FileEntry.cc
  26. 3 2
      src/HttpServerBodyCommand.cc
  27. 3 2
      src/HttpServerCommand.cc
  28. 2 1
      src/HttpServerResponseCommand.cc
  29. 3 2
      src/LpdMessageDispatcher.cc
  30. 8 4
      src/MultiUrlRequestInfo.cc
  31. 4 14
      src/Peer.cc
  32. 0 4
      src/Peer.h
  33. 4 3
      src/PeerAbstractCommand.cc
  34. 0 10
      src/PeerStat.h
  35. 3 6
      src/RequestSlot.cc
  36. 1 2
      src/RequestSlot.h
  37. 3 2
      src/SegmentMan.cc
  38. 2 1
      src/ServerStatMan.cc
  39. 2 1
      src/SleepCommand.cc
  40. 13 26
      src/SpeedCalc.cc
  41. 1 7
      src/SpeedCalc.h
  42. 9 3
      src/TimeA2.cc
  43. 12 0
      src/TimeA2.h
  44. 3 2
      src/TimeBasedCommand.cc
  45. 3 2
      src/TimeSeedCriteria.h
  46. 2 1
      src/UTMetadataRequestTracker.h
  47. 4 2
      src/UTPexExtensionMessage.cc
  48. 46 0
      src/wallclock.h
  49. 3 2
      test/TimeSeedCriteriaTest.cc
  50. 6 4
      test/UTPexExtensionMessageTest.cc

+ 52 - 0
ChangeLog

@@ -1,3 +1,55 @@
+2010-03-06  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Added Time global::wallclock to cache "current time" to reduce the
+	call gettimeofday(). Global variables are now in namespace global.
+	* src/AbstractCommand.cc
+	* src/ActivePeerConnectionCommand.cc
+	* src/AdaptiveURISelector.cc
+	* src/BtLeecherStateChoke.cc
+	* src/BtLeecherStateChoke.h
+	* src/BtSeederStateChoke.cc
+	* src/BtSeederStateChoke.h
+	* src/BtStopDownloadCommand.cc
+	* src/ConsoleStatCalc.cc
+	* src/DHTBucket.cc
+	* src/DHTGetPeersCommand.cc
+	* src/DHTMessageTrackerEntry.cc
+	* src/DHTNode.cc
+	* src/DHTPeerAnnounceEntry.cc
+	* src/DHTPeerAnnounceStorage.cc
+	* src/DHTSetup.cc
+	* src/DefaultBtAnnounce.cc
+	* src/DefaultBtInteractive.cc
+	* src/DefaultBtMessageDispatcher.cc
+	* src/DefaultPeerStorage.cc
+	* src/DefaultPieceStorage.cc
+	* src/DownloadCommand.cc
+	* src/DownloadEngine.cc
+	* src/FileEntry.cc
+	* src/HttpServerBodyCommand.cc
+	* src/HttpServerCommand.cc
+	* src/HttpServerResponseCommand.cc
+	* src/LpdMessageDispatcher.cc
+	* src/MultiUrlRequestInfo.cc
+	* src/Peer.cc
+	* src/Peer.h
+	* src/PeerAbstractCommand.cc
+	* src/PeerStat.h
+	* src/RequestSlot.cc
+	* src/RequestSlot.h
+	* src/SegmentMan.cc
+	* src/ServerStatMan.cc
+	* src/SleepCommand.cc
+	* src/SpeedCalc.cc
+	* src/SpeedCalc.h
+	* src/TimeA2.cc
+	* src/TimeA2.h
+	* src/TimeBasedCommand.cc
+	* src/TimeSeedCriteria.h
+	* src/UTMetadataRequestTracker.h
+	* src/UTPexExtensionMessage.cc
+	* src/wallclock.h
+
 2010-03-05  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Fixed the bug that util::itos(INT64_MIN) fails.

+ 3 - 2
src/AbstractCommand.cc

@@ -64,6 +64,7 @@
 #include "util.h"
 #include "LogFactory.h"
 #include "DownloadContext.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -134,7 +135,7 @@ bool AbstractCommand::execute() {
        (nameResolverCheck && nameResolveFinished()) ||
 #endif // ENABLE_ASYNC_DNS
        (!checkSocketIsReadable && !checkSocketIsWritable && !nameResolverCheck)) {
-      checkPoint.reset();
+      checkPoint = global::wallclock;
       if(!_requestGroup->getPieceStorage().isNull()) {
         _segments.clear();
         _requestGroup->getSegmentMan()->getInFlightSegment(_segments, cuid);
@@ -175,7 +176,7 @@ bool AbstractCommand::execute() {
         (StringFormat(MSG_NETWORK_PROBLEM,
                       socket->getSocketError().c_str()).str());
     } else {
-      if(checkPoint.elapsed(timeout)) {
+      if(checkPoint.difference(global::wallclock) >= timeout) {
         // timeout triggers ServerStat error state.
 
         SharedHandle<ServerStat> ss =

+ 3 - 2
src/ActivePeerConnectionCommand.cc

@@ -49,6 +49,7 @@
 #include "RequestGroup.h"
 #include "DownloadContext.h"
 #include "bittorrent_helper.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -76,8 +77,8 @@ bool ActivePeerConnectionCommand::execute() {
   if(_btRuntime->isHalt()) {
     return true;
   }
-  if(checkPoint.elapsed(interval)) {
-    checkPoint.reset();
+  if(checkPoint.difference(global::wallclock) >= interval) {
+    checkPoint = global::wallclock;
     TransferStat tstat = _requestGroup->calculateStat();
     const unsigned int maxDownloadLimit =
       _requestGroup->getMaxDownloadSpeedLimit();

+ 2 - 1
src/AdaptiveURISelector.cc

@@ -51,6 +51,7 @@
 #include "SimpleRandomizer.h"
 #include "SocketCore.h"
 #include "FileEntry.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -329,7 +330,7 @@ std::string AdaptiveURISelector::getFirstToTestUri
     power = (int)pow(2.0, (float)counter);
     /* We test the mirror another time if it has not been
      * tested since 2^counter days */
-    if(ss->getLastUpdated().difference() > power*24*60*60) {
+    if(ss->getLastUpdated().difference(global::wallclock) > power*24*60*60) {
       return *i;
     }
   }

+ 7 - 16
src/BtLeecherStateChoke.cc

@@ -41,6 +41,7 @@
 #include "LogFactory.h"
 #include "a2time.h"
 #include "SimpleRandomizer.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -51,12 +52,12 @@ BtLeecherStateChoke::BtLeecherStateChoke():
 
 BtLeecherStateChoke::~BtLeecherStateChoke() {}
 
-BtLeecherStateChoke::PeerEntry::PeerEntry
-(const SharedHandle<Peer>& peer, const struct timeval& now):
-  _peer(peer), _downloadSpeed(peer->calculateDownloadSpeed(now)),
+BtLeecherStateChoke::PeerEntry::PeerEntry(const SharedHandle<Peer>& peer):
+  _peer(peer), _downloadSpeed(peer->calculateDownloadSpeed()),
   // peer must be interested to us and sent block in the last 30 seconds
-  _regularUnchoker(peer->peerInterested() &&
-                   !peer->getLastDownloadUpdate().elapsed(30)) {}
+  _regularUnchoker
+  (peer->peerInterested() &&
+   peer->getLastDownloadUpdate().difference(global::wallclock) < 30) {}
 
 const SharedHandle<Peer>& BtLeecherStateChoke::PeerEntry::getPeer() const
 {
@@ -142,9 +143,6 @@ void BtLeecherStateChoke::regularUnchoke(std::vector<PeerEntry>& peerEntries)
     std::partition(peerEntries.begin(), peerEntries.end(),
                    std::mem_fun_ref(&PeerEntry::isRegularUnchoker));
   
-  struct timeval now;
-  gettimeofday(&now, 0);
-
   std::sort(peerEntries.begin(), rest);
 
   // the number of regular unchokers
@@ -180,18 +178,11 @@ void BtLeecherStateChoke::regularUnchoke(std::vector<PeerEntry>& peerEntries)
 }
 
 class BtLeecherStateChokeGenPeerEntry {
-private:
-  struct timeval _now;
 public:
-  BtLeecherStateChokeGenPeerEntry()
-  {
-    gettimeofday(&_now, 0);
-  }
-
   BtLeecherStateChoke::PeerEntry operator()
   (const SharedHandle<Peer>& peer) const
   {
-    return BtLeecherStateChoke::PeerEntry(peer, _now);
+    return BtLeecherStateChoke::PeerEntry(peer);
   }
 };
 

+ 1 - 1
src/BtLeecherStateChoke.h

@@ -61,7 +61,7 @@ private:
     unsigned int _downloadSpeed;
     bool _regularUnchoker;
   public:
-    PeerEntry(const SharedHandle<Peer>& peer, const struct timeval& now);
+    PeerEntry(const SharedHandle<Peer>& peer);
 
     bool operator<(const PeerEntry& rhs) const;
 

+ 5 - 11
src/BtSeederStateChoke.cc

@@ -40,6 +40,7 @@
 #include "Logger.h"
 #include "LogFactory.h"
 #include "SimpleRandomizer.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -51,12 +52,12 @@ BtSeederStateChoke::BtSeederStateChoke():
 BtSeederStateChoke::~BtSeederStateChoke() {}
 
 BtSeederStateChoke::PeerEntry::PeerEntry
-(const SharedHandle<Peer>& peer, const struct timeval& now):
+(const SharedHandle<Peer>& peer):
   _peer(peer),
   _outstandingUpload(peer->countOutstandingUpload()),
   _lastAmUnchoking(peer->getLastAmUnchoking()),
-  _recentUnchoking(!_lastAmUnchoking.elapsed(TIME_FRAME)),
-  _uploadSpeed(peer->calculateUploadSpeed(now))
+  _recentUnchoking(_lastAmUnchoking.difference(global::wallclock) < TIME_FRAME),
+  _uploadSpeed(peer->calculateUploadSpeed())
 {}
 
 bool
@@ -118,17 +119,10 @@ public:
 };
 
 class GenPeerEntry {
-private:
-  struct timeval _now;
 public:
-  GenPeerEntry()
-  {
-    gettimeofday(&_now, 0);
-  }
-
   BtSeederStateChoke::PeerEntry operator()(const SharedHandle<Peer>& peer) const
   {
-    return BtSeederStateChoke::PeerEntry(peer, _now);
+    return BtSeederStateChoke::PeerEntry(peer);
   }
 };
 

+ 1 - 1
src/BtSeederStateChoke.h

@@ -65,7 +65,7 @@ private:
     
     const static time_t TIME_FRAME = 20;
   public:
-    PeerEntry(const SharedHandle<Peer>& peer, const struct timeval& now);
+    PeerEntry(const SharedHandle<Peer>& peer);
 
     bool operator<(const PeerEntry& rhs) const;
 

+ 3 - 2
src/BtStopDownloadCommand.cc

@@ -39,6 +39,7 @@
 #include "Peer.h"
 #include "DownloadContext.h"
 #include "Logger.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -57,7 +58,7 @@ void BtStopDownloadCommand::preProcess()
   if(_btRuntime->isHalt() || _pieceStorage->downloadFinished()) {
     _exit = true;
   }
-  if(_checkPoint.elapsed(_timeout)) {
+  if(_checkPoint.difference(global::wallclock) >= _timeout) {
     logger->notice("GID#%d Stop downloading torrent due to"
                    " --bt-stop-timeout option.", _requestGroup->getGID());
     _requestGroup->setHaltRequested(true);
@@ -68,7 +69,7 @@ void BtStopDownloadCommand::preProcess()
 void BtStopDownloadCommand::process()
 {
   if(_requestGroup->calculateStat().getDownloadSpeed() > 0) {
-    _checkPoint.reset();
+    _checkPoint = global::wallclock;
   }
 }
 

+ 5 - 4
src/ConsoleStatCalc.cc

@@ -59,6 +59,7 @@
 #include "CheckIntegrityEntry.h"
 #include "util.h"
 #include "DownloadContext.h"
+#include "wallclock.h"
 #ifdef ENABLE_BITTORRENT
 # include "bittorrent_helper.h"
 # include "Peer.h"
@@ -214,10 +215,10 @@ ConsoleStatCalc::ConsoleStatCalc(time_t summaryInterval, bool humanReadable):
 void
 ConsoleStatCalc::calculateStat(const DownloadEngine* e)
 {
-  if(!_cp.elapsed(1)) {
+  if(_cp.difference(global::wallclock) < 1) {
     return;
   }
-  _cp.reset();
+  _cp = global::wallclock;
   const SizeFormatter& sizeFormatter = *_sizeFormatter.get();
 
 #ifdef __MINGW32__
@@ -243,8 +244,8 @@ ConsoleStatCalc::calculateStat(const DownloadEngine* e)
   std::ostringstream o;
   if(e->_requestGroupMan->countRequestGroup() > 0) {
     if((_summaryInterval > 0) &&
-       _lastSummaryNotified.elapsed(_summaryInterval)) {
-      _lastSummaryNotified.reset();
+       _lastSummaryNotified.difference(global::wallclock) >= _summaryInterval) {
+      _lastSummaryNotified = global::wallclock;
       printProgressSummary(e->_requestGroupMan->getRequestGroups(), cols, e,
                            sizeFormatter);
       std::cout << "\n";

+ 4 - 2
src/DHTBucket.cc

@@ -46,6 +46,7 @@
 #include "a2functional.h"
 #include "bittorrent_helper.h"
 #include "bitfield.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -246,12 +247,13 @@ bool DHTBucket::operator==(const DHTBucket& bucket) const
 
 bool DHTBucket::needsRefresh() const
 {
-  return _nodes.size() < K || _lastUpdated.elapsed(DHT_BUCKET_REFRESH_INTERVAL);
+  return _nodes.size() < K ||
+    _lastUpdated.difference(global::wallclock) >= DHT_BUCKET_REFRESH_INTERVAL;
 }
 
 void DHTBucket::notifyUpdate()
 {
-  _lastUpdated.reset();
+  _lastUpdated = global::wallclock;
 }
 
 class FindQuestionableNode {

+ 5 - 3
src/DHTGetPeersCommand.cc

@@ -46,6 +46,7 @@
 #include "Logger.h"
 #include "bittorrent_helper.h"
 #include "DownloadContext.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -72,8 +73,9 @@ bool DHTGetPeersCommand::execute()
     return true;
   }
   if(_task.isNull() &&
-     ((_numRetry > 0 && _lastGetPeerTime.elapsed(RETRY_INTERVAL)) ||
-      _lastGetPeerTime.elapsed(GET_PEER_INTERVAL))) {
+     ((_numRetry > 0 &&
+       _lastGetPeerTime.difference(global::wallclock) >= RETRY_INTERVAL) ||
+      _lastGetPeerTime.difference(global::wallclock) >= GET_PEER_INTERVAL)) {
     if(logger->debug()) {
       logger->debug("Issuing PeerLookup for infoHash=%s",
                     bittorrent::getInfoHashString
@@ -83,7 +85,7 @@ bool DHTGetPeersCommand::execute()
       (_requestGroup->getDownloadContext(), _btRuntime, _peerStorage);
     _taskQueue->addPeriodicTask2(_task);
   } else if(!_task.isNull() && _task->finished()) {
-    _lastGetPeerTime.reset();
+    _lastGetPeerTime = global::wallclock;
     if(_numRetry < MAX_RETRIES && _btRuntime->lessThanMinPeers()) {
       ++_numRetry;
     } else {

+ 2 - 1
src/DHTMessageTrackerEntry.cc

@@ -38,6 +38,7 @@
 #include "DHTMessageCallback.h"
 #include "DHTConstants.h"
 #include "util.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -53,7 +54,7 @@ DHTMessageTrackerEntry::DHTMessageTrackerEntry(const SharedHandle<DHTMessage>& s
 
 bool DHTMessageTrackerEntry::isTimeout() const
 {
-  return _dispatchedTime.elapsed(_timeout);
+  return _dispatchedTime.difference(global::wallclock) >= _timeout;
 }
 
 void DHTMessageTrackerEntry::extendTimeout()

+ 4 - 2
src/DHTNode.cc

@@ -39,6 +39,7 @@
 #include "util.h"
 #include "a2functional.h"
 #include "bittorrent_helper.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -88,7 +89,8 @@ bool DHTNode::isBad() const
 
 bool DHTNode::isQuestionable() const
 {
-  return !isBad() && _lastContact.elapsed(DHT_NODE_CONTACT_INTERVAL);
+  return !isBad() &&
+    _lastContact.difference(global::wallclock) >= DHT_NODE_CONTACT_INTERVAL;
 }
 
 void DHTNode::markGood()
@@ -103,7 +105,7 @@ void DHTNode::markBad()
 
 void DHTNode::updateLastContact()
 {
-  _lastContact.reset();
+  _lastContact = global::wallclock;
 }
 
 void DHTNode::timeout()

+ 3 - 2
src/DHTPeerAnnounceEntry.cc

@@ -38,6 +38,7 @@
 #include <algorithm>
 
 #include "Peer.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -73,7 +74,7 @@ public:
 
   bool operator()(const PeerAddrEntry& entry) const
   {
-    if(entry.getLastUpdated().elapsed(_timeout)) {
+    if(entry.getLastUpdated().difference(global::wallclock) >= _timeout) {
       return true;
     } else {
       return false;
@@ -104,7 +105,7 @@ void DHTPeerAnnounceEntry::getPeers
 
 void DHTPeerAnnounceEntry::notifyUpdate()
 {
-  _lastUpdated.reset();
+  _lastUpdated = global::wallclock;
 }
 
 } // namespace aria2

+ 3 - 1
src/DHTPeerAnnounceStorage.cc

@@ -47,6 +47,7 @@
 #include "Logger.h"
 #include "util.h"
 #include "a2functional.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -147,7 +148,8 @@ void DHTPeerAnnounceStorage::announcePeer()
   }
   for(std::deque<SharedHandle<DHTPeerAnnounceEntry> >::iterator i =
         _entries.begin(), eoi = _entries.end(); i != eoi; ++i) {
-    if((*i)->getLastUpdated().elapsed(DHT_PEER_ANNOUNCE_INTERVAL)) {
+    if((*i)->getLastUpdated().
+       difference(global::wallclock) >= DHT_PEER_ANNOUNCE_INTERVAL) {
       (*i)->notifyUpdate();
       SharedHandle<DHTTask> task =
         _taskFactory->createPeerAnnounceTask((*i)->getInfoHash());

+ 4 - 1
src/DHTSetup.cc

@@ -70,6 +70,7 @@
 #include "RecoverableException.h"
 #include "a2functional.h"
 #include "DownloadEngine.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -185,7 +186,9 @@ void DHTSetup::setup(std::vector<Command*>& commands,
           desnodes.begin(), eoi = desnodes.end(); i != eoi; ++i) {
       routingTable->addNode(*i);
     }
-    if(!desnodes.empty() && deserializer.getSerializedTime().elapsed(DHT_BUCKET_REFRESH_INTERVAL)) {
+    if(!desnodes.empty() &&
+       deserializer.getSerializedTime().
+       difference(global::wallclock) >= DHT_BUCKET_REFRESH_INTERVAL) {
       SharedHandle<DHTBucketRefreshTask> task
         (dynamic_pointer_cast<DHTBucketRefreshTask>(taskFactory->createBucketRefreshTask()));
       task->setForceRefresh(true);

+ 8 - 5
src/DefaultBtAnnounce.cc

@@ -52,6 +52,7 @@
 #include "Request.h"
 #include "bencode.h"
 #include "bittorrent_helper.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -77,10 +78,12 @@ DefaultBtAnnounce::~DefaultBtAnnounce() {
 }
 
 bool DefaultBtAnnounce::isDefaultAnnounceReady() {
-  return (trackers == 0 &&
-          prevAnnounceTime.elapsed(_userDefinedInterval==0?
-                                   minInterval:_userDefinedInterval) &&
-          !announceList.allTiersFailed());
+  return
+    (trackers == 0 &&
+     prevAnnounceTime.
+     difference(global::wallclock) >= (_userDefinedInterval==0?
+                                       minInterval:_userDefinedInterval) &&
+     !announceList.allTiersFailed());
 }
 
 bool DefaultBtAnnounce::isStoppedAnnounceReady() {
@@ -203,7 +206,7 @@ bool DefaultBtAnnounce::isAllAnnounceFailed() {
 }
 
 void DefaultBtAnnounce::resetAnnounce() {
-  prevAnnounceTime.reset();
+  prevAnnounceTime = global::wallclock;
   announceList.resetTier();
 }
 

+ 20 - 16
src/DefaultBtInteractive.cc

@@ -72,6 +72,7 @@
 #include "bittorrent_helper.h"
 #include "UTMetadataRequestFactory.h"
 #include "UTMetadataRequestTracker.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -144,8 +145,8 @@ BtMessageHandle DefaultBtInteractive::receiveAndSendHandshake() {
 void DefaultBtInteractive::doPostHandshakeProcessing() {
   // Set time 0 to haveCheckPoint to cache http/ftp download piece completion
   haveCheckPoint.setTimeInSec(0);
-  keepAliveCheckPoint.reset();
-  floodingCheckPoint.reset();
+  keepAliveCheckPoint = global::wallclock;
+  floodingCheckPoint = global::wallclock;
   _pexCheckPoint.setTimeInSec(0);
   if(peer->isExtendedMessagingEnabled()) {
     addHandshakeExtendedMessageToQueue();
@@ -229,7 +230,7 @@ void DefaultBtInteractive::decideChoking() {
 void DefaultBtInteractive::checkHave() {
   std::vector<size_t> indexes;
   _pieceStorage->getAdvertisedPieceIndexes(indexes, cuid, haveCheckPoint);
-  haveCheckPoint.reset();
+  haveCheckPoint = global::wallclock;
   if(indexes.size() >= 20) {
     if(peer->isFastExtensionEnabled() && _pieceStorage->allDownloadFinished()) {
       dispatcher->addMessageToQueue(messageFactory->createHaveAllMessage());
@@ -245,10 +246,10 @@ void DefaultBtInteractive::checkHave() {
 }
 
 void DefaultBtInteractive::sendKeepAlive() {
-  if(keepAliveCheckPoint.elapsed(keepAliveInterval)) {
+  if(keepAliveCheckPoint.difference(global::wallclock) >= keepAliveInterval) {
     dispatcher->addMessageToQueue(messageFactory->createKeepAliveMessage());
     dispatcher->sendMessages();
-    keepAliveCheckPoint.reset();
+    keepAliveCheckPoint = global::wallclock;
   }
 }
 
@@ -290,7 +291,7 @@ size_t DefaultBtInteractive::receiveMessages() {
       _peerStorage->updateTransferStatFor(peer);
       // pass through
     case BtRequestMessage::ID:
-      inactiveCheckPoint.reset();
+      inactiveCheckPoint = global::wallclock;
       break;
     }
   }
@@ -401,25 +402,27 @@ void DefaultBtInteractive::sendPendingMessage() {
 }
 
 void DefaultBtInteractive::detectMessageFlooding() {
-  if(floodingCheckPoint.elapsed(FLOODING_CHECK_INTERVAL)) {
+  if(floodingCheckPoint.
+     difference(global::wallclock) >= FLOODING_CHECK_INTERVAL) {
     if(floodingStat.getChokeUnchokeCount() >= 2 ||
        floodingStat.getKeepAliveCount() >= 2) {
       throw DL_ABORT_EX(EX_FLOODING_DETECTED);
     } else {
       floodingStat.reset();
     }
-    floodingCheckPoint.reset();
+    floodingCheckPoint = global::wallclock;
   }
 }
 
 void DefaultBtInteractive::checkActiveInteraction()
 {
+  time_t inactiveTime = inactiveCheckPoint.difference(global::wallclock);
   // To allow aria2 to accept mutially interested peer, disconnect unintersted
   // peer.
   {
     const time_t interval = 30;
     if(!peer->amInterested() && !peer->peerInterested() &&
-       inactiveCheckPoint.elapsed(interval)) {
+       inactiveTime >= interval) {
       // TODO change the message
       throw DL_ABORT_EX
         (StringFormat("Disconnect peer because we are not interested each other"
@@ -431,7 +434,7 @@ void DefaultBtInteractive::checkActiveInteraction()
   // are disconnected in a certain time period.
   {
     const time_t interval = 60;
-    if(inactiveCheckPoint.elapsed(interval)) {
+    if(inactiveTime >= interval) {
       throw DL_ABORT_EX
         (StringFormat(EX_DROP_INACTIVE_CONNECTION, interval).str());
     }
@@ -440,7 +443,8 @@ void DefaultBtInteractive::checkActiveInteraction()
 
 void DefaultBtInteractive::addPeerExchangeMessage()
 {
-  if(_pexCheckPoint.elapsed(UTPexExtensionMessage::DEFAULT_INTERVAL)) {
+  if(_pexCheckPoint.
+     difference(global::wallclock) >= UTPexExtensionMessage::DEFAULT_INTERVAL) {
     UTPexExtensionMessageHandle m
       (new UTPexExtensionMessage(peer->getExtensionMessageID("ut_pex")));
     const std::deque<SharedHandle<Peer> >& peers = _peerStorage->getPeers();
@@ -465,7 +469,7 @@ void DefaultBtInteractive::addPeerExchangeMessage()
     }
     BtMessageHandle msg = messageFactory->createBtExtendedMessage(m);
     dispatcher->addMessageToQueue(msg);
-    _pexCheckPoint.reset();
+    _pexCheckPoint = global::wallclock;
   }
 }
 
@@ -486,8 +490,8 @@ void DefaultBtInteractive::doInteractionProcessing() {
         _utMetadataRequestFactory->create(requests, num, _pieceStorage);
         dispatcher->addMessageToQueue(requests);
       }
-      if(_perSecCheckPoint.elapsed(1)) {
-        _perSecCheckPoint.reset();
+      if(_perSecCheckPoint.difference(global::wallclock) >= 1) {
+        _perSecCheckPoint = global::wallclock;
         // Drop timeout request after queuing message to give a chance
         // to other connection to request piece.
         std::vector<size_t> indexes =
@@ -509,8 +513,8 @@ void DefaultBtInteractive::doInteractionProcessing() {
 
     detectMessageFlooding();
 
-    if(_perSecCheckPoint.elapsed(1)) {
-      _perSecCheckPoint.reset();
+    if(_perSecCheckPoint.difference(global::wallclock) >= 1) {
+      _perSecCheckPoint = global::wallclock;
       dispatcher->checkRequestSlotAndDoNecessaryThing();
     }
     checkHave();

+ 2 - 13
src/DefaultBtMessageDispatcher.cc

@@ -257,7 +257,6 @@ private:
   SharedHandle<PieceStorage> _pieceStorage;
   BtMessageDispatcher* _messageDispatcher;
   WeakHandle<BtMessageFactory> _messageFactory;
-  const struct timeval& _now;
   time_t _requestTimeout;
   Logger* _logger;
 public:
@@ -265,20 +264,18 @@ public:
                           const SharedHandle<PieceStorage>& pieceStorage,
                           BtMessageDispatcher* dispatcher,
                           const WeakHandle<BtMessageFactory>& factory,
-                          const struct timeval& now,
                           time_t requestTimeout):
     _cuid(cuid),
     _peer(peer),
     _pieceStorage(pieceStorage),
     _messageDispatcher(dispatcher),
     _messageFactory(factory),
-    _now(now),
     _requestTimeout(requestTimeout),
     _logger(LogFactory::getInstance()) {}
 
   void operator()(const RequestSlot& slot)
   {
-    if(slot.isTimeout(_now, _requestTimeout)) {
+    if(slot.isTimeout(_requestTimeout)) {
       if(_logger->debug()) {
         _logger->debug(MSG_DELETING_REQUEST_SLOT_TIMEOUT,
                        _cuid,
@@ -305,19 +302,16 @@ public:
 class FindStaleRequestSlot {
 private:
   SharedHandle<PieceStorage> _pieceStorage;
-  const struct timeval& _now;
   time_t _requestTimeout;
 public:
   FindStaleRequestSlot(const SharedHandle<PieceStorage>& pieceStorage,
-                       const struct timeval& now,
                        time_t requestTimeout):
     _pieceStorage(pieceStorage),
-    _now(now),
     _requestTimeout(requestTimeout) {}
 
   bool operator()(const RequestSlot& slot)
   {
-    if(slot.isTimeout(_now, _requestTimeout)) {
+    if(slot.isTimeout(_requestTimeout)) {
       return true;
     } else {
       if(slot.getPiece()->hasBlock(slot.getBlockIndex())) {
@@ -331,20 +325,15 @@ public:
 
 void DefaultBtMessageDispatcher::checkRequestSlotAndDoNecessaryThing()
 {
-  struct timeval now;
-  gettimeofday(&now, 0);
-
   std::for_each(requestSlots.begin(), requestSlots.end(),
                 ProcessStaleRequestSlot(cuid,
                                         peer,
                                         _pieceStorage,
                                         this,
                                         messageFactory,
-                                        now,
                                         requestTimeout));
   requestSlots.erase(std::remove_if(requestSlots.begin(), requestSlots.end(),
                                     FindStaleRequestSlot(_pieceStorage,
-                                                         now,
                                                          requestTimeout)),
                      requestSlots.end());
 }

+ 11 - 12
src/DefaultPeerStorage.cc

@@ -45,6 +45,7 @@
 #include "BtSeederStateChoke.h"
 #include "BtLeecherStateChoke.h"
 #include "PieceStorage.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -200,11 +201,9 @@ void DefaultPeerStorage::getActivePeers
 
 static TransferStat calculateStatFor(const SharedHandle<Peer>& peer)
 {
-  struct timeval now;
-  gettimeofday(&now, 0);
   TransferStat s;
-  s.downloadSpeed = peer->calculateDownloadSpeed(now);
-  s.uploadSpeed = peer->calculateUploadSpeed(now);
+  s.downloadSpeed = peer->calculateDownloadSpeed();
+  s.uploadSpeed = peer->calculateUploadSpeed();
   s.sessionDownloadLength = peer->getSessionDownloadLength();
   s.sessionUploadLength = peer->getSessionUploadLength();
   return s;
@@ -213,21 +212,19 @@ static TransferStat calculateStatFor(const SharedHandle<Peer>& peer)
 TransferStat DefaultPeerStorage::calculateStat()
 {
   TransferStat stat;
-  if(_lastTransferStatMapUpdated.elapsedInMillis(250)) {
+  if(_lastTransferStatMapUpdated.differenceInMillis(global::wallclock) >= 250) {
     if(logger->debug()) {
       logger->debug("Updating TransferStat of PeerStorage");
     }
-    _lastTransferStatMapUpdated.reset();
+    _lastTransferStatMapUpdated = global::wallclock;
     _peerTransferStatMap.clear();
     std::vector<SharedHandle<Peer> > activePeers;
     getActivePeers(activePeers);
-    struct timeval now;
-    gettimeofday(&now, 0);
     for(std::vector<SharedHandle<Peer> >::const_iterator i =
           activePeers.begin(), eoi = activePeers.end(); i != eoi; ++i) {
       TransferStat s;
-      s.downloadSpeed = (*i)->calculateDownloadSpeed(now);
-      s.uploadSpeed = (*i)->calculateUploadSpeed(now);
+      s.downloadSpeed = (*i)->calculateDownloadSpeed();
+      s.uploadSpeed = (*i)->calculateUploadSpeed();
       s.sessionDownloadLength = (*i)->getSessionDownloadLength();
       s.sessionUploadLength = (*i)->getSessionUploadLength();
 
@@ -319,9 +316,11 @@ bool DefaultPeerStorage::chokeRoundIntervalElapsed()
 {
   const time_t CHOKE_ROUND_INTERVAL = 10;
   if(_pieceStorage->downloadFinished()) {
-    return _seederStateChoke->getLastRound().elapsed(CHOKE_ROUND_INTERVAL);
+    return _seederStateChoke->getLastRound().
+      difference(global::wallclock) >= CHOKE_ROUND_INTERVAL;
   } else {
-    return _leecherStateChoke->getLastRound().elapsed(CHOKE_ROUND_INTERVAL);
+    return _leecherStateChoke->getLastRound().
+      difference(global::wallclock) >= CHOKE_ROUND_INTERVAL;
   }
 }
 

+ 2 - 1
src/DefaultPieceStorage.cc

@@ -58,6 +58,7 @@
 #include "RarestPieceSelector.h"
 #include "array_fun.h"
 #include "PieceStatMan.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -566,7 +567,7 @@ public:
   FindElapsedHave(time_t elapsed):elapsed(elapsed) {}
 
   bool operator()(const HaveEntry& have) {
-    if(have.getRegisteredTime().elapsed(elapsed)) {
+    if(have.getRegisteredTime().difference(global::wallclock) >= elapsed) {
       return true;
     } else {
       return false;

+ 3 - 1
src/DownloadCommand.cc

@@ -58,6 +58,7 @@
 #include "StringFormat.h"
 #include "Decoder.h"
 #include "RequestGroupMan.h"
+#include "wallclock.h"
 #ifdef ENABLE_MESSAGE_DIGEST
 # include "MessageDigestHelper.h"
 #endif // ENABLE_MESSAGE_DIGEST
@@ -253,7 +254,8 @@ bool DownloadCommand::executeInternal() {
 void DownloadCommand::checkLowestDownloadSpeed() const
 {
   // calculate downloading speed
-  if(peerStat->getDownloadStartTime().elapsed(startupIdleTime)) {
+  if(peerStat->getDownloadStartTime().difference(global::wallclock) >=
+     startupIdleTime) {
     unsigned int nowSpeed = peerStat->calculateDownloadSpeed();
     if(lowestDownloadSpeedLimit > 0 &&  nowSpeed <= lowestDownloadSpeedLimit) {
       throw DL_ABORT_EX2(StringFormat(EX_TOO_SLOW_DOWNLOAD_SPEED,

+ 18 - 9
src/DownloadEngine.cc

@@ -76,6 +76,12 @@
 
 namespace aria2 {
 
+namespace global {
+
+// Global clock, this clock is reseted before executeCommand() call to
+// reduce the call gettimeofday() system call.
+Time wallclock;
+
 // 0 ... running
 // 1 ... stop signal detected
 // 2 ... stop signal processed by DownloadEngine
@@ -83,6 +89,8 @@ namespace aria2 {
 // 4 ... 2nd stop signal processed by DownloadEngine
 volatile sig_atomic_t globalHaltRequested = 0;
 
+} // namespace global
+
 DownloadEngine::DownloadEngine(const SharedHandle<EventPoll>& eventPoll):
   _eventPoll(eventPoll),
   logger(LogFactory::getInstance()),
@@ -136,9 +144,10 @@ void DownloadEngine::run()
   Time cp;
   cp.setTimeInSec(0);
   while(!commands.empty() || !_routineCommands.empty()) {
-    if(cp.elapsed(_refreshInterval)) {
+    global::wallclock.reset();
+    if(cp.difference(global::wallclock) >= _refreshInterval) {
       _refreshInterval = DEFAULT_REFRESH_INTERVAL;
-      cp.reset();
+      cp = global::wallclock;
       executeCommand(commands, Command::STATUS_ALL);
     } else {
       executeCommand(commands, Command::STATUS_ACTIVE);
@@ -211,16 +220,16 @@ void DownloadEngine::onEndOfRun()
 void DownloadEngine::afterEachIteration()
 {
   _requestGroupMan->calculateStat();
-  if(globalHaltRequested == 1) {
+  if(global::globalHaltRequested == 1) {
     logger->notice(_("Shutdown sequence commencing... Press Ctrl-C again for emergency shutdown."));
     requestHalt();
-    globalHaltRequested = 2;
+    global::globalHaltRequested = 2;
     setNoWait(true);
     setRefreshInterval(0);
-  } else if(globalHaltRequested == 3) {
+  } else if(global::globalHaltRequested == 3) {
     logger->notice(_("Emergency shutdown sequence commencing..."));
     _requestGroupMan->forceHalt();
-    globalHaltRequested = 4;
+    global::globalHaltRequested = 4;
     setNoWait(true);
     setRefreshInterval(0);
   }
@@ -275,12 +284,12 @@ void DownloadEngine::poolSocket(const std::string& ipaddr,
   std::multimap<std::string, SocketPoolEntry>::value_type p(addr, entry);
   _socketPool.insert(p);
 
-  if(_lastSocketPoolScan.elapsed(60)) {
+  if(_lastSocketPoolScan.difference(global::wallclock) >= 60) {
     std::multimap<std::string, SocketPoolEntry> newPool;
     if(logger->debug()) {
       logger->debug("Scaning SocketPool and erasing timed out entry.");
     }
-    _lastSocketPoolScan.reset();
+    _lastSocketPoolScan = global::wallclock;
     for(std::multimap<std::string, SocketPoolEntry>::iterator i =
           _socketPool.begin(), eoi = _socketPool.end(); i != eoi; ++i) {
       if(!(*i).second.isTimeout()) {
@@ -439,7 +448,7 @@ DownloadEngine::SocketPoolEntry::~SocketPoolEntry() {}
 
 bool DownloadEngine::SocketPoolEntry::isTimeout() const
 {
-  return _registeredTime.elapsed(_timeout);
+  return _registeredTime.difference(global::wallclock) >= _timeout;
 }
 
 cuid_t DownloadEngine::newCUID()

+ 3 - 1
src/FileEntry.cc

@@ -40,6 +40,7 @@
 #include "util.h"
 #include "URISelector.h"
 #include "LogFactory.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -172,7 +173,8 @@ FileEntry::findFasterRequest(const SharedHandle<Request>& base)
   // TODO hard coded value. See PREF_STARTUP_IDLE_TIME
   const int startupIdleTime = 10;
   if(basestat.isNull() ||
-     (basestat->getDownloadStartTime().elapsed(startupIdleTime) &&
+     (basestat->getDownloadStartTime().
+      difference(global::wallclock) >= startupIdleTime &&
       fastest->getAvgDownloadSpeed()*0.8 > basestat->calculateDownloadSpeed())){
     // TODO we should consider that "fastest" is very slow.
     SharedHandle<Request> fastestRequest = _requestPool.front();

+ 3 - 2
src/HttpServerBodyCommand.cc

@@ -50,6 +50,7 @@
 #include "XmlRpcMethodFactory.h"
 #include "XmlRpcResponse.h"
 #include "DownloadContext.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -79,7 +80,7 @@ bool HttpServerBodyCommand::execute()
   }
   try {
     if(_socket->isReadable(0) || _httpServer->getContentLength() == 0) {
-      _timeout.reset();
+      _timeout = global::wallclock;
 
       if(_httpServer->receiveBody()) {
         // Do something for requestpath and body
@@ -106,7 +107,7 @@ bool HttpServerBodyCommand::execute()
         return false;
       } 
     } else {
-      if(_timeout.elapsed(30)) {
+      if(_timeout.difference(global::wallclock) >= 30) {
         logger->info("HTTP request body timeout.");
         return true;
       } else {

+ 3 - 2
src/HttpServerCommand.cc

@@ -47,6 +47,7 @@
 #include "Option.h"
 #include "util.h"
 #include "DownloadContext.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -92,7 +93,7 @@ bool HttpServerCommand::execute()
   }
   try {
     if(_socket->isReadable(0)) {
-      _timeout.reset();
+      _timeout = global::wallclock;
       SharedHandle<HttpHeader> header;
 
       header = _httpServer->receiveRequest();
@@ -127,7 +128,7 @@ bool HttpServerCommand::execute()
       _e->setNoWait(true);
       return true;
     } else {
-      if(_timeout.elapsed(30)) {
+      if(_timeout.difference(global::wallclock) >= 30) {
         logger->info("HTTP request timeout.");
         return true;
       } else {

+ 2 - 1
src/HttpServerResponseCommand.cc

@@ -41,6 +41,7 @@
 #include "RequestGroupMan.h"
 #include "RecoverableException.h"
 #include "FileEntry.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -84,7 +85,7 @@ bool HttpServerResponseCommand::execute()
     }
     return true;
   } else {
-    if(_timeout.elapsed(10)) {
+    if(_timeout.difference(global::wallclock) >= 10) {
       logger->info("CUID#%d - HttpServer: Timeout while trasmitting response.",
                    cuid);
       return true;

+ 3 - 2
src/LpdMessageDispatcher.cc

@@ -38,6 +38,7 @@
 #include "LogFactory.h"
 #include "BtConstants.h"
 #include "RecoverableException.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -92,12 +93,12 @@ bool LpdMessageDispatcher::sendMessage()
 
 bool LpdMessageDispatcher::isAnnounceReady() const
 {
-  return _timer.elapsed(_interval);
+  return _timer.difference(global::wallclock) >= _interval;
 }
 
 void LpdMessageDispatcher::resetAnnounceTimer()
 {
-  _timer.reset();
+  _timer = global::wallclock;
 }
 
 namespace bittorrent {

+ 8 - 4
src/MultiUrlRequestInfo.cc

@@ -66,13 +66,17 @@ namespace aria2 {
 # define SA_RESETHAND 0x80000000
 #endif // SA_RESETHAND
 
+namespace global {
+
 extern volatile sig_atomic_t globalHaltRequested;
 
+} // namespace global
+
 static void handler(int signal) {
-  if(globalHaltRequested == 0) {
-    globalHaltRequested = 1;
-  } else if(globalHaltRequested == 2) {
-    globalHaltRequested = 3;
+  if(global::globalHaltRequested == 0) {
+    global::globalHaltRequested = 1;
+  } else if(global::globalHaltRequested == 2) {
+    global::globalHaltRequested = 3;
   }
 }
 

+ 4 - 14
src/Peer.cc

@@ -41,6 +41,7 @@
 #include "a2functional.h"
 #include "PeerSessionResource.h"
 #include "BtMessageDispatcher.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -215,24 +216,12 @@ unsigned int Peer::calculateUploadSpeed()
   return _res->getPeerStat().calculateUploadSpeed();
 }
 
-unsigned int Peer::calculateUploadSpeed(const struct timeval& now)
-{
-  assert(_res);
-  return _res->getPeerStat().calculateUploadSpeed(now);
-}
-
 unsigned int Peer::calculateDownloadSpeed()
 {
   assert(_res);
   return _res->getPeerStat().calculateDownloadSpeed();
 }
 
-unsigned int Peer::calculateDownloadSpeed(const struct timeval& now)
-{
-  assert(_res);
-  return _res->getPeerStat().calculateDownloadSpeed(now);
-}
-
 uint64_t Peer::getSessionUploadLength() const
 {
   assert(_res);
@@ -330,12 +319,13 @@ void Peer::setAllBitfield() {
 
 void Peer::startBadCondition()
 {
-  _badConditionStartTime.reset();
+  _badConditionStartTime = global::wallclock;
 }
 
 bool Peer::isGood() const
 {
-  return _badConditionStartTime.elapsed(BAD_CONDITION_INTERVAL);
+  return _badConditionStartTime.
+    difference(global::wallclock) >= BAD_CONDITION_INTERVAL;
 }
 
 uint8_t Peer::getExtensionMessageID(const std::string& name) const

+ 0 - 4
src/Peer.h

@@ -205,15 +205,11 @@ public:
    */
   unsigned int calculateUploadSpeed();
 
-  unsigned int calculateUploadSpeed(const struct timeval& now);
-
   /**
    * Returns the transfer rate from remote host to localhost.
    */
   unsigned int calculateDownloadSpeed();
 
-  unsigned int calculateDownloadSpeed(const struct timeval& now);
-
   /**
    * Returns the number of bytes uploaded to the remote host.
    */

+ 4 - 3
src/PeerAbstractCommand.cc

@@ -43,6 +43,7 @@
 #include "prefs.h"
 #include "DownloadFailureException.h"
 #include "StringFormat.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -88,13 +89,13 @@ bool PeerAbstractCommand::execute()
        (checkSocketIsReadable && _readEvent) ||
        (checkSocketIsWritable && _writeEvent) ||
        _hupEvent) {
-      checkPoint.reset();
+      checkPoint = global::wallclock;
     } else if(_errorEvent) {
       throw DL_ABORT_EX
         (StringFormat(MSG_NETWORK_PROBLEM,
                       socket->getSocketError().c_str()).str());
     }
-    if(checkPoint.elapsed(timeout)) {
+    if(checkPoint.difference(global::wallclock) >= timeout) {
       throw DL_ABORT_EX(EX_TIME_OUT);
     }
     return executeInternal();
@@ -183,7 +184,7 @@ void PeerAbstractCommand::setNoCheck(bool check)
 
 void PeerAbstractCommand::updateKeepAlive()
 {
-  checkPoint.reset();
+  checkPoint = global::wallclock;
 }
 
 } // namespace aria2

+ 0 - 10
src/PeerStat.h

@@ -82,8 +82,6 @@ public:
                             _sessionDownloadLength(0),
                             _sessionUploadLength(0) {}
 
-  ~PeerStat() {}
-
   /**
    * Returns current download speed in byte per sec.
    */
@@ -91,10 +89,6 @@ public:
     return downloadSpeed.calculateSpeed();
   }
 
-  unsigned int calculateDownloadSpeed(const struct timeval& now) {
-    return downloadSpeed.calculateSpeed(now);
-  }
-
   unsigned int calculateAvgDownloadSpeed() {
     _avgDownloadSpeed = downloadSpeed.calculateAvgSpeed();
     return _avgDownloadSpeed;
@@ -104,10 +98,6 @@ public:
     return uploadSpeed.calculateSpeed();
   }
 
-  unsigned int calculateUploadSpeed(const struct timeval& now) {
-    return uploadSpeed.calculateSpeed(now);
-  }
-
   unsigned int calculateAvgUploadSpeed() {
     _avgUploadSpeed = uploadSpeed.calculateAvgSpeed();
     return _avgUploadSpeed;

+ 3 - 6
src/RequestSlot.cc

@@ -33,6 +33,7 @@
  */
 /* copyright --> */
 #include "RequestSlot.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -46,12 +47,8 @@ void RequestSlot::setDispatchedTime(time_t secFromEpoch) {
   dispatchedTime.setTimeInSec(secFromEpoch);
 }
 
-bool RequestSlot::isTimeout(const struct timeval& now, time_t timeoutSec) const {
-  return dispatchedTime.difference(now) >= timeoutSec;
-}
-
-unsigned int RequestSlot::getLatencyInMillis() const {
-  return dispatchedTime.differenceInMillis();
+bool RequestSlot::isTimeout(time_t timeoutSec) const {
+  return dispatchedTime.difference(global::wallclock) >= timeoutSec;
 }
 
 bool RequestSlot::isNull(const RequestSlot& requestSlot) {

+ 1 - 2
src/RequestSlot.h

@@ -113,8 +113,7 @@ public:
   void setDispatchedTime();
   void setDispatchedTime(time_t secFromEpoch);
 
-  bool isTimeout(const struct timeval& now, time_t timeoutSec) const;
-  unsigned int getLatencyInMillis() const;
+  bool isTimeout(time_t timeoutSec) const;
 
   size_t getIndex() const { return index; }
   void setIndex(size_t index) { this->index = index; }

+ 3 - 2
src/SegmentMan.cc

@@ -51,6 +51,7 @@
 #include "DownloadContext.h"
 #include "Piece.h"
 #include "FileEntry.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -336,8 +337,8 @@ void SegmentMan::updateFastestPeerStat(const SharedHandle<PeerStat>& peerStat)
 unsigned int SegmentMan::calculateDownloadSpeed()
 {
   unsigned int speed = 0;
-  if(_lastPeerStatDlspdMapUpdated.elapsedInMillis(250)) {
-    _lastPeerStatDlspdMapUpdated.reset();
+  if(_lastPeerStatDlspdMapUpdated.differenceInMillis(global::wallclock) >= 250){
+    _lastPeerStatDlspdMapUpdated = global::wallclock;
     _peerStatDlspdMap.clear();
     for(std::vector<SharedHandle<PeerStat> >::const_iterator i =
           peerStats.begin(), eoi = peerStats.end(); i != eoi; ++i) {

+ 2 - 1
src/ServerStatMan.cc

@@ -43,6 +43,7 @@
 #include "ServerStat.h"
 #include "util.h"
 #include "RecoverableException.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -148,7 +149,7 @@ public:
 
   bool operator()(const SharedHandle<ServerStat>& ss) const
   {
-    return ss->getLastUpdated().elapsed(_timeout);
+    return ss->getLastUpdated().difference(global::wallclock) >= _timeout;
   }
 };
 

+ 2 - 1
src/SleepCommand.cc

@@ -36,6 +36,7 @@
 #include "RequestGroup.h"
 #include "DownloadEngine.h"
 #include "DownloadContext.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -54,7 +55,7 @@ SleepCommand::~SleepCommand() {
 bool SleepCommand::execute() {
   if(_requestGroup->downloadFinished() || _requestGroup->isHaltRequested()) {
     return true;
-  } else if(checkPoint.elapsed(wait)) {
+  } else if(checkPoint.difference(global::wallclock) >= wait) {
     engine->commands.push_back(nextCommand);
     nextCommand = 0;
     return true;

+ 13 - 26
src/SpeedCalc.cc

@@ -33,23 +33,25 @@
  */
 /* copyright --> */
 #include "SpeedCalc.h"
+
 #include <algorithm>
 #include <functional>
 
+#include "wallclock.h"
+
 namespace aria2 {
 
 #define CHANGE_INTERVAL_SEC 15
 
-class Reset {
-public:
-  void operator()(Time& tm) {
-    tm.reset();
-  }
-};
+SpeedCalc::SpeedCalc():sw(0), maxSpeed(0), prevSpeed(0), accumulatedLength(0),
+                       nextInterval(CHANGE_INTERVAL_SEC)
+{
+  std::fill(&lengthArray[0], &lengthArray[2], 0);
+}
 
 void SpeedCalc::reset() {
   std::fill(&lengthArray[0], &lengthArray[2], 0);
-  std::for_each(&cpArray[0], &cpArray[2], Reset());
+  std::for_each(&cpArray[0], &cpArray[2], std::mem_fun_ref(&Time::reset));
   sw = 0;
   maxSpeed = 0;
   prevSpeed = 0;
@@ -59,22 +61,7 @@ void SpeedCalc::reset() {
 }
 
 unsigned int SpeedCalc::calculateSpeed() {
-  int64_t milliElapsed = cpArray[sw].differenceInMillis();
-  if(milliElapsed) {
-    unsigned int speed = lengthArray[sw]*1000/milliElapsed;
-    prevSpeed = speed;
-    maxSpeed = std::max(speed, maxSpeed);
-    if(isIntervalOver(milliElapsed)) {
-      changeSw();
-    }
-    return speed;
-  } else {
-    return prevSpeed;
-  }
-}
-
-unsigned int SpeedCalc::calculateSpeed(const struct timeval& now) {
-  int64_t milliElapsed = cpArray[sw].differenceInMillis(now);
+  int64_t milliElapsed = cpArray[sw].differenceInMillis(global::wallclock);
   if(milliElapsed) {
     unsigned int speed = lengthArray[sw]*1000/milliElapsed;
     prevSpeed = speed;
@@ -98,7 +85,7 @@ void SpeedCalc::update(size_t bytes) {
 }
 
 bool SpeedCalc::isIntervalOver() const {
-  return nextInterval <= cpArray[sw].difference();
+  return nextInterval <= cpArray[sw].difference(global::wallclock);
 }
 
 bool SpeedCalc::isIntervalOver(int64_t milliElapsed) const
@@ -110,11 +97,11 @@ void SpeedCalc::changeSw() {
   lengthArray[sw] = 0;
   cpArray[sw].reset();
   sw ^= 0x01;
-  nextInterval = cpArray[sw].difference()+CHANGE_INTERVAL_SEC;
+  nextInterval = cpArray[sw].difference(global::wallclock)+CHANGE_INTERVAL_SEC;
 }
 
 unsigned int SpeedCalc::calculateAvgSpeed() const {
-  uint64_t milliElapsed = start.differenceInMillis();
+  uint64_t milliElapsed = start.differenceInMillis(global::wallclock);
 
   // if milliElapsed is too small, the average speed is rubish, better return 0
   if(milliElapsed > 4) {

+ 1 - 7
src/SpeedCalc.h

@@ -57,19 +57,13 @@ private:
 
   void changeSw();
 public:
-  SpeedCalc() {
-    reset();
-  }
-
-  ~SpeedCalc() {}
+  SpeedCalc();
 
   /**
    * Returns download/upload speed in byte per sec
    */
   unsigned int calculateSpeed();
 
-  unsigned int calculateSpeed(const struct timeval& now);
-
   unsigned int getMaxSpeed() const {
     return maxSpeed;
   }

+ 9 - 3
src/TimeA2.cc

@@ -113,13 +113,14 @@ bool Time::isNewer(const Time& time) const {
   return util::difftv(this->tv, time.tv) > 0;
 }
 
-time_t Time::difference() const {
-  return util::difftvsec(getCurrentTime(), tv);
+time_t Time::difference() const
+{
+  return util::difftv(getCurrentTime(), tv)/1000000;
 }
 
 time_t Time::difference(const struct timeval& now) const
 {
-  return util::difftvsec(now, tv);
+  return util::difftv(now, tv)/1000000;
 }
 
 int64_t Time::differenceInMillis() const {
@@ -156,6 +157,11 @@ void Time::setTimeInSec(time_t sec) {
   tv.tv_usec = 0;
 }
 
+void Time::advance(time_t sec)
+{
+  tv.tv_sec += sec;
+}
+
 bool Time::good() const
 {
   return _good;

+ 12 - 0
src/TimeA2.h

@@ -77,10 +77,20 @@ public:
 
   time_t difference(const struct timeval& now) const;
 
+  time_t difference(const Time& now) const
+  {
+    return difference(now.tv);
+  }
+
   int64_t differenceInMillis() const;
 
   int64_t differenceInMillis(const struct timeval& now) const;
 
+  int64_t differenceInMillis(const Time& now) const
+  {
+    return differenceInMillis(now.tv);
+  }
+
   // Returns true if this object's time value is zero.
   bool isZero() const;
 
@@ -95,6 +105,8 @@ public:
 
   bool isNewer(const Time& time) const;
 
+  void advance(time_t sec);
+
   bool good() const;
 
   // Returns !good()

+ 3 - 2
src/TimeBasedCommand.cc

@@ -34,6 +34,7 @@
 /* copyright --> */
 #include "TimeBasedCommand.h"
 #include "DownloadEngine.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -51,8 +52,8 @@ bool TimeBasedCommand::execute()
   if(_exit) {
     return true;
   }
-  if(_checkPoint.elapsed(_interval)) {
-    _checkPoint.reset();
+  if(_checkPoint.difference(global::wallclock) >= _interval) {
+    _checkPoint = global::wallclock;
     process();
     if(_exit) {
       return true;

+ 3 - 2
src/TimeSeedCriteria.h

@@ -37,6 +37,7 @@
 
 #include "SeedCriteria.h"
 #include "TimeA2.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -50,11 +51,11 @@ public:
   virtual ~TimeSeedCriteria() {}
 
   virtual void reset() {
-    watch.reset();
+    watch = global::wallclock;
   }
 
   virtual bool evaluate() {
-    return watch.elapsed(duration);
+    return watch.difference(global::wallclock) >= duration;
   }
 
   void setDuration(time_t duration) {

+ 2 - 1
src/UTMetadataRequestTracker.h

@@ -40,6 +40,7 @@
 #include <vector>
 
 #include "TimeA2.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -55,7 +56,7 @@ private:
 
     bool elapsed(time_t t) const
     {
-      return _dispatchedTime.elapsed(t);
+      return _dispatchedTime.difference(global::wallclock) >= t;
     }
 
     bool operator==(const RequestEntry& e) const

+ 4 - 2
src/UTPexExtensionMessage.cc

@@ -43,6 +43,7 @@
 #include "StringFormat.h"
 #include "bencode.h"
 #include "a2functional.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -101,7 +102,7 @@ void UTPexExtensionMessage::doReceivedAction()
 bool UTPexExtensionMessage::addFreshPeer(const SharedHandle<Peer>& peer)
 {
   if(!peer->isIncomingPeer() &&
-     !peer->getFirstContactTime().elapsed(_interval)) {
+     peer->getFirstContactTime().difference(global::wallclock) < _interval) {
     _freshPeers.push_back(peer);
     return true;
   } else {
@@ -117,7 +118,8 @@ bool UTPexExtensionMessage::freshPeersAreFull() const
 bool UTPexExtensionMessage::addDroppedPeer(const SharedHandle<Peer>& peer)
 {
   if(!peer->isIncomingPeer() &&
-     !peer->getBadConditionStartTime().elapsed(_interval)) {
+     peer->getBadConditionStartTime().
+     difference(global::wallclock) < _interval) {
     _droppedPeers.push_back(peer);
     return true;
   } else {

+ 46 - 0
src/wallclock.h

@@ -0,0 +1,46 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "TimeA2.h"
+
+namespace aria2 {
+
+namespace global {
+
+// wallclock is defined in DownloadEngine.cc
+extern Time wallclock;
+
+} // namespace global
+
+} // namespace aria2

+ 3 - 2
test/TimeSeedCriteriaTest.cc

@@ -3,6 +3,7 @@
 #include <cppunit/extensions/HelperMacros.h>
 
 #include "util.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -21,8 +22,8 @@ CPPUNIT_TEST_SUITE_REGISTRATION(TimeSeedCriteriaTest);
 
 void TimeSeedCriteriaTest::testEvaluate() {
   TimeSeedCriteria cri(1);
-  // Seel 2seconds. 1 seconds are not enough in some systems.
-  util::sleep(2);
+  global::wallclock.reset();
+  global::wallclock.advance(2);
   CPPUNIT_ASSERT(cri.evaluate());
   cri.reset();
   cri.setDuration(10);

+ 6 - 4
test/UTPexExtensionMessageTest.cc

@@ -11,6 +11,7 @@
 #include "MockPeerStorage.h"
 #include "Exception.h"
 #include "FileEntry.h"
+#include "wallclock.h"
 
 namespace aria2 {
 
@@ -34,6 +35,7 @@ public:
   void setUp()
   {
     _peerStorage.reset(new MockPeerStorage());
+    global::wallclock.reset();
   }
 
   void testGetExtensionMessageID();
@@ -69,15 +71,15 @@ void UTPexExtensionMessageTest::testGetBencodedData()
   SharedHandle<Peer> p1(new Peer("192.168.0.1", 6881));
   p1->allocateSessionResource(256*1024, 1024*1024);
   p1->setAllBitfield();
-  msg.addFreshPeer(p1);// added seeder, check add.f flag
+  CPPUNIT_ASSERT(msg.addFreshPeer(p1));// added seeder, check add.f flag
   SharedHandle<Peer> p2(new Peer("10.1.1.2", 9999));
-  msg.addFreshPeer(p2);
+  CPPUNIT_ASSERT(msg.addFreshPeer(p2));
   SharedHandle<Peer> p3(new Peer("192.168.0.2", 6882));
   p3->startBadCondition();
-  msg.addDroppedPeer(p3);
+  CPPUNIT_ASSERT(msg.addDroppedPeer(p3));
   SharedHandle<Peer> p4(new Peer("10.1.1.3", 10000));
   p4->startBadCondition();
-  msg.addDroppedPeer(p4);
+  CPPUNIT_ASSERT(msg.addDroppedPeer(p4));
 
   unsigned char c1[6];
   unsigned char c2[6];