2006-06-12 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

To add Time class which represents a specific instant in time 
and
	its precision is microseconds. Time checking procedures were 
rewritten
	using this object.

	* src/Time.h: New class.
	* src/Time.cc: New class.
	* src/AbstractCommand.h
	(updateCheckPoint): Removed.
	(isTimeoutDetected): Removed.
	(checkPoint): Changed the type to Time.
	(timeout): New variable.
	(setTimeout): New function.
	* src/AbstractCommand.cc
	(AbstractCommand): Removed the initialization of checkPoint.
	Added the initialization of timeout.
	(updateCheckPoint): Removed.
	(isTimeoutDetected): Removed.
	(execute): Use checkPoint.reset() and checkPoint.elapsed().
	* src/PeerChokeCommand.h
	(checkPoint): Changed the type to Time.
	* src/PeerChokeCommand.cc
	(PeerChokeCommand): Removed the initialization of checkPoint.
	(execute): Rewritten using Time object.
	* src/TrackerWatcherCommand.h
	(checkPoint): Changed the type to Time.
	* src/TrackerWatcherCommand.cc
	(TrackerWatcherCommand): Removed the initialization of 
checkPoint.
	(execute): Rewritten.
	* src/ConsoleDownloadEngine.h
	(cp): Changed the type to Time.
	(startup): Changed the type to Time.
	* src/ConsoleDownloadEngine.cc
	(initStatistics): Use cp.reset(), startup.reset().
	(calculateStatistics): Rewritten using Time object.
	* src/PeerAbstractCommand.h
	(updateCheckPoint): Removed.
	(isTimeoutDetected): Removed.
	(checkPoint): Changed the type to Time.
	* src/PeerAbstractCommand.cc
	(PeerAbstractCommand): Removed the initialization of checkPoint.
	(updateCheckPoint): Removed.
	(isTimeoutDetected): Removed.
	(execute): Use checkPoint.reset() and checkPoint.elapsed().
	* src/PeerInteractionCommand.cc
	(PeerInteractionCommand): Removed the initializations of struct
	timeval variables.
	* src/PeerInteractionCommand.h
	(keepAliveCheckPoint): Changed the type to Time.
	(chokeCheckPoint): Changed the type to Time.
	(freqCheckPoint): Changed the type to Time.
	(haveCheckTime): Changed the type to Time.
	* src/PeerInteractionCommand.cc
	(executeInternal): Rewritten using Time object.
	(detectMessageFlooding): Rewritten using Time object.
	(checkLongTimePeerChoking): Rewritten using Time object.
	(sendKeepAlive): Rewritten using Time object.
	(checkHave): Rewritten using Time object.
	* src/SleepCommand.h
	(checkPoint): Changed the type to Time.
	* src/SleepCommand.cc
	(SleepCommand): Removed the initialization of checkPoint.
	(execute): Rewritten using Time object.
	* src/TorrentAutoSaveCommand.h
	(checkPoint): Changed the type to Time.
	* src/TorrentAutoSaveCommand.cc
	(TorrentAutoSaveCommand): Removed the initialization of 
checkPoint.
	(execute): Rewritten.
	* src/DownloadCommand.h
	(sw): Changed the type to Time.
	* src/DownloadCommand.cc
	(DownloadCommand): Removed the initialization of sw.
	(executeInternal): Rewritten.
	* src/RequestSlot.h
	(dispatchedTime): Changed the type to Time.
	* src/RequestSlot.cc
	(RequestSlot): Removed the call to setDispatchedTime().
	(setDispatchedTime): Rewirtten.
	(isTimeout): Rewritten.
	(getLatencyInMillis): Rewritten.
	* src/TorrentDownloadEngine.h
	(cp): Changed the type to Time[2].
	(startup): Changed the type to Time.
	* src/TorrentDownloadEngine.cc
	(initStatistics): Rewritten.
	(calculateStatistics): Rewritten.
	* src/DownloadEngine.cc
	(run): Rewritten.
	
	To detect all attempts to connect to the tracker are failed:

	* src/AbstractCommand.cc
	(execute): Increment e->segmentMan->errors if a command aborted.
	* src/SegmentMan.h
	(errors): New variable.
	* src/SegmentMan.cc
	(SegmentMan): Added the initialization of errors.
	(init): Added the initialization of errors.
	* src/TrackerWatcherCommand.cc
	(execute): If e->segmentMan->errors > 0 then assume that the 
tracker
	request was failed.
	
	To handle snubbed peers:
	
	* src/PeerChokeCommand.cc
	(optUnchokingPeer): Snubbed peers don't get unchoked.
	(execute): Snubbed peers don't get unchoked.
	* src/PeerInteraction.h
	(REQUEST_TIME_OUT): Changed the value from 120 to 60.
	* src/PeerInteraction.cc
	(checkRequestSlot): A peer get marked as "snubbed" if it doesn't 
send
	back the requested 16k block in 60 seconds.
	* src/PieceMessage.cc
	(receivedAction): A peer's snubbed state is cleard if it sends
	the requested 16k block in 60 seconds.
	* src/Peer.h
	(snubbing): New variable.
	* src/Peer.cc
	(resetStatus): Added snubbed = false.
	
	To fix the bug that causes have message is not sent:

	* src/PeerInteractionCommand.cc
	(~PeerInteractionCommand): Removed 
e->torrentMan->unadvertisePiece().
	(FLOODING_CHECK_INTERVAL): New definition(temporal).
	(detectMessageFlooding): Use FLOODING_CHECK_INTERVAL.
	* src/TorrentMan.h
	(HaveEntry): New class.
	(advertisePiece): Rewritten.
	(getAdvertisedPieceIndexes): Rewritten.
	(Haves): Changed the type.
	(getAdvertisedPieceIndexes): Added an argument.
	
	Others:
	
	* src/TorrentMan.h
	(DEFAULT_ANNOUNCE_INTERVAL): Changed the value to 1800.
	(DEFAULT_ANNOUNCE_MIN_INTERVAL): Changed the value to 1800.
	* src/TorrentMan.cc
	(getPeer): Don't check the number of connections here.
	(setupInternal1): Changed peerId.

	* src/PeerInteractionCommand.h
	(KEEP_ALIVE_INTERVAL): New definition.
	(sendKeepAlive): Use KEEP_ALIVE_INTERVAL.

	* src/main.cc
	(main): SA_ONESHOT was replaced with SA_RESETHAND.

	* src/DownloadEngine.h: Removed unnecessary header includes.
pull/1/head
Tatsuhiro Tsujikawa 2006-06-12 16:55:08 +00:00
parent 7e36107f45
commit d380b7b6ab
42 changed files with 503 additions and 296 deletions

152
ChangeLog
View File

@ -1,3 +1,155 @@
2006-06-12 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
To add Time class which represents a specific instant in time and
its precision is microseconds. Time checking procedures were rewritten
using this object.
* src/Time.h: New class.
* src/Time.cc: New class.
* src/AbstractCommand.h
(updateCheckPoint): Removed.
(isTimeoutDetected): Removed.
(checkPoint): Changed the type to Time.
(timeout): New variable.
(setTimeout): New function.
* src/AbstractCommand.cc
(AbstractCommand): Removed the initialization of checkPoint.
Added the initialization of timeout.
(updateCheckPoint): Removed.
(isTimeoutDetected): Removed.
(execute): Use checkPoint.reset() and checkPoint.elapsed().
* src/PeerChokeCommand.h
(checkPoint): Changed the type to Time.
* src/PeerChokeCommand.cc
(PeerChokeCommand): Removed the initialization of checkPoint.
(execute): Rewritten using Time object.
* src/TrackerWatcherCommand.h
(checkPoint): Changed the type to Time.
* src/TrackerWatcherCommand.cc
(TrackerWatcherCommand): Removed the initialization of checkPoint.
(execute): Rewritten.
* src/ConsoleDownloadEngine.h
(cp): Changed the type to Time.
(startup): Changed the type to Time.
* src/ConsoleDownloadEngine.cc
(initStatistics): Use cp.reset(), startup.reset().
(calculateStatistics): Rewritten using Time object.
* src/PeerAbstractCommand.h
(updateCheckPoint): Removed.
(isTimeoutDetected): Removed.
(checkPoint): Changed the type to Time.
* src/PeerAbstractCommand.cc
(PeerAbstractCommand): Removed the initialization of checkPoint.
(updateCheckPoint): Removed.
(isTimeoutDetected): Removed.
(execute): Use checkPoint.reset() and checkPoint.elapsed().
* src/PeerInteractionCommand.cc
(PeerInteractionCommand): Removed the initializations of struct
timeval variables.
* src/PeerInteractionCommand.h
(keepAliveCheckPoint): Changed the type to Time.
(chokeCheckPoint): Changed the type to Time.
(freqCheckPoint): Changed the type to Time.
(haveCheckTime): Changed the type to Time.
* src/PeerInteractionCommand.cc
(executeInternal): Rewritten using Time object.
(detectMessageFlooding): Rewritten using Time object.
(checkLongTimePeerChoking): Rewritten using Time object.
(sendKeepAlive): Rewritten using Time object.
(checkHave): Rewritten using Time object.
* src/SleepCommand.h
(checkPoint): Changed the type to Time.
* src/SleepCommand.cc
(SleepCommand): Removed the initialization of checkPoint.
(execute): Rewritten using Time object.
* src/TorrentAutoSaveCommand.h
(checkPoint): Changed the type to Time.
* src/TorrentAutoSaveCommand.cc
(TorrentAutoSaveCommand): Removed the initialization of checkPoint.
(execute): Rewritten.
* src/DownloadCommand.h
(sw): Changed the type to Time.
* src/DownloadCommand.cc
(DownloadCommand): Removed the initialization of sw.
(executeInternal): Rewritten.
* src/RequestSlot.h
(dispatchedTime): Changed the type to Time.
* src/RequestSlot.cc
(RequestSlot): Removed the call to setDispatchedTime().
(setDispatchedTime): Rewirtten.
(isTimeout): Rewritten.
(getLatencyInMillis): Rewritten.
* src/TorrentDownloadEngine.h
(cp): Changed the type to Time[2].
(startup): Changed the type to Time.
* src/TorrentDownloadEngine.cc
(initStatistics): Rewritten.
(calculateStatistics): Rewritten.
* src/DownloadEngine.cc
(run): Rewritten.
To detect all attempts to connect to the tracker are failed:
* src/AbstractCommand.cc
(execute): Increment e->segmentMan->errors if a command aborted.
* src/SegmentMan.h
(errors): New variable.
* src/SegmentMan.cc
(SegmentMan): Added the initialization of errors.
(init): Added the initialization of errors.
* src/TrackerWatcherCommand.cc
(execute): If e->segmentMan->errors > 0 then assume that the tracker
request was failed.
To handle snubbed peers:
* src/PeerChokeCommand.cc
(optUnchokingPeer): Snubbed peers don't get unchoked.
(execute): Snubbed peers don't get unchoked.
* src/PeerInteraction.h
(REQUEST_TIME_OUT): Changed the value from 120 to 60.
* src/PeerInteraction.cc
(checkRequestSlot): A peer get marked as "snubbed" if it doesn't send
back the requested 16k block in 60 seconds.
* src/PieceMessage.cc
(receivedAction): A peer's snubbed state is cleard if it sends
the requested 16k block in 60 seconds.
* src/Peer.h
(snubbing): New variable.
* src/Peer.cc
(resetStatus): Added snubbed = false.
To fix the bug that causes have message is not sent:
* src/PeerInteractionCommand.cc
(~PeerInteractionCommand): Removed e->torrentMan->unadvertisePiece().
(FLOODING_CHECK_INTERVAL): New definition(temporal).
(detectMessageFlooding): Use FLOODING_CHECK_INTERVAL.
* src/TorrentMan.h
(HaveEntry): New class.
(advertisePiece): Rewritten.
(getAdvertisedPieceIndexes): Rewritten.
(Haves): Changed the type.
(getAdvertisedPieceIndexes): Added an argument.
Others:
* src/TorrentMan.h
(DEFAULT_ANNOUNCE_INTERVAL): Changed the value to 1800.
(DEFAULT_ANNOUNCE_MIN_INTERVAL): Changed the value to 1800.
* src/TorrentMan.cc
(getPeer): Don't check the number of connections here.
(setupInternal1): Changed peerId.
* src/PeerInteractionCommand.h
(KEEP_ALIVE_INTERVAL): New definition.
(sendKeepAlive): Use KEEP_ALIVE_INTERVAL.
* src/main.cc
(main): SA_ONESHOT was replaced with SA_RESETHAND.
* src/DownloadEngine.h: Removed unnecessary header includes.
2006-05-29 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> 2006-05-29 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
To fix the bug that causes segfaults if a tracker returns a zero-length To fix the bug that causes segfaults if a tracker returns a zero-length

20
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59 for aria2c 0.5.0. # Generated by GNU Autoconf 2.59 for aria2c 0.5.1.
# #
# Report bugs to <tujikawa@rednoah.com>. # Report bugs to <tujikawa@rednoah.com>.
# #
@ -269,8 +269,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package. # Identity of this package.
PACKAGE_NAME='aria2c' PACKAGE_NAME='aria2c'
PACKAGE_TARNAME='aria2c' PACKAGE_TARNAME='aria2c'
PACKAGE_VERSION='0.5.0' PACKAGE_VERSION='0.5.1'
PACKAGE_STRING='aria2c 0.5.0' PACKAGE_STRING='aria2c 0.5.1'
PACKAGE_BUGREPORT='tujikawa@rednoah.com' PACKAGE_BUGREPORT='tujikawa@rednoah.com'
ac_unique_file="src/Socket.h" ac_unique_file="src/Socket.h"
@ -788,7 +788,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures aria2c 0.5.0 to adapt to many kinds of systems. \`configure' configures aria2c 0.5.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -854,7 +854,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of aria2c 0.5.0:";; short | recursive ) echo "Configuration of aria2c 0.5.1:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -994,7 +994,7 @@ fi
test -n "$ac_init_help" && exit 0 test -n "$ac_init_help" && exit 0
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
aria2c configure 0.5.0 aria2c configure 0.5.1
generated by GNU Autoconf 2.59 generated by GNU Autoconf 2.59
Copyright (C) 2003 Free Software Foundation, Inc. Copyright (C) 2003 Free Software Foundation, Inc.
@ -1008,7 +1008,7 @@ cat >&5 <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by aria2c $as_me 0.5.0, which was It was created by aria2c $as_me 0.5.1, which was
generated by GNU Autoconf 2.59. Invocation command line was generated by GNU Autoconf 2.59. Invocation command line was
$ $0 $@ $ $0 $@
@ -1651,7 +1651,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='aria2c' PACKAGE='aria2c'
VERSION='0.5.0' VERSION='0.5.1'
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@ -11528,7 +11528,7 @@ _ASBOX
} >&5 } >&5
cat >&5 <<_CSEOF cat >&5 <<_CSEOF
This file was extended by aria2c $as_me 0.5.0, which was This file was extended by aria2c $as_me 0.5.1, which was
generated by GNU Autoconf 2.59. Invocation command line was generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -11591,7 +11591,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\ ac_cs_version="\\
aria2c config.status 0.5.0 aria2c config.status 0.5.1
configured by $0, generated by GNU Autoconf 2.59, configured by $0, generated by GNU Autoconf 2.59,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"

View File

@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
# #
AC_PREREQ(2.59) AC_PREREQ(2.59)
AC_INIT(aria2c, 0.5.0, tujikawa@rednoah.com) AC_INIT(aria2c, 0.5.1, tujikawa@rednoah.com)
AM_INIT_AUTOMAKE() AM_INIT_AUTOMAKE()
AM_PATH_CPPUNIT(1.10.2) AM_PATH_CPPUNIT(1.10.2)
AC_CONFIG_SRCDIR([src/Socket.h]) AC_CONFIG_SRCDIR([src/Socket.h])

View File

@ -9,7 +9,7 @@
# General Public License and is *not* in the public domain. # General Public License and is *not* in the public domain.
PACKAGE = aria2c PACKAGE = aria2c
VERSION = 0.5.0 VERSION = 0.5.1
SHELL = /bin/sh SHELL = /bin/sh

View File

@ -27,7 +27,6 @@
#include "message.h" #include "message.h"
#include "SleepCommand.h" #include "SleepCommand.h"
#include "prefs.h" #include "prefs.h"
#include <sys/time.h>
AbstractCommand::AbstractCommand(int cuid, Request* req, DownloadEngine* e, const Socket* s): AbstractCommand::AbstractCommand(int cuid, Request* req, DownloadEngine* e, const Socket* s):
Command(cuid), req(req), e(e), checkSocketIsReadable(false), checkSocketIsWritable(false) { Command(cuid), req(req), e(e), checkSocketIsReadable(false), checkSocketIsWritable(false) {
@ -38,8 +37,7 @@ AbstractCommand::AbstractCommand(int cuid, Request* req, DownloadEngine* e, cons
} else { } else {
socket = NULL; socket = NULL;
} }
this->checkPoint.tv_sec = 0; timeout = this->e->option->getAsInt(PREF_TIMEOUT);
this->checkPoint.tv_usec = 0;
} }
AbstractCommand::~AbstractCommand() { AbstractCommand::~AbstractCommand() {
@ -50,33 +48,12 @@ AbstractCommand::~AbstractCommand() {
} }
} }
void AbstractCommand::updateCheckPoint() {
gettimeofday(&checkPoint, NULL);
}
bool AbstractCommand::isTimeoutDetected() {
struct timeval now;
gettimeofday(&now, NULL);
if(checkPoint.tv_sec == 0 && checkPoint.tv_usec == 0) {
checkPoint = now;
return false;
} else {
int elapsed = Util::difftvsec(now, checkPoint);
if(elapsed >= e->option->getAsInt(PREF_TIMEOUT)) {
return true;
} else {
return false;
}
}
}
bool AbstractCommand::execute() { bool AbstractCommand::execute() {
try { try {
if(checkSocketIsReadable && readCheckTarget->isReadable(0) || if(checkSocketIsReadable && readCheckTarget->isReadable(0) ||
checkSocketIsWritable && writeCheckTarget->isWritable(0) || checkSocketIsWritable && writeCheckTarget->isWritable(0) ||
!checkSocketIsReadable && !checkSocketIsWritable) { !checkSocketIsReadable && !checkSocketIsWritable) {
checkPoint.reset();
updateCheckPoint();
Segment seg = { 0, 0, 0, false }; Segment seg = { 0, 0, 0, false };
if(e->segmentMan->downloadStarted) { if(e->segmentMan->downloadStarted) {
// get segment information in order to set Range header. // get segment information in order to set Range header.
@ -88,7 +65,7 @@ bool AbstractCommand::execute() {
} }
return executeInternal(seg); return executeInternal(seg);
} else { } else {
if(isTimeoutDetected()) { if(checkPoint.elapsed(timeout)) {
throw new DlRetryEx(EX_TIME_OUT); throw new DlRetryEx(EX_TIME_OUT);
} }
e->commands.push_back(this); e->commands.push_back(this);
@ -99,6 +76,7 @@ bool AbstractCommand::execute() {
onAbort(err); onAbort(err);
delete(err); delete(err);
req->resetUrl(); req->resetUrl();
e->segmentMan->errors++;
return true; return true;
} catch(DlRetryEx* err) { } catch(DlRetryEx* err) {
logger->error(MSG_RESTARTING_DOWNLOAD, err, cuid); logger->error(MSG_RESTARTING_DOWNLOAD, err, cuid);
@ -111,6 +89,7 @@ bool AbstractCommand::execute() {
delete(err); delete(err);
if(isAbort) { if(isAbort) {
logger->error(MSG_MAX_TRY, cuid, req->getTryCount()); logger->error(MSG_MAX_TRY, cuid, req->getTryCount());
e->segmentMan->errors++;
return true; return true;
} else { } else {
return prepareForRetry(e->option->getAsInt(PREF_RETRY_WAIT)); return prepareForRetry(e->option->getAsInt(PREF_RETRY_WAIT));

View File

@ -26,13 +26,12 @@
#include "Request.h" #include "Request.h"
#include "DownloadEngine.h" #include "DownloadEngine.h"
#include "SegmentMan.h" #include "SegmentMan.h"
#include <sys/time.h> #include "Time.h"
class AbstractCommand : public Command { class AbstractCommand : public Command {
private: private:
void updateCheckPoint(); Time checkPoint;
bool isTimeoutDetected(); int timeout;
struct timeval checkPoint;
protected: protected:
Request* req; Request* req;
DownloadEngine* e; DownloadEngine* e;
@ -44,6 +43,7 @@ protected:
void setReadCheckSocket(Socket* socket); void setReadCheckSocket(Socket* socket);
void setWriteCheckSocket(Socket* socket); void setWriteCheckSocket(Socket* socket);
void setTimeout(int timeout) { this->timeout = timeout; }
private: private:
bool checkSocketIsReadable; bool checkSocketIsReadable;
bool checkSocketIsWritable; bool checkSocketIsWritable;

View File

@ -40,14 +40,14 @@ void ConsoleDownloadEngine::sendStatistics(long long int currentSize, long long
} }
void ConsoleDownloadEngine::initStatistics() { void ConsoleDownloadEngine::initStatistics() {
cp.tv_sec = cp.tv_usec = 0; cp.reset();
startup.reset();
speed = 0; speed = 0;
psize = 0; psize = 0;
avgSpeed = 0; avgSpeed = 0;
eta = 0; eta = 0;
startupLength = 0; startupLength = 0;
isStartupLengthSet = false; isStartupLengthSet = false;
gettimeofday(&startup, NULL);
} }
void ConsoleDownloadEngine::calculateStatistics() { void ConsoleDownloadEngine::calculateStatistics() {
@ -56,28 +56,24 @@ void ConsoleDownloadEngine::calculateStatistics() {
startupLength = dlSize; startupLength = dlSize;
isStartupLengthSet = true; isStartupLengthSet = true;
} }
struct timeval now; int elapsed = cp.difference();
gettimeofday(&now, NULL); if(elapsed >= 1) {
if(cp.tv_sec == 0 && cp.tv_usec == 0) { int nspeed = (int)((dlSize-psize)/elapsed);
cp = now; speed = (nspeed+speed)/2;
cp.reset();
psize = dlSize; psize = dlSize;
} else {
int elapsed = Util::difftvsec(now, cp);
if(elapsed >= 1) {
int nspeed = (int)((dlSize-psize)/elapsed);
speed = (nspeed+speed)/2;
cp = now;
psize = dlSize;
avgSpeed = (int)((dlSize-startupLength)/Util::difftvsec(now, startup)); int elapsedFromStartup = startup.difference();
if(avgSpeed < 0) { if(elapsedFromStartup > 0) {
avgSpeed = 0; avgSpeed = (int)((dlSize-startupLength)/elapsedFromStartup);
} else if(avgSpeed != 0 && segmentMan->totalSize > 0) {
eta = (segmentMan->totalSize-dlSize)/avgSpeed;
}
sendStatistics(dlSize, segmentMan->totalSize);
} }
if(avgSpeed < 0) {
avgSpeed = 0;
} else if(avgSpeed != 0 && segmentMan->totalSize > 0) {
eta = (segmentMan->totalSize-dlSize)/avgSpeed;
}
sendStatistics(dlSize, segmentMan->totalSize);
} }
} }

View File

@ -23,14 +23,15 @@
#define _D_CONSOLE_DOWNLOAD_ENGINE_H_ #define _D_CONSOLE_DOWNLOAD_ENGINE_H_
#include "DownloadEngine.h" #include "DownloadEngine.h"
#include "Time.h"
class ConsoleDownloadEngine : public DownloadEngine { class ConsoleDownloadEngine : public DownloadEngine {
private: private:
struct timeval cp; Time cp;
long long int psize; long long int psize;
int speed; int speed;
// The time when startup // The time when startup
struct timeval startup; Time startup;
// The number of bytes downloaded at startup // The number of bytes downloaded at startup
long long int startupLength; long long int startupLength;
bool isStartupLengthSet; bool isStartupLengthSet;

View File

@ -27,10 +27,7 @@
#include "InitiateConnectionCommandFactory.h" #include "InitiateConnectionCommandFactory.h"
#include "message.h" #include "message.h"
DownloadCommand::DownloadCommand(int cuid, Request* req, DownloadEngine* e, const Socket* s):AbstractCommand(cuid, req, e, s), lastSize(0) { DownloadCommand::DownloadCommand(int cuid, Request* req, DownloadEngine* e, const Socket* s):AbstractCommand(cuid, req, e, s), lastSize(0) {}
sw.tv_sec = 0;
sw.tv_usec = 0;
}
DownloadCommand::~DownloadCommand() {} DownloadCommand::~DownloadCommand() {}
@ -54,18 +51,11 @@ bool DownloadCommand::executeInternal(Segment seg) {
seg.ds += bufSize; seg.ds += bufSize;
} }
// calculate downloading speed // calculate downloading speed
struct timeval now; int diff = sw.difference();
gettimeofday(&now, NULL); if(diff >= 1) {
if(sw.tv_sec == 0 && sw.tv_usec == 0) { seg.speed = (int)((seg.ds-lastSize)/(diff*1.0));
sw = now; sw.reset();
lastSize = seg.ds; lastSize = seg.ds;
} else {
int diff = Util::difftvsec(now, sw);
if(diff >= 1) {
seg.speed = (int)((seg.ds-lastSize)/(diff*1.0));
sw = now;
lastSize = seg.ds;
}
} }
if(e->segmentMan->totalSize != 0 && bufSize == 0) { if(e->segmentMan->totalSize != 0 && bufSize == 0) {
throw new DlRetryEx(EX_GOT_EOF); throw new DlRetryEx(EX_GOT_EOF);

View File

@ -24,14 +24,13 @@
#include "AbstractCommand.h" #include "AbstractCommand.h"
#include "TransferEncoding.h" #include "TransferEncoding.h"
#include <sys/time.h> #include "Time.h"
#include <string>
using namespace std; using namespace std;
class DownloadCommand : public AbstractCommand { class DownloadCommand : public AbstractCommand {
private: private:
struct timeval sw; Time sw;
long long int lastSize; long long int lastSize;
protected: protected:
bool executeInternal(Segment segment); bool executeInternal(Segment segment);

View File

@ -22,6 +22,7 @@
#include "DownloadEngine.h" #include "DownloadEngine.h"
#include "Util.h" #include "Util.h"
#include "LogFactory.h" #include "LogFactory.h"
#include "Time.h"
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -48,15 +49,11 @@ void DownloadEngine::cleanQueue() {
void DownloadEngine::run() { void DownloadEngine::run() {
initStatistics(); initStatistics();
struct timeval cp; Time cp;
cp.tv_sec = 0;
cp.tv_usec = 0;
Sockets activeSockets; Sockets activeSockets;
while(!commands.empty()) { while(!commands.empty()) {
struct timeval now; if(cp.elapsed(1)) {
gettimeofday(&now, NULL); cp.reset();
if(Util::difftvsec(now, cp) >= 1) {
cp = now;
int max = commands.size(); int max = commands.size();
for(int i = 0; i < max; i++) { for(int i = 0; i < max; i++) {
Command* com = commands.front(); Command* com = commands.front();

View File

@ -28,8 +28,6 @@
#include "common.h" #include "common.h"
#include "Logger.h" #include "Logger.h"
#include "Option.h" #include "Option.h"
#include <sys/time.h>
#include <deque>
typedef deque<Socket*> Sockets; typedef deque<Socket*> Sockets;
typedef deque<Command*> Commands; typedef deque<Command*> Commands;

View File

@ -101,7 +101,8 @@ SRCS = Socket.cc Socket.h\
AllowedFastMessage.cc AllowedFastMessage.h\ AllowedFastMessage.cc AllowedFastMessage.h\
SuggestPieceMessage.cc SuggestPieceMessage.h\ SuggestPieceMessage.cc SuggestPieceMessage.h\
SimplePeerMessage.cc SimplePeerMessage.h\ SimplePeerMessage.cc SimplePeerMessage.h\
NullLogger.h NullLogger.h\
Time.cc Time.h
noinst_LIBRARIES = libaria2c.a noinst_LIBRARIES = libaria2c.a
libaria2c_a_SOURCES = $(SRCS) libaria2c_a_SOURCES = $(SRCS)
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\

View File

@ -109,7 +109,7 @@ am__objects_1 = Socket.$(OBJEXT) SocketCore.$(OBJEXT) \
PortMessage.$(OBJEXT) HaveAllMessage.$(OBJEXT) \ PortMessage.$(OBJEXT) HaveAllMessage.$(OBJEXT) \
HaveNoneMessage.$(OBJEXT) RejectMessage.$(OBJEXT) \ HaveNoneMessage.$(OBJEXT) RejectMessage.$(OBJEXT) \
AllowedFastMessage.$(OBJEXT) SuggestPieceMessage.$(OBJEXT) \ AllowedFastMessage.$(OBJEXT) SuggestPieceMessage.$(OBJEXT) \
SimplePeerMessage.$(OBJEXT) SimplePeerMessage.$(OBJEXT) Time.$(OBJEXT)
am_libaria2c_a_OBJECTS = $(am__objects_1) am_libaria2c_a_OBJECTS = $(am__objects_1)
libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS) libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
am__installdirs = "$(DESTDIR)$(bindir)" am__installdirs = "$(DESTDIR)$(bindir)"
@ -360,7 +360,8 @@ SRCS = Socket.cc Socket.h\
AllowedFastMessage.cc AllowedFastMessage.h\ AllowedFastMessage.cc AllowedFastMessage.h\
SuggestPieceMessage.cc SuggestPieceMessage.h\ SuggestPieceMessage.cc SuggestPieceMessage.h\
SimplePeerMessage.cc SimplePeerMessage.h\ SimplePeerMessage.cc SimplePeerMessage.h\
NullLogger.h NullLogger.h\
Time.cc Time.h
noinst_LIBRARIES = libaria2c.a noinst_LIBRARIES = libaria2c.a
libaria2c_a_SOURCES = $(SRCS) libaria2c_a_SOURCES = $(SRCS)
@ -525,6 +526,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SplitFirstSegmentSplitter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SplitFirstSegmentSplitter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SplitSlowestSegmentSplitter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SplitSlowestSegmentSplitter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SuggestPieceMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SuggestPieceMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Time.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentAutoSaveCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentAutoSaveCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentConsoleDownloadEngine.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentConsoleDownloadEngine.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentDownloadEngine.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentDownloadEngine.Po@am__quote@

View File

@ -59,6 +59,7 @@ void Peer::resetStatus() {
resetDeltaDownload(); resetDeltaDownload();
chokingRequired = true; chokingRequired = true;
optUnchoking = false; optUnchoking = false;
snubbing = false;
fastExtensionEnabled = false; fastExtensionEnabled = false;
latency = DEFAULT_LATENCY; latency = DEFAULT_LATENCY;
fastSet.clear(); fastSet.clear();

View File

@ -46,6 +46,7 @@ public:
int cuid; int cuid;
bool chokingRequired; bool chokingRequired;
bool optUnchoking; bool optUnchoking;
bool snubbing;
private: private:
char peerId[PEER_ID_LENGTH]; char peerId[PEER_ID_LENGTH];
BitfieldMan* bitfield; BitfieldMan* bitfield;
@ -65,6 +66,7 @@ public:
peerChoking(true), peerInterested(false), peerChoking(true), peerInterested(false),
tryCount(0), error(0), cuid(0), tryCount(0), error(0), cuid(0),
chokingRequired(true), optUnchoking(false), chokingRequired(true), optUnchoking(false),
snubbing(false),
bitfield(NULL), bitfield(NULL),
fastExtensionEnabled(false), fastExtensionEnabled(false),
peerUpload(0), peerDownload(0), peerUpload(0), peerDownload(0),
@ -107,8 +109,8 @@ public:
void setAllBitfield(); void setAllBitfield();
/** /**
* operation = 1: set index-th bit 1 * operation = 1: set index-th bit to 1
* operation = 0: set index-th bit 0 * operation = 0: set index-th bit to 0
*/ */
void updateBitfield(int index, int operation); void updateBitfield(int index, int operation);

View File

@ -25,7 +25,6 @@
#include "Util.h" #include "Util.h"
#include "message.h" #include "message.h"
#include "prefs.h" #include "prefs.h"
#include <sys/time.h>
PeerAbstractCommand::PeerAbstractCommand(int cuid, Peer* peer, TorrentDownloadEngine* e, const Socket* s): PeerAbstractCommand::PeerAbstractCommand(int cuid, Peer* peer, TorrentDownloadEngine* e, const Socket* s):
Command(cuid), e(e), peer(peer), Command(cuid), e(e), peer(peer),
@ -38,8 +37,6 @@ PeerAbstractCommand::PeerAbstractCommand(int cuid, Peer* peer, TorrentDownloadEn
} else { } else {
socket = NULL; socket = NULL;
} }
this->checkPoint.tv_sec = 0;
this->checkPoint.tv_usec = 0;
timeout = e->option->getAsInt(PREF_TIMEOUT); timeout = e->option->getAsInt(PREF_TIMEOUT);
e->torrentMan->connections++; e->torrentMan->connections++;
} }
@ -53,26 +50,6 @@ PeerAbstractCommand::~PeerAbstractCommand() {
e->torrentMan->connections--; e->torrentMan->connections--;
} }
void PeerAbstractCommand::updateCheckPoint() {
gettimeofday(&checkPoint, NULL);
}
bool PeerAbstractCommand::isTimeoutDetected() {
struct timeval now;
gettimeofday(&now, NULL);
if(checkPoint.tv_sec == 0 && checkPoint.tv_usec == 0) {
checkPoint = now;
return false;
} else {
int elapsed = Util::difftvsec(now, checkPoint);
if(elapsed >= timeout) {
return true;
} else {
return false;
}
}
}
bool PeerAbstractCommand::execute() { bool PeerAbstractCommand::execute() {
if(e->torrentMan->isHalt()) { if(e->torrentMan->isHalt()) {
return true; return true;
@ -82,12 +59,9 @@ bool PeerAbstractCommand::execute() {
e->getUploadSpeed() <= uploadLimit*1024) || e->getUploadSpeed() <= uploadLimit*1024) ||
checkSocketIsReadable && readCheckTarget->isReadable(0) || checkSocketIsReadable && readCheckTarget->isReadable(0) ||
checkSocketIsWritable && writeCheckTarget->isWritable(0)) { checkSocketIsWritable && writeCheckTarget->isWritable(0)) {
updateCheckPoint(); checkPoint.reset();
} }
if(isTimeoutDetected()) { if(checkPoint.elapsed(timeout)) {
// TODO following 2 lines will be deleted.
checkPoint.tv_sec = 0;
checkPoint.tv_usec = 0;
throw new DlRetryEx(EX_TIME_OUT); throw new DlRetryEx(EX_TIME_OUT);
} }
return executeInternal(); return executeInternal();

View File

@ -25,13 +25,11 @@
#include "Command.h" #include "Command.h"
#include "Request.h" #include "Request.h"
#include "TorrentDownloadEngine.h" #include "TorrentDownloadEngine.h"
#include <sys/time.h> #include "Time.h"
class PeerAbstractCommand : public Command { class PeerAbstractCommand : public Command {
private: private:
void updateCheckPoint(); Time checkPoint;
bool isTimeoutDetected();
struct timeval checkPoint;
int timeout; int timeout;
protected: protected:
TorrentDownloadEngine* e; TorrentDownloadEngine* e;

View File

@ -22,10 +22,7 @@
#include "PeerChokeCommand.h" #include "PeerChokeCommand.h"
#include "Util.h" #include "Util.h"
PeerChokeCommand::PeerChokeCommand(int cuid, int interval, TorrentDownloadEngine* e):Command(cuid), interval(interval), e(e), rotate(0) { PeerChokeCommand::PeerChokeCommand(int cuid, int interval, TorrentDownloadEngine* e):Command(cuid), interval(interval), e(e), rotate(0) {}
checkPoint.tv_sec = 0;
checkPoint.tv_usec = 0;
}
PeerChokeCommand::~PeerChokeCommand() {} PeerChokeCommand::~PeerChokeCommand() {}
@ -41,23 +38,16 @@ void PeerChokeCommand::optUnchokingPeer(Peers& peers) const {
return; return;
} }
random_shuffle(peers.begin(), peers.end()); random_shuffle(peers.begin(), peers.end());
int optUnchokCount = 1;
for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) { for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
(*itr)->optUnchoking = false; Peers::value_type peer = *itr;
} if(optUnchokCount > 0 && !peer->snubbing) {
Peer* peer = peers.front(); optUnchokCount--;
peer->optUnchoking = true; peer->optUnchoking = true;
logger->debug("opt, unchoking %s, delta=%d", logger->debug("opt, unchoking %s, delta=%d",
peer->ipaddr.c_str(), peer->getDeltaUpload()); peer->ipaddr.c_str(), peer->getDeltaUpload());
if(e->torrentMan->isEndGame()) { } else {
Peers::iterator itr = peers.begin()+1; peer->optUnchoking = false;
for(; itr != peers.end(); itr++) {
Peer* peer = *itr;
if(peer->amInterested && peer->peerInterested) {
peer->optUnchoking = true;
logger->debug("opt, unchoking %s, delta=%d",
peer->ipaddr.c_str(), peer->getDeltaUpload());
break;
}
} }
} }
} }
@ -96,10 +86,8 @@ bool PeerChokeCommand::execute() {
if(e->torrentMan->isHalt()) { if(e->torrentMan->isHalt()) {
return true; return true;
} }
struct timeval now; if(checkPoint.elapsed(interval)) {
gettimeofday(&now, NULL); checkPoint.reset();
if(Util::difftvsec(now, checkPoint) >= interval) {
checkPoint = now;
Peers peers = e->torrentMan->getActivePeers(); Peers peers = e->torrentMan->getActivePeers();
setAllPeerChoked(peers); setAllPeerChoked(peers);
if(e->torrentMan->downloadComplete()) { if(e->torrentMan->downloadComplete()) {
@ -107,14 +95,14 @@ bool PeerChokeCommand::execute() {
} else { } else {
orderByUploadRate(peers); orderByUploadRate(peers);
} }
int unchokingCount = peers.size() >= 4 ? 4 : peers.size(); int unchokingCount = 4;//peers.size() >= 4 ? 4 : peers.size();
for(Peers::iterator itr = peers.begin(); unchokingCount > 0 && itr != peers.end(); ) { for(Peers::iterator itr = peers.begin(); itr != peers.end() && unchokingCount > 0; ) {
Peer* peer = *itr; Peer* peer = *itr;
if(peer->peerInterested) { if(peer->peerInterested && !peer->snubbing) {
unchokingCount--;
peer->chokingRequired = false; peer->chokingRequired = false;
peer->optUnchoking = false; peer->optUnchoking = false;
itr = peers.erase(itr); itr = peers.erase(itr);
unchokingCount--;
logger->debug("cat01, unchoking %s, delta=%d", peer->ipaddr.c_str(), peer->getDeltaUpload()); logger->debug("cat01, unchoking %s, delta=%d", peer->ipaddr.c_str(), peer->getDeltaUpload());
} else { } else {
itr++; itr++;
@ -122,7 +110,7 @@ bool PeerChokeCommand::execute() {
} }
for(Peers::iterator itr = peers.begin(); itr != peers.end(); ) { for(Peers::iterator itr = peers.begin(); itr != peers.end(); ) {
Peer* peer = *itr; Peer* peer = *itr;
if(!peer->peerInterested) { if(!peer->peerInterested && !peer->snubbing) {
peer->chokingRequired = false; peer->chokingRequired = false;
peer->optUnchoking = false; peer->optUnchoking = false;
itr = peers.erase(itr); itr = peers.erase(itr);

View File

@ -24,13 +24,14 @@
#include "Command.h" #include "Command.h"
#include "TorrentDownloadEngine.h" #include "TorrentDownloadEngine.h"
#include "Time.h"
class PeerChokeCommand : public Command { class PeerChokeCommand : public Command {
private: private:
int interval; int interval;
TorrentDownloadEngine* e; TorrentDownloadEngine* e;
int rotate; int rotate;
struct timeval checkPoint; Time checkPoint;
void orderByUploadRate(Peers& peers) const; void orderByUploadRate(Peers& peers) const;
void orderByDownloadRate(Peers& peers) const; void orderByDownloadRate(Peers& peers) const;

View File

@ -231,6 +231,7 @@ void PeerInteraction::checkRequestSlot() {
Piece& piece = getDownloadPiece(slot.getIndex()); Piece& piece = getDownloadPiece(slot.getIndex());
piece.cancelBlock(slot.getBlockIndex()); piece.cancelBlock(slot.getBlockIndex());
itr = requestSlots.erase(itr); itr = requestSlots.erase(itr);
peer->snubbing = true;
} else { } else {
Piece piece = getDownloadPiece(slot.getIndex()); Piece piece = getDownloadPiece(slot.getIndex());
if(piece.hasBlock(slot.getBlockIndex()) || if(piece.hasBlock(slot.getBlockIndex()) ||

View File

@ -43,7 +43,7 @@
#include "SuggestPieceMessage.h" #include "SuggestPieceMessage.h"
#include "RequestSlot.h" #include "RequestSlot.h"
#define REQUEST_TIME_OUT 120 #define REQUEST_TIME_OUT 60
#define ALLOWED_FAST_SET_SIZE 10 #define ALLOWED_FAST_SET_SIZE 10
typedef deque<RequestSlot> RequestSlots; typedef deque<RequestSlot> RequestSlots;

View File

@ -41,12 +41,6 @@ PeerInteractionCommand::PeerInteractionCommand(int cuid, Peer* peer,
e->torrentMan, this->peer); e->torrentMan, this->peer);
peerInteraction->setUploadLimit(e->option->getAsInt(PREF_UPLOAD_LIMIT)); peerInteraction->setUploadLimit(e->option->getAsInt(PREF_UPLOAD_LIMIT));
setUploadLimit(e->option->getAsInt(PREF_UPLOAD_LIMIT)); setUploadLimit(e->option->getAsInt(PREF_UPLOAD_LIMIT));
keepAliveCheckPoint.tv_sec = 0;
keepAliveCheckPoint.tv_usec = 0;
chokeCheckPoint.tv_sec = 0;
chokeCheckPoint.tv_usec = 0;
freqCheckPoint.tv_sec = 0;
freqCheckPoint.tv_usec = 0;
chokeUnchokeCount = 0; chokeUnchokeCount = 0;
haveCount = 0; haveCount = 0;
keepAliveCount = 0; keepAliveCount = 0;
@ -55,7 +49,6 @@ PeerInteractionCommand::PeerInteractionCommand(int cuid, Peer* peer,
PeerInteractionCommand::~PeerInteractionCommand() { PeerInteractionCommand::~PeerInteractionCommand() {
delete peerInteraction; delete peerInteraction;
e->torrentMan->unadvertisePiece(cuid);
e->torrentMan->deleteActivePeer(this->peer); e->torrentMan->deleteActivePeer(this->peer);
} }
@ -89,6 +82,7 @@ bool PeerInteractionCommand::executeInternal() {
peer->ipaddr.c_str(), peer->port, peer->ipaddr.c_str(), peer->port,
handshakeMessage->toString().c_str()); handshakeMessage->toString().c_str());
delete handshakeMessage; delete handshakeMessage;
haveCheckTime.reset();
peerInteraction->sendBitfield(); peerInteraction->sendBitfield();
peerInteraction->sendAllowedFast(); peerInteraction->sendAllowedFast();
sequence = WIRED; sequence = WIRED;
@ -105,6 +99,7 @@ bool PeerInteractionCommand::executeInternal() {
handshakeMessage->toString().c_str()); handshakeMessage->toString().c_str());
delete handshakeMessage; delete handshakeMessage;
peerInteraction->sendHandshake(); peerInteraction->sendHandshake();
haveCheckTime.reset();
peerInteraction->sendBitfield(); peerInteraction->sendBitfield();
peerInteraction->sendAllowedFast(); peerInteraction->sendAllowedFast();
sequence = WIRED; sequence = WIRED;
@ -134,24 +129,19 @@ bool PeerInteractionCommand::executeInternal() {
return false; return false;
} }
#define FLOODING_CHECK_INTERVAL 5
void PeerInteractionCommand::detectMessageFlooding() { void PeerInteractionCommand::detectMessageFlooding() {
struct timeval now; if(freqCheckPoint.elapsed(FLOODING_CHECK_INTERVAL)) {
gettimeofday(&now, NULL); if(chokeUnchokeCount*1.0/FLOODING_CHECK_INTERVAL >= 0.4
if(freqCheckPoint.tv_sec == 0 && freqCheckPoint.tv_usec == 0) { //|| haveCount*1.0/elapsed >= 20.0
freqCheckPoint = now; || keepAliveCount*1.0/FLOODING_CHECK_INTERVAL >= 1.0) {
} else { throw new DlAbortEx("Flooding detected.");
int elapsed = Util::difftvsec(now, freqCheckPoint); } else {
if(elapsed >= 5) { chokeUnchokeCount = 0;
if(chokeUnchokeCount*1.0/elapsed >= 0.4 haveCount = 0;
//|| haveCount*1.0/elapsed >= 20.0 keepAliveCount = 0;
|| keepAliveCount*1.0/elapsed >= 1.0) { freqCheckPoint.reset();
throw new DlAbortEx("Flooding detected.");
} else {
chokeUnchokeCount = 0;
haveCount = 0;
keepAliveCount = 0;
freqCheckPoint = now;
}
} }
} }
} }
@ -160,21 +150,13 @@ void PeerInteractionCommand::checkLongTimePeerChoking() {
if(e->torrentMan->downloadComplete()) { if(e->torrentMan->downloadComplete()) {
return; return;
} }
struct timeval now; if(peer->amInterested && peer->peerChoking) {
gettimeofday(&now, NULL); if(chokeCheckPoint.elapsed(MAX_PEER_CHOKING_INTERVAL)) {
if(chokeCheckPoint.tv_sec == 0 && chokeCheckPoint.tv_usec == 0) { logger->info("CUID#%d - The peer is choking too long.", cuid);
if(peer->amInterested && peer->peerChoking) { peer->snubbing = true;
chokeCheckPoint = now;
} }
} else { } else {
if(peer->amInterested && peer->peerChoking) { chokeCheckPoint.reset();
if(Util::difftvsec(now, chokeCheckPoint) >= MAX_PEER_CHOKING_INTERVAL) {
throw new DlAbortEx("Too long choking.");
}
} else {
chokeCheckPoint.tv_sec = 0;
chokeCheckPoint.tv_usec = 0;
}
} }
} }
@ -251,24 +233,19 @@ void PeerInteractionCommand::onAbort(Exception* ex) {
} }
void PeerInteractionCommand::sendKeepAlive() { void PeerInteractionCommand::sendKeepAlive() {
if(keepAliveCheckPoint.tv_sec == 0 && keepAliveCheckPoint.tv_usec == 0) { if(keepAliveCheckPoint.elapsed(KEEP_ALIVE_INTERVAL)) {
gettimeofday(&keepAliveCheckPoint, NULL); if(peerInteraction->countMessageInQueue() == 0) {
} else { peerInteraction->addMessage(peerInteraction->createKeepAliveMessage());
struct timeval now; peerInteraction->sendMessages(e->getUploadSpeed());
gettimeofday(&now, NULL);
if(Util::difftvsec(now, keepAliveCheckPoint) >= 120) {
if(peerInteraction->countMessageInQueue() == 0) {
peerInteraction->addMessage(peerInteraction->createKeepAliveMessage());
peerInteraction->sendMessages(e->getUploadSpeed());
}
keepAliveCheckPoint = now;
} }
keepAliveCheckPoint.reset();
} }
} }
void PeerInteractionCommand::checkHave() { void PeerInteractionCommand::checkHave() {
e->torrentMan->unadvertisePiece(cuid); PieceIndexes indexes =
PieceIndexes indexes = e->torrentMan->getAdvertisedPieceIndexes(cuid); e->torrentMan->getAdvertisedPieceIndexes(cuid, haveCheckTime);
haveCheckTime.reset();
if(indexes.size() >= 20) { if(indexes.size() >= 20) {
if(peer->isFastExtensionEnabled()) { if(peer->isFastExtensionEnabled()) {
if(e->torrentMan->hasAllPieces()) { if(e->torrentMan->hasAllPieces()) {

View File

@ -25,19 +25,22 @@
#include "PeerAbstractCommand.h" #include "PeerAbstractCommand.h"
#include "PeerConnection.h" #include "PeerConnection.h"
#include "PeerInteraction.h" #include "PeerInteraction.h"
#include "Time.h"
using namespace std; using namespace std;
#define MAX_PEER_CHOKING_INTERVAL (3*60) #define MAX_PEER_CHOKING_INTERVAL (1*60)
#define KEEP_ALIVE_INTERVAL 120
class PeerInteractionCommand : public PeerAbstractCommand { class PeerInteractionCommand : public PeerAbstractCommand {
private: private:
int sequence; int sequence;
PeerInteraction* peerInteraction; PeerInteraction* peerInteraction;
struct timeval keepAliveCheckPoint; Time keepAliveCheckPoint;
struct timeval chokeCheckPoint; Time chokeCheckPoint;
struct timeval freqCheckPoint; Time freqCheckPoint;
Time haveCheckTime;
int chokeUnchokeCount; int chokeUnchokeCount;
int haveCount; int haveCount;
int keepAliveCount; int keepAliveCount;

View File

@ -59,6 +59,7 @@ void PieceMessage::receivedAction() {
peer->addPeerUpload(blockLength); peer->addPeerUpload(blockLength);
if(!RequestSlot::isNull(slot) && if(!RequestSlot::isNull(slot) &&
peerInteraction->hasDownloadPiece(slot.getIndex())) { peerInteraction->hasDownloadPiece(slot.getIndex())) {
peer->snubbing = false;
//logger->debug("CUID#%d - Latency=%d", cuid, slot.getLatencyInMillis()); //logger->debug("CUID#%d - Latency=%d", cuid, slot.getLatencyInMillis());
peer->updateLatency(slot.getLatencyInMillis()); peer->updateLatency(slot.getLatencyInMillis());
Piece& piece = peerInteraction->getDownloadPiece(slot.getIndex()); Piece& piece = peerInteraction->getDownloadPiece(slot.getIndex());

View File

@ -23,9 +23,7 @@
#include "Util.h" #include "Util.h"
RequestSlot::RequestSlot(int index, int begin, int length, int blockIndex) RequestSlot::RequestSlot(int index, int begin, int length, int blockIndex)
:index(index), begin(begin), length(length), blockIndex(blockIndex) { :index(index), begin(begin), length(length), blockIndex(blockIndex) {}
setDispatchedTime();
}
RequestSlot::RequestSlot(const RequestSlot& requestSlot) { RequestSlot::RequestSlot(const RequestSlot& requestSlot) {
copy(requestSlot); copy(requestSlot);
@ -49,17 +47,15 @@ void RequestSlot::copy(const RequestSlot& requestSlot) {
RequestSlot RequestSlot::nullSlot(0, 0, 0, 0); RequestSlot RequestSlot::nullSlot(0, 0, 0, 0);
void RequestSlot::setDispatchedTime() { void RequestSlot::setDispatchedTime() {
gettimeofday(&dispatchedTime, NULL); dispatchedTime.reset();
} }
bool RequestSlot::isTimeout(int timeoutSec) const { bool RequestSlot::isTimeout(int timeoutSec) const {
return getLatencyInMillis() > timeoutSec*1000; return dispatchedTime.differenceInMillis() > timeoutSec*1000;
} }
int RequestSlot::getLatencyInMillis() const { int RequestSlot::getLatencyInMillis() const {
struct timeval now; return dispatchedTime.differenceInMillis();
gettimeofday(&now, NULL);
return Util::difftv(now, dispatchedTime)/1000;
} }
bool RequestSlot::isNull(const RequestSlot& requestSlot) { bool RequestSlot::isNull(const RequestSlot& requestSlot) {

View File

@ -23,11 +23,11 @@
#define _D_REQUEST_SLOT_H_ #define _D_REQUEST_SLOT_H_
#include "common.h" #include "common.h"
#include <sys/time.h> #include "Time.h"
class RequestSlot { class RequestSlot {
private: private:
struct timeval dispatchedTime; Time dispatchedTime;
int index; int index;
int begin; int begin;
int length; int length;

View File

@ -34,6 +34,7 @@
SegmentMan::SegmentMan():totalSize(0), SegmentMan::SegmentMan():totalSize(0),
isSplittable(true), isSplittable(true),
downloadStarted(false), downloadStarted(false),
errors(0),
dir("."), dir("."),
splitter(NULL), splitter(NULL),
diskWriter(NULL) { diskWriter(NULL) {
@ -241,6 +242,7 @@ void SegmentMan::init() {
totalSize = 0; totalSize = 0;
isSplittable = false; isSplittable = false;
downloadStarted = false; downloadStarted = false;
errors = 0;
segments.clear(); segments.clear();
diskWriter->closeFile(); diskWriter->closeFile();
} }

View File

@ -84,6 +84,11 @@ public:
*/ */
string ufilename; string ufilename;
/**
* Represents the number of failures(usually, DlAbortEx) in downloads.
*/
int errors;
const Option* option; const Option* option;
SegmentSplitter* splitter; SegmentSplitter* splitter;
DiskWriter* diskWriter; DiskWriter* diskWriter;
@ -91,7 +96,7 @@ public:
SegmentMan(); SegmentMan();
~SegmentMan(); ~SegmentMan();
// Initializes totalSize, isSplittable, downloadStarted. // Initializes totalSize, isSplittable, downloadStarted, errors.
// Clears command queue. Also, closes diskWriter. // Clears command queue. Also, closes diskWriter.
void init(); void init();

View File

@ -23,9 +23,7 @@
#include "Util.h" #include "Util.h"
SleepCommand::SleepCommand(int cuid, DownloadEngine* e, Command* nextCommand, int wait): SleepCommand::SleepCommand(int cuid, DownloadEngine* e, Command* nextCommand, int wait):
Command(cuid), engine(e), nextCommand(nextCommand), wait(wait) { Command(cuid), engine(e), nextCommand(nextCommand), wait(wait) {}
gettimeofday(&checkPoint, NULL);
}
SleepCommand::~SleepCommand() { SleepCommand::~SleepCommand() {
if(nextCommand != NULL) { if(nextCommand != NULL) {
@ -34,9 +32,7 @@ SleepCommand::~SleepCommand() {
} }
bool SleepCommand::execute() { bool SleepCommand::execute() {
struct timeval now; if(checkPoint.elapsed(wait)) {
gettimeofday(&now, NULL);
if(Util::difftvsec(now, checkPoint) >= wait) {
engine->commands.push_back(nextCommand); engine->commands.push_back(nextCommand);
nextCommand = NULL; nextCommand = NULL;
return true; return true;

View File

@ -24,14 +24,14 @@
#include "DownloadEngine.h" #include "DownloadEngine.h"
#include "Command.h" #include "Command.h"
#include <sys/time.h> #include "Time.h"
class SleepCommand:public Command { class SleepCommand:public Command {
private: private:
DownloadEngine* engine; DownloadEngine* engine;
Command* nextCommand; Command* nextCommand;
int wait; int wait;
struct timeval checkPoint; Time checkPoint;
public: public:
SleepCommand(int cuid, DownloadEngine* e, Command* nextCommand, int wait); SleepCommand(int cuid, DownloadEngine* e, Command* nextCommand, int wait);
~SleepCommand(); ~SleepCommand();

70
src/Time.cc Normal file
View File

@ -0,0 +1,70 @@
/* <!-- copyright */
/*
* aria2 - a simple utility for downloading files faster
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* copyright --> */
#include "Time.h"
#include "Util.h"
Time::Time() {
reset();
}
Time::Time(const Time& time) {
tv = time.tv;
}
Time::~Time() {}
Time& Time::operator=(const Time& time) {
if(this != &time) {
tv = time.tv;
}
return *this;
}
void Time::reset() {
gettimeofday(&tv, 0);
}
struct timeval Time::getCurrentTime() const {
struct timeval now;
gettimeofday(&now, 0);
return now;
}
bool Time::elapsed(int sec) const {
return Util::difftvsec(getCurrentTime(), tv) >= sec;
}
bool Time::elapsedInMillis(int millis) const {
return Util::difftv(getCurrentTime(), tv)/1000 >= millis;
}
bool Time::isNewer(const Time& time) const {
return Util::difftvsec(this->tv, time.tv) > 0;
}
int Time::difference() const {
return Util::difftvsec(getCurrentTime(), tv);
}
long long int Time::differenceInMillis() const {
return Util::difftv(getCurrentTime(), tv)/1000;
}

71
src/Time.h Normal file
View File

@ -0,0 +1,71 @@
/* <!-- copyright */
/*
* aria2 - a simple utility for downloading files faster
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* copyright --> */
#ifndef _D_TIME_H_
#define _D_TIME_H_
#include "common.h"
#include <sys/time.h>
class Time {
private:
struct timeval tv;
struct timeval getCurrentTime() const;
public:
// The time value is initialized so that it represents the time at which
// this object was created.
Time();
Time(const Time& time);
Time& operator=(const Time& time);
~Time();
// Makes this object's time value up to date.
void reset();
bool elapsed(int sec) const;
bool elapsedInMillis(int millis) const;
int difference() const;
long long int differenceInMillis() const;
// Returns true if this object's time value is zero.
bool isZero() const { return tv.tv_sec == 0 && tv.tv_usec == 0; }
long long int getTimeInMicros() const {
return tv.tv_sec*1000*1000+tv.tv_usec;
}
long long int getTimeInMillis() const {
return tv.tv_sec*1000+tv.tv_usec/1000;
}
// Returns this object's time value in seconds.
int getTime() const {
return tv.tv_sec;
}
bool isNewer(const Time& time) const;
};
#endif // _D_TIME_H_

View File

@ -22,21 +22,13 @@
#include "TorrentAutoSaveCommand.h" #include "TorrentAutoSaveCommand.h"
#include "Util.h" #include "Util.h"
TorrentAutoSaveCommand::TorrentAutoSaveCommand(int cuid, TorrentDownloadEngine* e, int interval):Command(cuid), e(e), interval(interval) { TorrentAutoSaveCommand::TorrentAutoSaveCommand(int cuid, TorrentDownloadEngine* e, int interval):Command(cuid), e(e), interval(interval) {}
checkPoint.tv_sec = 0;
checkPoint.tv_usec = 0;
}
TorrentAutoSaveCommand::~TorrentAutoSaveCommand() {} TorrentAutoSaveCommand::~TorrentAutoSaveCommand() {}
bool TorrentAutoSaveCommand::execute() { bool TorrentAutoSaveCommand::execute() {
if(e->torrentMan->downloadComplete() || e->torrentMan->isHalt()) { if(checkPoint.elapsed(interval) || e->torrentMan->isHalt()) {
return true; checkPoint.reset();
}
struct timeval now;
gettimeofday(&now, NULL);
if(Util::difftvsec(now, checkPoint) >= interval) {
checkPoint = now;
e->torrentMan->save(); e->torrentMan->save();
if(e->torrentMan->isHalt()) { if(e->torrentMan->isHalt()) {
return true; return true;

View File

@ -24,12 +24,13 @@
#include "Command.h" #include "Command.h"
#include "TorrentDownloadEngine.h" #include "TorrentDownloadEngine.h"
#include "Time.h"
class TorrentAutoSaveCommand : public Command { class TorrentAutoSaveCommand : public Command {
private: private:
TorrentDownloadEngine* e; TorrentDownloadEngine* e;
int interval; int interval;
struct timeval checkPoint; Time checkPoint;
public: public:
TorrentAutoSaveCommand(int cuid, TorrentDownloadEngine* e, int interval); TorrentAutoSaveCommand(int cuid, TorrentDownloadEngine* e, int interval);
~TorrentAutoSaveCommand(); ~TorrentAutoSaveCommand();

View File

@ -57,9 +57,9 @@ void TorrentDownloadEngine::initStatistics() {
downloadSpeed = 0; downloadSpeed = 0;
uploadSpeed = 0; uploadSpeed = 0;
lastElapsed = 0; lastElapsed = 0;
gettimeofday(&cp[0], NULL); cp[0].reset();
gettimeofday(&cp[1], NULL); cp[1].reset();
gettimeofday(&startup, NULL); startup.reset();
sessionDownloadLengthArray[0] = 0; sessionDownloadLengthArray[0] = 0;
sessionDownloadLengthArray[1] = 0; sessionDownloadLengthArray[1] = 0;
sessionUploadLengthArray[0] = 0; sessionUploadLengthArray[0] = 0;
@ -82,9 +82,7 @@ int TorrentDownloadEngine::calculateSpeed(long long int sessionLength, int elaps
} }
void TorrentDownloadEngine::calculateStatistics() { void TorrentDownloadEngine::calculateStatistics() {
struct timeval now; int elapsed = cp[currentCp].difference();
gettimeofday(&now, NULL);
int elapsed = Util::difftvsec(now, cp[currentCp]);
sessionDownloadLengthArray[0] += torrentMan->getDeltaDownloadLength(); sessionDownloadLengthArray[0] += torrentMan->getDeltaDownloadLength();
sessionUploadLengthArray[0] += torrentMan->getDeltaUploadLength(); sessionUploadLengthArray[0] += torrentMan->getDeltaUploadLength();
@ -111,8 +109,11 @@ void TorrentDownloadEngine::calculateStatistics() {
} }
if(elapsed-lastElapsed >= 1) { if(elapsed-lastElapsed >= 1) {
avgSpeed = calculateSpeed(sessionDownloadLength, int elapsedFromStartup = startup.difference();
Util::difftvsec(now, startup)); if(elapsedFromStartup > 0) {
avgSpeed = calculateSpeed(sessionDownloadLength,
elapsedFromStartup);
}
if(avgSpeed < 0) { if(avgSpeed < 0) {
avgSpeed = 0; avgSpeed = 0;
} else if(avgSpeed != 0) { } else if(avgSpeed != 0) {
@ -126,7 +127,7 @@ void TorrentDownloadEngine::calculateStatistics() {
if(elapsed > 15) { if(elapsed > 15) {
sessionDownloadLengthArray[currentCp] = 0; sessionDownloadLengthArray[currentCp] = 0;
sessionUploadLengthArray[currentCp] = 0; sessionUploadLengthArray[currentCp] = 0;
cp[currentCp] = now; cp[currentCp].reset();
lastElapsed = 0; lastElapsed = 0;
currentCp = currentCp ? 0 : 1; currentCp = currentCp ? 0 : 1;
} }

View File

@ -24,6 +24,7 @@
#include "DownloadEngine.h" #include "DownloadEngine.h"
#include "TorrentMan.h" #include "TorrentMan.h"
#include "Time.h"
class TorrentDownloadEngine : public DownloadEngine { class TorrentDownloadEngine : public DownloadEngine {
private: private:
@ -32,7 +33,7 @@ private:
void initStatistics(); void initStatistics();
void calculateStatistics(); void calculateStatistics();
protected: protected:
struct timeval cp[2]; Time cp[2];
long long int sessionDownloadLengthArray[2]; long long int sessionDownloadLengthArray[2];
long long int sessionUploadLengthArray[2]; long long int sessionUploadLengthArray[2];
int currentCp; int currentCp;
@ -43,7 +44,7 @@ protected:
long long int selectedDownloadLengthDiff; long long int selectedDownloadLengthDiff;
long long int selectedTotalLength; long long int selectedTotalLength;
// The time when startup // The time when startup
struct timeval startup; Time startup;
// The number of bytes downloaded since startup // The number of bytes downloaded since startup
long long int sessionDownloadLength; long long int sessionDownloadLength;
// The average speed(bytes per second) since startup // The average speed(bytes per second) since startup

View File

@ -130,9 +130,6 @@ void TorrentMan::deleteOldErrorPeers() {
} }
Peer* TorrentMan::getPeer() const { Peer* TorrentMan::getPeer() const {
if(connections > MAX_PEER_UPDATE) {
return Peer::nullPeer;
}
for(Peers::const_iterator itr = peers.begin(); itr != peers.end(); itr++) { for(Peers::const_iterator itr = peers.begin(); itr != peers.end(); itr++) {
Peer* p = *itr; Peer* p = *itr;
if(p->cuid == 0 && p->error < MAX_PEER_ERROR) { if(p->cuid == 0 && p->error < MAX_PEER_ERROR) {
@ -401,8 +398,8 @@ void TorrentMan::readFileEntry(FileEntries& fileEntries, Directory** pTopDir, co
} }
void TorrentMan::setupInternal1(const string& metaInfoFile) { void TorrentMan::setupInternal1(const string& metaInfoFile) {
peerId = "-A2****-"; peerId = "-aria2-";
for(int i = 0; i < 12; i++) { for(int i = 0; i < 20-(int)peerId.size(); i++) {
peerId += Util::itos((int)(((double)10)*random()/(RAND_MAX+1.0))); peerId += Util::itos((int)(((double)10)*random()/(RAND_MAX+1.0)));
} }
@ -652,3 +649,21 @@ void TorrentMan::onDownloadComplete() {
finishSelectiveDownloadingMode(); finishSelectiveDownloadingMode();
} }
} }
void TorrentMan::advertisePiece(int cuid, int index) {
HaveEntry entry(cuid, index);
haves.push_back(entry);
};
PieceIndexes TorrentMan::getAdvertisedPieceIndexes(int myCuid,
Time lastCheckTime) const {
PieceIndexes indexes;
for(Haves::const_iterator itr = haves.begin(); itr != haves.end(); itr++) {
const Haves::value_type& have = *itr;
if(have.cuid == myCuid || lastCheckTime.isNewer(have.registeredTime)) {
continue;
}
indexes.push_back(have.index);
}
return indexes;
}

View File

@ -33,6 +33,7 @@
#include "FileEntry.h" #include "FileEntry.h"
#include "DiskAdaptor.h" #include "DiskAdaptor.h"
#include "Request.h" #include "Request.h"
#include "Time.h"
#include <deque> #include <deque>
#include <map> #include <map>
#include <string> #include <string>
@ -42,16 +43,26 @@ using namespace std;
#define INFO_HASH_LENGTH 20 #define INFO_HASH_LENGTH 20
#define PEER_ID_LENGTH 20 #define PEER_ID_LENGTH 20
#define DEFAULT_ANNOUNCE_INTERVAL 300 #define DEFAULT_ANNOUNCE_INTERVAL 1800
#define DEFAULT_ANNOUNCE_MIN_INTERVAL 300 #define DEFAULT_ANNOUNCE_MIN_INTERVAL 1800
#define MAX_PEERS 55 #define MAX_PEERS 55
#define MAX_PEER_UPDATE 15 #define MAX_PEER_UPDATE 15
#define MAX_PEER_LIST_SIZE 250 #define MAX_PEER_LIST_SIZE 250
#define END_GAME_PIECE_NUM 20 #define END_GAME_PIECE_NUM 20
#define MAX_PEER_ERROR 5 #define MAX_PEER_ERROR 5
class HaveEntry {
public:
int cuid;
int index;
Time registeredTime;
HaveEntry(int cuid, int index):
cuid(cuid),
index(index) {}
};
typedef deque<Peer*> Peers; typedef deque<Peer*> Peers;
typedef multimap<int, int> Haves; typedef deque<HaveEntry> Haves;
typedef deque<int> PieceIndexes; typedef deque<int> PieceIndexes;
typedef deque<Piece> Pieces; typedef deque<Piece> Pieces;
@ -164,26 +175,9 @@ public:
string getPieceHash(int index) const; string getPieceHash(int index) const;
void advertisePiece(int cuid, int index) { void advertisePiece(int cuid, int index);
Haves::value_type vt(cuid, index);
haves.insert(vt);
}
PieceIndexes getAdvertisedPieceIndexes(int myCuid) const { PieceIndexes getAdvertisedPieceIndexes(int myCuid, Time lastCheckTime) const;
PieceIndexes indexes;
for(Haves::const_iterator itr = haves.begin(); itr != haves.end(); itr++) {
const Haves::value_type& have = *itr;
if(have.first == myCuid) {
continue;
}
indexes.push_back(have.second);
}
return indexes;
}
void unadvertisePiece(int cuid) {
haves.erase(cuid);
}
long long int getTotalLength() const { return totalLength; } long long int getTotalLength() const { return totalLength; }
void setTotalLength(long long int length) { totalLength = length; } void setTotalLength(long long int length) { totalLength = length; }

View File

@ -26,19 +26,21 @@
TrackerWatcherCommand::TrackerWatcherCommand(int cuid, TrackerWatcherCommand::TrackerWatcherCommand(int cuid,
TorrentDownloadEngine* e, TorrentDownloadEngine* e,
int interval): int interval):
Command(cuid), e(e), interval(interval) { Command(cuid), e(e), interval(interval) {}
checkPoint.tv_sec = 0;
checkPoint.tv_usec = 0;
}
TrackerWatcherCommand::~TrackerWatcherCommand() {} TrackerWatcherCommand::~TrackerWatcherCommand() {}
bool TrackerWatcherCommand::execute() { bool TrackerWatcherCommand::execute() {
struct timeval now; if(e->segmentMan->errors > 0) {
gettimeofday(&now, NULL); // we assume the tracker request has failed.
e->torrentMan->trackers = 0;
e->segmentMan->init();
}
if(e->torrentMan->trackers == 0 && if(e->torrentMan->trackers == 0 &&
(Util::difftvsec(now, checkPoint) >= interval || e->torrentMan->isHalt())) { (e->torrentMan->connections < MAX_PEER_UPDATE ||
checkPoint = now; e->torrentMan->isHalt() ||
checkPoint.elapsed(interval))) {
checkPoint.reset();
e->torrentMan->req->resetTryCount(); e->torrentMan->req->resetTryCount();
int numWant = 50; int numWant = 50;
if(e->torrentMan->connections >= MIN_PEERS || e->torrentMan->isHalt()) { if(e->torrentMan->connections >= MIN_PEERS || e->torrentMan->isHalt()) {
@ -90,7 +92,7 @@ bool TrackerWatcherCommand::execute() {
Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(e->torrentMan->getNewCuid(), e->torrentMan->req, e); Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(e->torrentMan->getNewCuid(), e->torrentMan->req, e);
e->commands.push_back(command); e->commands.push_back(command);
e->torrentMan->trackers++; e->torrentMan->trackers++;
logger->info("CUID#%d - creating new tracker request command #%d", cuid, logger->info("CUID#%d - Creating new tracker request command #%d", cuid,
command->getCuid()); command->getCuid());
if(e->torrentMan->isHalt()) { if(e->torrentMan->isHalt()) {
return true; return true;

View File

@ -24,7 +24,7 @@
#include "Command.h" #include "Command.h"
#include "TorrentDownloadEngine.h" #include "TorrentDownloadEngine.h"
#include <sys/time.h> #include "Time.h"
#define MIN_PEERS 15 #define MIN_PEERS 15
@ -32,7 +32,7 @@ class TrackerWatcherCommand : public Command {
private: private:
TorrentDownloadEngine* e; TorrentDownloadEngine* e;
int interval; int interval;
struct timeval checkPoint; Time checkPoint;
public: public:
TrackerWatcherCommand(int cuid, TorrentDownloadEngine* e, int interval); TrackerWatcherCommand(int cuid, TorrentDownloadEngine* e, int interval);
~TrackerWatcherCommand(); ~TrackerWatcherCommand();

View File

@ -647,8 +647,8 @@ int main(int argc, char* argv[]) {
if(!torrentFile.empty() || followTorrent && readyToTorrentMode) { if(!torrentFile.empty() || followTorrent && readyToTorrentMode) {
try { try {
//op->put(PREF_MAX_TRIES, "0"); //op->put(PREF_MAX_TRIES, "0");
setSignalHander(SIGINT, torrentHandler, SA_ONESHOT); setSignalHander(SIGINT, torrentHandler, SA_RESETHAND);
setSignalHander(SIGTERM, torrentHandler, SA_ONESHOT); setSignalHander(SIGTERM, torrentHandler, SA_RESETHAND);
Request* req = new Request(); Request* req = new Request();
req->isTorrent = true; req->isTorrent = true;