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>
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
# 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>.
#
@ -269,8 +269,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='aria2c'
PACKAGE_TARNAME='aria2c'
PACKAGE_VERSION='0.5.0'
PACKAGE_STRING='aria2c 0.5.0'
PACKAGE_VERSION='0.5.1'
PACKAGE_STRING='aria2c 0.5.1'
PACKAGE_BUGREPORT='tujikawa@rednoah.com'
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.
# This message is too long to be a string in the A/UX 3.1 sh.
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]...
@ -854,7 +854,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of aria2c 0.5.0:";;
short | recursive ) echo "Configuration of aria2c 0.5.1:";;
esac
cat <<\_ACEOF
@ -994,7 +994,7 @@ fi
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
aria2c configure 0.5.0
aria2c configure 0.5.1
generated by GNU Autoconf 2.59
Copyright (C) 2003 Free Software Foundation, Inc.
@ -1008,7 +1008,7 @@ cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
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
$ $0 $@
@ -1651,7 +1651,7 @@ fi
# Define the identity of the package.
PACKAGE='aria2c'
VERSION='0.5.0'
VERSION='0.5.1'
cat >>confdefs.h <<_ACEOF
@ -11528,7 +11528,7 @@ _ASBOX
} >&5
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
CONFIG_FILES = $CONFIG_FILES
@ -11591,7 +11591,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
aria2c config.status 0.5.0
aria2c config.status 0.5.1
configured by $0, generated by GNU Autoconf 2.59,
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.
#
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_PATH_CPPUNIT(1.10.2)
AC_CONFIG_SRCDIR([src/Socket.h])

View File

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

View File

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

View File

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

View File

@ -40,14 +40,14 @@ void ConsoleDownloadEngine::sendStatistics(long long int currentSize, long long
}
void ConsoleDownloadEngine::initStatistics() {
cp.tv_sec = cp.tv_usec = 0;
cp.reset();
startup.reset();
speed = 0;
psize = 0;
avgSpeed = 0;
eta = 0;
startupLength = 0;
isStartupLengthSet = false;
gettimeofday(&startup, NULL);
}
void ConsoleDownloadEngine::calculateStatistics() {
@ -56,28 +56,24 @@ void ConsoleDownloadEngine::calculateStatistics() {
startupLength = dlSize;
isStartupLengthSet = true;
}
struct timeval now;
gettimeofday(&now, NULL);
if(cp.tv_sec == 0 && cp.tv_usec == 0) {
cp = now;
int elapsed = cp.difference();
if(elapsed >= 1) {
int nspeed = (int)((dlSize-psize)/elapsed);
speed = (nspeed+speed)/2;
cp.reset();
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));
if(avgSpeed < 0) {
avgSpeed = 0;
} else if(avgSpeed != 0 && segmentMan->totalSize > 0) {
eta = (segmentMan->totalSize-dlSize)/avgSpeed;
}
sendStatistics(dlSize, segmentMan->totalSize);
int elapsedFromStartup = startup.difference();
if(elapsedFromStartup > 0) {
avgSpeed = (int)((dlSize-startupLength)/elapsedFromStartup);
}
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_
#include "DownloadEngine.h"
#include "Time.h"
class ConsoleDownloadEngine : public DownloadEngine {
private:
struct timeval cp;
Time cp;
long long int psize;
int speed;
// The time when startup
struct timeval startup;
Time startup;
// The number of bytes downloaded at startup
long long int startupLength;
bool isStartupLengthSet;

View File

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

View File

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

View File

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

View File

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

View File

@ -101,7 +101,8 @@ SRCS = Socket.cc Socket.h\
AllowedFastMessage.cc AllowedFastMessage.h\
SuggestPieceMessage.cc SuggestPieceMessage.h\
SimplePeerMessage.cc SimplePeerMessage.h\
NullLogger.h
NullLogger.h\
Time.cc Time.h
noinst_LIBRARIES = libaria2c.a
libaria2c_a_SOURCES = $(SRCS)
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) \
HaveNoneMessage.$(OBJEXT) RejectMessage.$(OBJEXT) \
AllowedFastMessage.$(OBJEXT) SuggestPieceMessage.$(OBJEXT) \
SimplePeerMessage.$(OBJEXT)
SimplePeerMessage.$(OBJEXT) Time.$(OBJEXT)
am_libaria2c_a_OBJECTS = $(am__objects_1)
libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
am__installdirs = "$(DESTDIR)$(bindir)"
@ -360,7 +360,8 @@ SRCS = Socket.cc Socket.h\
AllowedFastMessage.cc AllowedFastMessage.h\
SuggestPieceMessage.cc SuggestPieceMessage.h\
SimplePeerMessage.cc SimplePeerMessage.h\
NullLogger.h
NullLogger.h\
Time.cc Time.h
noinst_LIBRARIES = libaria2c.a
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)/SplitSlowestSegmentSplitter.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)/TorrentConsoleDownloadEngine.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentDownloadEngine.Po@am__quote@

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -25,19 +25,22 @@
#include "PeerAbstractCommand.h"
#include "PeerConnection.h"
#include "PeerInteraction.h"
#include "Time.h"
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 {
private:
int sequence;
PeerInteraction* peerInteraction;
struct timeval keepAliveCheckPoint;
struct timeval chokeCheckPoint;
struct timeval freqCheckPoint;
Time keepAliveCheckPoint;
Time chokeCheckPoint;
Time freqCheckPoint;
Time haveCheckTime;
int chokeUnchokeCount;
int haveCount;
int keepAliveCount;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -24,14 +24,14 @@
#include "DownloadEngine.h"
#include "Command.h"
#include <sys/time.h>
#include "Time.h"
class SleepCommand:public Command {
private:
DownloadEngine* engine;
Command* nextCommand;
int wait;
struct timeval checkPoint;
Time checkPoint;
public:
SleepCommand(int cuid, DownloadEngine* e, Command* nextCommand, int wait);
~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 "Util.h"
TorrentAutoSaveCommand::TorrentAutoSaveCommand(int cuid, TorrentDownloadEngine* e, int interval):Command(cuid), e(e), interval(interval) {
checkPoint.tv_sec = 0;
checkPoint.tv_usec = 0;
}
TorrentAutoSaveCommand::TorrentAutoSaveCommand(int cuid, TorrentDownloadEngine* e, int interval):Command(cuid), e(e), interval(interval) {}
TorrentAutoSaveCommand::~TorrentAutoSaveCommand() {}
bool TorrentAutoSaveCommand::execute() {
if(e->torrentMan->downloadComplete() || e->torrentMan->isHalt()) {
return true;
}
struct timeval now;
gettimeofday(&now, NULL);
if(Util::difftvsec(now, checkPoint) >= interval) {
checkPoint = now;
if(checkPoint.elapsed(interval) || e->torrentMan->isHalt()) {
checkPoint.reset();
e->torrentMan->save();
if(e->torrentMan->isHalt()) {
return true;

View File

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

View File

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

View File

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

View File

@ -130,9 +130,6 @@ void TorrentMan::deleteOldErrorPeers() {
}
Peer* TorrentMan::getPeer() const {
if(connections > MAX_PEER_UPDATE) {
return Peer::nullPeer;
}
for(Peers::const_iterator itr = peers.begin(); itr != peers.end(); itr++) {
Peer* p = *itr;
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) {
peerId = "-A2****-";
for(int i = 0; i < 12; i++) {
peerId = "-aria2-";
for(int i = 0; i < 20-(int)peerId.size(); i++) {
peerId += Util::itos((int)(((double)10)*random()/(RAND_MAX+1.0)));
}
@ -652,3 +649,21 @@ void TorrentMan::onDownloadComplete() {
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 "DiskAdaptor.h"
#include "Request.h"
#include "Time.h"
#include <deque>
#include <map>
#include <string>
@ -42,16 +43,26 @@ using namespace std;
#define INFO_HASH_LENGTH 20
#define PEER_ID_LENGTH 20
#define DEFAULT_ANNOUNCE_INTERVAL 300
#define DEFAULT_ANNOUNCE_MIN_INTERVAL 300
#define DEFAULT_ANNOUNCE_INTERVAL 1800
#define DEFAULT_ANNOUNCE_MIN_INTERVAL 1800
#define MAX_PEERS 55
#define MAX_PEER_UPDATE 15
#define MAX_PEER_LIST_SIZE 250
#define END_GAME_PIECE_NUM 20
#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 multimap<int, int> Haves;
typedef deque<HaveEntry> Haves;
typedef deque<int> PieceIndexes;
typedef deque<Piece> Pieces;
@ -164,26 +175,9 @@ public:
string getPieceHash(int index) const;
void advertisePiece(int cuid, int index) {
Haves::value_type vt(cuid, index);
haves.insert(vt);
}
void advertisePiece(int cuid, int index);
PieceIndexes getAdvertisedPieceIndexes(int myCuid) 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);
}
PieceIndexes getAdvertisedPieceIndexes(int myCuid, Time lastCheckTime) const;
long long int getTotalLength() const { return totalLength; }
void setTotalLength(long long int length) { totalLength = length; }

View File

@ -26,19 +26,21 @@
TrackerWatcherCommand::TrackerWatcherCommand(int cuid,
TorrentDownloadEngine* e,
int interval):
Command(cuid), e(e), interval(interval) {
checkPoint.tv_sec = 0;
checkPoint.tv_usec = 0;
}
Command(cuid), e(e), interval(interval) {}
TrackerWatcherCommand::~TrackerWatcherCommand() {}
bool TrackerWatcherCommand::execute() {
struct timeval now;
gettimeofday(&now, NULL);
if(e->segmentMan->errors > 0) {
// we assume the tracker request has failed.
e->torrentMan->trackers = 0;
e->segmentMan->init();
}
if(e->torrentMan->trackers == 0 &&
(Util::difftvsec(now, checkPoint) >= interval || e->torrentMan->isHalt())) {
checkPoint = now;
(e->torrentMan->connections < MAX_PEER_UPDATE ||
e->torrentMan->isHalt() ||
checkPoint.elapsed(interval))) {
checkPoint.reset();
e->torrentMan->req->resetTryCount();
int numWant = 50;
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);
e->commands.push_back(command);
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());
if(e->torrentMan->isHalt()) {
return true;

View File

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

View File

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