2007-10-12 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

Implemented BitTorrent/http/ftp integrated download.
	I've rewritten lots of files and now some headers have forward
	class declarations to reduce compile time.
	The implementation is extremely alpha stage, I recommend to use this
	for testing purpose only.
pull/1/head
Tatsuhiro Tsujikawa 2007-10-11 16:58:24 +00:00
parent e26bbbb9ee
commit 048a2cf597
252 changed files with 8646 additions and 5343 deletions

View File

@ -1,3 +1,11 @@
2007-10-12 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Implemented BitTorrent/http/ftp integrated download.
I've rewritten lots of files and now some headers have forward
class declarations to reduce compile time.
The implementation is extremely alpha stage, I recommend to use this
for testing purpose only.
2007-09-14 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> 2007-09-14 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Fixed the compilation error on 64bit platform. Fixed the compilation error on 64bit platform.

7
TODO
View File

@ -47,4 +47,9 @@
src/PeerChokeCommand.h src/PeerChokeCommand.h
src/TorrentAutoSaveCommand.h src/TorrentAutoSaveCommand.h
* Rewrite MetaFileUtil * Rewrite MetaFileUtil
* Integrate FTP/HTTP/BitTorrent downloads from metalinks * Reconsider the use of RecoverableException and FatalException
* Limit the number of opening file to,say,100 in MultiDiskAdaptor.
* Implement duplicate download checking in Bt
* Implement the feature to treat http/ftp as auxuality download method for BitTorrent
* Fixed the download error when sending "CWD //*" to the ftp server

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.61 for aria2c 0.11.3. # Generated by GNU Autoconf 2.61 for aria2c 0.12.0alpha.
# #
# Report bugs to <t-tujikawa@users.sourceforge.net>. # Report bugs to <t-tujikawa@users.sourceforge.net>.
# #
@ -574,8 +574,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.11.3' PACKAGE_VERSION='0.12.0alpha'
PACKAGE_STRING='aria2c 0.11.3' PACKAGE_STRING='aria2c 0.12.0alpha'
PACKAGE_BUGREPORT='t-tujikawa@users.sourceforge.net' PACKAGE_BUGREPORT='t-tujikawa@users.sourceforge.net'
ac_unique_file="src/Socket.h" ac_unique_file="src/Socket.h"
@ -1298,7 +1298,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.11.3 to adapt to many kinds of systems. \`configure' configures aria2c 0.12.0alpha to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1369,7 +1369,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.11.3:";; short | recursive ) echo "Configuration of aria2c 0.12.0alpha:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1490,7 +1490,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
aria2c configure 0.11.3 aria2c configure 0.12.0alpha
generated by GNU Autoconf 2.61 generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@ -1504,7 +1504,7 @@ cat >config.log <<_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.11.3, which was It was created by aria2c $as_me 0.12.0alpha, which was
generated by GNU Autoconf 2.61. Invocation command line was generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@ $ $0 $@
@ -2300,7 +2300,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='aria2c' PACKAGE='aria2c'
VERSION='0.11.3' VERSION='0.12.0alpha'
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@ -14327,7 +14327,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by aria2c $as_me 0.11.3, which was This file was extended by aria2c $as_me 0.12.0alpha, which was
generated by GNU Autoconf 2.61. Invocation command line was generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -14380,7 +14380,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\ ac_cs_version="\\
aria2c config.status 0.11.3 aria2c config.status 0.12.0alpha
configured by $0, generated by GNU Autoconf 2.61, configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" with options \\"`echo "$ac_configure_args" | sed 's/^ //; 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.11.3, t-tujikawa@users.sourceforge.net) AC_INIT(aria2c, 0.12.0alpha, t-tujikawa@users.sourceforge.net)
AC_CANONICAL_HOST AC_CANONICAL_HOST
AC_CANONICAL_SYSTEM AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE() AM_INIT_AUTOMAKE()

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.11.3 VERSION = 0.12.0alpha
SHELL = /bin/sh SHELL = /bin/sh

View File

@ -4,6 +4,7 @@
../src/TorrentRequestInfo.cc \ ../src/TorrentRequestInfo.cc \
../src/UrlRequestInfo.cc \ ../src/UrlRequestInfo.cc \
../src/main.cc \ ../src/main.cc \
../src/version_usage.cc \
../src/DefaultPieceStorage.cc \ ../src/DefaultPieceStorage.cc \
../src/DefaultBtAnnounce.cc \ ../src/DefaultBtAnnounce.cc \
../src/DefaultBtProgressInfoFile.cc \ ../src/DefaultBtProgressInfoFile.cc \

View File

@ -4,6 +4,7 @@ src/DownloadEngineFactory.cc
src/TorrentRequestInfo.cc src/TorrentRequestInfo.cc
src/UrlRequestInfo.cc src/UrlRequestInfo.cc
src/main.cc src/main.cc
src/version_usage.cc
src/DefaultPieceStorage.cc src/DefaultPieceStorage.cc
src/DefaultBtAnnounce.cc src/DefaultBtAnnounce.cc
src/DefaultBtProgressInfoFile.cc src/DefaultBtProgressInfoFile.cc

View File

@ -33,44 +33,64 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "AbstractCommand.h" #include "AbstractCommand.h"
#include "SegmentMan.h"
#include "NameResolver.h"
#include "CUIDCounter.h"
#include "DlAbortEx.h" #include "DlAbortEx.h"
#include "DlRetryEx.h" #include "DlRetryEx.h"
#include "FatalException.h"
#include "InitiateConnectionCommandFactory.h" #include "InitiateConnectionCommandFactory.h"
#include "Util.h" #include "Util.h"
#include "message.h" #include "message.h"
#include "SleepCommand.h" #include "SleepCommand.h"
#include "prefs.h" #include "prefs.h"
#include "DNSCache.h" #include "DNSCache.h"
#include "FatalException.h" #include "SingleFileDownloadContext.h"
#include "DefaultPieceStorage.h"
#include "UnknownLengthPieceStorage.h"
#include "File.h"
#include "StreamCheckIntegrityEntry.h"
#include "DefaultBtProgressInfoFile.h"
#include "CheckIntegrityCommand.h"
#include "DiskAdaptor.h"
#include "PeerStat.h"
#include "Segment.h"
#include "DiskWriterFactory.h"
#include "Option.h"
AbstractCommand::AbstractCommand(int32_t cuid, AbstractCommand::AbstractCommand(int32_t cuid,
const RequestHandle& req, const RequestHandle& req,
RequestGroup* requestGroup, RequestGroup* requestGroup,
DownloadEngine* e, DownloadEngine* e,
const SocketHandle& s): const SocketHandle& s):
Command(cuid), req(req), _requestGroup(requestGroup), e(e), socket(s), Command(cuid), RequestGroupAware(requestGroup),
req(req), e(e), socket(s),
segment(0),
checkSocketIsReadable(false), checkSocketIsWritable(false), checkSocketIsReadable(false), checkSocketIsWritable(false),
nameResolverCheck(false) { nameResolverCheck(false)
{
setReadCheckSocket(socket); setReadCheckSocket(socket);
timeout = this->e->option->getAsInt(PREF_TIMEOUT); timeout = this->e->option->getAsInt(PREF_TIMEOUT);
++_requestGroup->numConnection; _requestGroup->increaseStreamConnection();
} }
AbstractCommand::~AbstractCommand() { AbstractCommand::~AbstractCommand() {
disableReadCheckSocket(); disableReadCheckSocket();
disableWriteCheckSocket(); disableWriteCheckSocket();
--_requestGroup->numConnection; _requestGroup->decreaseStreamConnection();
} }
bool AbstractCommand::execute() { bool AbstractCommand::execute() {
try { try {
if(_requestGroup->getSegmentMan()->finished()) { if(_requestGroup->downloadFinished() || _requestGroup->isHaltRequested()) {
//logger->debug("CUID#%d - finished.", cuid); //logger->debug("CUID#%d - finished.", cuid);
return true; return true;
} }
PeerStatHandle peerStat = _requestGroup->getSegmentMan()->getPeerStat(cuid); PeerStatHandle peerStat = 0;
if(peerStat.get()) { if(!_requestGroup->getSegmentMan().isNull()) {
peerStat = _requestGroup->getSegmentMan()->getPeerStat(cuid);
}
if(!peerStat.isNull()) {
if(peerStat->getStatus() == PeerStat::REQUEST_IDLE) { if(peerStat->getStatus() == PeerStat::REQUEST_IDLE) {
logger->info(MSG_ABORT_REQUESTED, cuid); logger->info(MSG_ABORT_REQUESTED, cuid);
onAbort(0); onAbort(0);
@ -86,9 +106,8 @@ bool AbstractCommand::execute() {
#endif // ENABLE_ASYNC_DNS #endif // ENABLE_ASYNC_DNS
!checkSocketIsReadable && !checkSocketIsWritable && !nameResolverCheck) { !checkSocketIsReadable && !checkSocketIsWritable && !nameResolverCheck) {
checkPoint.reset(); checkPoint.reset();
if(_requestGroup->getSegmentMan()->downloadStarted) { if(!_requestGroup->getPieceStorage().isNull()) {
// TODO Segment::isNull(), Change method name, it is very confusing. if(segment.isNull()) {
if(segment->isNull()) {
segment = _requestGroup->getSegmentMan()->getSegment(cuid); segment = _requestGroup->getSegmentMan()->getSegment(cuid);
if(segment.isNull()) { if(segment.isNull()) {
logger->info(MSG_NO_SEGMENT_AVAILABLE, cuid); logger->info(MSG_NO_SEGMENT_AVAILABLE, cuid);
@ -98,26 +117,17 @@ bool AbstractCommand::execute() {
} }
return executeInternal(); return executeInternal();
} else { } else {
if(checkPoint.elapsed(timeout)) { 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);
return false; return false;
} }
} catch(FatalException* err) {
logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
onAbort(err);
delete(err);
req->resetUrl();
_requestGroup->getSegmentMan()->errors++;
return true;
} catch(DlAbortEx* err) { } catch(DlAbortEx* err) {
logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str()); logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
onAbort(err); onAbort(err);
delete(err); delete(err);
req->resetUrl(); req->resetUrl();
_requestGroup->getSegmentMan()->errors++;
tryReserved(); tryReserved();
return true; return true;
} catch(DlRetryEx* err) { } catch(DlRetryEx* err) {
@ -132,13 +142,16 @@ bool AbstractCommand::execute() {
logger->info(MSG_MAX_TRY, cuid, req->getTryCount()); logger->info(MSG_MAX_TRY, cuid, req->getTryCount());
logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str()); logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
delete(err); delete(err);
_requestGroup->getSegmentMan()->errors++;
tryReserved(); tryReserved();
return true; return true;
} else { } else {
delete(err); delete(err);
return prepareForRetry(e->option->getAsInt(PREF_RETRY_WAIT)); return prepareForRetry(e->option->getAsInt(PREF_RETRY_WAIT));
} }
} catch(FatalException* err) {
delete(err);
_requestGroup->setHaltRequested(true);
return true;
} }
} }
@ -148,7 +161,9 @@ void AbstractCommand::tryReserved() {
} }
bool AbstractCommand::prepareForRetry(int32_t wait) { bool AbstractCommand::prepareForRetry(int32_t wait) {
_requestGroup->getSegmentMan()->cancelSegment(cuid); if(!_requestGroup->getPieceStorage().isNull()) {
_requestGroup->getSegmentMan()->cancelSegment(cuid);
}
Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, req, _requestGroup, e); Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, req, _requestGroup, e);
if(wait == 0) { if(wait == 0) {
e->commands.push_back(command); e->commands.push_back(command);
@ -162,7 +177,9 @@ bool AbstractCommand::prepareForRetry(int32_t wait) {
void AbstractCommand::onAbort(Exception* ex) { void AbstractCommand::onAbort(Exception* ex) {
logger->debug(MSG_UNREGISTER_CUID, cuid); logger->debug(MSG_UNREGISTER_CUID, cuid);
//_segmentMan->unregisterId(cuid); //_segmentMan->unregisterId(cuid);
_requestGroup->getSegmentMan()->cancelSegment(cuid); if(!_requestGroup->getPieceStorage().isNull()) {
_requestGroup->getSegmentMan()->cancelSegment(cuid);
}
} }
void AbstractCommand::disableReadCheckSocket() { void AbstractCommand::disableReadCheckSocket() {
@ -272,3 +289,138 @@ bool AbstractCommand::nameResolveFinished() const {
return false; return false;
} }
#endif // ENABLE_ASYNC_DNS #endif // ENABLE_ASYNC_DNS
void AbstractCommand::loadAndOpenFile()
{
if(!_requestGroup->isPreLocalFileCheckEnabled()) {
_requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
return;
}
//_requestGroup->setProgressInfoFile(new DefaultBtProgressInfoFile(_requestGroup->getDownloadContext(), _requestGroup->getPieceStorage(), e->option));
BtProgressInfoFileHandle progressInfoFile =
new DefaultBtProgressInfoFile(_requestGroup->getDownloadContext(), _requestGroup->getPieceStorage(), e->option);
if(progressInfoFile->exists()) {
progressInfoFile->load();
_requestGroup->getPieceStorage()->getDiskAdaptor()->openExistingFile();
} else {
File outfile(_requestGroup->getFilePath());
if(outfile.exists() && e->option->get(PREF_CONTINUE) == V_TRUE) {
if(_requestGroup->getTotalLength() < outfile.size()) {
throw new FatalException(EX_FILE_LENGTH_MISMATCH_BETWEEN_LOCAL_AND_REMOTE,
_requestGroup->getFilePath().c_str(),
Util::llitos(outfile.size()).c_str(),
Util::llitos(_requestGroup->getTotalLength()).c_str());
}
_requestGroup->getPieceStorage()->getDiskAdaptor()->openExistingFile();
_requestGroup->getPieceStorage()->markPiecesDone(outfile.size());
} else {
#ifdef ENABLE_MESSAGE_DIGEST
if(outfile.exists() && e->option->get(PREF_CHECK_INTEGRITY) == V_TRUE) {
_requestGroup->getPieceStorage()->getDiskAdaptor()->openExistingFile();
} else {
shouldCancelDownloadForSafety();
_requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
}
#else // ENABLE_MESSAGE_DIGEST
shouldCancelDownloadForSafety();
_requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
#endif // ENABLE_MESSAGE_DIGEST
}
}
_requestGroup->setProgressInfoFile(progressInfoFile);
}
void AbstractCommand::shouldCancelDownloadForSafety()
{
File outfile(_requestGroup->getFilePath());
if(outfile.exists() && !_requestGroup->getProgressInfoFile()->exists()) {
if(e->option->get(PREF_AUTO_FILE_RENAMING) == V_TRUE) {
if(tryAutoFileRenaming()) {
logger->notice("File already exists. Renamed to %s.",
_requestGroup->getFilePath().c_str());
} else {
logger->notice("File renaming failed: %s",
_requestGroup->getFilePath().c_str());
throw new FatalException(EX_DOWNLOAD_ABORTED);
}
} else if(e->option->get(PREF_ALLOW_OVERWRITE) != V_TRUE) {
logger->notice(MSG_FILE_ALREADY_EXISTS,
_requestGroup->getFilePath().c_str(),
_requestGroup->getProgressInfoFile()->getFilename().c_str());
throw new FatalException(EX_DOWNLOAD_ABORTED);
}
}
}
bool AbstractCommand::tryAutoFileRenaming()
{
string filepath = _requestGroup->getFilePath();
if(filepath.empty()) {
return false;
}
for(int32_t i = 1; i < 10000; ++i) {
File newfile(filepath+"."+Util::itos(i));
if(!newfile.exists()) {
SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setUFilename(newfile.getBasename());
return true;
}
}
return false;
}
void AbstractCommand::initPieceStorage()
{
if(_requestGroup->getDownloadContext()->getTotalLength() == 0) {
UnknownLengthPieceStorageHandle ps = new UnknownLengthPieceStorage(_requestGroup->getDownloadContext(), e->option);
if(!_requestGroup->getDiskWriterFactory().isNull()) {
ps->setDiskWriterFactory(_requestGroup->getDiskWriterFactory());
}
_requestGroup->setPieceStorage(ps);
} else {
DefaultPieceStorageHandle ps = new DefaultPieceStorage(_requestGroup->getDownloadContext(), e->option);
if(!_requestGroup->getDiskWriterFactory().isNull()) {
ps->setDiskWriterFactory(_requestGroup->getDiskWriterFactory());
}
_requestGroup->setPieceStorage(ps);
}
_requestGroup->getPieceStorage()->initStorage();
_requestGroup->initSegmentMan();
}
bool AbstractCommand::downloadFinishedByFileLength()
{
// check existence of control file using ProgressInfoFile class.
if(_requestGroup->getProgressInfoFile()->exists()) {
return false;
}
// TODO consider the case when the getFilePath() returns dir path.
File outfile(_requestGroup->getFilePath());
if(outfile.exists() &&
_requestGroup->getTotalLength() == outfile.size()) {
_requestGroup->getPieceStorage()->markAllPiecesDone();
return true;
} else {
return false;
}
}
void AbstractCommand::prepareForNextAction(Command* nextCommand)
{
CheckIntegrityEntryHandle entry =
new StreamCheckIntegrityEntry(req, _requestGroup, nextCommand);
#ifdef ENABLE_MESSAGE_DIGEST
if(File(_requestGroup->getFilePath()).size() > 0 &&
e->option->get(PREF_CHECK_INTEGRITY) == V_TRUE &&
entry->isValidationReady()) {
entry->initValidator();
logger->debug("Issuing CheckIntegrityCommand.");
CheckIntegrityCommand* command =
new CheckIntegrityCommand(CUIDCounterSingletonHolder::instance()->newID(), _requestGroup, e, entry);
e->commands.push_back(command);
} else
#endif // ENABLE_MESSAGE_DIGEST
{
e->addCommand(entry->prepareForNextAction(e));
}
}

View File

@ -36,20 +36,24 @@
#define _D_ABSTRACT_COMMAND_H_ #define _D_ABSTRACT_COMMAND_H_
#include "Command.h" #include "Command.h"
#include "Request.h"
#include "DownloadEngine.h"
#include "SegmentMan.h"
#include "TimeA2.h" #include "TimeA2.h"
#include "RecoverableException.h" #include "RequestGroupAware.h"
#include "RequestGroup.h" #include "Socket.h"
class AbstractCommand : public Command { class Request;
extern typedef SharedHandle<Request> RequestHandle;
class DownloadEngine;
class Segment;
extern typedef SharedHandle<Segment> SegmentHandle;
class NameResolver;
extern typedef SharedHandle<NameResolver> NameResolverHandle;
class AbstractCommand : public Command, public RequestGroupAware {
private: private:
Time checkPoint; Time checkPoint;
int32_t timeout; int32_t timeout;
protected: protected:
RequestHandle req; RequestHandle req;
RequestGroup* _requestGroup;
DownloadEngine* e; DownloadEngine* e;
SocketHandle socket; SocketHandle socket;
SegmentHandle segment; SegmentHandle segment;
@ -70,12 +74,26 @@ protected:
virtual bool nameResolveFinished() const; virtual bool nameResolveFinished() const;
#endif // ENABLE_ASYNC_DNS #endif // ENABLE_ASYNC_DNS
void setTimeout(int32_t timeout) { this->timeout = timeout; } void setTimeout(int32_t timeout) { this->timeout = timeout; }
void loadAndOpenFile();
bool tryAutoFileRenaming();
void initPieceStorage();
bool downloadFinishedByFileLength();
void prepareForNextAction(Command* nextCommand = 0);
void shouldCancelDownloadForSafety();
private: private:
bool checkSocketIsReadable; bool checkSocketIsReadable;
bool checkSocketIsWritable; bool checkSocketIsWritable;
SocketHandle readCheckTarget; SocketHandle readCheckTarget;
SocketHandle writeCheckTarget; SocketHandle writeCheckTarget;
bool nameResolverCheck; bool nameResolverCheck;
public: public:
AbstractCommand(int32_t cuid, const RequestHandle& req, RequestGroup* requestGroup, DownloadEngine* e, const SocketHandle& s = SocketHandle()); AbstractCommand(int32_t cuid, const RequestHandle& req, RequestGroup* requestGroup, DownloadEngine* e, const SocketHandle& s = SocketHandle());
virtual ~AbstractCommand(); virtual ~AbstractCommand();

View File

@ -33,7 +33,6 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "AbstractDiskWriter.h" #include "AbstractDiskWriter.h"
#include "DlAbortEx.h"
#include "File.h" #include "File.h"
#include "Util.h" #include "Util.h"
#include "message.h" #include "message.h"
@ -47,8 +46,6 @@
AbstractDiskWriter::AbstractDiskWriter(): AbstractDiskWriter::AbstractDiskWriter():
fd(-1), fd(-1),
fileAllocator(0),
glowFileAllocator(0),
logger(LogFactory::getInstance()) logger(LogFactory::getInstance())
{} {}
@ -57,7 +54,9 @@ AbstractDiskWriter::~AbstractDiskWriter()
closeFile(); closeFile();
} }
void AbstractDiskWriter::openFile(const string& filename, int64_t totalLength) { void AbstractDiskWriter::openFile(const string& filename, int64_t totalLength)
throw(DlAbortEx*)
{
File f(filename); File f(filename);
if(f.exists()) { if(f.exists()) {
openExistingFile(filename, totalLength); openExistingFile(filename, totalLength);
@ -66,14 +65,18 @@ void AbstractDiskWriter::openFile(const string& filename, int64_t totalLength) {
} }
} }
void AbstractDiskWriter::closeFile() { void AbstractDiskWriter::closeFile()
{
if(fd >= 0) { if(fd >= 0) {
close(fd); close(fd);
fd = -1; fd = -1;
} }
} }
void AbstractDiskWriter::openExistingFile(const string& filename, int64_t totalLength) { void AbstractDiskWriter::openExistingFile(const string& filename,
int64_t totalLength)
throw(DlAbortEx*)
{
this->filename = filename; this->filename = filename;
File f(filename); File f(filename);
if(!f.isFile()) { if(!f.isFile()) {
@ -83,17 +86,11 @@ void AbstractDiskWriter::openExistingFile(const string& filename, int64_t totalL
if((fd = open(filename.c_str(), O_RDWR|O_BINARY, OPEN_MODE)) < 0) { if((fd = open(filename.c_str(), O_RDWR|O_BINARY, OPEN_MODE)) < 0) {
throw new DlAbortEx(EX_FILE_OPEN, filename.c_str(), strerror(errno)); throw new DlAbortEx(EX_FILE_OPEN, filename.c_str(), strerror(errno));
} }
if(f.size() < totalLength) {
if(!fileAllocator.isNull()) {
logger->notice(MSG_ALLOCATING_FILE,
filename.c_str(),
Util::ullitos(totalLength).c_str());
glowFileAllocator->allocate(fd, totalLength);
}
}
} }
void AbstractDiskWriter::createFile(const string& filename, int32_t addFlags) { void AbstractDiskWriter::createFile(const string& filename, int32_t addFlags)
throw(DlAbortEx*)
{
this->filename = filename; this->filename = filename;
// TODO proper filename handling needed // TODO proper filename handling needed
assert(filename.size()); assert(filename.size());
@ -105,28 +102,36 @@ void AbstractDiskWriter::createFile(const string& filename, int32_t addFlags) {
} }
} }
int32_t AbstractDiskWriter::writeDataInternal(const char* data, int32_t len) { int32_t AbstractDiskWriter::writeDataInternal(const unsigned char* data, int32_t len)
{
return write(fd, data, len); return write(fd, data, len);
} }
int32_t AbstractDiskWriter::readDataInternal(char* data, int32_t len) { int32_t AbstractDiskWriter::readDataInternal(unsigned char* data, int32_t len)
{
return read(fd, data, len); return read(fd, data, len);
} }
void AbstractDiskWriter::seek(int64_t offset) { void AbstractDiskWriter::seek(int64_t offset)
throw(DlAbortEx*)
{
if(offset != lseek(fd, offset, SEEK_SET)) { if(offset != lseek(fd, offset, SEEK_SET)) {
throw new DlAbortEx(EX_FILE_SEEK, filename.c_str(), strerror(errno)); throw new DlAbortEx(EX_FILE_SEEK, filename.c_str(), strerror(errno));
} }
} }
void AbstractDiskWriter::writeData(const char* data, int32_t len, int64_t offset) { void AbstractDiskWriter::writeData(const unsigned char* data, int32_t len, int64_t offset)
throw(DlAbortEx*)
{
seek(offset); seek(offset);
if(writeDataInternal(data, len) < 0) { if(writeDataInternal(data, len) < 0) {
throw new DlAbortEx(EX_FILE_WRITE, filename.c_str(), strerror(errno)); throw new DlAbortEx(EX_FILE_WRITE, filename.c_str(), strerror(errno));
} }
} }
int32_t AbstractDiskWriter::readData(char* data, int32_t len, int64_t offset) { int32_t AbstractDiskWriter::readData(unsigned char* data, int32_t len, int64_t offset)
throw(DlAbortEx*)
{
int32_t ret; int32_t ret;
seek(offset); seek(offset);
if((ret = readDataInternal(data, len)) < 0) { if((ret = readDataInternal(data, len)) < 0) {
@ -136,13 +141,21 @@ int32_t AbstractDiskWriter::readData(char* data, int32_t len, int64_t offset) {
} }
void AbstractDiskWriter::truncate(int64_t length) void AbstractDiskWriter::truncate(int64_t length)
throw(DlAbortEx*)
{ {
if(fd == -1) {
throw new DlAbortEx("File not opened.");
}
ftruncate(fd, length); ftruncate(fd, length);
} }
// TODO the file descriptor fd must be opened before calling this function. // TODO the file descriptor fd must be opened before calling this function.
int64_t AbstractDiskWriter::size() const int64_t AbstractDiskWriter::size() const
throw(DlAbortEx*)
{ {
if(fd == -1) {
throw new DlAbortEx("File not opened.");
}
struct stat fileStat; struct stat fileStat;
if(fstat(fd, &fileStat) < 0) { if(fstat(fd, &fileStat) < 0) {
return 0; return 0;

View File

@ -36,52 +36,40 @@
#define _D_ABSTRACT_DISK_WRITER_H_ #define _D_ABSTRACT_DISK_WRITER_H_
#include "DiskWriter.h" #include "DiskWriter.h"
#include "FileAllocator.h"
#include "Logger.h" #include "Logger.h"
#include "DlAbortEx.h"
class AbstractDiskWriter : public DiskWriter { class AbstractDiskWriter : public DiskWriter {
protected: protected:
string filename; string filename;
int32_t fd; int32_t fd;
FileAllocatorHandle fileAllocator;
FileAllocatorHandle glowFileAllocator;
const Logger* logger; const Logger* logger;
void createFile(const string& filename, int32_t addFlags = 0); void createFile(const string& filename, int32_t addFlags = 0) throw(DlAbortEx*);
private: private:
int32_t writeDataInternal(const char* data, int32_t len); int32_t writeDataInternal(const unsigned char* data, int32_t len);
int32_t readDataInternal(char* data, int32_t len); int32_t readDataInternal(unsigned char* data, int32_t len);
void seek(int64_t offset); void seek(int64_t offset) throw(DlAbortEx*);
public: public:
AbstractDiskWriter(); AbstractDiskWriter();
virtual ~AbstractDiskWriter(); virtual ~AbstractDiskWriter();
virtual void openFile(const string& filename, int64_t totalLength = 0); virtual void openFile(const string& filename, int64_t totalLength = 0) throw(DlAbortEx*);
virtual void closeFile(); virtual void closeFile();
virtual void openExistingFile(const string& filename, int64_t totalLength = 0); virtual void openExistingFile(const string& filename, int64_t totalLength = 0) throw(DlAbortEx*);
virtual void writeData(const char* data, int32_t len, int64_t offset); virtual void writeData(const unsigned char* data, int32_t len, int64_t offset) throw(DlAbortEx*);
virtual int32_t readData(char* data, int32_t len, int64_t offset); virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) throw(DlAbortEx*);
void setFileAllocator(const FileAllocatorHandle& fileAllocator) virtual void truncate(int64_t length) throw(DlAbortEx*);
{
this->fileAllocator = fileAllocator;
}
void setGlowFileAllocator(const FileAllocatorHandle& fileAllocator) virtual int64_t size() const throw(DlAbortEx*);
{
this->glowFileAllocator = fileAllocator;
}
virtual void truncate(int64_t length);
virtual int64_t size() const;
}; };
#endif // _D_ABSTRACT_DISK_WRITER_H_ #endif // _D_ABSTRACT_DISK_WRITER_H_

View File

@ -33,6 +33,9 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "AbstractProxyRequestCommand.h" #include "AbstractProxyRequestCommand.h"
#include "DownloadEngine.h"
#include "RequestGroup.h"
#include "Request.h"
#include "HttpConnection.h" #include "HttpConnection.h"
#include "prefs.h" #include "prefs.h"

View File

@ -36,7 +36,9 @@
#define _D_ABSTRACT_PROXY_REQUEST_COMMAND_H_ #define _D_ABSTRACT_PROXY_REQUEST_COMMAND_H_
#include "AbstractCommand.h" #include "AbstractCommand.h"
#include "HttpConnection.h"
class HttpConnection;
extern typedef SharedHandle<HttpConnection> HttpConnectionHandle;
class AbstractProxyRequestCommand : public AbstractCommand { class AbstractProxyRequestCommand : public AbstractCommand {
protected: protected:

View File

@ -33,6 +33,11 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "AbstractProxyResponseCommand.h" #include "AbstractProxyResponseCommand.h"
#include "HttpConnection.h"
#include "Request.h"
#include "RequestGroup.h"
#include "DownloadEngine.h"
#include "HttpResponse.h"
#include "HttpRequestCommand.h" #include "HttpRequestCommand.h"
#include "DlRetryEx.h" #include "DlRetryEx.h"
#include "message.h" #include "message.h"

View File

@ -36,7 +36,9 @@
#define _D_ABSTRACT_PROXY_RESPONSE_COMMAND_H_ #define _D_ABSTRACT_PROXY_RESPONSE_COMMAND_H_
#include "AbstractCommand.h" #include "AbstractCommand.h"
#include "HttpConnection.h"
class HttpConnection;
extern typedef SharedHandle<HttpConnection> HttpConnectionHandle;
class AbstractProxyResponseCommand : public AbstractCommand { class AbstractProxyResponseCommand : public AbstractCommand {
protected: protected:

View File

@ -34,28 +34,40 @@
/* copyright --> */ /* copyright --> */
#include "AbstractSingleDiskAdaptor.h" #include "AbstractSingleDiskAdaptor.h"
#include "File.h" #include "File.h"
#include "SingleFileAllocationIterator.h"
void AbstractSingleDiskAdaptor::initAndOpenFile() { void AbstractSingleDiskAdaptor::initAndOpenFile()
throw(DlAbortEx*)
{
diskWriter->initAndOpenFile(getFilePath(), totalLength); diskWriter->initAndOpenFile(getFilePath(), totalLength);
} }
void AbstractSingleDiskAdaptor::openFile() { void AbstractSingleDiskAdaptor::openFile()
throw(DlAbortEx*)
{
diskWriter->openFile(getFilePath(), totalLength); diskWriter->openFile(getFilePath(), totalLength);
} }
void AbstractSingleDiskAdaptor::closeFile() { void AbstractSingleDiskAdaptor::closeFile()
{
diskWriter->closeFile(); diskWriter->closeFile();
} }
void AbstractSingleDiskAdaptor::openExistingFile() { void AbstractSingleDiskAdaptor::openExistingFile()
throw(DlAbortEx*)
{
diskWriter->openExistingFile(getFilePath(), totalLength); diskWriter->openExistingFile(getFilePath(), totalLength);
} }
void AbstractSingleDiskAdaptor::writeData(const unsigned char* data, int32_t len, int64_t offset) { void AbstractSingleDiskAdaptor::writeData(const unsigned char* data, int32_t len, int64_t offset)
throw(DlAbortEx*)
{
diskWriter->writeData(data, len, offset); diskWriter->writeData(data, len, offset);
} }
int32_t AbstractSingleDiskAdaptor::readData(unsigned char* data, int32_t len, int64_t offset) { int32_t AbstractSingleDiskAdaptor::readData(unsigned char* data, int32_t len, int64_t offset)
throw(DlAbortEx*)
{
return diskWriter->readData(data, len, offset); return diskWriter->readData(data, len, offset);
} }
@ -63,3 +75,8 @@ bool AbstractSingleDiskAdaptor::fileExists()
{ {
return File(getFilePath()).exists(); return File(getFilePath()).exists();
} }
FileAllocationIteratorHandle AbstractSingleDiskAdaptor::fileAllocationIterator()
{
return new SingleFileAllocationIterator(this);
}

View File

@ -37,6 +37,7 @@
#include "DiskAdaptor.h" #include "DiskAdaptor.h"
#include "DiskWriter.h" #include "DiskWriter.h"
#include "DlAbortEx.h"
class AbstractSingleDiskAdaptor : public DiskAdaptor { class AbstractSingleDiskAdaptor : public DiskAdaptor {
protected: protected:
@ -47,26 +48,33 @@ public:
virtual ~AbstractSingleDiskAdaptor() {} virtual ~AbstractSingleDiskAdaptor() {}
virtual void initAndOpenFile(); virtual void initAndOpenFile() throw(DlAbortEx*);
virtual void openFile(); virtual void openFile() throw(DlAbortEx*);
virtual void closeFile(); virtual void closeFile();
virtual void openExistingFile(); virtual void openExistingFile() throw(DlAbortEx*);
virtual void writeData(const unsigned char* data, int32_t len, virtual void writeData(const unsigned char* data, int32_t len,
int64_t offset); int64_t offset) throw(DlAbortEx*);
virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset); virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) throw(DlAbortEx*);
virtual bool fileExists(); virtual bool fileExists();
virtual int64_t size() const virtual int64_t size() const throw(DlAbortEx*)
{ {
return getTotalLength(); return diskWriter->size();
} }
virtual void truncate(int64_t length) throw(DlAbortEx*)
{
diskWriter->truncate(length);
}
virtual FileAllocationIteratorHandle fileAllocationIterator();
void setDiskWriter(const DiskWriterHandle diskWriter) { void setDiskWriter(const DiskWriterHandle diskWriter) {
this->diskWriter = diskWriter; this->diskWriter = diskWriter;
} }

View File

@ -37,6 +37,22 @@
#include "CUIDCounter.h" #include "CUIDCounter.h"
#include "message.h" #include "message.h"
ActivePeerConnectionCommand::ActivePeerConnectionCommand(int cuid,
RequestGroup* requestGroup,
DownloadEngine* e,
const BtContextHandle& btContext,
int32_t interval)
:Command(cuid),
BtContextAwareCommand(btContext),
RequestGroupAware(requestGroup),
interval(interval),
e(e),
_lowestSpeedLimit(20*1024),
_numNewConnection(5)
{}
ActivePeerConnectionCommand::~ActivePeerConnectionCommand() {}
bool ActivePeerConnectionCommand::execute() { bool ActivePeerConnectionCommand::execute() {
if(btRuntime->isHalt()) { if(btRuntime->isHalt()) {
return true; return true;
@ -63,7 +79,7 @@ void ActivePeerConnectionCommand::connectToPeer(const PeerHandle& peer)
} }
peer->cuid = CUIDCounterSingletonHolder::instance()->newID(); peer->cuid = CUIDCounterSingletonHolder::instance()->newID();
PeerInitiateConnectionCommand* command = PeerInitiateConnectionCommand* command =
new PeerInitiateConnectionCommand(peer->cuid, peer, e, btContext); new PeerInitiateConnectionCommand(peer->cuid, _requestGroup, peer, e, btContext);
e->commands.push_back(command); e->commands.push_back(command);
logger->info(MSG_CONNECTING_TO_PEER, logger->info(MSG_CONNECTING_TO_PEER,
cuid, peer->ipaddr.c_str()); cuid, peer->ipaddr.c_str());

View File

@ -35,30 +35,30 @@
#ifndef _D_ACTIVE_PEER_CONNECTION_COMMAND_H_ #ifndef _D_ACTIVE_PEER_CONNECTION_COMMAND_H_
#define _D_ACTIVE_PEER_CONNECTION_COMMAND_H_ #define _D_ACTIVE_PEER_CONNECTION_COMMAND_H_
#include "Command.h"
#include "BtContextAwareCommand.h" #include "BtContextAwareCommand.h"
#include "TorrentDownloadEngine.h" #include "DownloadEngine.h"
#include "TimeA2.h" #include "TimeA2.h"
#include "RequestGroupAware.h"
class ActivePeerConnectionCommand : public BtContextAwareCommand { class ActivePeerConnectionCommand : public Command,
public BtContextAwareCommand,
public RequestGroupAware
{
private: private:
int32_t interval; // UNIT: sec int32_t interval; // UNIT: sec
TorrentDownloadEngine* e; DownloadEngine* e;
Time checkPoint; Time checkPoint;
int32_t _lowestSpeedLimit; // UNIT: byte/sec int32_t _lowestSpeedLimit; // UNIT: byte/sec
int32_t _numNewConnection; // the number of the connection to establish. int32_t _numNewConnection; // the number of the connection to establish.
public: public:
ActivePeerConnectionCommand(int cuid, ActivePeerConnectionCommand(int cuid,
TorrentDownloadEngine* e, RequestGroup* requestGroup,
DownloadEngine* e,
const BtContextHandle& btContext, const BtContextHandle& btContext,
int32_t interval) int32_t interval);
:BtContextAwareCommand(cuid, btContext),
interval(interval),
e(e),
_lowestSpeedLimit(20*1024),
_numNewConnection(5)
{}
virtual ~ActivePeerConnectionCommand() {} virtual ~ActivePeerConnectionCommand();
virtual bool execute(); virtual bool execute();

View File

@ -36,7 +36,7 @@
#define _D_ALPHA_NUMBER_DECORATOR_H_ #define _D_ALPHA_NUMBER_DECORATOR_H_
#include "NumberDecorator.h" #include "NumberDecorator.h"
#include "FatalException.h" #include "DlAbortEx.h"
class AlphaNumberDecorator : public NumberDecorator class AlphaNumberDecorator : public NumberDecorator
{ {
@ -64,7 +64,7 @@ public:
virtual string decorate(int32_t number) virtual string decorate(int32_t number)
{ {
if(number < 0) { if(number < 0) {
throw new FatalException("The number must be greater than 0."); throw new DlAbortEx("The number must be greater than 0.");
} }
if(number == 0) { if(number == 0) {
return widen(_zero, _width); return widen(_zero, _width);

View File

@ -33,10 +33,17 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "AutoSaveCommand.h" #include "AutoSaveCommand.h"
#include "DownloadEngine.h"
#include "RequestGroupMan.h"
AutoSaveCommand::AutoSaveCommand(int32_t cuid, DownloadEngine* e, int32_t interval):
TimeBasedCommand(cuid, e, interval) {}
AutoSaveCommand::~AutoSaveCommand() {}
void AutoSaveCommand::preProcess() void AutoSaveCommand::preProcess()
{ {
if(_e->_requestGroupMan->downloadFinished()) { if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
_exit = true; _exit = true;
} }
} }

View File

@ -40,10 +40,9 @@
class AutoSaveCommand : public TimeBasedCommand class AutoSaveCommand : public TimeBasedCommand
{ {
public: public:
AutoSaveCommand(int32_t cuid, DownloadEngine* e, int32_t interval): AutoSaveCommand(int32_t cuid, DownloadEngine* e, int32_t interval);
TimeBasedCommand(cuid, e, interval) {}
virtual ~AutoSaveCommand() {} virtual ~AutoSaveCommand();
virtual void preProcess(); virtual void preProcess();

52
src/BinaryStream.h Normal file
View File

@ -0,0 +1,52 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_BINARY_STREAM_H_
#define _D_BINARY_STREAM_H_
#include "common.h"
#include "DlAbortEx.h"
class BinaryStream {
public:
virtual ~BinaryStream() {}
virtual void writeData(const unsigned char* data, int32_t len, int64_t offset) = 0;
virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) = 0;
};
typedef SharedHandle<BinaryStream> BinaryStreamHandle;
#endif // _D_BINARY_STREAM_H_

View File

@ -32,37 +32,29 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#ifndef _D_CONSOLE_DOWNLOAD_ENGINE_H_ #include "BtCheckIntegrityEntry.h"
#define _D_CONSOLE_DOWNLOAD_ENGINE_H_ #include "BtSetup.h"
#include "BtFileAllocationEntry.h"
#include "CUIDCounter.h"
#include "RequestGroup.h"
#include "PieceStorage.h"
#include "DownloadEngine.h" #include "DownloadEngine.h"
#include "TimeA2.h" #include "FileAllocationMan.h"
#include "DiskAdaptor.h"
class ConsoleDownloadEngine : public DownloadEngine { BtCheckIntegrityEntry::BtCheckIntegrityEntry(RequestGroup* requestGroup):
private: CheckIntegrityEntry(requestGroup, 0) {}
Time cp;
int64_t psize;
int32_t speed;
// The time when startup
Time startup;
// The number of bytes downloaded at startup
int64_t startupLength;
bool isStartupLengthSet;
// The average speed(bytes per second) since startup
int32_t avgSpeed;
// The estimated remaining time to complete the download.
int32_t eta;
protected:
void sendStatistics(int64_t currentSize, int64_t totalSize);
virtual void initStatistics();
virtual void calculateStatistics();
virtual void onEndOfRun();
virtual void afterEachIteration();
public:
ConsoleDownloadEngine();
~ConsoleDownloadEngine();
void fillCommand(); BtCheckIntegrityEntry::~BtCheckIntegrityEntry() {}
};
#endif // _D_CONSOLE_DOWNLOAD_ENGINE_H_ Commands BtCheckIntegrityEntry::prepareForNextAction(DownloadEngine* e)
{
Commands commands;
FileAllocationEntryHandle entry = new BtFileAllocationEntry(_requestGroup);
if(_requestGroup->isFileAllocationEnabled() && !_requestGroup->getPieceStorage()->getDiskAdaptor()->fileAllocationIterator()->finished()) {
e->_fileAllocationMan->pushFileAllocationEntry(entry);
} else {
commands = entry->prepareForNextAction(e);
}
return commands;
}

View File

@ -0,0 +1,51 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_BT_CHECK_INTEGRITY_ENTRY_H_
#define _D_BT_CHECK_INTEGRITY_ENTRY_H_
#include "CheckIntegrityEntry.h"
class BtCheckIntegrityEntry : public CheckIntegrityEntry {
public:
BtCheckIntegrityEntry(RequestGroup* requestGroup);
virtual ~BtCheckIntegrityEntry();
virtual Commands prepareForNextAction(DownloadEngine* e);
};
typedef SharedHandle<BtCheckIntegrityEntry> BtCheckIntegrityEntryHandle;
#endif // _D_BT_FILE_ALLOCATION_ENTRY_H_

View File

@ -35,57 +35,40 @@
#ifndef _D_BT_CONTEXT_H_ #ifndef _D_BT_CONTEXT_H_
#define _D_BT_CONTEXT_H_ #define _D_BT_CONTEXT_H_
#include "common.h" #include "DownloadContext.h"
#include "FileEntry.h"
#include "AnnounceTier.h"
#define INFO_HASH_LENGTH 20 #define INFO_HASH_LENGTH 20
#define MAX_PEER_ERROR 5 #define MAX_PEER_ERROR 5
#define MAX_PEERS 55 #define MAX_PEERS 55
class AnnounceTier;
extern typedef SharedHandle<AnnounceTier> AnnounceTierHandle;
typedef deque<AnnounceTierHandle> AnnounceTiers; typedef deque<AnnounceTierHandle> AnnounceTiers;
class BtContext { class RequestGroup;
class BtContext:public DownloadContext {
public: public:
virtual ~BtContext() {} virtual ~BtContext() {}
enum FILE_MODE {
SINGLE,
MULTI
};
virtual const unsigned char* getInfoHash() const = 0; virtual const unsigned char* getInfoHash() const = 0;
virtual int32_t getInfoHashLength() const = 0; virtual int32_t getInfoHashLength() const = 0;
virtual string getInfoHashAsString() const = 0; virtual string getInfoHashAsString() const = 0;
virtual string getPieceHash(int32_t index) const = 0;
virtual const Strings& getPieceHashes() const = 0;
virtual int64_t getTotalLength() const = 0;
virtual FILE_MODE getFileMode() const = 0;
virtual FileEntries getFileEntries() const = 0;
virtual AnnounceTiers getAnnounceTiers() const = 0; virtual AnnounceTiers getAnnounceTiers() const = 0;
virtual void load(const string& torrentFile) = 0; virtual void load(const string& torrentFile) = 0;
virtual string getName() const = 0;
virtual int32_t getPieceLength() const = 0;
virtual int32_t getNumPieces() const = 0;
/** /**
* Returns the peer id of localhost, 20 byte length * Returns the peer id of localhost, 20 byte length
*/ */
virtual const unsigned char* getPeerId() = 0; virtual const unsigned char* getPeerId() = 0;
virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize) = 0; virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize) = 0;
virtual RequestGroup* getOwnerRequestGroup() = 0;
}; };

View File

@ -35,9 +35,7 @@
#include "BtContextAwareCommand.h" #include "BtContextAwareCommand.h"
#include "BtRegistry.h" #include "BtRegistry.h"
BtContextAwareCommand::BtContextAwareCommand(int cuid, BtContextAwareCommand::BtContextAwareCommand(const BtContextHandle& btContext):
const BtContextHandle& btContext):
Command(cuid),
btContext(btContext), btContext(btContext),
btRuntime(BT_RUNTIME(btContext)), btRuntime(BT_RUNTIME(btContext)),
pieceStorage(PIECE_STORAGE(btContext)), pieceStorage(PIECE_STORAGE(btContext)),

View File

@ -35,7 +35,7 @@
#ifndef _D_BT_CONTEXT_AWARE_COMMAND_H_ #ifndef _D_BT_CONTEXT_AWARE_COMMAND_H_
#define _D_BT_CONTEXT_AWARE_COMMAND_H_ #define _D_BT_CONTEXT_AWARE_COMMAND_H_
#include "Command.h" #include "common.h"
#include "BtContext.h" #include "BtContext.h"
#include "BtRuntime.h" #include "BtRuntime.h"
#include "PieceStorage.h" #include "PieceStorage.h"
@ -43,7 +43,8 @@
#include "BtAnnounce.h" #include "BtAnnounce.h"
#include "BtProgressInfoFile.h" #include "BtProgressInfoFile.h"
class BtContextAwareCommand : public Command { class BtContextAwareCommand
{
protected: protected:
BtContextHandle btContext; BtContextHandle btContext;
BtRuntimeHandle btRuntime; BtRuntimeHandle btRuntime;
@ -52,7 +53,7 @@ protected:
BtAnnounceHandle btAnnounce; BtAnnounceHandle btAnnounce;
BtProgressInfoFileHandle btProgressInfoFile; BtProgressInfoFileHandle btProgressInfoFile;
public: public:
BtContextAwareCommand(int cuid, const BtContextHandle& btContext); BtContextAwareCommand(const BtContextHandle& btContext);
virtual ~BtContextAwareCommand(); virtual ~BtContextAwareCommand();
}; };

83
src/BtDependency.cc Normal file
View File

@ -0,0 +1,83 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "BtDependency.h"
#include "RequestGroup.h"
#include "Option.h"
#include "LogFactory.h"
#include "DefaultBtContext.h"
#include "RecoverableException.h"
#include "message.h"
#include "prefs.h"
BtDependency::BtDependency(const RequestGroupWeakHandle& dependant,
const RequestGroupWeakHandle& dependee,
const Option* option):
_dependant(dependant),
_dependee(dependee),
_option(option),
_logger(LogFactory::getInstance()) {}
BtDependency::~BtDependency() {}
bool BtDependency::resolve()
{
if(_dependee->getNumCommand() == 0 && _dependee->downloadFinished()) {
DefaultBtContextHandle btContext = new DefaultBtContext();
try {
btContext->load(_dependee->getFilePath());
if(_option->defined(PREF_PEER_ID_PREFIX)) {
btContext->setPeerIdPrefix(_option->get(PREF_PEER_ID_PREFIX));
}
btContext->setDir(_dependant->getDownloadContext()->getDir());
} catch(RecoverableException* e) {
_logger->error(EX_EXCEPTION_CAUGHT, e);
delete e;
_logger->debug("BtDependency for GID#%d failed. Go without Bt.",
_dependant->getGID());
return true;
}
_logger->debug("Dependency resolved for GID#%d", _dependant->getGID());
_dependant->setDownloadContext(btContext);
btContext->setOwnerRequestGroup(_dependant.get());
return true;
} else if(_dependee->getNumCommand() == 0) {
// _dependee's download failed.
_logger->debug("BtDependency for GID#%d failed. Go without Bt.",
_dependant->getGID());
return true;
} else {
return false;
}
}

View File

@ -32,30 +32,33 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#ifndef _D_TORRENT_REQUEST_INFO_H_ #ifndef _D_BT_DEPENDENCY_H_
#define _D_TORRENT_REQUEST_INFO_H_ #define _D_BT_DEPENDENCY_H_
#include "RequestInfo.h" #include "Dependency.h"
#include "TorrentDownloadEngine.h"
#include "BtContext.h"
class TorrentRequestInfo : public RequestInfo { class RequestGroup;
extern typedef WeakHandle<RequestGroup> RequestGroupWeakHandle;
class Option;
class Logger;
class BtDependency : public Dependency
{
private: private:
string torrentFile; RequestGroupWeakHandle _dependant;
Strings targetFiles; RequestGroupWeakHandle _dependee;
const Option* _option;
const Logger* _logger;
public: public:
TorrentRequestInfo(const string& torrentFile, Option* op): BtDependency(const RequestGroupWeakHandle& dependant,
RequestInfo(op), const RequestGroupWeakHandle& dependee,
torrentFile(torrentFile) {} const Option* option);
virtual ~TorrentRequestInfo() {} virtual ~BtDependency();
virtual RequestInfos execute(); virtual bool resolve();
void setTargetFiles(const Strings& targetFiles) {
this->targetFiles = targetFiles;
}
}; };
#endif // _D_TORRENT_REQUEST_INFO_H_ typedef SharedHandle<BtDependency> BtDependencyHandle;
#endif // _D_BT_DEPENDENCY_H_

View File

@ -32,27 +32,22 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#include "TorrentAutoSaveCommand.h" #include "BtFileAllocationEntry.h"
#include "Util.h" #include "BtSetup.h"
#include "RequestGroup.h"
#include "Command.h"
#include "DownloadEngine.h"
TorrentAutoSaveCommand::TorrentAutoSaveCommand(int32_t cuid, BtFileAllocationEntry::BtFileAllocationEntry(RequestGroup* requestGroup):
TorrentDownloadEngine* e, FileAllocationEntry(requestGroup, 0) {}
const BtContextHandle& btContext,
int32_t interval):
BtContextAwareCommand(cuid, btContext),
e(e),
interval(interval) {}
TorrentAutoSaveCommand::~TorrentAutoSaveCommand() {} BtFileAllocationEntry::~BtFileAllocationEntry() {}
bool TorrentAutoSaveCommand::execute() { Commands BtFileAllocationEntry::prepareForNextAction(DownloadEngine* e)
if(checkPoint.elapsed(interval) || btRuntime->isHalt()) { {
checkPoint.reset(); Commands commands = BtSetup().setup(_requestGroup, e, e->option);
btProgressInfoFile->save(); // TODO don't integerate http/ftp when multi-file torrent
if(btRuntime->isHalt()) { Commands streamCommands = _requestGroup->createNextCommandWithAdj(e, 0);
return true; copy(streamCommands.begin(), streamCommands.end(), back_inserter(commands));
} return commands;
}
e->commands.push_back(this);
return false;
} }

View File

@ -0,0 +1,56 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_BT_FILE_ALLOCATION_ENTRY_H_
#define _D_BT_FILE_ALLOCATION_ENTRY_H_
#include "FileAllocationEntry.h"
class RequestGroup;
class DownloadEngine;
class Command;
extern typedef deque<Command*> Commands;
class BtFileAllocationEntry : public FileAllocationEntry {
public:
BtFileAllocationEntry(RequestGroup* requestGroup);
virtual ~BtFileAllocationEntry();
virtual Commands prepareForNextAction(DownloadEngine* e);
};
typedef SharedHandle<BtFileAllocationEntry> BtFileAllocationEntryHandle;
#endif // _D_BT_FILE_ALLOCATION_ENTRY_H_

View File

@ -39,8 +39,8 @@
#include "DlAbortEx.h" #include "DlAbortEx.h"
#include "BtChokingEvent.h" #include "BtChokingEvent.h"
#include "BtCancelSendingPieceEvent.h" #include "BtCancelSendingPieceEvent.h"
#include "DiskAdaptorWriter.h"
#include "MessageDigestHelper.h" #include "MessageDigestHelper.h"
#include "DiskAdaptor.h"
void BtPieceMessage::setBlock(const unsigned char* block, int32_t blockLength) { void BtPieceMessage::setBlock(const unsigned char* block, int32_t blockLength) {
delete [] this->block; delete [] this->block;
@ -193,7 +193,7 @@ bool BtPieceMessage::checkPieceHash(const PieceHandle& piece) {
int64_t offset = int64_t offset =
((int64_t)piece->getIndex())*btContext->getPieceLength(); ((int64_t)piece->getIndex())*btContext->getPieceLength();
return MessageDigestHelper::digest("sha1", new DiskAdaptorWriter(pieceStorage->getDiskAdaptor()), offset, piece->getLength()) return MessageDigestHelper::digest("sha1", pieceStorage->getDiskAdaptor(), offset, piece->getLength())
== btContext->getPieceHash(piece->getIndex()); == btContext->getPieceHash(piece->getIndex());
} }

View File

@ -32,28 +32,31 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#include "ConsoleFileAllocationMonitor.h" #include "BtPostDownloadHandler.h"
#include "Util.h" #include "DefaultBtContext.h"
#include "prefs.h"
#include "RequestGroup.h"
#include "Option.h"
void ConsoleFileAllocationMonitor::showProgress() { BtPostDownloadHandler::BtPostDownloadHandler(const Option* option):
int32_t progressPercentage = (int32_t)(((current-min)*1.0/(max-min))*100); PostDownloadHandler(".torrent", option)
int32_t numOfStar = progressPercentage/10*2; {}
cout << "\r "; BtPostDownloadHandler::~BtPostDownloadHandler() {}
cout << "\r";
cout << "|"; RequestGroups BtPostDownloadHandler::getNextRequestGroups(const string& path)
for(int32_t i = 0; i < numOfStar; ++i) { {
cout << "*"; RequestGroupHandle rg = new RequestGroup(_option, Strings());
DefaultBtContextHandle btContext = new DefaultBtContext();
btContext->load(path);
if(_option->defined(PREF_PEER_ID_PREFIX)) {
btContext->setPeerIdPrefix(_option->get(PREF_PEER_ID_PREFIX));
} }
for(int32_t i = 0; i < 20-numOfStar; ++i) { btContext->setDir(_option->get(PREF_DIR));
cout << " "; rg->setDownloadContext(btContext);
} btContext->setOwnerRequestGroup(rg.get());
cout << "|";
cout << progressPercentage << "%"; RequestGroups groups;
cout << "("; groups.push_back(rg);
cout << Util::ullitos(current, true) << "/" << Util::ullitos(max, true); return groups;
cout << ")";
cout << flush;
// Example,
// |******************* | 95%(1,333,3256/1,553,3232 bytes)
} }

View File

@ -0,0 +1,51 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_BT_POST_DOWNLOAD_HANDLER_H_
#define _D_BT_POST_DOWNLOAD_HANDLER_H_
#include "PostDownloadHandler.h"
class BtPostDownloadHandler:public PostDownloadHandler
{
public:
BtPostDownloadHandler(const Option* option);
virtual ~BtPostDownloadHandler();
virtual RequestGroups getNextRequestGroups(const string& path);
};
typedef SharedHandle<BtPostDownloadHandler> BtPostDownloadHandlerHandle;
#endif // _D_BT_POST_DOWNLOAD_HANDLER_H_

View File

@ -43,8 +43,6 @@ public:
virtual string getFilename() = 0; virtual string getFilename() = 0;
virtual void setFilename(const string& filename) = 0;
virtual bool exists() = 0; virtual bool exists() = 0;
virtual void save() = 0; virtual void save() = 0;

View File

@ -35,6 +35,7 @@
#include "BtRegistry.h" #include "BtRegistry.h"
#include "DlAbortEx.h" #include "DlAbortEx.h"
BtContextMap BtRegistry::btContextMap;
PeerStorageMap BtRegistry::peerStorageMap; PeerStorageMap BtRegistry::peerStorageMap;
PieceStorageMap BtRegistry::pieceStorageMap; PieceStorageMap BtRegistry::pieceStorageMap;
BtAnnounceMap BtRegistry::btAnnounceMap; BtAnnounceMap BtRegistry::btAnnounceMap;
@ -42,93 +43,77 @@ BtRuntimeMap BtRegistry::btRuntimeMap;
BtProgressInfoFileMap BtRegistry::btProgressInfoFileMap; BtProgressInfoFileMap BtRegistry::btProgressInfoFileMap;
PeerObjectClusterRegistry BtRegistry::peerObjectClusterRegistry; PeerObjectClusterRegistry BtRegistry::peerObjectClusterRegistry;
PeerStorageHandle BtRegistry::getPeerStorage(const string& key) { PeerStorageHandle BtRegistry::getPeerStorage(const string& key)
PeerStorageMap::iterator itr = peerStorageMap.find(key); {
if(itr == peerStorageMap.end()) { return peerStorageMap.getHandle(key);
return PeerStorageHandle(0);
} else {
return itr->second;
}
} }
bool BtRegistry::registerPeerStorage(const string& key, void BtRegistry::registerPeerStorage(const string& key,
const PeerStorageHandle& peerStorage) { const PeerStorageHandle& peerStorage)
PeerStorageMap::value_type p(key, peerStorage); {
pair<PeerStorageMap::iterator, bool> retval = peerStorageMap.insert(p); peerStorageMap.registerHandle(key, peerStorage);
return retval.second;
} }
PieceStorageHandle PieceStorageHandle
BtRegistry::getPieceStorage(const string& key) { BtRegistry::getPieceStorage(const string& key)
PieceStorageMap::iterator itr = pieceStorageMap.find(key); {
if(itr == pieceStorageMap.end()) { return pieceStorageMap.getHandle(key);
return PieceStorageHandle(0);
} else {
return itr->second;
}
} }
bool void
BtRegistry::registerPieceStorage(const string& key, BtRegistry::registerPieceStorage(const string& key,
const PieceStorageHandle& pieceStorage) { const PieceStorageHandle& pieceStorage)
pieceStorageMap.erase(key); {
PieceStorageMap::value_type p(key, pieceStorage); pieceStorageMap.registerHandle(key, pieceStorage);
pair<PieceStorageMap::iterator, bool> retval = pieceStorageMap.insert(p);
return retval.second;
} }
BtRuntimeHandle BtRegistry::getBtRuntime(const string& key) { BtRuntimeHandle BtRegistry::getBtRuntime(const string& key)
BtRuntimeMap::iterator itr = btRuntimeMap.find(key); {
if(itr == btRuntimeMap.end()) { return btRuntimeMap.getHandle(key);
return BtRuntimeHandle(0);
} else {
return itr->second;
}
} }
bool void
BtRegistry::registerBtRuntime(const string& key, BtRegistry::registerBtRuntime(const string& key,
const BtRuntimeHandle& btRuntime) { const BtRuntimeHandle& btRuntime)
BtRuntimeMap::value_type p(key, btRuntime); {
pair<BtRuntimeMap::iterator, bool> retval = btRuntimeMap.registerHandle(key, btRuntime);
btRuntimeMap.insert(p);
return retval.second;
} }
BtAnnounceHandle BtRegistry::getBtAnnounce(const string& key) { BtAnnounceHandle BtRegistry::getBtAnnounce(const string& key)
BtAnnounceMap::iterator itr = btAnnounceMap.find(key); {
if(itr == btAnnounceMap.end()) { return btAnnounceMap.getHandle(key);
return BtAnnounceHandle(0);
} else {
return itr->second;
}
} }
bool void
BtRegistry::registerBtAnnounce(const string& key, BtRegistry::registerBtAnnounce(const string& key,
const BtAnnounceHandle& btAnnounce) { const BtAnnounceHandle& btAnnounce)
BtAnnounceMap::value_type p(key, btAnnounce); {
pair<BtAnnounceMap::iterator, bool> retval = btAnnounceMap.registerHandle(key, btAnnounce);
btAnnounceMap.insert(p);
return retval.second;
} }
BtProgressInfoFileHandle BtRegistry::getBtProgressInfoFile(const string& key) { BtProgressInfoFileHandle BtRegistry::getBtProgressInfoFile(const string& key)
BtProgressInfoFileMap::iterator itr = btProgressInfoFileMap.find(key); {
if(itr == btProgressInfoFileMap.end()) { return btProgressInfoFileMap.getHandle(key);
return BtProgressInfoFileHandle(0);
} else {
return itr->second;
}
} }
bool void
BtRegistry::registerBtProgressInfoFile(const string& key, BtRegistry::registerBtProgressInfoFile(const string& key,
const BtProgressInfoFileHandle& btProgressInfoFile) { const BtProgressInfoFileHandle& btProgressInfoFile)
BtProgressInfoFileMap::value_type p(key, btProgressInfoFile); {
pair<BtProgressInfoFileMap::iterator, bool> retval = btProgressInfoFileMap.registerHandle(key, btProgressInfoFile);
btProgressInfoFileMap.insert(p); }
return retval.second;
BtContextHandle
BtRegistry::getBtContext(const string& key)
{
return btContextMap.getHandle(key);
}
void
BtRegistry::registerBtContext(const string& key,
const BtContextHandle& btContext)
{
btContextMap.registerHandle(key, btContext);
} }
PeerObjectClusterHandle PeerObjectClusterHandle
@ -150,7 +135,8 @@ BtRegistry::unregisterPeerObjectCluster(const string& key)
peerObjectClusterRegistry.unregisterHandle(key); peerObjectClusterRegistry.unregisterHandle(key);
} }
void BtRegistry::clear() { void BtRegistry::unregisterAll() {
btContextMap.clear();
peerStorageMap.clear(); peerStorageMap.clear();
pieceStorageMap.clear(); pieceStorageMap.clear();
btAnnounceMap.clear(); btAnnounceMap.clear();
@ -158,3 +144,14 @@ void BtRegistry::clear() {
btProgressInfoFileMap.clear(); btProgressInfoFileMap.clear();
peerObjectClusterRegistry.clear(); peerObjectClusterRegistry.clear();
} }
void BtRegistry::unregister(const string& key)
{
btContextMap.unregisterHandle(key);
peerStorageMap.unregisterHandle(key);
pieceStorageMap.unregisterHandle(key);
btAnnounceMap.unregisterHandle(key);
btRuntimeMap.unregisterHandle(key);
btProgressInfoFileMap.unregisterHandle(key);
peerObjectClusterRegistry.unregisterHandle(key);
}

View File

@ -36,6 +36,7 @@
#define _D_BT_REGISTRY_H_ #define _D_BT_REGISTRY_H_
#include "common.h" #include "common.h"
#include "BtContext.h"
#include "PeerStorage.h" #include "PeerStorage.h"
#include "PieceStorage.h" #include "PieceStorage.h"
#include "BtAnnounce.h" #include "BtAnnounce.h"
@ -45,11 +46,12 @@
#include "HandleRegistry.h" #include "HandleRegistry.h"
#include <map> #include <map>
typedef map<string, PeerStorageHandle> PeerStorageMap; typedef HandleRegistry<string, PeerStorage> PeerStorageMap;
typedef map<string, PieceStorageHandle> PieceStorageMap; typedef HandleRegistry<string, PieceStorage> PieceStorageMap;
typedef map<string, BtAnnounceHandle> BtAnnounceMap; typedef HandleRegistry<string, BtAnnounce> BtAnnounceMap;
typedef map<string, BtRuntimeHandle> BtRuntimeMap; typedef HandleRegistry<string, BtRuntime> BtRuntimeMap;
typedef map<string, BtProgressInfoFileHandle> BtProgressInfoFileMap; typedef HandleRegistry<string, BtProgressInfoFile> BtProgressInfoFileMap;
typedef HandleRegistry<string, BtContext> BtContextMap;
// for BtMessageFactory // for BtMessageFactory
typedef HandleRegistry<string, PeerObject> PeerObjectCluster; typedef HandleRegistry<string, PeerObject> PeerObjectCluster;
@ -60,6 +62,7 @@ class BtRegistry {
private: private:
BtRegistry() {} BtRegistry() {}
static BtContextMap btContextMap;
static PeerStorageMap peerStorageMap; static PeerStorageMap peerStorageMap;
static PieceStorageMap pieceStorageMap; static PieceStorageMap pieceStorageMap;
static BtAnnounceMap btAnnounceMap; static BtAnnounceMap btAnnounceMap;
@ -67,24 +70,28 @@ private:
static BtProgressInfoFileMap btProgressInfoFileMap; static BtProgressInfoFileMap btProgressInfoFileMap;
static PeerObjectClusterRegistry peerObjectClusterRegistry; static PeerObjectClusterRegistry peerObjectClusterRegistry;
public: public:
static BtContextHandle getBtContext(const string& key);
static void registerBtContext(const string& key,
const BtContextHandle& btContext);
static PeerStorageHandle getPeerStorage(const string& key); static PeerStorageHandle getPeerStorage(const string& key);
static bool registerPeerStorage(const string& key, static void registerPeerStorage(const string& key,
const PeerStorageHandle& peer); const PeerStorageHandle& peer);
static PieceStorageHandle getPieceStorage(const string& key); static PieceStorageHandle getPieceStorage(const string& key);
static bool registerPieceStorage(const string& key, static void registerPieceStorage(const string& key,
const PieceStorageHandle& pieceStorage); const PieceStorageHandle& pieceStorage);
static BtRuntimeHandle getBtRuntime(const string& key); static BtRuntimeHandle getBtRuntime(const string& key);
static bool registerBtRuntime(const string& key, static void registerBtRuntime(const string& key,
const BtRuntimeHandle& btRuntime); const BtRuntimeHandle& btRuntime);
static BtAnnounceHandle getBtAnnounce(const string& key); static BtAnnounceHandle getBtAnnounce(const string& key);
static bool registerBtAnnounce(const string& key, static void registerBtAnnounce(const string& key,
const BtAnnounceHandle& btAnnounce); const BtAnnounceHandle& btAnnounce);
static BtProgressInfoFileHandle getBtProgressInfoFile(const string& key); static BtProgressInfoFileHandle getBtProgressInfoFile(const string& key);
static bool registerBtProgressInfoFile(const string& key, static void registerBtProgressInfoFile(const string& key,
const BtProgressInfoFileHandle& btProgressInfoFile); const BtProgressInfoFileHandle& btProgressInfoFile);
// for PeerObject // for PeerObject
@ -98,7 +105,9 @@ public:
static void static void
unregisterPeerObjectCluster(const string& key); unregisterPeerObjectCluster(const string& key);
static void clear(); static void unregisterAll();
static void unregister(const string& key);
}; };
#define PEER_STORAGE(btContext) \ #define PEER_STORAGE(btContext) \

View File

@ -46,12 +46,14 @@ private:
int32_t port; int32_t port;
bool halt; bool halt;
int32_t connections; int32_t connections;
bool _ready;
public: public:
BtRuntime(): BtRuntime():
uploadLengthAtStartup(0), uploadLengthAtStartup(0),
port(0), port(0),
halt(false), halt(false),
connections(0) connections(0),
_ready(false)
{} {}
~BtRuntime() {} ~BtRuntime() {}
@ -83,7 +85,11 @@ public:
bool lessThanMinPeer() const { return connections < MIN_PEERS; } bool lessThanMinPeer() const { return connections < MIN_PEERS; }
bool lessThanEqMinPeer() const { return connections <= MIN_PEERS; } bool lessThanEqMinPeer() const { return connections <= MIN_PEERS; }
bool ready() { return _ready; }
void setReady(bool go) { _ready = go; }
}; };
typedef SharedHandle<BtRuntime> BtRuntimeHandle; typedef SharedHandle<BtRuntime> BtRuntimeHandle;

97
src/BtSetup.cc Normal file
View File

@ -0,0 +1,97 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "BtSetup.h"
#include "RequestGroup.h"
#include "DownloadEngine.h"
#include "Option.h"
#include "BtRegistry.h"
#include "PeerListenCommand.h"
#include "TrackerWatcherCommand.h"
#include "SeedCheckCommand.h"
#include "PeerChokeCommand.h"
#include "ActivePeerConnectionCommand.h"
#include "UnionSeedCriteria.h"
#include "TimeSeedCriteria.h"
#include "ShareRatioSeedCriteria.h"
#include "DefaultPieceStorage.h"
#include "DefaultBtProgressInfoFile.h"
#include "CUIDCounter.h"
#include "prefs.h"
Commands BtSetup::setup(RequestGroup* requestGroup,
DownloadEngine* e,
const Option* option)
{
Commands commands;
BtContextHandle btContext = requestGroup->getDownloadContext();
if(btContext.isNull()) {
return commands;
}
// TODO following process is moved to BtSetup
// commands
commands.push_back(new TrackerWatcherCommand(CUIDCounterSingletonHolder::instance()->newID(),
requestGroup,
e,
btContext));
commands.push_back(new PeerChokeCommand(CUIDCounterSingletonHolder::instance()->newID(),
requestGroup,
e,
btContext,
10));
commands.push_back(new ActivePeerConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(),
requestGroup,
e,
btContext,
30));
SharedHandle<UnionSeedCriteria> unionCri = new UnionSeedCriteria();
if(option->defined(PREF_SEED_TIME)) {
unionCri->addSeedCriteria(new TimeSeedCriteria(option->getAsInt(PREF_SEED_TIME)*60));
}
if(option->defined(PREF_SEED_RATIO)) {
unionCri->addSeedCriteria(new ShareRatioSeedCriteria(option->getAsDouble(PREF_SEED_RATIO), btContext));
}
if(unionCri->getSeedCriterion().size() > 0) {
commands.push_back(new SeedCheckCommand(CUIDCounterSingletonHolder::instance()->newID(),
requestGroup,
e,
btContext,
unionCri));
}
BT_RUNTIME(btContext)->setReady(true);
return commands;
}

View File

@ -32,20 +32,22 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#ifndef _D_DEFAULT_FILE_ALLOCATOR_H_ #ifndef _D_BT_SETUP_H_
#define _D_DEFAULT_FILE_ALLOCATOR_H_ #define _D_BT_SETUP_H_
#include "FileAllocator.h" #include "common.h"
class DefaultFileAllocator : public FileAllocator { class RequestGroup;
class DownloadEngine;
class Option;
class Command;
extern typedef deque<Command*> Commands;
class BtSetup {
public: public:
DefaultFileAllocator() {} Commands setup(RequestGroup* requestGroup,
DownloadEngine* e,
virtual ~DefaultFileAllocator() {} const Option* option);
virtual void allocate(int fd, int64_t totalLength);
}; };
typedef SharedHandle<DefaultFileAllocator> DefaultFileAllocatorHandle; #endif // _D_BT_SETUP_H_
#endif // _D_DEFAULT_FILE_ALLOCATOR_H_

View File

@ -38,34 +38,35 @@
ByteArrayDiskWriter::ByteArrayDiskWriter() { ByteArrayDiskWriter::ByteArrayDiskWriter() {
} }
ByteArrayDiskWriter::~ByteArrayDiskWriter() { ByteArrayDiskWriter::~ByteArrayDiskWriter() {}
closeFile();
}
void ByteArrayDiskWriter::clear() { void ByteArrayDiskWriter::clear()
{
buf.str(""); buf.str("");
} }
void ByteArrayDiskWriter::initAndOpenFile(const string& filename, void ByteArrayDiskWriter::initAndOpenFile(const string& filename,
int64_t totalLength) { int64_t totalLength)
{
clear(); clear();
} }
void ByteArrayDiskWriter::openFile(const string& filename, void ByteArrayDiskWriter::openFile(const string& filename,
int64_t totalLength) { int64_t totalLength)
initAndOpenFile(filename); {
} }
void ByteArrayDiskWriter::closeFile() { void ByteArrayDiskWriter::closeFile()
clear(); {}
}
void ByteArrayDiskWriter::openExistingFile(const string& filename, void ByteArrayDiskWriter::openExistingFile(const string& filename,
int64_t totalLength) { int64_t totalLength)
{
openFile(filename); openFile(filename);
} }
void ByteArrayDiskWriter::writeData(const char* data, int32_t dataLength, int64_t position) { void ByteArrayDiskWriter::writeData(const unsigned char* data, int32_t dataLength, int64_t position)
{
if(size() < position) { if(size() < position) {
buf.seekg(0, ios::end); buf.seekg(0, ios::end);
for(int32_t i = size(); i < position; ++i) { for(int32_t i = size(); i < position; ++i) {
@ -74,12 +75,13 @@ void ByteArrayDiskWriter::writeData(const char* data, int32_t dataLength, int64_
} else { } else {
buf.seekg(position, ios::beg); buf.seekg(position, ios::beg);
} }
buf.write(data, dataLength); buf.write(reinterpret_cast<const char*>(data), dataLength);
} }
int32_t ByteArrayDiskWriter::readData(char* data, int32_t len, int64_t position) { int32_t ByteArrayDiskWriter::readData(unsigned char* data, int32_t len, int64_t position)
{
buf.seekg(position, ios::beg); buf.seekg(position, ios::beg);
buf.read(data, len); buf.read(reinterpret_cast<char*>(data), len);
// TODO we have to call buf.clear() here? YES // TODO we have to call buf.clear() here? YES
buf.clear(); buf.clear();
return buf.gcount(); return buf.gcount();

View File

@ -55,9 +55,8 @@ public:
virtual void openExistingFile(const string& filename, int64_t totalLength = 0); virtual void openExistingFile(const string& filename, int64_t totalLength = 0);
// position is ignored virtual void writeData(const unsigned char* data, int32_t len, int64_t position);
virtual void writeData(const char* data, int32_t len, int64_t position = 0); virtual int32_t readData(unsigned char* data, int32_t len, int64_t position);
virtual int32_t readData(char* data, int32_t len, int64_t position);
// Not implemented yet // Not implemented yet
virtual void truncate(int64_t length) {} virtual void truncate(int64_t length) {}

View File

@ -0,0 +1,52 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_BYTE_ARRAY_DISK_WRITER_FACTORY_H_
#define _D_BYTE_ARRAY_DISK_WRITER_FACTORY_H_
#include "DiskWriterFactory.h"
#include "ByteArrayDiskWriter.h"
class ByteArrayDiskWriterFactory:public DiskWriterFactory
{
public:
DiskWriterHandle newDiskWriter()
{
return new ByteArrayDiskWriter();
}
};
typedef SharedHandle<ByteArrayDiskWriterFactory> ByteArrayDiskWriterFactoryHandle;
#endif // _D_BYTE_ARRAY_DISK_WRITER_FACTORY_H_

View File

@ -33,6 +33,9 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "CheckIntegrityCommand.h" #include "CheckIntegrityCommand.h"
#include "CheckIntegrityMan.h"
#include "CheckIntegrityEntry.h"
#include "RequestGroup.h"
#include "FileAllocationEntry.h" #include "FileAllocationEntry.h"
#include "InitiateConnectionCommandFactory.h" #include "InitiateConnectionCommandFactory.h"
#include "DlAbortEx.h" #include "DlAbortEx.h"
@ -40,7 +43,7 @@
#include "DownloadCommand.h" #include "DownloadCommand.h"
#include "prefs.h" #include "prefs.h"
CheckIntegrityCommand::CheckIntegrityCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const CheckIntegrityEntryHandle& entry): CheckIntegrityCommand::CheckIntegrityCommand(int32_t cuid, RequestGroup* requestGroup, DownloadEngine* e, const CheckIntegrityEntryHandle& entry):
RealtimeCommand(cuid, requestGroup, e), RealtimeCommand(cuid, requestGroup, e),
_entry(entry) _entry(entry)
{ {
@ -54,25 +57,16 @@ CheckIntegrityCommand::~CheckIntegrityCommand()
bool CheckIntegrityCommand::executeInternal() bool CheckIntegrityCommand::executeInternal()
{ {
if(_requestGroup->isHaltRequested()) {
return true;
}
_entry->validateChunk(); _entry->validateChunk();
if(_entry->finished()) { if(_entry->finished()) {
_entry->updatePieceStorage();
if(_requestGroup->downloadFinished()) { if(_requestGroup->downloadFinished()) {
logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, cuid, _requestGroup->getFilePath().c_str()); logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, cuid, _requestGroup->getFilePath().c_str());
return true;
}
if(_requestGroup->needsFileAllocation()) {
FileAllocationEntryHandle entry = new FileAllocationEntry(cuid, _entry->getCurrentRequest(), _requestGroup, _entry->popNextDownloadCommand(), _requestGroup->getExistingFileLength());
_e->_fileAllocationMan->pushFileAllocationEntry(entry);
} else { } else {
if(_timer.difference() <= _e->option->getAsInt(PREF_DIRECT_DOWNLOAD_TIMEOUT) && _e->addCommand(_entry->prepareForNextAction(_e));
_entry->getNextDownloadCommand()) {
_e->commands.push_back(_entry->popNextDownloadCommand());
} else {
Commands commands = _requestGroup->createNextCommandWithAdj(_e, -1);
Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, _entry->getCurrentRequest(), _requestGroup, _e);
commands.push_front(command);
_e->addCommand(commands);
}
} }
return true; return true;
} else { } else {
@ -84,12 +78,6 @@ bool CheckIntegrityCommand::executeInternal()
bool CheckIntegrityCommand::handleException(Exception* e) bool CheckIntegrityCommand::handleException(Exception* e)
{ {
logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid); logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid);
delete e;
logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str()); logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str());
// TODO this is wrong. There may exist invalid chunk data before catching
// exception. Fix this.
// The one of the solution is having a copy of bitfield before settting its
// all bit to 1. If exception is thrown, then assign the copy to the bitfield.
_requestGroup->markPieceDone(_entry->getCurrentLength());
return true; return true;
} }

View File

@ -36,16 +36,17 @@
#define _D_CHECK_INTEGRITY_COMMAND_H_ #define _D_CHECK_INTEGRITY_COMMAND_H_
#include "RealtimeCommand.h" #include "RealtimeCommand.h"
#include "IteratableChunkChecksumValidator.h"
#include "CheckIntegrityEntry.h"
#include "TimeA2.h" #include "TimeA2.h"
class CheckIntegrityEntry;
extern typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
class CheckIntegrityCommand : public RealtimeCommand { class CheckIntegrityCommand : public RealtimeCommand {
private: private:
CheckIntegrityEntryHandle _entry; CheckIntegrityEntryHandle _entry;
Time _timer; Time _timer;
public: public:
CheckIntegrityCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const CheckIntegrityEntryHandle& entry); CheckIntegrityCommand(int32_t cuid, RequestGroup* requestGroup, DownloadEngine* e, const CheckIntegrityEntryHandle& entry);
virtual ~CheckIntegrityCommand(); virtual ~CheckIntegrityCommand();

View File

@ -34,33 +34,64 @@
/* copyright --> */ /* copyright --> */
#include "CheckIntegrityEntry.h" #include "CheckIntegrityEntry.h"
#include "DlAbortEx.h" #include "DlAbortEx.h"
#include "Command.h"
#include "RequestGroup.h"
#include "IteratableChunkChecksumValidator.h"
#include "DownloadContext.h"
#include "DownloadEngine.h"
CheckIntegrityEntry::CheckIntegrityEntry(RequestGroup* requestGroup,
Command* nextCommand):
RequestGroupEntry(requestGroup, nextCommand),
_validator(0)
{}
CheckIntegrityEntry::~CheckIntegrityEntry() {}
void CheckIntegrityEntry::validateChunk() void CheckIntegrityEntry::validateChunk()
{ {
_validator->validateChunk(); _validator->validateChunk();
} }
bool CheckIntegrityEntry::finished() const int64_t CheckIntegrityEntry::getTotalLength()
{
if(_validator.isNull()) {
return 0;
} else {
return _validator->getTotalLength();
}
}
int64_t CheckIntegrityEntry::getCurrentLength()
{
if(_validator.isNull()) {
return 0;
} else {
return _validator->getCurrentOffset();
}
}
bool CheckIntegrityEntry::finished()
{ {
return _validator->finished(); return _validator->finished();
} }
int64_t CheckIntegrityEntry::getCurrentLength() const bool CheckIntegrityEntry::isValidationReady()
{ {
return _validator->getCurrentOffset(); DownloadContextHandle dctx = _requestGroup->getDownloadContext();
return dctx->getPieceHashes().size() > 0 &&
dctx->getPieceHashes().size() == (uint32_t)dctx->getNumPieces();
} }
void CheckIntegrityEntry::initValidator() void CheckIntegrityEntry::initValidator()
{ {
IteratableChunkChecksumValidatorHandle validator = IteratableChunkChecksumValidatorHandle validator =
new IteratableChunkChecksumValidator(); new IteratableChunkChecksumValidator(_requestGroup->getDownloadContext(),
validator->setChunkChecksum(_requestGroup->getChunkChecksum()); _requestGroup->getPieceStorage());
validator->setDiskWriter(_requestGroup->getSegmentMan()->diskWriter);
validator->setBitfield(_requestGroup->getSegmentMan()->getBitfield());
if(!validator->canValidate()) {
// insufficient checksums.
throw new DlAbortEx("Insufficient checksums.");
}
validator->init();
_validator = validator; _validator = validator;
} }
void CheckIntegrityEntry::updatePieceStorage()
{
_validator->updatePieceStorage();
}

View File

@ -36,29 +36,37 @@
#define _D_CHECK_INTEGRITY_ENTRY_H_ #define _D_CHECK_INTEGRITY_ENTRY_H_
#include "RequestGroupEntry.h" #include "RequestGroupEntry.h"
#include "IteratableChunkChecksumValidator.h"
class CheckIntegrityEntry : public RequestGroupEntry { class IteratableChunkChecksumValidator;
extern typedef SharedHandle<IteratableChunkChecksumValidator> IteratableChunkChecksumValidatorHandle;
class Command;
extern typedef deque<Command*> Commands;
class DownloadEngine;
class CheckIntegrityEntry : public RequestGroupEntry,
public ProgressAwareEntry {
private: private:
IteratableChunkChecksumValidatorHandle _validator; IteratableChunkChecksumValidatorHandle _validator;
public: public:
CheckIntegrityEntry(int cuid, CheckIntegrityEntry(RequestGroup* requestGroup, Command* nextCommand = 0);
const RequestHandle& currentRequest,
RequestGroup* requestGroup,
DownloadCommand* nextDownloadCommand = 0):
RequestGroupEntry(cuid, currentRequest, requestGroup, nextDownloadCommand),
_validator(0)
{}
virtual ~CheckIntegrityEntry() {} virtual ~CheckIntegrityEntry();
virtual int64_t getCurrentLength() const; virtual int64_t getTotalLength();
virtual bool finished() const; virtual int64_t getCurrentLength();
virtual bool finished();
bool isValidationReady();
void initValidator(); void initValidator();
void validateChunk(); void validateChunk();
void updatePieceStorage();
virtual Commands prepareForNextAction(DownloadEngine* e) = 0;
}; };
typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle; typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;

72
src/CheckIntegrityMan.cc Normal file
View File

@ -0,0 +1,72 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "CheckIntegrityMan.h"
#include "CheckIntegrityEntry.h"
CheckIntegrityMan::CheckIntegrityMan() {}
CheckIntegrityMan::~CheckIntegrityMan() {}
void CheckIntegrityMan::addCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry)
{
_checkIntegrityEntries.push_back(entry);
}
bool CheckIntegrityMan::removeCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry)
{
CheckIntegrityEntries::iterator itr = find(_checkIntegrityEntries.begin(),
_checkIntegrityEntries.end(),
entry);
if(itr == _checkIntegrityEntries.end()) {
return false;
} else {
_checkIntegrityEntries.erase(itr);
return true;
}
}
CheckIntegrityEntryHandle CheckIntegrityMan::getFirstCheckIntegrityEntry() const
{
if(_checkIntegrityEntries.empty()) {
return 0;
} else {
return _checkIntegrityEntries.front();
}
}
int32_t CheckIntegrityMan::countCheckIntegrityEntry() const
{
return _checkIntegrityEntries.size();
}

View File

@ -36,43 +36,26 @@
#define _D_CHECK_INTEGRITY_MAN_H_ #define _D_CHECK_INTEGRITY_MAN_H_
#include "common.h" #include "common.h"
#include "CheckIntegrityEntry.h"
class CheckIntegrityEntry;
extern typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
extern typedef deque<CheckIntegrityEntryHandle> CheckIntegrityEntries;
class CheckIntegrityMan { class CheckIntegrityMan {
private: private:
CheckIntegrityEntries _checkIntegrityEntries; CheckIntegrityEntries _checkIntegrityEntries;
public: public:
void addCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry) CheckIntegrityMan();
{
_checkIntegrityEntries.push_back(entry);
}
bool removeCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry) ~CheckIntegrityMan();
{
CheckIntegrityEntries::iterator itr = find(_checkIntegrityEntries.begin(),
_checkIntegrityEntries.end(),
entry);
if(itr == _checkIntegrityEntries.end()) {
return false;
} else {
_checkIntegrityEntries.erase(itr);
return true;
}
}
CheckIntegrityEntryHandle getFirstCheckIntegrityEntry() const void addCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry);
{
if(_checkIntegrityEntries.empty()) {
return 0;
} else {
return _checkIntegrityEntries.front();
}
}
int32_t countCheckIntegrityEntry() const bool removeCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry);
{
return _checkIntegrityEntries.size(); CheckIntegrityEntryHandle getFirstCheckIntegrityEntry() const;
}
int32_t countCheckIntegrityEntry() const;
}; };
typedef SharedHandle<CheckIntegrityMan> CheckIntegrityManHandle; typedef SharedHandle<CheckIntegrityMan> CheckIntegrityManHandle;

View File

@ -39,9 +39,11 @@
void ChecksumCommand::initValidator() void ChecksumCommand::initValidator()
{ {
_validator = new IteratableChecksumValidator(); _validator = new IteratableChecksumValidator();
_validator->setChecksum(_requestGroup->getChecksum()); // TODO checksum will be held by DownloadContext
_validator->setDiskWriter(_requestGroup->getSegmentMan()->diskWriter); _validator->setChecksum(0);
_validator->setBitfield(_requestGroup->getSegmentMan()->getBitfield()); //_validator->setDiskWriter(new DiskAdaptorWriter(_requestGroup->getSegmentMan()->getDiskAdaptor()));
// TODO we should use PieceStorage instead of BitfieldMan
//_validator->setBitfield(_requestGroup->getSegmentMan()->getBitfield());
if(!_validator->canValidate()) { if(!_validator->canValidate()) {
// insufficient checksums. // insufficient checksums.
throw new DlAbortEx(EX_INSUFFICIENT_CHECKSUM); throw new DlAbortEx(EX_INSUFFICIENT_CHECKSUM);
@ -51,6 +53,9 @@ void ChecksumCommand::initValidator()
bool ChecksumCommand::executeInternal() bool ChecksumCommand::executeInternal()
{ {
if(_e->isHaltRequested()) {
return true;
}
_validator->validateChunk(); _validator->validateChunk();
if(_validator->finished()) { if(_validator->finished()) {
if(_requestGroup->downloadFinished()) { if(_requestGroup->downloadFinished()) {
@ -70,7 +75,6 @@ bool ChecksumCommand::executeInternal()
bool ChecksumCommand::handleException(Exception* e) bool ChecksumCommand::handleException(Exception* e)
{ {
logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid); logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid);
delete e;
logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str()); logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str());
// TODO We need to set bitfield back to the state when validation begun. // TODO We need to set bitfield back to the state when validation begun.
// The one of the solution is having a copy of bitfield before settting its // The one of the solution is having a copy of bitfield before settting its

View File

@ -47,12 +47,12 @@ public:
RealtimeCommand(cuid, requestGroup, e), RealtimeCommand(cuid, requestGroup, e),
_validator(0) _validator(0)
{ {
++_requestGroup->numConnection; _requestGroup->increaseNumCommand();
} }
virtual ~ChecksumCommand() virtual ~ChecksumCommand()
{ {
--_requestGroup->numConnection; _requestGroup->decreaseNumCommand();
} }
void initValidator(); void initValidator();

View File

@ -79,6 +79,11 @@ public:
return ""; return "";
} }
} }
const Strings& getChecksums() const
{
return _checksums;
}
int32_t getChecksumLength() const int32_t getChecksumLength() const
{ {

View File

@ -38,6 +38,7 @@
void ChunkChecksumValidator::validate() void ChunkChecksumValidator::validate()
{ {
/*
if(!_validator->canValidate()) { if(!_validator->canValidate()) {
// insufficient checksums. // insufficient checksums.
logger->error(MSG_INSUFFICIENT_CHECKSUM, logger->error(MSG_INSUFFICIENT_CHECKSUM,
@ -63,4 +64,5 @@ void ChunkChecksumValidator::validate()
} }
fileAllocationMonitor->setCurrentValue(numChecksum); fileAllocationMonitor->setCurrentValue(numChecksum);
fileAllocationMonitor->showProgress(); fileAllocationMonitor->showProgress();
*/
} }

View File

@ -1,210 +0,0 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "ConsoleDownloadEngine.h"
#include "Util.h"
#include <signal.h>
#include <iomanip>
volatile sig_atomic_t haltRequested = 0;
ConsoleDownloadEngine::ConsoleDownloadEngine() {}
ConsoleDownloadEngine::~ConsoleDownloadEngine() {}
void ConsoleDownloadEngine::sendStatistics(int64_t currentSize, int64_t totalSize) {
cout << "\r ";
cout << "\r";
if(_requestGroupMan->countRequestGroup() > 0) {
RequestGroupHandle firstRequestGroup = _requestGroupMan->getRequestGroup(0);
int32_t dlSpeed = firstRequestGroup->calculateDownloadSpeed();
int32_t eta = 0;
if(firstRequestGroup->getTotalLength() > 0 && dlSpeed > 0) {
eta = (firstRequestGroup->getTotalLength()-firstRequestGroup->getDownloadLength())/dlSpeed;
}
cout << "["
<< "#" << firstRequestGroup->getGID() << " "
<< "SIZE:"
<< Util::abbrevSize(firstRequestGroup->getDownloadLength())
<< "B"
<< "/"
<< Util::abbrevSize(firstRequestGroup->getTotalLength())
<< "B";
if(firstRequestGroup->getTotalLength() > 0) {
cout << "("
<< 100*firstRequestGroup->getDownloadLength()/firstRequestGroup->getTotalLength()
<< "%)";
}
cout << " "
<< "CN:"
<< firstRequestGroup->numConnection;
cout << " "
<< "SPD:"
<< fixed << setprecision(2) << dlSpeed/1024.0 << "KiB/s";
if(eta > 0) {
cout << " "
<< "ETA:"
<< Util::secfmt(eta);
}
cout << "]";
if(_requestGroupMan->countRequestGroup() > 1) {
cout << "("
<< _requestGroupMan->countRequestGroup()-1
<< "more...)";
}
}
if(_requestGroupMan->countRequestGroup() > 1) {
cout << " "
<< "[TOTAL SPD:"
<< fixed << setprecision(2) << speed/1024.0 << "KiB/s" << "]";
}
{
FileAllocationEntryHandle entry = _fileAllocationMan->getCurrentFileAllocationEntry();
if(!entry.isNull()) {
cout << " "
<< "[FileAlloc:"
<< "#" << entry->getRequestGroup()->getGID() << " "
<< Util::abbrevSize(entry->getCurrentLength())
<< "B"
<< "/"
<< Util::abbrevSize(entry->getTotalLength())
<< "B"
<< "("
<< 100*entry->getCurrentLength()/entry->getTotalLength()
<< "%)";
cout << "]";
if(_fileAllocationMan->countFileAllocationEntryInQueue() > 0) {
cout << "("
<< _fileAllocationMan->countFileAllocationEntryInQueue()
<< "waiting...)";
}
}
}
#ifdef ENABLE_MESSAGE_DIGEST
{
CheckIntegrityEntryHandle entry = _checkIntegrityMan->getFirstCheckIntegrityEntry();
if(!entry.isNull()) {
cout << " "
<< "[Checksum:"
<< "#" << entry->getRequestGroup()->getGID() << " "
<< Util::abbrevSize(entry->getCurrentLength())
<< "B"
<< "/"
<< Util::abbrevSize(entry->getTotalLength())
<< "B"
<< "("
<< 100*entry->getCurrentLength()/entry->getTotalLength()
<< "%)";
cout << "]";
if(_checkIntegrityMan->countCheckIntegrityEntry() > 1) {
cout << "("
<< _checkIntegrityMan->countCheckIntegrityEntry()-1
<< "more...)";
}
}
}
#endif // ENABLE_MESSAGE_DIGEST
cout << flush;
}
void ConsoleDownloadEngine::initStatistics() {
cp.reset();
startup.reset();
speed = 0;
psize = 0;
avgSpeed = 0;
eta = 0;
startupLength = 0;
isStartupLengthSet = false;
}
void ConsoleDownloadEngine::calculateStatistics() {
int64_t dlSize = _requestGroupMan->getDownloadLength();
if(!isStartupLengthSet && dlSize > 0) {
startupLength = dlSize;
psize = dlSize;
isStartupLengthSet = true;
}
int32_t elapsed = cp.difference();
if(elapsed >= 1) {
int32_t nspeed = (dlSize-psize)/elapsed;
if(nspeed < 0) {
nspeed = 0;
}
speed = (nspeed+speed)/2;
cp.reset();
psize = dlSize;
int32_t elapsedFromStartup = startup.difference();
if(elapsedFromStartup > 0) {
avgSpeed = (dlSize-startupLength)/elapsedFromStartup;
}
int64_t totalLength = _requestGroupMan->getTotalLength();
if(avgSpeed < 0) {
avgSpeed = 0;
} else if(avgSpeed != 0 && totalLength > 0) {
eta = (totalLength-dlSize)/avgSpeed;
}
sendStatistics(dlSize, totalLength);
}
}
void ConsoleDownloadEngine::onEndOfRun() {
_requestGroupMan->closeFile();
// if(segmentMan->finished()) {
// segmentMan->remove();
// } else {
// segmentMan->save();
// }
}
void ConsoleDownloadEngine::afterEachIteration() {
if(haltRequested) {
printf(_("\nstopping application...\n"));
fflush(stdout);
_requestGroupMan->save();
_requestGroupMan->closeFile();
printf(_("done\n"));
exit(EXIT_SUCCESS);
}
}
void ConsoleDownloadEngine::fillCommand()
{
addCommand(_requestGroupMan->getInitialCommands(this));
}

162
src/ConsoleStatCalc.cc Normal file
View File

@ -0,0 +1,162 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "ConsoleStatCalc.h"
#include "RequestGroupMan.h"
#include "RequestGroup.h"
#include "FileAllocationMan.h"
#include "FileAllocationEntry.h"
#include "CheckIntegrityMan.h"
#include "CheckIntegrityEntry.h"
#include "Util.h"
#include <iomanip>
void
ConsoleStatCalc::calculateStat(const RequestGroupManHandle& requestGroupMan,
const FileAllocationManHandle& fileAllocationMan,
const CheckIntegrityManHandle& checkIntegrityMan)
{
if(!_cp.elapsed(1)) {
return;
}
_cp.reset();
cout << "\r ";
cout << "\r";
if(requestGroupMan->countRequestGroup() > 0) {
RequestGroupHandle firstRequestGroup = requestGroupMan->getRequestGroup(0);
TransferStat stat = firstRequestGroup->calculateStat();
//int32_t dlSpeed = firstRequestGroup->calculateDownloadSpeed();
int32_t eta = 0;
if(firstRequestGroup->getTotalLength() > 0 && stat.getDownloadSpeed() > 0) {
eta = (firstRequestGroup->getTotalLength()-firstRequestGroup->getCompletedLength())/stat.getDownloadSpeed();
}
cout << "["
<< "#" << firstRequestGroup->getGID() << " "
<< "SIZE:"
<< Util::abbrevSize(firstRequestGroup->getCompletedLength())
<< "B"
<< "/"
<< Util::abbrevSize(firstRequestGroup->getTotalLength())
<< "B";
if(firstRequestGroup->getTotalLength() > 0) {
cout << "("
<< 100*firstRequestGroup->getCompletedLength()/firstRequestGroup->getTotalLength()
<< "%)";
}
cout << " "
<< "CN:"
<< firstRequestGroup->getNumConnection();
cout << " "
<< "SPD:"
<< fixed << setprecision(2) << stat.getDownloadSpeed()/1024.0 << "KiB/s";
if(stat.getSessionUploadLength() > 0) {
cout << " "
<< "UP:"
<< fixed << setprecision(2) << stat.getUploadSpeed()/1024.0 << "KiB/s"
<< "(" << Util::abbrevSize(stat.getAllTimeUploadLength()) << ")";
}
if(eta > 0) {
cout << " "
<< "ETA:"
<< Util::secfmt(eta);
}
cout << "]";
if(requestGroupMan->countRequestGroup() > 1) {
cout << "("
<< requestGroupMan->countRequestGroup()-1
<< "more...)";
}
}
if(requestGroupMan->countRequestGroup() > 1) {
TransferStat stat = requestGroupMan->calculateStat();
cout << " "
<< "[TOTAL SPD:"
<< fixed << setprecision(2) << stat.getDownloadSpeed()/1024.0 << "KiB/s" << "]";
}
{
FileAllocationEntryHandle entry = fileAllocationMan->getCurrentFileAllocationEntry();
if(!entry.isNull()) {
cout << " "
<< "[FileAlloc:"
<< "#" << entry->getRequestGroup()->getGID() << " "
<< Util::abbrevSize(entry->getCurrentLength())
<< "B"
<< "/"
<< Util::abbrevSize(entry->getTotalLength())
<< "B"
<< "(";
if(entry->getTotalLength() > 0) {
cout << 100*entry->getCurrentLength()/entry->getTotalLength();
} else {
cout << "--";
}
cout << "%)"
<< "]";
if(fileAllocationMan->countFileAllocationEntryInQueue() > 0) {
cout << "("
<< fileAllocationMan->countFileAllocationEntryInQueue()
<< "waiting...)";
}
}
}
#ifdef ENABLE_MESSAGE_DIGEST
{
CheckIntegrityEntryHandle entry = checkIntegrityMan->getFirstCheckIntegrityEntry();
if(!entry.isNull()) {
cout << " "
<< "[Checksum:"
<< "#" << entry->getRequestGroup()->getGID() << " "
<< Util::abbrevSize(entry->getCurrentLength())
<< "B"
<< "/"
<< Util::abbrevSize(entry->getTotalLength())
<< "B"
<< "("
<< 100*entry->getCurrentLength()/entry->getTotalLength()
<< "%)";
cout << "]";
if(checkIntegrityMan->countCheckIntegrityEntry() > 1) {
cout << "("
<< checkIntegrityMan->countCheckIntegrityEntry()-1
<< "more...)";
}
}
}
#endif // ENABLE_MESSAGE_DIGEST
cout << flush;
}

View File

@ -32,20 +32,24 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#ifndef _D_TRACKER_SEGMENT_MAN_FACTORY_H_ #ifndef _D_CONSOLE_STAT_CALC_H_
#define _D_TRACKER_SEGMENT_MAN_FACTORY_H_ #define _D_CONSOLE_STAT_CALC_H_
#include "AbstractSegmentManFactory.h" #include "StatCalc.h"
#include "TimeA2.h"
class TrackerSegmentManFactory : public AbstractSegmentManFactory { class ConsoleStatCalc:public StatCalc
{
private:
Time _cp;
public: public:
TrackerSegmentManFactory(const Option* option):AbstractSegmentManFactory(option) {} virtual ~ConsoleStatCalc() {}
virtual ~TrackerSegmentManFactory() {} virtual void calculateStat(const RequestGroupManHandle& requestGroupMan,
const FileAllocationManHandle& fileAllocationMan,
virtual SegmentManHandle createNewInstance(); const CheckIntegrityManHandle& checkIntegrityMan);
}; };
typedef SharedHandle<TrackerSegmentManFactory> TrackerSegmentManFactoryHandle; typedef SharedHandle<ConsoleStatCalc> ConsoleStatCalcHandle;
#endif // _D_TRACKER_SEGMENT_MAN_FACTORY_H_ #endif // _D_CONSOLE_STAT_CALC_H_

View File

@ -36,13 +36,17 @@
#include "Util.h" #include "Util.h"
#include "message.h" #include "message.h"
void CopyDiskAdaptor::onDownloadComplete() { void CopyDiskAdaptor::onDownloadComplete()
throw(DlAbortEx*)
{
closeFile(); closeFile();
fixFilename(); fixFilename();
openFile(); openFile();
} }
void CopyDiskAdaptor::fixFilename() { void CopyDiskAdaptor::fixFilename()
throw(DlAbortEx*)
{
int64_t offset = 0; int64_t offset = 0;
for(FileEntries::iterator itr = fileEntries.begin(); for(FileEntries::iterator itr = fileEntries.begin();
itr != fileEntries.end(); itr++) { itr != fileEntries.end(); itr++) {
@ -59,6 +63,7 @@ void CopyDiskAdaptor::fixFilename() {
} }
} }
string CopyDiskAdaptor::getFilePath() { string CopyDiskAdaptor::getFilePath()
{
return storeDir+"/"+tempFilename; return storeDir+"/"+tempFilename;
} }

View File

@ -36,13 +36,14 @@
#define _D_COPY_DISK_ADAPTOR_H_ #define _D_COPY_DISK_ADAPTOR_H_
#include "AbstractSingleDiskAdaptor.h" #include "AbstractSingleDiskAdaptor.h"
#include "DlAbortEx.h"
class CopyDiskAdaptor : public AbstractSingleDiskAdaptor { class CopyDiskAdaptor : public AbstractSingleDiskAdaptor {
private: private:
string tempFilename; string tempFilename;
string topDir; string topDir;
void fixFilename(); void fixFilename() throw(DlAbortEx*);
public: public:
CopyDiskAdaptor() {} CopyDiskAdaptor() {}
@ -50,7 +51,7 @@ public:
virtual string getFilePath(); virtual string getFilePath();
virtual void onDownloadComplete(); virtual void onDownloadComplete() throw(DlAbortEx*);
// tempFilename is relative to storeDir // tempFilename is relative to storeDir
void setTempFilename(const string& tempFilename) { void setTempFilename(const string& tempFilename) {

View File

@ -42,9 +42,10 @@
#include "Util.h" #include "Util.h"
#include "MessageDigestHelper.h" #include "MessageDigestHelper.h"
#include "a2netcompat.h" #include "a2netcompat.h"
#include "AnnounceTier.h"
#include <libgen.h> #include <libgen.h>
DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-") {} DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-"), _ownerRequestGroup(0) {}
DefaultBtContext::~DefaultBtContext() {} DefaultBtContext::~DefaultBtContext() {}
@ -248,6 +249,11 @@ int32_t DefaultBtContext::getNumPieces() const {
return numPieces; return numPieces;
} }
string DefaultBtContext::getActualBasePath() const
{
return _dir+"/"+name;
}
Integers DefaultBtContext::computeFastSet(const string& ipaddr, int32_t fastSetSize) Integers DefaultBtContext::computeFastSet(const string& ipaddr, int32_t fastSetSize)
{ {
Integers fastSet; Integers fastSet;

View File

@ -59,6 +59,8 @@ private:
string _peerIdPrefix; string _peerIdPrefix;
AnnounceTiers announceTiers; AnnounceTiers announceTiers;
RequestGroup* _ownerRequestGroup;
void clear(); void clear();
void extractPieceHash(const unsigned char* hashData, void extractPieceHash(const unsigned char* hashData,
int32_t hashDataLength, int32_t hashDataLength,
@ -90,6 +92,11 @@ private:
virtual FileEntries getFileEntries() const; virtual FileEntries getFileEntries() const;
virtual string getPieceHashAlgo() const
{
return "sha1";
}
virtual AnnounceTiers getAnnounceTiers() const; virtual AnnounceTiers getAnnounceTiers() const;
virtual void load(const string& torrentFile); virtual void load(const string& torrentFile);
@ -100,6 +107,8 @@ private:
virtual int32_t getNumPieces() const; virtual int32_t getNumPieces() const;
virtual string getActualBasePath() const;
virtual const unsigned char* getPeerId() { virtual const unsigned char* getPeerId() {
if(peerId == "") { if(peerId == "") {
peerId = generatePeerId(); peerId = generatePeerId();
@ -109,6 +118,11 @@ private:
virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize); virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize);
virtual RequestGroup* getOwnerRequestGroup()
{
return _ownerRequestGroup;
}
string generatePeerId() const; string generatePeerId() const;
void setPeerIdPrefix(const string& peerIdPrefix) void setPeerIdPrefix(const string& peerIdPrefix)
@ -126,7 +140,11 @@ private:
{ {
this->numPieces = numPieces; this->numPieces = numPieces;
} }
void setOwnerRequestGroup(RequestGroup* owner)
{
_ownerRequestGroup = owner;
}
}; };
typedef SharedHandle<DefaultBtContext> DefaultBtContextHandle; typedef SharedHandle<DefaultBtContext> DefaultBtContextHandle;

View File

@ -33,6 +33,9 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DefaultBtProgressInfoFile.h" #include "DefaultBtProgressInfoFile.h"
#include "DownloadContext.h"
#include "PieceStorage.h"
#include "Option.h"
#include "BtRegistry.h" #include "BtRegistry.h"
#include "LogFactory.h" #include "LogFactory.h"
#include "prefs.h" #include "prefs.h"
@ -41,143 +44,245 @@
#include "File.h" #include "File.h"
#include "Util.h" #include "Util.h"
#include "a2io.h" #include "a2io.h"
#include <fstream>
#include <errno.h> #include <errno.h>
DefaultBtProgressInfoFile::DefaultBtProgressInfoFile(const BtContextHandle& btContext, DefaultBtProgressInfoFile::DefaultBtProgressInfoFile(const DownloadContextHandle& dctx,
const PieceStorageHandle& pieceStorage,
const Option* option): const Option* option):
btContext(btContext), _dctx(dctx),
option(option), _pieceStorage(pieceStorage),
pieceStorage(PIECE_STORAGE(btContext)), _option(option),
btRuntime(BT_RUNTIME(btContext)), _logger(LogFactory::getInstance())
peerStorage(PEER_STORAGE(btContext))
{ {
logger = LogFactory::getInstance(); _filename = _dctx->getActualBasePath()+".aria2";
string storeDir = option->get(PREF_DIR);
filename = storeDir+"/"+btContext->getName()+".aria2";
} }
DefaultBtProgressInfoFile::~DefaultBtProgressInfoFile() {} DefaultBtProgressInfoFile::~DefaultBtProgressInfoFile() {}
void DefaultBtProgressInfoFile::save() { bool DefaultBtProgressInfoFile::isTorrentDownload()
logger->info(MSG_SAVING_SEGMENT_FILE, filename.c_str()); {
string filenameTemp = filename+"__temp"; return !BtContextHandle(_dctx).isNull();
FILE* file = openFile(filenameTemp, "wb"); }
try {
if(fwrite(btContext->getInfoHash(),
btContext->getInfoHashLength(), 1, file) < 1) {
throw string("writeError:info hash");
}
if(fwrite(pieceStorage->getBitfield(),
pieceStorage->getBitfieldLength(), 1, file) < 1) {
throw string("writeError:bitfield");
}
TransferStat stat = peerStorage->calculateStat();
int64_t allTimeDownloadLength = pieceStorage->getCompletedLength();
if(fwrite(&allTimeDownloadLength,
sizeof(allTimeDownloadLength), 1, file) < 1) {
throw string("writeError:download length");
}
int64_t allTimeUploadLength =
btRuntime->getUploadLengthAtStartup()+
stat.getSessionUploadLength();
if(fwrite(&allTimeUploadLength,
sizeof(allTimeUploadLength), 1, file) < 1) {
throw string("writeError:upload length");
}
fclose(file);
logger->info(MSG_SAVED_SEGMENT_FILE);
} catch(string ex) {
fclose(file);
throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
filename.c_str(), strerror(errno));
}
if(rename(filenameTemp.c_str(), filename.c_str()) == -1) { void DefaultBtProgressInfoFile::save() {
_logger->info(MSG_SAVING_SEGMENT_FILE, _filename.c_str());
string filenameTemp = _filename+"__temp";
ofstream o(filenameTemp.c_str(), ios::out|ios::binary);
o.exceptions(ios::failbit);
try {
bool torrentDownload = isTorrentDownload();
// file version: 16 bits
// value: '0'
int16_t version = 0;
o.write(reinterpret_cast<const char*>(&version), sizeof(int16_t));
// extension: 32 bits
// If this is BitTorrent download, then 0x00000001
// Otherwise, 0x00000000
char extension[4];
memset(extension, 0, sizeof(extension));
if(torrentDownload) {
extension[3] = 1;
}
o.write(reinterpret_cast<const char*>(&extension), sizeof(extension));
if(torrentDownload) {
// infoHashLength:
// length: 32 bits
BtContextHandle btContext = _dctx;
int32_t infoHashLength = btContext->getInfoHashLength();
o.write(reinterpret_cast<const char*>(&infoHashLength), sizeof(int32_t));
// infoHash:
o.write(reinterpret_cast<const char*>(btContext->getInfoHash()),
btContext->getInfoHashLength());
} else {
// infoHashLength:
// length: 32 bits
int32_t infoHashLength = 0;
o.write(reinterpret_cast<const char*>(&infoHashLength), sizeof(int32_t));
}
// pieceLength: 32 bits
int32_t pieceLength = _dctx->getPieceLength();
o.write(reinterpret_cast<const char*>(&pieceLength), sizeof(int32_t));
// totalLength: 64 bits
int64_t totalLength = _dctx->getTotalLength();
o.write(reinterpret_cast<const char*>(&totalLength), sizeof(int64_t));
// uploadLength: 64 bits
int64_t uploadLength = 0;
if(torrentDownload) {
BtContextHandle btContext = _dctx;
TransferStat stat = PEER_STORAGE(btContext)->calculateStat();
uploadLength = stat.getAllTimeUploadLength();
}
o.write(reinterpret_cast<const char*>(&uploadLength), sizeof(int64_t));
// bitfieldLength: 32 bits
int32_t bitfieldLength = _pieceStorage->getBitfieldLength();
o.write(reinterpret_cast<const char*>(&bitfieldLength), sizeof(int32_t));
// bitfield
o.write(reinterpret_cast<const char*>(_pieceStorage->getBitfield()), _pieceStorage->getBitfieldLength());
// the number of in-flight piece: 32 bits
// TODO implement this
int32_t numInFlightPiece = _pieceStorage->countInFlightPiece();
o.write(reinterpret_cast<const char*>(&numInFlightPiece), sizeof(int32_t));
Pieces inFlightPieces = _pieceStorage->getInFlightPieces();
for(Pieces::const_iterator itr = inFlightPieces.begin();
itr != inFlightPieces.end(); ++itr) {
int32_t index = (*itr)->getIndex();
o.write(reinterpret_cast<const char*>(&index), sizeof(int32_t));
int32_t length = (*itr)->getLength();
o.write(reinterpret_cast<const char*>(&length), sizeof(int32_t));
int32_t bitfieldLength = (*itr)->getBitfieldLength();
o.write(reinterpret_cast<const char*>(&bitfieldLength), sizeof(int32_t));
o.write(reinterpret_cast<const char*>((*itr)->getBitfield()), bitfieldLength);
}
o.close();
_logger->info(MSG_SAVED_SEGMENT_FILE);
} catch(ios::failure const& exception) {
// TODO ios::failure doesn't give us the reasons of failure...
throw new DlAbortEx(EX_SEGMENT_FILE_WRITE, throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
filename.c_str(), strerror(errno)); _filename.c_str(), strerror(errno));
}
if(rename(filenameTemp.c_str(), _filename.c_str()) == -1) {
throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
_filename.c_str(), strerror(errno));
} }
} }
void DefaultBtProgressInfoFile::load() { void DefaultBtProgressInfoFile::load()
logger->info(MSG_LOADING_SEGMENT_FILE, filename.c_str()); {
FILE* file = openFile(filename, "r+b"); _logger->info(MSG_LOADING_SEGMENT_FILE, _filename.c_str());
ifstream in(_filename.c_str(), ios::in|ios::binary);
in.exceptions(ios::failbit);
unsigned char* savedInfoHash = 0; unsigned char* savedInfoHash = 0;
unsigned char* savedBitfield = 0; unsigned char* savedBitfield = 0;
try { try {
savedInfoHash = new unsigned char[btContext->getInfoHashLength()]; unsigned char version[2];
savedBitfield = new unsigned char[pieceStorage->getBitfieldLength()]; in.read((char*)version, sizeof(version));
if(fread(savedInfoHash, btContext->getInfoHashLength(), 1, file) < 1) { if(string("0000") != Util::toHex(version, sizeof(version))) {
throw string("readError"); throw new DlAbortEx("Unsupported ctrl file version: %s",
Util::toHex(version, sizeof(version)).c_str());
} }
if(Util::toHex(savedInfoHash, btContext->getInfoHashLength()) != unsigned char extension[4];
btContext->getInfoHashAsString()) { in.read((char*)extension, sizeof(extension));
throw string("infoHashMismatch");
bool infoHashCheckEnabled = false;
if(extension[3]&1 && isTorrentDownload()) {
infoHashCheckEnabled = true;
_logger->debug("InfoHash checking enabled.");
} }
if(fread(savedBitfield, pieceStorage->getBitfieldLength(), 1, file) < 1) {
throw string("readError"); int32_t infoHashLength;
in.read(reinterpret_cast<char*>(&infoHashLength), sizeof(infoHashLength));
if(infoHashLength < 0 || infoHashLength == 0 && infoHashCheckEnabled) {
throw new DlAbortEx("Invalid info hash length: %d", infoHashLength);
} }
pieceStorage->setBitfield(savedBitfield, if(infoHashLength > 0) {
pieceStorage->getBitfieldLength()); savedInfoHash = new unsigned char[infoHashLength];
// allTimeDownloadLength exists for only a compatibility reason. in.read(reinterpret_cast<char*>(savedInfoHash), infoHashLength);
int64_t allTimeDownloadLength; BtContextHandle btContext = _dctx;
if(fread(&allTimeDownloadLength, if(infoHashCheckEnabled &&
sizeof(allTimeDownloadLength), 1, file) < 1) { Util::toHex(savedInfoHash, infoHashLength) != btContext->getInfoHashAsString()) {
throw string("readError"); throw new DlAbortEx("info hash mismatch. expected: %s, actual: %s",
btContext->getInfoHashAsString().c_str(),
Util::toHex(savedInfoHash, infoHashLength).c_str());
}
delete [] savedInfoHash;
savedInfoHash = 0;
} }
int64_t allTimeUploadLength;
if(fread(&allTimeUploadLength, // TODO implement the conversion mechanism between different piece length.
sizeof(allTimeUploadLength), 1, file) < 1) { int32_t pieceLength;
throw string("readError"); in.read(reinterpret_cast<char*>(&pieceLength), sizeof(pieceLength));
if(pieceLength != _dctx->getPieceLength()) {
throw new DlAbortEx("piece length mismatch. expected: %d, actual: %d",
_dctx->getPieceLength(), pieceLength);
} }
btRuntime->setUploadLengthAtStartup(allTimeUploadLength);
int64_t totalLength;
in.read(reinterpret_cast<char*>(&totalLength), sizeof(totalLength));
if(totalLength != _dctx->getTotalLength()) {
throw new DlAbortEx("total length mismatch. expected: %s, actual: %s",
Util::llitos(_dctx->getTotalLength()).c_str(),
Util::llitos(totalLength).c_str());
}
int64_t uploadLength;
in.read(reinterpret_cast<char*>(&uploadLength), sizeof(uploadLength));
if(isTorrentDownload()) {
BT_RUNTIME(BtContextHandle(_dctx))->setUploadLengthAtStartup(uploadLength);
}
// TODO implement the conversion mechanism between different piece length.
int32_t bitfieldLength;
in.read(reinterpret_cast<char*>(&bitfieldLength), sizeof(bitfieldLength));
if(_pieceStorage->getBitfieldLength() != bitfieldLength) {
throw new DlAbortEx("bitfield length mismatch. expected: %d, actual: %d",
_pieceStorage->getBitfieldLength(),
bitfieldLength);
}
// TODO implement the conversion mechanism between different piece length.
savedBitfield = new unsigned char[bitfieldLength];
in.read(reinterpret_cast<char*>(savedBitfield), bitfieldLength);
_pieceStorage->setBitfield(savedBitfield, bitfieldLength);
delete [] savedBitfield; delete [] savedBitfield;
savedBitfield = 0; savedBitfield = 0;
delete [] savedInfoHash;
savedInfoHash = 0; int32_t numInFlightPiece;
fclose(file); in.read(reinterpret_cast<char*>(&numInFlightPiece), sizeof(numInFlightPiece));
} catch(string ex) {
if(savedBitfield) { Pieces inFlightPieces;
while(numInFlightPiece--) {
int32_t index;
in.read(reinterpret_cast<char*>(&index), sizeof(index));
if(!(0 <= index && index < _dctx->getNumPieces())) {
throw new DlAbortEx("piece index out of range: %d", index);
}
int32_t length;
in.read(reinterpret_cast<char*>(&length), sizeof(length));
if(!(0 < length && length <=_dctx->getPieceLength())) {
throw new DlAbortEx("piece length out of range: %d", length);
}
PieceHandle piece = new Piece(index, length);
int32_t bitfieldLength;
in.read(reinterpret_cast<char*>(&bitfieldLength), sizeof(bitfieldLength));
if(piece->getBitfieldLength() != bitfieldLength) {
throw new DlAbortEx("piece bitfield length mismatch. expected: %d actual: %d",
piece->getBitfieldLength(), bitfieldLength);
}
savedBitfield = new unsigned char[bitfieldLength];
in.read(reinterpret_cast<char*>(savedBitfield), bitfieldLength);
piece->setBitfield(savedBitfield, bitfieldLength);
delete [] savedBitfield; delete [] savedBitfield;
savedBitfield = 0;
inFlightPieces.push_back(piece);
} }
if(savedInfoHash) { _pieceStorage->addInFlightPiece(inFlightPieces);
delete [] savedInfoHash;
} _logger->info(MSG_LOADED_SEGMENT_FILE);
fclose(file); } catch(ios::failure const& exception) {
if(ex == "infoHashMismatch") { delete [] savedBitfield;
throw new DlAbortEx(EX_INFOHASH_MISMATCH_IN_SEGFILE); delete [] savedInfoHash;
} else { // TODO ios::failure doesn't give us the reasons of failure...
throw new DlAbortEx(EX_SEGMENT_FILE_READ, throw new DlAbortEx(EX_SEGMENT_FILE_READ,
filename.c_str(), strerror(errno)); _filename.c_str(), strerror(errno));
} }
}
logger->info(MSG_LOADED_SEGMENT_FILE);
} }
void DefaultBtProgressInfoFile::removeFile() { void DefaultBtProgressInfoFile::removeFile() {
if(exists()) { if(exists()) {
File f(filename); File f(_filename);
f.remove(); f.remove();
} }
} }
FILE* DefaultBtProgressInfoFile::openFile(const string& filename,
const string& mode) const
{
FILE* file = fopen(filename.c_str(), mode.c_str());
if(!file) {
throw new DlAbortEx(EX_SEGMENT_FILE_OPEN,
filename.c_str(), strerror(errno));
}
return file;
}
bool DefaultBtProgressInfoFile::exists() { bool DefaultBtProgressInfoFile::exists() {
File f(filename); File f(_filename);
if(f.isFile()) { if(f.isFile()) {
logger->info(MSG_SEGMENT_FILE_EXISTS, filename.c_str()); _logger->info(MSG_SEGMENT_FILE_EXISTS, _filename.c_str());
return true; return true;
} else { } else {
logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, filename.c_str()); _logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, _filename.c_str());
return false; return false;
} }
} }

View File

@ -36,49 +36,33 @@
#define _D_DEFAULT_BT_PROGRESS_INFO_FILE_H_ #define _D_DEFAULT_BT_PROGRESS_INFO_FILE_H_
#include "BtProgressInfoFile.h" #include "BtProgressInfoFile.h"
#include "BtContext.h"
#include "PieceStorage.h" class DownloadContext;
#include "BtRuntime.h" extern typedef SharedHandle<DownloadContext> DownloadContextHandle;
#include "PeerStorage.h" class PieceStorage;
#include "Logger.h" extern typedef SharedHandle<PieceStorage> PieceStorageHandle;
#include "Option.h" class Logger;
class Option;
class DefaultBtProgressInfoFile : public BtProgressInfoFile { class DefaultBtProgressInfoFile : public BtProgressInfoFile {
private: private:
BtContextHandle btContext; DownloadContextHandle _dctx;
const Option* option; PieceStorageHandle _pieceStorage;
Logger* logger; const Option* _option;
PieceStorageHandle pieceStorage; const Logger* _logger;
BtRuntimeHandle btRuntime; string _filename;
PeerStorageHandle peerStorage;
string filename; bool isTorrentDownload();
FILE* openFile(const string& filename, const string& mode) const;
public: public:
DefaultBtProgressInfoFile(const BtContextHandle& btContext, DefaultBtProgressInfoFile(const DownloadContextHandle& btContext,
const PieceStorageHandle& pieceStorage,
const Option* option); const Option* option);
virtual ~DefaultBtProgressInfoFile(); virtual ~DefaultBtProgressInfoFile();
void setBtRuntime(const BtRuntimeHandle& btRuntime) { virtual string getFilename() { return _filename; }
this->btRuntime = btRuntime;
}
BtRuntimeHandle getBtRuntime() const { return btRuntime; }
void setPieceStorage(const PieceStorageHandle& pieceStorage) {
this->pieceStorage = pieceStorage;
}
PieceStorageHandle getPieceStorage() const { return pieceStorage; }
void setPeerStorage(const PeerStorageHandle& peerStorage) {
this->peerStorage = peerStorage;
}
PeerStorageHandle getPeerStorage() const { return peerStorage; }
virtual void setFilename(const string& filename) {
this->filename = filename;
}
virtual string getFilename() { return filename; }
virtual bool exists(); virtual bool exists();
virtual void save(); virtual void save();

View File

@ -33,10 +33,7 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DefaultDiskWriter.h" #include "DefaultDiskWriter.h"
#include "DlAbortEx.h"
#include "message.h" #include "message.h"
#include "DefaultFileAllocator.h"
#include "GlowFileAllocator.h"
#include "prefs.h" #include "prefs.h"
#include "Util.h" #include "Util.h"
#include <errno.h> #include <errno.h>
@ -48,38 +45,7 @@ DefaultDiskWriter::~DefaultDiskWriter() {}
void DefaultDiskWriter::initAndOpenFile(const string& filename, void DefaultDiskWriter::initAndOpenFile(const string& filename,
int64_t totalLength) int64_t totalLength)
throw(DlAbortEx*)
{ {
createFile(filename); createFile(filename);
try {
if(totalLength > 0) {
if(fileAllocator.isNull()) {
ftruncate(fd, 0);
} else {
logger->notice(MSG_ALLOCATING_FILE,
filename.c_str(),
Util::ullitos(totalLength).c_str());
fileAllocator->allocate(fd, totalLength);
}
}
} catch(RecoverableException *e) {
throw new DlAbortEx(e, EX_FILE_WRITE, filename.c_str(), strerror(errno));
}
}
DefaultDiskWriter* DefaultDiskWriter::createNewDiskWriter(const Option* option)
{
DefaultDiskWriter* diskWriter = new DefaultDiskWriter();
if(option->get(PREF_FILE_ALLOCATION) == V_PREALLOC) {
DefaultFileAllocatorHandle allocator = new DefaultFileAllocator();
allocator->setFileAllocationMonitor(FileAllocationMonitorFactory::getFactory()->createNewMonitor());
diskWriter->setFileAllocator(allocator);
GlowFileAllocatorHandle glowAllocator = new GlowFileAllocator();
glowAllocator->setFileAllocationMonitor(FileAllocationMonitorFactory::getFactory()->createNewMonitor());
diskWriter->setGlowFileAllocator(glowAllocator);
} else {
diskWriter->setFileAllocator(0);
diskWriter->setGlowFileAllocator(0);
}
return diskWriter;
} }

View File

@ -37,6 +37,7 @@
#include "AbstractDiskWriter.h" #include "AbstractDiskWriter.h"
#include "Option.h" #include "Option.h"
#include "DlAbortEx.h"
class DefaultDiskWriter:public AbstractDiskWriter { class DefaultDiskWriter:public AbstractDiskWriter {
public: public:
@ -45,9 +46,7 @@ public:
virtual ~DefaultDiskWriter(); virtual ~DefaultDiskWriter();
virtual void initAndOpenFile(const string& filename, virtual void initAndOpenFile(const string& filename,
int64_t totalLength = 0); int64_t totalLength = 0) throw(DlAbortEx*);
static DefaultDiskWriter* createNewDiskWriter(const Option* option);
}; };
typedef SharedHandle<DefaultDiskWriter> DefaultDiskWriterHandle; typedef SharedHandle<DefaultDiskWriter> DefaultDiskWriterHandle;

View File

@ -0,0 +1,52 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_DEFAULT_DISK_WRITER_FACTORY_H_
#define _D_DEFAULT_DISK_WRITER_FACTORY_H_
#include "DiskWriterFactory.h"
#include "DefaultDiskWriter.h"
class DefaultDiskWriterFactory:public DiskWriterFactory
{
public:
DiskWriterHandle newDiskWriter()
{
return new DefaultDiskWriter();
}
};
typedef SharedHandle<DefaultDiskWriterFactory> DefaultDiskWriterFactoryHandle;
#endif // _D_DEFAULT_DISK_WRITER_FACTORY_H_

View File

@ -192,6 +192,8 @@ TransferStat DefaultPeerStorage::calculateStat() {
TransferStat stat = calStat.getTransferStat(); TransferStat stat = calStat.getTransferStat();
stat.sessionDownloadLength += removedPeerSessionDownloadLength; stat.sessionDownloadLength += removedPeerSessionDownloadLength;
stat.sessionUploadLength += removedPeerSessionUploadLength; stat.sessionUploadLength += removedPeerSessionUploadLength;
stat.setAllTimeUploadLength(btRuntime->getUploadLengthAtStartup()+
stat.getSessionUploadLength());
return stat; return stat;
} }

View File

@ -33,29 +33,31 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DefaultPieceStorage.h" #include "DefaultPieceStorage.h"
#include "DownloadContext.h"
#include "Piece.h"
#include "Peer.h"
#include "LogFactory.h" #include "LogFactory.h"
#include "prefs.h" #include "prefs.h"
#include "DirectDiskAdaptor.h" #include "DirectDiskAdaptor.h"
#include "MultiDiskAdaptor.h" #include "MultiDiskAdaptor.h"
#include "CopyDiskAdaptor.h" #include "CopyDiskAdaptor.h"
#include "DefaultDiskWriter.h" #include "DiskWriter.h"
#include "DlAbortEx.h"
#include "BitfieldManFactory.h" #include "BitfieldManFactory.h"
#include "FileAllocationMonitor.h"
#include "DiskAdaptorWriter.h"
#include "ChunkChecksumValidator.h"
#include "message.h" #include "message.h"
#include "DefaultDiskWriterFactory.h"
#include "DlAbortEx.h"
DefaultPieceStorage::DefaultPieceStorage(BtContextHandle btContext, const Option* option): DefaultPieceStorage::DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option):
btContext(btContext), downloadContext(downloadContext),
diskAdaptor(0), diskAdaptor(0),
_diskWriterFactory(new DefaultDiskWriterFactory()),
endGamePieceNum(END_GAME_PIECE_NUM), endGamePieceNum(END_GAME_PIECE_NUM),
option(option) option(option)
{ {
bitfieldMan = bitfieldMan =
BitfieldManFactory::getFactoryInstance()-> BitfieldManFactory::getFactoryInstance()->
createBitfieldMan(btContext->getPieceLength(), createBitfieldMan(downloadContext->getPieceLength(),
btContext->getTotalLength()); downloadContext->getTotalLength());
logger = LogFactory::getInstance(); logger = LogFactory::getInstance();
} }
@ -63,16 +65,19 @@ DefaultPieceStorage::~DefaultPieceStorage() {
delete bitfieldMan; delete bitfieldMan;
} }
bool DefaultPieceStorage::hasMissingPiece(const PeerHandle& peer) { bool DefaultPieceStorage::hasMissingPiece(const PeerHandle& peer)
{
return bitfieldMan->hasMissingPiece(peer->getBitfield(), return bitfieldMan->hasMissingPiece(peer->getBitfield(),
peer->getBitfieldLength()); peer->getBitfieldLength());
} }
bool DefaultPieceStorage::isEndGame() { bool DefaultPieceStorage::isEndGame()
{
return bitfieldMan->countMissingBlock() <= endGamePieceNum; return bitfieldMan->countMissingBlock() <= endGamePieceNum;
} }
int32_t DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer) { int32_t DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer)
{
int32_t index = -1; int32_t index = -1;
if(isEndGame()) { if(isEndGame()) {
index = bitfieldMan->getMissingIndex(peer->getBitfield(), index = bitfieldMan->getMissingIndex(peer->getBitfield(),
@ -84,7 +89,8 @@ int32_t DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer) {
return index; return index;
} }
PieceHandle DefaultPieceStorage::checkOutPiece(int32_t index) { PieceHandle DefaultPieceStorage::checkOutPiece(int32_t index)
{
if(index == -1) { if(index == -1) {
return 0; return 0;
} }
@ -104,7 +110,8 @@ PieceHandle DefaultPieceStorage::checkOutPiece(int32_t index) {
* Newly instantiated piece is not added to usedPieces. * Newly instantiated piece is not added to usedPieces.
* Because it is waste of memory and there is no chance to use them later. * Because it is waste of memory and there is no chance to use them later.
*/ */
PieceHandle DefaultPieceStorage::getPiece(int32_t index) { PieceHandle DefaultPieceStorage::getPiece(int32_t index)
{
if(0 <= index && index <= bitfieldMan->getMaxIndex()) { if(0 <= index && index <= bitfieldMan->getMaxIndex()) {
PieceHandle piece = findUsedPiece(index); PieceHandle piece = findUsedPiece(index);
if(piece.isNull()) { if(piece.isNull()) {
@ -119,7 +126,8 @@ PieceHandle DefaultPieceStorage::getPiece(int32_t index) {
} }
} }
void DefaultPieceStorage::addUsedPiece(const PieceHandle& piece) { void DefaultPieceStorage::addUsedPiece(const PieceHandle& piece)
{
usedPieces.push_back(piece); usedPieces.push_back(piece);
} }
@ -134,7 +142,8 @@ public:
} }
}; };
PieceHandle DefaultPieceStorage::findUsedPiece(int32_t index) const { PieceHandle DefaultPieceStorage::findUsedPiece(int32_t index) const
{
Pieces::const_iterator itr = find_if(usedPieces.begin(), Pieces::const_iterator itr = find_if(usedPieces.begin(),
usedPieces.end(), usedPieces.end(),
FindPiece(index)); FindPiece(index));
@ -145,12 +154,14 @@ PieceHandle DefaultPieceStorage::findUsedPiece(int32_t index) const {
} }
} }
PieceHandle DefaultPieceStorage::getMissingPiece(const PeerHandle& peer) { PieceHandle DefaultPieceStorage::getMissingPiece(const PeerHandle& peer)
{
int32_t index = getMissingPieceIndex(peer); int32_t index = getMissingPieceIndex(peer);
return checkOutPiece(index); return checkOutPiece(index);
} }
int32_t DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer) { int32_t DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer)
{
int32_t index = -1; int32_t index = -1;
if(peer->isFastExtensionEnabled() && peer->countFastSet() > 0) { if(peer->isFastExtensionEnabled() && peer->countFastSet() > 0) {
BitfieldMan tempBitfield(bitfieldMan->getBlockLength(), BitfieldMan tempBitfield(bitfieldMan->getBlockLength(),
@ -172,12 +183,28 @@ int32_t DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer) {
return index; return index;
} }
PieceHandle DefaultPieceStorage::getMissingFastPiece(const PeerHandle& peer) { PieceHandle DefaultPieceStorage::getMissingFastPiece(const PeerHandle& peer)
{
int32_t index = getMissingFastPieceIndex(peer); int32_t index = getMissingFastPieceIndex(peer);
return checkOutPiece(index); return checkOutPiece(index);
} }
void DefaultPieceStorage::deleteUsedPiece(const PieceHandle& piece) { PieceHandle DefaultPieceStorage::getMissingPiece()
{
return checkOutPiece(bitfieldMan->getSparseMissingUnusedIndex());
}
PieceHandle DefaultPieceStorage::getMissingPiece(int32_t index)
{
if(hasPiece(index) || isPieceUsed(index)) {
return 0;
} else {
return checkOutPiece(index);
}
}
void DefaultPieceStorage::deleteUsedPiece(const PieceHandle& piece)
{
if(piece.isNull()) { if(piece.isNull()) {
return; return;
} }
@ -187,7 +214,8 @@ void DefaultPieceStorage::deleteUsedPiece(const PieceHandle& piece) {
} }
} }
void DefaultPieceStorage::reduceUsedPieces(int32_t delMax) { void DefaultPieceStorage::reduceUsedPieces(int32_t delMax)
{
int32_t toDelete = usedPieces.size()-delMax; int32_t toDelete = usedPieces.size()-delMax;
if(toDelete <= 0) { if(toDelete <= 0) {
return; return;
@ -204,7 +232,8 @@ void DefaultPieceStorage::reduceUsedPieces(int32_t delMax) {
} }
int32_t DefaultPieceStorage::deleteUsedPiecesByFillRate(int32_t fillRate, int32_t DefaultPieceStorage::deleteUsedPiecesByFillRate(int32_t fillRate,
int32_t toDelete) { int32_t toDelete)
{
int32_t deleted = 0; int32_t deleted = 0;
for(Pieces::iterator itr = usedPieces.begin(); for(Pieces::iterator itr = usedPieces.begin();
itr != usedPieces.end() && deleted < toDelete;) { itr != usedPieces.end() && deleted < toDelete;) {
@ -224,7 +253,8 @@ int32_t DefaultPieceStorage::deleteUsedPiecesByFillRate(int32_t fillRate,
return deleted; return deleted;
} }
void DefaultPieceStorage::completePiece(const PieceHandle& piece) { void DefaultPieceStorage::completePiece(const PieceHandle& piece)
{
if(piece.isNull()) { if(piece.isNull()) {
return; return;
} }
@ -250,17 +280,20 @@ void DefaultPieceStorage::completePiece(const PieceHandle& piece) {
} }
} }
bool DefaultPieceStorage::isSelectiveDownloadingMode() { bool DefaultPieceStorage::isSelectiveDownloadingMode()
{
return bitfieldMan->isFilterEnabled(); return bitfieldMan->isFilterEnabled();
} }
void DefaultPieceStorage::finishSelectiveDownloadingMode() { void DefaultPieceStorage::finishSelectiveDownloadingMode()
{
bitfieldMan->clearFilter(); bitfieldMan->clearFilter();
diskAdaptor->addAllDownloadEntry(); diskAdaptor->addAllDownloadEntry();
} }
// not unittested // not unittested
void DefaultPieceStorage::cancelPiece(const PieceHandle& piece) { void DefaultPieceStorage::cancelPiece(const PieceHandle& piece)
{
if(piece.isNull()) { if(piece.isNull()) {
return; return;
} }
@ -272,29 +305,40 @@ void DefaultPieceStorage::cancelPiece(const PieceHandle& piece) {
} }
} }
bool DefaultPieceStorage::hasPiece(int32_t index) { bool DefaultPieceStorage::hasPiece(int32_t index)
{
return bitfieldMan->isBitSet(index); return bitfieldMan->isBitSet(index);
} }
int64_t DefaultPieceStorage::getTotalLength() { bool DefaultPieceStorage::isPieceUsed(int32_t index)
{
return bitfieldMan->isUseBitSet(index);
}
int64_t DefaultPieceStorage::getTotalLength()
{
return bitfieldMan->getTotalLength(); return bitfieldMan->getTotalLength();
} }
int64_t DefaultPieceStorage::getFilteredTotalLength() { int64_t DefaultPieceStorage::getFilteredTotalLength()
{
return bitfieldMan->getFilteredTotalLength(); return bitfieldMan->getFilteredTotalLength();
} }
int64_t DefaultPieceStorage::getCompletedLength() { int64_t DefaultPieceStorage::getCompletedLength()
{
return bitfieldMan->getCompletedLength(); return bitfieldMan->getCompletedLength();
} }
int64_t DefaultPieceStorage::getFilteredCompletedLength() { int64_t DefaultPieceStorage::getFilteredCompletedLength()
{
return bitfieldMan->getFilteredCompletedLength(); return bitfieldMan->getFilteredCompletedLength();
} }
// not unittested // not unittested
void DefaultPieceStorage::setFileFilter(const Strings& filePaths) { void DefaultPieceStorage::setFileFilter(const Strings& filePaths)
if(btContext->getFileMode() != BtContext::MULTI || filePaths.empty()) { {
if(downloadContext->getFileMode() != DownloadContext::MULTI || filePaths.empty()) {
return; return;
} }
diskAdaptor->removeAllDownloadEntry(); diskAdaptor->removeAllDownloadEntry();
@ -309,7 +353,8 @@ void DefaultPieceStorage::setFileFilter(const Strings& filePaths) {
bitfieldMan->enableFilter(); bitfieldMan->enableFilter();
} }
void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes) { void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes)
{
Strings filePaths; Strings filePaths;
const FileEntries& entries = diskAdaptor->getFileEntries(); const FileEntries& entries = diskAdaptor->getFileEntries();
for(int32_t i = 0; i < (int32_t)entries.size(); i++) { for(int32_t i = 0; i < (int32_t)entries.size(); i++) {
@ -322,66 +367,77 @@ void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes) {
} }
// not unittested // not unittested
void DefaultPieceStorage::clearFileFilter() { void DefaultPieceStorage::clearFileFilter()
{
bitfieldMan->clearFilter(); bitfieldMan->clearFilter();
diskAdaptor->addAllDownloadEntry(); diskAdaptor->addAllDownloadEntry();
} }
// not unittested // not unittested
bool DefaultPieceStorage::downloadFinished() { bool DefaultPieceStorage::downloadFinished()
{
return bitfieldMan->isFilteredAllBitSet(); return bitfieldMan->isFilteredAllBitSet();
} }
// not unittested // not unittested
bool DefaultPieceStorage::allDownloadFinished() { bool DefaultPieceStorage::allDownloadFinished()
{
return bitfieldMan->isAllBitSet(); return bitfieldMan->isAllBitSet();
} }
// not unittested // not unittested
void DefaultPieceStorage::initStorage() { void DefaultPieceStorage::initStorage()
if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) { {
if(btContext->getFileMode() == BtContext::SINGLE) { if(downloadContext->getFileMode() == DownloadContext::SINGLE) {
DefaultDiskWriterHandle writer = DefaultDiskWriter::createNewDiskWriter(option); logger->debug("Instantiating DirectDiskAdaptor");
DirectDiskAdaptorHandle directDiskAdaptor = new DirectDiskAdaptor(); DiskWriterHandle writer = _diskWriterFactory->newDiskWriter();
directDiskAdaptor->setDiskWriter(writer); DirectDiskAdaptorHandle directDiskAdaptor = new DirectDiskAdaptor();
directDiskAdaptor->setTotalLength(btContext->getTotalLength()); directDiskAdaptor->setDiskWriter(writer);
this->diskAdaptor = directDiskAdaptor; directDiskAdaptor->setTotalLength(downloadContext->getTotalLength());
} else { this->diskAdaptor = directDiskAdaptor;
} else {
// file mode == DownloadContext::MULTI
if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) {
logger->debug("Instantiating MultiDiskAdaptor");
MultiDiskAdaptorHandle multiDiskAdaptor = new MultiDiskAdaptor(); MultiDiskAdaptorHandle multiDiskAdaptor = new MultiDiskAdaptor();
multiDiskAdaptor->setPieceLength(btContext->getPieceLength()); multiDiskAdaptor->setPieceLength(downloadContext->getPieceLength());
multiDiskAdaptor->setTopDir(btContext->getName()); multiDiskAdaptor->setTopDir(downloadContext->getName());
multiDiskAdaptor->setOption(option); multiDiskAdaptor->setOption(option);
this->diskAdaptor = multiDiskAdaptor; this->diskAdaptor = multiDiskAdaptor;
} else {
logger->debug("Instantiating CopyDiskAdaptor");
DiskWriterHandle writer = _diskWriterFactory->newDiskWriter();
CopyDiskAdaptorHandle copyDiskAdaptor = new CopyDiskAdaptor();
copyDiskAdaptor->setDiskWriter(writer);
copyDiskAdaptor->setTempFilename(downloadContext->getName()+".a2tmp");
copyDiskAdaptor->setTotalLength(downloadContext->getTotalLength());
if(downloadContext->getFileMode() == DownloadContext::MULTI) {
copyDiskAdaptor->setTopDir(downloadContext->getName());
}
this->diskAdaptor = copyDiskAdaptor;
} }
} else {
DefaultDiskWriterHandle writer = DefaultDiskWriter::createNewDiskWriter(option);
CopyDiskAdaptorHandle copyDiskAdaptor = new CopyDiskAdaptor();
copyDiskAdaptor->setDiskWriter(writer);
copyDiskAdaptor->setTempFilename(btContext->getName()+".a2tmp");
copyDiskAdaptor->setTotalLength(btContext->getTotalLength());
if(btContext->getFileMode() == BtContext::MULTI) {
copyDiskAdaptor->setTopDir(btContext->getName());
}
this->diskAdaptor = copyDiskAdaptor;
}
string storeDir = option->get(PREF_DIR);
if(storeDir == "") {
storeDir = ".";
} }
string storeDir = downloadContext->getDir();//option->get(PREF_DIR);
// if(storeDir == "") {
// storeDir = ".";
// }
diskAdaptor->setStoreDir(storeDir); diskAdaptor->setStoreDir(storeDir);
diskAdaptor->setFileEntries(btContext->getFileEntries()); diskAdaptor->setFileEntries(downloadContext->getFileEntries());
} }
void DefaultPieceStorage::setBitfield(const unsigned char* bitfield, void DefaultPieceStorage::setBitfield(const unsigned char* bitfield,
int32_t bitfieldLength) { int32_t bitfieldLength)
{
bitfieldMan->setBitfield(bitfield, bitfieldLength); bitfieldMan->setBitfield(bitfield, bitfieldLength);
} }
int32_t DefaultPieceStorage::getBitfieldLength() { int32_t DefaultPieceStorage::getBitfieldLength()
{
return bitfieldMan->getBitfieldLength(); return bitfieldMan->getBitfieldLength();
} }
const unsigned char* DefaultPieceStorage::getBitfield() { const unsigned char* DefaultPieceStorage::getBitfield()
{
return bitfieldMan->getBitfield(); return bitfieldMan->getBitfield();
} }
@ -389,17 +445,20 @@ DiskAdaptorHandle DefaultPieceStorage::getDiskAdaptor() {
return diskAdaptor; return diskAdaptor;
} }
int32_t DefaultPieceStorage::getPieceLength(int32_t index) { int32_t DefaultPieceStorage::getPieceLength(int32_t index)
{
return bitfieldMan->getBlockLength(index); return bitfieldMan->getBlockLength(index);
} }
void DefaultPieceStorage::advertisePiece(int32_t cuid, int32_t index) { void DefaultPieceStorage::advertisePiece(int32_t cuid, int32_t index)
{
HaveEntry entry(cuid, index); HaveEntry entry(cuid, index);
haves.push_front(entry); haves.push_front(entry);
} }
Integers DefaultPieceStorage::getAdvertisedPieceIndexes(int32_t myCuid, Integers DefaultPieceStorage::getAdvertisedPieceIndexes(int32_t myCuid,
const Time& lastCheckTime) { const Time& lastCheckTime)
{
Integers indexes; Integers indexes;
for(Haves::const_iterator itr = haves.begin(); itr != haves.end(); itr++) { for(Haves::const_iterator itr = haves.begin(); itr != haves.end(); itr++) {
const Haves::value_type& have = *itr; const Haves::value_type& have = *itr;
@ -430,7 +489,8 @@ public:
} }
}; };
void DefaultPieceStorage::removeAdvertisedPiece(int32_t elapsed) { void DefaultPieceStorage::removeAdvertisedPiece(int32_t elapsed)
{
Haves::iterator itr = Haves::iterator itr =
find_if(haves.begin(), haves.end(), FindElapsedHave(elapsed)); find_if(haves.begin(), haves.end(), FindElapsedHave(elapsed));
if(itr != haves.end()) { if(itr != haves.end()) {
@ -444,19 +504,33 @@ void DefaultPieceStorage::markAllPiecesDone()
bitfieldMan->setAllBit(); bitfieldMan->setAllBit();
} }
void DefaultPieceStorage::checkIntegrity() void DefaultPieceStorage::markPiecesDone(int64_t length)
{ {
logger->notice(MSG_VALIDATING_FILE, // TODO implement this
diskAdaptor->getFilePath().c_str()); abort();
ChunkChecksumHandle chunkChecksum = new ChunkChecksum("sha1", }
btContext->getPieceHashes(),
btContext->getPieceLength()); void DefaultPieceStorage::markPieceMissing(int32_t index)
IteratableChunkChecksumValidatorHandle iv = new IteratableChunkChecksumValidator(); {
iv->setDiskWriter(new DiskAdaptorWriter(diskAdaptor)); bitfieldMan->unsetBit(index);
iv->setBitfield(bitfieldMan); }
iv->setChunkChecksum(chunkChecksum);
void DefaultPieceStorage::addInFlightPiece(const Pieces& pieces)
ChunkChecksumValidator v(iv); {
v.setFileAllocationMonitor(FileAllocationMonitorFactory::getFactory()->createNewMonitor()); copy(pieces.begin(), pieces.end(), back_inserter(usedPieces));
v.validate(); }
int32_t DefaultPieceStorage::countInFlightPiece()
{
return usedPieces.size();
}
Pieces DefaultPieceStorage::getInFlightPieces()
{
return usedPieces;
}
void DefaultPieceStorage::setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory)
{
_diskWriterFactory = diskWriterFactory;
} }

View File

@ -36,13 +36,15 @@
#define _D_DEFAULT_PIECE_STORAGE_H_ #define _D_DEFAULT_PIECE_STORAGE_H_
#include "PieceStorage.h" #include "PieceStorage.h"
#include "BtContext.h"
#include "DiskAdaptor.h" class DownloadContext;
#include "BitfieldMan.h" extern typedef SharedHandle<DownloadContext> DownloadContextHandle;
#include "Logger.h" class BitfieldMan;
#include "Option.h" class Logger;
#include "Piece.h" class Option;
#include "FileAllocator.h" extern typedef deque<PieceHandle> Pieces;
class DiskWriterFactory;
extern typedef SharedHandle<DiskWriterFactory> DiskWriterFactoryHandle;
#define END_GAME_PIECE_NUM 20 #define END_GAME_PIECE_NUM 20
@ -67,15 +69,15 @@ typedef deque<HaveEntry> Haves;
class DefaultPieceStorage : public PieceStorage { class DefaultPieceStorage : public PieceStorage {
private: private:
BtContextHandle btContext; DownloadContextHandle downloadContext;
BitfieldMan* bitfieldMan; BitfieldMan* bitfieldMan;
DiskAdaptorHandle diskAdaptor; DiskAdaptorHandle diskAdaptor;
DiskWriterFactoryHandle _diskWriterFactory;
Pieces usedPieces; Pieces usedPieces;
int32_t endGamePieceNum; int32_t endGamePieceNum;
Logger* logger; Logger* logger;
const Option* option; const Option* option;
Haves haves; Haves haves;
FileAllocatorHandle createFileAllocator();
int32_t getMissingPieceIndex(const PeerHandle& peer); int32_t getMissingPieceIndex(const PeerHandle& peer);
int32_t getMissingFastPieceIndex(const PeerHandle& peer); int32_t getMissingFastPieceIndex(const PeerHandle& peer);
@ -85,7 +87,7 @@ private:
void deleteUsedPiece(const PieceHandle& piece); void deleteUsedPiece(const PieceHandle& piece);
PieceHandle findUsedPiece(int32_t index) const; PieceHandle findUsedPiece(int32_t index) const;
public: public:
DefaultPieceStorage(BtContextHandle btContext, const Option* option); DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option);
virtual ~DefaultPieceStorage(); virtual ~DefaultPieceStorage();
virtual bool hasMissingPiece(const PeerHandle& peer); virtual bool hasMissingPiece(const PeerHandle& peer);
@ -94,6 +96,10 @@ public:
virtual PieceHandle getMissingFastPiece(const PeerHandle& peer); virtual PieceHandle getMissingFastPiece(const PeerHandle& peer);
virtual PieceHandle getMissingPiece();
virtual PieceHandle getMissingPiece(int32_t index);
virtual PieceHandle getPiece(int32_t index); virtual PieceHandle getPiece(int32_t index);
virtual void completePiece(const PieceHandle& piece); virtual void completePiece(const PieceHandle& piece);
@ -102,6 +108,8 @@ public:
virtual bool hasPiece(int32_t index); virtual bool hasPiece(int32_t index);
virtual bool isPieceUsed(int32_t index);
virtual int64_t getTotalLength(); virtual int64_t getTotalLength();
virtual int64_t getFilteredTotalLength(); virtual int64_t getFilteredTotalLength();
@ -156,13 +164,24 @@ public:
virtual void markAllPiecesDone(); virtual void markAllPiecesDone();
virtual void checkIntegrity(); virtual void markPiecesDone(int64_t length);
virtual void markPieceMissing(int32_t index);
virtual void addInFlightPiece(const Pieces& pieces);
virtual int32_t countInFlightPiece();
virtual Pieces getInFlightPieces();
/** /**
* This method is made private for test purpose only. * This method is made private for test purpose only.
*/ */
void addUsedPiece(const PieceHandle& piece); void addUsedPiece(const PieceHandle& piece);
void setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory);
}; };
typedef SharedHandle<DefaultPieceStorage> DefaultPieceStorageHandle;
#endif // _D_DEFAULT_PIECE_STORAGE_H_ #endif // _D_DEFAULT_PIECE_STORAGE_H_

View File

@ -36,13 +36,14 @@
#include "prefs.h" #include "prefs.h"
#include "DefaultDiskWriter.h" #include "DefaultDiskWriter.h"
SegmentManHandle DefaultSegmentManFactory::createNewInstance() SegmentManHandle DefaultSegmentManFactory::createNewInstance(const DownloadContextHandle& dctx,
const PieceStorageHandle& ps)
{ {
SegmentManHandle segmentMan = new SegmentMan(); SegmentManHandle segmentMan = new SegmentMan(_option, dctx, ps);
segmentMan->diskWriter = new DefaultDiskWriter(); //segmentMan->diskWriter = new DefaultDiskWriter();
segmentMan->dir = _option->get(PREF_DIR); //segmentMan->dir = _option->get(PREF_DIR);
// TODO disable this in multi-simultaneous download mode. // TODO disable this in multi-simultaneous download mode.
//segmentMan->ufilename = _option->get(PREF_OUT); //segmentMan->ufilename = _option->get(PREF_OUT);
segmentMan->option = _option; //segmentMan->option = _option;
return segmentMan; return segmentMan;
} }

View File

@ -43,7 +43,8 @@ public:
virtual ~DefaultSegmentManFactory() {} virtual ~DefaultSegmentManFactory() {}
virtual SegmentManHandle createNewInstance(); virtual SegmentManHandle createNewInstance(const DownloadContextHandle& dc,
const PieceStorageHandle& ps);
}; };
typedef SharedHandle<DefaultSegmentManFactory> DefaultSegmentManFactoryHandle; typedef SharedHandle<DefaultSegmentManFactory> DefaultSegmentManFactoryHandle;

View File

@ -32,6 +32,18 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#include "FileAllocationMonitor.h" #ifndef _D_DEPENDENCY_H_
#define _D_DEPENDENCY_H_
FileAllocationMonitorFactoryHandle FileAllocationMonitorFactory::factory = 0; #include "common.h"
class Dependency {
public:
virtual ~Dependency() {}
virtual bool resolve() = 0;
};
typedef SharedHandle<Dependency> DependencyHandle;
#endif // _D_DEPENDENCY_H_

View File

@ -34,11 +34,14 @@
/* copyright --> */ /* copyright --> */
#include "DirectDiskAdaptor.h" #include "DirectDiskAdaptor.h"
string DirectDiskAdaptor::getFilePath() { string DirectDiskAdaptor::getFilePath()
{
return storeDir+"/"+fileEntries.front()->getPath(); return storeDir+"/"+fileEntries.front()->getPath();
} }
void DirectDiskAdaptor::onDownloadComplete() { void DirectDiskAdaptor::onDownloadComplete()
throw(DlAbortEx*)
{
closeFile(); closeFile();
openFile(); openFile();
} }

View File

@ -36,6 +36,7 @@
#define _D_DIRECT_DISK_ADAPTOR_H_ #define _D_DIRECT_DISK_ADAPTOR_H_
#include "AbstractSingleDiskAdaptor.h" #include "AbstractSingleDiskAdaptor.h"
#include "DlAbortEx.h"
class DirectDiskAdaptor : public AbstractSingleDiskAdaptor { class DirectDiskAdaptor : public AbstractSingleDiskAdaptor {
public: public:
@ -44,7 +45,7 @@ public:
virtual string getFilePath(); virtual string getFilePath();
virtual void onDownloadComplete(); virtual void onDownloadComplete() throw(DlAbortEx*);
}; };
typedef SharedHandle<DirectDiskAdaptor> DirectDiskAdaptorHandle; typedef SharedHandle<DirectDiskAdaptor> DirectDiskAdaptorHandle;

View File

@ -33,7 +33,6 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DiskAdaptor.h" #include "DiskAdaptor.h"
#include "DlAbortEx.h"
#include "LogFactory.h" #include "LogFactory.h"
#include "message.h" #include "message.h"
@ -41,7 +40,9 @@ DiskAdaptor::DiskAdaptor():logger(LogFactory::getInstance()) {}
DiskAdaptor::~DiskAdaptor() {} DiskAdaptor::~DiskAdaptor() {}
FileEntryHandle DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) const { FileEntryHandle DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) const
throw(DlAbortEx*)
{
for(FileEntries::const_iterator itr = fileEntries.begin(); for(FileEntries::const_iterator itr = fileEntries.begin();
itr != fileEntries.end(); itr++) { itr != fileEntries.end(); itr++) {
if((*itr)->getPath() == fileEntryPath) { if((*itr)->getPath() == fileEntryPath) {
@ -51,7 +52,8 @@ FileEntryHandle DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) c
throw new DlAbortEx(EX_NO_SUCH_FILE_ENTRY, fileEntryPath.c_str()); throw new DlAbortEx(EX_NO_SUCH_FILE_ENTRY, fileEntryPath.c_str());
} }
bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath) { bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath)
{
for(FileEntries::iterator itr = fileEntries.begin(); for(FileEntries::iterator itr = fileEntries.begin();
itr != fileEntries.end(); itr++) { itr != fileEntries.end(); itr++) {
if((*itr)->getPath() == fileEntryPath) { if((*itr)->getPath() == fileEntryPath) {
@ -62,7 +64,8 @@ bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath) {
return false; return false;
} }
bool DiskAdaptor::addDownloadEntry(int index) { bool DiskAdaptor::addDownloadEntry(int index)
{
if(fileEntries.size() <= (unsigned int)index) { if(fileEntries.size() <= (unsigned int)index) {
return false; return false;
} }
@ -70,14 +73,16 @@ bool DiskAdaptor::addDownloadEntry(int index) {
return true; return true;
} }
void DiskAdaptor::addAllDownloadEntry() { void DiskAdaptor::addAllDownloadEntry()
{
for(FileEntries::iterator itr = fileEntries.begin(); for(FileEntries::iterator itr = fileEntries.begin();
itr != fileEntries.end(); itr++) { itr != fileEntries.end(); itr++) {
(*itr)->setRequested(true); (*itr)->setRequested(true);
} }
} }
void DiskAdaptor::removeAllDownloadEntry() { void DiskAdaptor::removeAllDownloadEntry()
{
for(FileEntries::iterator itr = fileEntries.begin(); for(FileEntries::iterator itr = fileEntries.begin();
itr != fileEntries.end(); itr++) { itr != fileEntries.end(); itr++) {
(*itr)->setRequested(false); (*itr)->setRequested(false);

View File

@ -35,11 +35,13 @@
#ifndef _D_DISK_ADAPTOR_H_ #ifndef _D_DISK_ADAPTOR_H_
#define _D_DISK_ADAPTOR_H_ #define _D_DISK_ADAPTOR_H_
#include "common.h" #include "BinaryStream.h"
#include "FileEntry.h" #include "FileEntry.h"
#include "Logger.h" #include "Logger.h"
#include "FileAllocationIterator.h"
#include "DlAbortEx.h"
class DiskAdaptor { class DiskAdaptor:public BinaryStream {
protected: protected:
string storeDir; string storeDir;
FileEntries fileEntries; FileEntries fileEntries;
@ -56,10 +58,6 @@ public:
virtual void initAndOpenFile() = 0; virtual void initAndOpenFile() = 0;
virtual void writeData(const unsigned char* data, int32_t len, int64_t offset) = 0;
virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) = 0;
virtual void onDownloadComplete() = 0; virtual void onDownloadComplete() = 0;
virtual bool fileExists() = 0; virtual bool fileExists() = 0;
@ -68,11 +66,15 @@ public:
virtual int64_t size() const = 0; virtual int64_t size() const = 0;
// optional behavior
virtual void truncate(int64_t length) {}
void setFileEntries(const FileEntries& fileEntries) { void setFileEntries(const FileEntries& fileEntries) {
this->fileEntries = fileEntries; this->fileEntries = fileEntries;
} }
FileEntryHandle getFileEntryFromPath(const string& fileEntryPath) const; FileEntryHandle
getFileEntryFromPath(const string& fileEntryPath) const throw(DlAbortEx*);
const FileEntries& getFileEntries() const { return fileEntries; } const FileEntries& getFileEntries() const { return fileEntries; }
@ -87,6 +89,8 @@ public:
void setStoreDir(const string& storeDir) { this->storeDir = storeDir; } void setStoreDir(const string& storeDir) { this->storeDir = storeDir; }
const string& getStoreDir() const { return this->storeDir; } const string& getStoreDir() const { return this->storeDir; }
virtual FileAllocationIteratorHandle fileAllocationIterator() = 0;
}; };
typedef SharedHandle<DiskAdaptor> DiskAdaptorHandle; typedef SharedHandle<DiskAdaptor> DiskAdaptorHandle;

View File

@ -35,15 +35,14 @@
#ifndef _D_DISK_WRITER_H_ #ifndef _D_DISK_WRITER_H_
#define _D_DISK_WRITER_H_ #define _D_DISK_WRITER_H_
#include "common.h" #include "BinaryStream.h"
#include "DlAbortEx.h"
using namespace std;
/** /**
* Interface for writing to a binary stream of bytes. * Interface for writing to a binary stream of bytes.
* *
*/ */
class DiskWriter { class DiskWriter:public BinaryStream {
public: public:
virtual ~DiskWriter() {} virtual ~DiskWriter() {}
/** /**
@ -51,13 +50,14 @@ public:
* If the file exists, then it is truncated to 0 length. * If the file exists, then it is truncated to 0 length.
* @param filename the file name to be opened. * @param filename the file name to be opened.
*/ */
virtual void initAndOpenFile(const string& filename, int64_t totalLength = 0) = 0; virtual void initAndOpenFile(const string& filename, int64_t totalLength = 0) = 0;
virtual void openFile(const string& filename, int64_t totalLength = 0) = 0; virtual void openFile(const string& filename, int64_t totalLength = 0) = 0;
/** /**
* Closes this output stream. * Closes this output stream.
*/ */
// TODO we have to examine the return value of close()
virtual void closeFile() = 0; virtual void closeFile() = 0;
/** /**
@ -68,26 +68,6 @@ public:
*/ */
virtual void openExistingFile(const string& filename, int64_t totalLength = 0) = 0; virtual void openExistingFile(const string& filename, int64_t totalLength = 0) = 0;
/*
* Writes len bytes from data to this binary stream at offset position.
* In case where offset position is not concerned(just write data
* sequencially, for example), those subclasses can ignore the offset value.
*
* @param data the data
* @param len the number of bytes to write
* @param position the offset of this binary stream
*/
virtual void writeData(const char* data, int32_t len, int64_t position = 0) = 0;
virtual void writeData(const unsigned char* data, int32_t len, int64_t position = 0)
{
writeData((const char*)data, len, position);
}
virtual int32_t readData(char* data, int32_t len, int64_t position) = 0;
virtual int32_t readData(unsigned char* data, int32_t len, int64_t position) {
return readData((char*)data, len, position);
}
virtual void truncate(int64_t length) = 0; virtual void truncate(int64_t length) = 0;
// Returns file length // Returns file length

View File

@ -32,20 +32,19 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#ifndef _D_GLOW_FILE_ALLOCATOR_H_ #ifndef _D_DISK_WRITER_FACTORY_H_
#define _D_GLOW_FILE_ALLOCATOR_H_ #define _D_DISK_WRITER_FACTORY_H_
#include "FileAllocator.h" #include "common.h"
#include "DiskWriter.h"
class GlowFileAllocator : public FileAllocator { class DiskWriterFactory {
public: public:
GlowFileAllocator() {} virtual ~DiskWriterFactory() {}
virtual ~GlowFileAllocator() {} virtual DiskWriterHandle newDiskWriter() = 0;
virtual void allocate(int fd, int64_t totalLength);
}; };
typedef SharedHandle<GlowFileAllocator> GlowFileAllocatorHandle; typedef SharedHandle<DiskWriterFactory> DiskWriterFactoryHandle;
#endif // _D_GLOW_FILE_ALLOCATOR_H_ #endif // _D_DISK_WRITER_FACTORY_H_

View File

@ -33,16 +33,20 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DownloadCommand.h" #include "DownloadCommand.h"
#include "SegmentMan.h"
#include "PeerStat.h"
#include "TransferEncoding.h"
#include "DownloadContext.h"
#include "Util.h" #include "Util.h"
#include "DlRetryEx.h" #include "DlRetryEx.h"
#include "DlAbortEx.h" #include "DlAbortEx.h"
#include "HttpInitiateConnectionCommand.h"
#include "InitiateConnectionCommandFactory.h" #include "InitiateConnectionCommandFactory.h"
#include "message.h" #include "message.h"
#include "prefs.h" #include "prefs.h"
#ifdef ENABLE_MESSAGE_DIGEST #include "DiskAdaptor.h"
# include "ChecksumCommand.h" #include "Segment.h"
#endif // ENABLE_MESSAGE_DIGEST #include "PieceStorage.h"
#include "Option.h"
#include <stdlib.h> #include <stdlib.h>
DownloadCommand::DownloadCommand(int cuid, DownloadCommand::DownloadCommand(int cuid,
@ -80,17 +84,23 @@ bool DownloadCommand::executeInternal() {
socket->readData(buf, bufSize); socket->readData(buf, bufSize);
if(transferDecoder.isNull()) { if(transferDecoder.isNull()) {
_requestGroup->getSegmentMan()->diskWriter->writeData(buf, bufSize, _requestGroup->getPieceStorage()->getDiskAdaptor()->writeData((const unsigned char*)buf, bufSize,
segment->getPositionToWrite()); segment->getPositionToWrite());
segment->writtenLength += bufSize; //logger->debug("bufSize = %d, posToWrite = %lld", bufSize, segment->getPositionToWrite());
segment->updateWrittenLength(bufSize);
//logger->debug("overflow length = %d, next posToWrite = %lld", segment->getOverflowLength(), segment->getPositionToWrite());
//logger->debug("%s", Util::toHex(segment->getPiece()->getBitfield(),
//segment->getPiece()->getBitfieldLength()).c_str());
//segment->writtenLength += bufSize;
peerStat->updateDownloadLength(bufSize); peerStat->updateDownloadLength(bufSize);
} else { } else {
int32_t infbufSize = 16*1024; int32_t infbufSize = 16*1024;
char infbuf[infbufSize]; char infbuf[infbufSize];
transferDecoder->inflate(infbuf, infbufSize, buf, bufSize); transferDecoder->inflate(infbuf, infbufSize, buf, bufSize);
_requestGroup->getSegmentMan()->diskWriter->writeData(infbuf, infbufSize, _requestGroup->getPieceStorage()->getDiskAdaptor()->writeData((const unsigned char*)infbuf, infbufSize,
segment->getPositionToWrite()); segment->getPositionToWrite());
segment->writtenLength += infbufSize; segment->updateWrittenLength(infbufSize);
//segment->writtenLength += infbufSize;
peerStat->updateDownloadLength(infbufSize); peerStat->updateDownloadLength(infbufSize);
} }
// calculate downloading speed // calculate downloading speed
@ -103,7 +113,7 @@ bool DownloadCommand::executeInternal() {
req->getHost().c_str()); req->getHost().c_str());
} }
} }
if(_requestGroup->getSegmentMan()->totalSize != 0 && bufSize == 0) { if(_requestGroup->getTotalLength() != 0 && bufSize == 0) {
throw new DlRetryEx(EX_GOT_EOF); throw new DlRetryEx(EX_GOT_EOF);
} }
if(!transferDecoder.isNull() && transferDecoder->finished() if(!transferDecoder.isNull() && transferDecoder->finished()
@ -112,11 +122,22 @@ bool DownloadCommand::executeInternal() {
if(!transferDecoder.isNull()) transferDecoder->end(); if(!transferDecoder.isNull()) transferDecoder->end();
logger->info(MSG_SEGMENT_DOWNLOAD_COMPLETED, cuid); logger->info(MSG_SEGMENT_DOWNLOAD_COMPLETED, cuid);
_requestGroup->getSegmentMan()->completeSegment(cuid, segment); _requestGroup->getSegmentMan()->completeSegment(cuid, segment);
// TODO According to the current plan, checksum is held by DownloadContext.
#ifdef ENABLE_MESSAGE_DIGEST
if(e->option->get(PREF_REALTIME_CHUNK_CHECKSUM) == V_TRUE) {
string pieceHash = _requestGroup->getDownloadContext()->getPieceHash(segment->getIndex());
if(!pieceHash.empty()) {
_requestGroup->getSegmentMan()->validatePieceHash(segment, pieceHash);
}
}
#endif // ENABLE_MESSAGE_DIGEST
/*
#ifdef ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST
if(e->option->get(PREF_REALTIME_CHUNK_CHECKSUM) == V_TRUE) { if(e->option->get(PREF_REALTIME_CHUNK_CHECKSUM) == V_TRUE) {
_requestGroup->getSegmentMan()->tryChunkChecksumValidation(segment, _requestGroup->getChunkChecksum()); _requestGroup->getSegmentMan()->tryChunkChecksumValidation(segment, _requestGroup->getChunkChecksum());
} }
#endif // ENABLE_MESSAGE_DIGEST #endif // ENABLE_MESSAGE_DIGEST
*/
// this unit is going to download another segment. // this unit is going to download another segment.
return prepareForNextSegment(); return prepareForNextSegment();
} else { } else {
@ -127,7 +148,9 @@ bool DownloadCommand::executeInternal() {
} }
bool DownloadCommand::prepareForNextSegment() { bool DownloadCommand::prepareForNextSegment() {
if(_requestGroup->getSegmentMan()->finished()) { if(_requestGroup->downloadFinished()) {
// TODO According to the current plan, checksum is held by DownloadContext.
/*
#ifdef ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST
if(!_requestGroup->getChecksum().isNull() && if(!_requestGroup->getChecksum().isNull() &&
!_requestGroup->getChecksum()->isEmpty()) { !_requestGroup->getChecksum()->isEmpty()) {
@ -136,6 +159,7 @@ bool DownloadCommand::prepareForNextSegment() {
e->commands.push_back(command); e->commands.push_back(command);
} }
#endif // ENABLE_MESSAGE_DIGEST #endif // ENABLE_MESSAGE_DIGEST
*/
return true; return true;
} else { } else {
// Merge segment with next segment, if segment.index+1 == nextSegment.index // Merge segment with next segment, if segment.index+1 == nextSegment.index
@ -143,15 +167,15 @@ bool DownloadCommand::prepareForNextSegment() {
while(1) { while(1) {
SegmentHandle nextSegment = SegmentHandle nextSegment =
_requestGroup->getSegmentMan()->getSegment(cuid, _requestGroup->getSegmentMan()->getSegment(cuid,
tempSegment->index+1); tempSegment->getIndex()+1);
if(nextSegment.isNull()) { if(nextSegment.isNull()) {
break; break;
} else { } else {
if(nextSegment->writtenLength > 0) { if(nextSegment->getWrittenLength() > 0) {
return prepareForRetry(0); return prepareForRetry(0);
} }
nextSegment->writtenLength = nextSegment->updateWrittenLength(tempSegment->getOverflowLength());
tempSegment->writtenLength-tempSegment->length; //tempSegment->writtenLength-tempSegment->length;
if(nextSegment->complete()) { if(nextSegment->complete()) {
_requestGroup->getSegmentMan()->completeSegment(cuid, nextSegment); _requestGroup->getSegmentMan()->completeSegment(cuid, nextSegment);
tempSegment = nextSegment; tempSegment = nextSegment;
@ -165,3 +189,8 @@ bool DownloadCommand::prepareForNextSegment() {
return prepareForRetry(0); return prepareForRetry(0);
} }
} }
void DownloadCommand::setTransferDecoder(const TransferEncodingHandle& transferDecoder)
{
this->transferDecoder = transferDecoder;
}

View File

@ -36,11 +36,11 @@
#define _D_DOWNLOAD_COMMAND_H_ #define _D_DOWNLOAD_COMMAND_H_
#include "AbstractCommand.h" #include "AbstractCommand.h"
#include "TransferEncoding.h"
#include "TimeA2.h"
#include "PeerStat.h"
using namespace std; class TransferEncoding;
extern typedef SharedHandle<TransferEncoding> TransferEncodingHandle;
class PeerStat;
extern typedef SharedHandle<PeerStat> PeerStatHandle;
class DownloadCommand : public AbstractCommand { class DownloadCommand : public AbstractCommand {
private: private:
@ -62,10 +62,7 @@ public:
const SocketHandle& s); const SocketHandle& s);
virtual ~DownloadCommand(); virtual ~DownloadCommand();
void setTransferDecoder(const TransferEncodingHandle& transferDecoder) void setTransferDecoder(const TransferEncodingHandle& transferDecoder);
{
this->transferDecoder = transferDecoder;
}
void setMaxDownloadSpeedLimit(int32_t maxDownloadSpeedLimit) { void setMaxDownloadSpeedLimit(int32_t maxDownloadSpeedLimit) {
this->maxDownloadSpeedLimit = maxDownloadSpeedLimit; this->maxDownloadSpeedLimit = maxDownloadSpeedLimit;

99
src/DownloadContext.h Normal file
View File

@ -0,0 +1,99 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_DOWNLOAD_CONTEXT_H_
#define _D_DOWNLOAD_CONTEXT_H_
#include "common.h"
#include "FileEntry.h"
class DownloadContext
{
protected:
string _dir;
public:
DownloadContext():_dir(".") {}
virtual ~DownloadContext() {}
enum FILE_MODE {
SINGLE,
MULTI
};
virtual string getPieceHash(int32_t index) const = 0;
virtual const Strings& getPieceHashes() const = 0;
virtual int64_t getTotalLength() const = 0;
virtual FILE_MODE getFileMode() const = 0;
virtual FileEntries getFileEntries() const = 0;
virtual string getName() const = 0;
virtual int32_t getPieceLength() const = 0;
virtual int32_t getNumPieces() const = 0;
virtual string getPieceHashAlgo() const = 0;
/**
* Returns an actual file path.
* If this contains a single file entry, then returns its file path,
* for example, "/tmp/downloads/aria2.txt"
* If this contains multiple file entries(i,e /tmp/downloads/aria2.txt,
* /tmp/downloads/aria2.bin), then returns its base dir path,
* for example, "/tmp/downloads"
*/
virtual string getActualBasePath() const = 0;
string getDir() const
{
return _dir;
}
void setDir(const string& dir)
{
_dir = dir;
}
};
typedef SharedHandle<DownloadContext> DownloadContextHandle;
#endif // _D_DOWNLOAD_CONTEXT_H_

View File

@ -33,6 +33,15 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DownloadEngine.h" #include "DownloadEngine.h"
#include "Socket.h"
#include "NameResolver.h"
#include "StatCalc.h"
#include "RequestGroup.h"
#include "RequestGroupMan.h"
#include "FileAllocationMan.h"
#ifdef ENABLE_MESSAGE_DIGEST
#include "CheckIntegrityMan.h"
#endif // ENABLE_MESSAGE_DIGEST
#include "Util.h" #include "Util.h"
#include "LogFactory.h" #include "LogFactory.h"
#include "TimeA2.h" #include "TimeA2.h"
@ -41,11 +50,38 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <signal.h>
#include <algorithm> #include <algorithm>
using namespace std; volatile sig_atomic_t globalHaltRequested;
SocketEntry::SocketEntry(const SocketHandle& socket,
Command* command,
TYPE type):
socket(socket), command(command), type(type) {}
bool SocketEntry::operator==(const SocketEntry& entry)
{
return socket == entry.socket &&
command == entry.command &&
type == entry.type;
}
#ifdef ENABLE_ASYNC_DNS
NameResolverEntry::NameResolverEntry(const NameResolverHandle& nameResolver,
Command* command):
nameResolver(nameResolver), command(command) {}
bool NameResolverEntry::operator==(const NameResolverEntry& entry)
{
return nameResolver == entry.nameResolver &&
command == entry.command;
}
#endif // ENABLE_ASYNC_DNS
DownloadEngine::DownloadEngine():logger(LogFactory::getInstance()), DownloadEngine::DownloadEngine():logger(LogFactory::getInstance()),
_statCalc(0),
_haltRequested(false),
noWait(false), noWait(false),
_requestGroupMan(0), _requestGroupMan(0),
_fileAllocationMan(0) _fileAllocationMan(0)
@ -83,7 +119,6 @@ void DownloadEngine::executeCommand(Command::STATUS statusFilter)
} }
void DownloadEngine::run() { void DownloadEngine::run() {
initStatistics();
Time cp; Time cp;
cp.setTimeInSec(0); cp.setTimeInSec(0);
Commands activeCommands; Commands activeCommands;
@ -232,6 +267,38 @@ bool DownloadEngine::deleteSocketForWriteCheck(const SocketHandle& socket,
return deleteSocket(entry); return deleteSocket(entry);
} }
void DownloadEngine::calculateStatistics()
{
if(!_statCalc.isNull()) {
_statCalc->calculateStat(_requestGroupMan, _fileAllocationMan, _checkIntegrityMan);
}
}
void DownloadEngine::onEndOfRun()
{
_requestGroupMan->closeFile();
_requestGroupMan->save();
}
void DownloadEngine::afterEachIteration()
{
if(globalHaltRequested) {
globalHaltRequested = false;
_haltRequested = true;
_requestGroupMan->halt();
}
}
void DownloadEngine::fillCommand()
{
addCommand(_requestGroupMan->getInitialCommands(this));
}
void DownloadEngine::setStatCalc(const StatCalcHandle& statCalc)
{
_statCalc = statCalc;
}
#ifdef ENABLE_ASYNC_DNS #ifdef ENABLE_ASYNC_DNS
bool DownloadEngine::addNameResolverCheck(const NameResolverHandle& resolver, bool DownloadEngine::addNameResolverCheck(const NameResolverHandle& resolver,
Command* command) { Command* command) {
@ -262,4 +329,10 @@ bool DownloadEngine::deleteNameResolverCheck(const NameResolverHandle& resolver,
return true; return true;
} }
} }
void DownloadEngine::addCommand(const Commands& commands)
{
this->commands.insert(this->commands.end(), commands.begin(), commands.end());
}
#endif // ENABLE_ASYNC_DNS #endif // ENABLE_ASYNC_DNS

View File

@ -35,20 +35,26 @@
#ifndef _D_DOWNLOAD_ENGINE_H_ #ifndef _D_DOWNLOAD_ENGINE_H_
#define _D_DOWNLOAD_ENGINE_H_ #define _D_DOWNLOAD_ENGINE_H_
#include "Command.h"
#include "Socket.h"
#include "SegmentMan.h"
#include "common.h" #include "common.h"
#include "Logger.h" #include "Command.h"
#include "Option.h"
#include "NameResolver.h"
#include "RequestGroupMan.h"
#include "FileAllocationMan.h"
#ifdef ENABLE_MESSAGE_DIGEST
# include "CheckIntegrityMan.h"
#endif // ENABLE_MESSAGE_DIGEST
typedef deque<SocketHandle> Sockets; class SocketCore;
extern typedef SharedHandle<SocketCore> SocketHandle;
extern typedef deque<SocketHandle> Sockets;
class Logger;
class Option;
class NameResolver;
extern typedef SharedHandle<NameResolver> NameResolverHandle;
class RequestGroupMan;
extern typedef SharedHandle<RequestGroupMan> RequestGroupManHandle;
class FileAllocationMan;
extern typedef SharedHandle<FileAllocationMan> FileAllocationManHandle;
class StatCalc;
extern typedef SharedHandle<StatCalc> StatCalcHandle;
#ifdef ENABLE_MESSAGE_DIGEST
class CheckIntegrityMan;
extern typedef SharedHandle<CheckIntegrityMan> CheckIntegrityManHandle;
#endif // ENABLE_MESSAGE_DIGEST
class SocketEntry { class SocketEntry {
public: public:
@ -63,15 +69,9 @@ public:
public: public:
SocketEntry(const SocketHandle& socket, SocketEntry(const SocketHandle& socket,
Command* command, Command* command,
TYPE type): TYPE type);
socket(socket), command(command), type(type) {}
~SocketEntry() {}
bool operator==(const SocketEntry& entry) { bool operator==(const SocketEntry& entry);
return socket == entry.socket &&
command == entry.command &&
type == entry.type;
}
}; };
typedef deque<SocketEntry> SocketEntries; typedef deque<SocketEntry> SocketEntries;
@ -83,14 +83,9 @@ public:
Command* command; Command* command;
public: public:
NameResolverEntry(const NameResolverHandle& nameResolver, NameResolverEntry(const NameResolverHandle& nameResolver,
Command* command): Command* command);
nameResolver(nameResolver), command(command) {}
~NameResolverEntry() {}
bool operator==(const NameResolverEntry& entry) { bool operator==(const NameResolverEntry& entry);
return nameResolver == entry.nameResolver &&
command == entry.command;
}
}; };
typedef deque<NameResolverEntry> NameResolverEntries; typedef deque<NameResolverEntry> NameResolverEntries;
@ -108,16 +103,26 @@ private:
fd_set wfdset; fd_set wfdset;
int32_t fdmax; int32_t fdmax;
const Logger* logger;
StatCalcHandle _statCalc;
bool _haltRequested;
void shortSleep() const; void shortSleep() const;
bool addSocket(const SocketEntry& socketEntry); bool addSocket(const SocketEntry& socketEntry);
bool deleteSocket(const SocketEntry& socketEntry); bool deleteSocket(const SocketEntry& socketEntry);
void executeCommand(Command::STATUS statusFilter); void executeCommand(Command::STATUS statusFilter);
protected:
const Logger* logger; /**
virtual void initStatistics() = 0; * Delegates to StatCalc
virtual void calculateStatistics() = 0; */
virtual void onEndOfRun() = 0; void calculateStatistics();
virtual void afterEachIteration() {}
void onEndOfRun();
void afterEachIteration();
public: public:
bool noWait; bool noWait;
Commands commands; Commands commands;
@ -152,11 +157,19 @@ public:
Command* command); Command* command);
#endif // ENABLE_ASYNC_DNS #endif // ENABLE_ASYNC_DNS
void addCommand(const Commands& commands) void addCommand(const Commands& commands);
void fillCommand();
void setStatCalc(const StatCalcHandle& statCalc);
bool isHaltRequested() const
{ {
this->commands.insert(this->commands.end(), commands.begin(), commands.end()); return _haltRequested;
} }
}; };
typedef SharedHandle<DownloadEngine> DownloadEngineHandle;
#endif // _D_DOWNLOAD_ENGINE_H_ #endif // _D_DOWNLOAD_ENGINE_H_

View File

@ -33,46 +33,31 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DownloadEngineFactory.h" #include "DownloadEngineFactory.h"
#include "prefs.h" #include "LogFactory.h"
#include "DefaultDiskWriter.h" #include "Option.h"
#include "InitiateConnectionCommandFactory.h" #include "RequestGroup.h"
#include "Util.h" #include "DownloadEngine.h"
#include "FileAllocator.h" #include "RequestGroupMan.h"
#include "FileAllocationMonitor.h"
#include "FillRequestGroupCommand.h"
#include "CUIDCounter.h"
#include "FileAllocationDispatcherCommand.h"
#include "FileAllocationMan.h" #include "FileAllocationMan.h"
#include "AutoSaveCommand.h"
#ifdef ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST
# include "CheckIntegrityMan.h" # include "CheckIntegrityMan.h"
#endif // ENABLE_MESSAGE_DIGEST #endif // ENABLE_MESSAGE_DIGEST
#ifdef ENABLE_BITTORRENT #include "prefs.h"
# include "PeerListenCommand.h" #include "Util.h"
# include "TrackerWatcherCommand.h" #include "CUIDCounter.h"
# include "TrackerUpdateCommand.h" #include "FillRequestGroupCommand.h"
# include "TorrentAutoSaveCommand.h" #include "FileAllocationDispatcherCommand.h"
# include "SeedCheckCommand.h" #include "AutoSaveCommand.h"
# include "PeerChokeCommand.h" #include "HaveEraseCommand.h"
# include "HaveEraseCommand.h" #include "PeerListenCommand.h"
# include "ActivePeerConnectionCommand.h"
# include "UnionSeedCriteria.h"
# include "TimeSeedCriteria.h"
# include "ShareRatioSeedCriteria.h"
# include "DefaultPieceStorage.h"
# include "DefaultPeerStorage.h"
# include "DefaultBtAnnounce.h"
# include "DefaultBtProgressInfoFile.h"
#endif // ENABLE_BITTORRENT
ConsoleDownloadEngine* DownloadEngineFactory::DownloadEngineFactory():
DownloadEngineFactory::newConsoleEngine(const Option* op, _logger(LogFactory::getInstance()) {}
const RequestGroups& requestGroups)
DownloadEngineHandle
DownloadEngineFactory::newDownloadEngine(Option* op,
const RequestGroups& requestGroups)
{ {
// set PREF_OUT parameter to requestGroup in non-multi download mode.
if(requestGroups.size() == 1) {
requestGroups.front()->setUserDefinedFilename(op->get(PREF_OUT));
}
RequestGroups workingSet; RequestGroups workingSet;
RequestGroups reservedSet; RequestGroups reservedSet;
if(op->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS) < (int32_t)requestGroups.size()) { if(op->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS) < (int32_t)requestGroups.size()) {
@ -83,109 +68,24 @@ DownloadEngineFactory::newConsoleEngine(const Option* op,
workingSet = requestGroups; workingSet = requestGroups;
} }
ConsoleDownloadEngine* e = new ConsoleDownloadEngine(); DownloadEngineHandle e = new DownloadEngine();
e->option = op; e->option = op;
RequestGroupManHandle requestGroupMan = new RequestGroupMan(workingSet, RequestGroupManHandle requestGroupMan =
op->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS)); new RequestGroupMan(workingSet,
op->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS));
requestGroupMan->addReservedGroup(reservedSet); requestGroupMan->addReservedGroup(reservedSet);
e->_requestGroupMan = requestGroupMan; e->_requestGroupMan = requestGroupMan;
e->_fileAllocationMan = new FileAllocationMan(); e->_fileAllocationMan = new FileAllocationMan();
#ifdef ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST
e->_checkIntegrityMan = new CheckIntegrityMan(); e->_checkIntegrityMan = new CheckIntegrityMan();
#endif // ENABLE_MESSAGE_DIGEST #endif // ENABLE_MESSAGE_DIGEST
e->commands.push_back(new FillRequestGroupCommand(CUIDCounterSingletonHolder::instance()->newID(), e, 1)); e->commands.push_back(new FillRequestGroupCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get(), 1));
e->commands.push_back(new FileAllocationDispatcherCommand(CUIDCounterSingletonHolder::instance()->newID(), e)); e->commands.push_back(new FileAllocationDispatcherCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get()));
e->commands.push_back(new AutoSaveCommand(CUIDCounterSingletonHolder::instance()->newID(), e, op->getAsInt(PREF_AUTO_SAVE_INTERVAL))); e->commands.push_back(new AutoSaveCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get(), op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
return e; e->commands.push_back(new HaveEraseCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get(), 10));
}
ConsoleDownloadEngine*
DownloadEngineFactory::newConsoleEngine(const Option* op,
const Requests& requests,
const Requests& reserved)
{
ConsoleDownloadEngine* e = new ConsoleDownloadEngine();
e->option = op;
// e->segmentMan = new SegmentMan();
// e->segmentMan->diskWriter = DefaultDiskWriter::createNewDiskWriter(op);
// e->segmentMan->dir = op->get(PREF_DIR);
// e->segmentMan->ufilename = op->get(PREF_OUT);
// e->segmentMan->option = op;
// e->segmentMan->reserved = reserved;
// int cuidCounter = 1;
// for(Requests::const_iterator itr = requests.begin();
// itr != requests.end();
// itr++, cuidCounter++) {
// e->commands.push_back(InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuidCounter, *itr, e));
// }
return e;
}
#ifdef ENABLE_BITTORRENT
TorrentConsoleDownloadEngine*
DownloadEngineFactory::newTorrentConsoleEngine(const BtContextHandle& btContext,
const Option* op,
const Strings& targetFiles)
{
TorrentConsoleDownloadEngine* te = new TorrentConsoleDownloadEngine();
te->option = op;
RequestGroupManHandle requestGroupMan = new RequestGroupMan();
te->_requestGroupMan = requestGroupMan;
// ByteArrayDiskWriter* byteArrayDiskWriter = new ByteArrayDiskWriter();
// te->segmentMan = new SegmentMan();
// te->segmentMan->diskWriter = byteArrayDiskWriter;
// te->segmentMan->option = op;
BtRuntimeHandle btRuntime(new BtRuntime());
BtRegistry::registerBtRuntime(btContext->getInfoHashAsString(), btRuntime);
PieceStorageHandle pieceStorage(new DefaultPieceStorage(btContext, op));
BtRegistry::registerPieceStorage(btContext->getInfoHashAsString(), pieceStorage);
PeerStorageHandle peerStorage(new DefaultPeerStorage(btContext, op));
BtRegistry::registerPeerStorage(btContext->getInfoHashAsString(), peerStorage);
BtAnnounceHandle btAnnounce(new DefaultBtAnnounce(btContext, op));
BtRegistry::registerBtAnnounce(btContext->getInfoHashAsString(), btAnnounce);
btAnnounce->shuffleAnnounce();
BtProgressInfoFileHandle btProgressInfoFile(new DefaultBtProgressInfoFile(btContext, op));
BtRegistry::registerBtProgressInfoFile(btContext->getInfoHashAsString(),
btProgressInfoFile);
BtRegistry::registerPeerObjectCluster(btContext->getInfoHashAsString(),
new PeerObjectCluster());
/*
DefaultBtMessageFactoryAdaptorHandle factoryAdaptor =
new DefaultBtMessageFactoryAdaptor();
BtRegistry::registerBtMessageFactoryAdaptor(btContext->getInfoHashAsString(),
factoryAdaptor);
BtMessageFactoryClusterHandle factoryCluster = new BtMessageFactoryCluster();
BtRegistry::registerBtMessageFactoryCluster(btContext->getInfoHashAsString(),
factoryCluster);
BtMessageDispatcherClusterHandle dispatcherCluster =
new BtMessageDispatcherCluster();
BtRegistry::registerBtMessageDispatcherCluster(btContext->getInfoHashAsString(),
dispatcherCluster);
*/
te->setBtContext(btContext);
// initialize file storage
pieceStorage->initStorage();
Integers selectIndexes;
Util::unfoldRange(op->get(PREF_SELECT_FILE), selectIndexes);
if(selectIndexes.size()) {
pieceStorage->setFileFilter(selectIndexes);
} else {
pieceStorage->setFileFilter(targetFiles);
}
PeerListenCommand* listenCommand = PeerListenCommand* listenCommand =
new PeerListenCommand(CUIDCounterSingletonHolder::instance()->newID(), new PeerListenCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get());
te, btContext);
int32_t port; int32_t port;
int32_t listenPort = op->getAsInt(PREF_LISTEN_PORT); int32_t listenPort = op->getAsInt(PREF_LISTEN_PORT);
if(listenPort == -1) { if(listenPort == -1) {
@ -194,48 +94,13 @@ DownloadEngineFactory::newTorrentConsoleEngine(const BtContextHandle& btContext,
port = listenCommand->bindPort(listenPort, listenPort); port = listenCommand->bindPort(listenPort, listenPort);
} }
if(port == -1) { if(port == -1) {
printf(_("Errors occurred while binding port.\n")); _logger->error(_("Errors occurred while binding port.\n"));
exit(EXIT_FAILURE); delete listenCommand;
} else {
op->put(PREF_LISTEN_PORT, Util::itos(port).c_str());
e->commands.push_back(listenCommand);
} }
btRuntime->setListenPort(port); //btRuntime->setListenPort(port);
te->commands.push_back(listenCommand);
te->commands.push_back(new TrackerWatcherCommand(CUIDCounterSingletonHolder::instance()->newID(),
te,
btContext));
te->commands.push_back(new TrackerUpdateCommand(CUIDCounterSingletonHolder::instance()->newID(),
te,
btContext));
te->commands.push_back(new TorrentAutoSaveCommand(CUIDCounterSingletonHolder::instance()->newID(),
te,
btContext,
op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
te->commands.push_back(new PeerChokeCommand(CUIDCounterSingletonHolder::instance()->newID(),
te,
btContext,
10));
te->commands.push_back(new HaveEraseCommand(CUIDCounterSingletonHolder::instance()->newID(),
te,
btContext,
10));
te->commands.push_back(new ActivePeerConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(),
te,
btContext,
30));
SharedHandle<UnionSeedCriteria> unionCri = new UnionSeedCriteria(); return e;
if(op->defined(PREF_SEED_TIME)) {
unionCri->addSeedCriteria(new TimeSeedCriteria(op->getAsInt(PREF_SEED_TIME)*60));
}
if(op->defined(PREF_SEED_RATIO)) {
unionCri->addSeedCriteria(new ShareRatioSeedCriteria(op->getAsDouble(PREF_SEED_RATIO), btContext));
}
if(unionCri->getSeedCriterion().size() > 0) {
te->commands.push_back(new SeedCheckCommand(CUIDCounterSingletonHolder::instance()->newID(),
te,
btContext,
unionCri));
}
return te;
} }
#endif // ENABLE_BITTORRENT

View File

@ -36,28 +36,23 @@
#define _D_DOWNLOAD_ENGINE_FACTORY_H_ #define _D_DOWNLOAD_ENGINE_FACTORY_H_
#include "common.h" #include "common.h"
#include "ConsoleDownloadEngine.h"
#ifdef ENABLE_BITTORRENT class Logger;
# include "TorrentConsoleDownloadEngine.h" class Option;
#endif // ENABLE_BITTORRENT class RequestGroup;
extern typedef SharedHandle<RequestGroup> RequestGroupHandle;
extern typedef deque<RequestGroupHandle> RequestGroups;
class DownloadEngine;
extern typedef SharedHandle<DownloadEngine> DownloadEngineHandle;
class DownloadEngineFactory { class DownloadEngineFactory {
private:
const Logger* _logger;
public: public:
static ConsoleDownloadEngine* DownloadEngineFactory();
newConsoleEngine(const Option* op,
const RequestGroups& requestGroups);
static ConsoleDownloadEngine* DownloadEngineHandle
newConsoleEngine(const Option* option, newDownloadEngine(Option* op, const RequestGroups& requestGroups);
const Requests& requests,
const Requests& reserved);
#ifdef ENABLE_BITTORRENT
static TorrentConsoleDownloadEngine*
newTorrentConsoleEngine(const BtContextHandle& btContext,
const Option* option,
const Strings& targetFiles);
#endif // ENABLE_BITTORRENT
}; };
#endif // _D_DOWNLOAD_ENGINE_FACTORY_H_ #endif // _D_DOWNLOAD_ENGINE_FACTORY_H_

View File

@ -37,6 +37,11 @@
#include "a2io.h" #include "a2io.h"
#include <libgen.h> #include <libgen.h>
#ifdef __MINGW32__
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif // __MINGW32__
File::File(const string& name):name(name) {} File::File(const string& name):name(name) {}
File::~File() {} File::~File() {}
@ -140,3 +145,21 @@ bool File::isDir(const string& filename)
{ {
return File(filename).isDir(); return File(filename).isDir();
} }
bool File::renameTo(const string& dest)
{
#ifdef __MINGW32__
/* MinGW's rename() doesn't delete an existing destination */
if (_access(dest.c_str(), 0) == 0) {
if (_unlink(dest.c_str()) != 0) {
return false;
}
}
#endif // __MINGW32__
if(rename(name.c_str(), dest.c_str()) == 0) {
name = dest;
return true;
} else {
return false;
}
}

View File

@ -96,6 +96,8 @@ public:
string getDirname() const; string getDirname() const;
static bool isDir(const string& filename); static bool isDir(const string& filename);
bool renameTo(const string& dest);
}; };
#endif // _D_FILE_H_ #endif // _D_FILE_H_

View File

@ -33,45 +33,48 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "FileAllocationCommand.h" #include "FileAllocationCommand.h"
#include "InitiateConnectionCommandFactory.h" #include "FileAllocationMan.h"
#include "FileAllocationEntry.h"
#include "message.h" #include "message.h"
#include "DownloadCommand.h" #include "DownloadCommand.h"
#include "prefs.h" #include "prefs.h"
#include "Util.h" #include "Util.h"
FileAllocationCommand::FileAllocationCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const FileAllocationEntryHandle& fileAllocationEntry):
RealtimeCommand(cuid, requestGroup, e),
_fileAllocationEntry(fileAllocationEntry) {}
FileAllocationCommand::~FileAllocationCommand() {}
bool FileAllocationCommand::executeInternal() bool FileAllocationCommand::executeInternal()
{ {
_fileAllocationEntry->allocateChunk(); if(_e->isHaltRequested()) {
if(_fileAllocationEntry->finished()) {
logger->debug(MSG_ALLOCATION_COMPLETED,
_timer.difference(),
Util::llitos(_requestGroup->getTotalLength(), true).c_str());
_e->_fileAllocationMan->markCurrentFileAllocationEntryDone();
if(_timer.difference() <= _e->option->getAsInt(PREF_DIRECT_DOWNLOAD_TIMEOUT) &&
_fileAllocationEntry->getNextDownloadCommand()) {
_e->commands.push_back(_fileAllocationEntry->popNextDownloadCommand());
} else {
Commands commands = _requestGroup->createNextCommandWithAdj(_e, -1);
Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, _fileAllocationEntry->getCurrentRequest(), _requestGroup, _e);
commands.push_front(command);
_e->addCommand(commands);
}
return true; return true;
} else { }
_e->commands.push_back(this); try {
return false; _fileAllocationEntry->allocateChunk();
if(_fileAllocationEntry->finished()) {
logger->debug(MSG_ALLOCATION_COMPLETED,
_timer.difference(),
Util::llitos(_requestGroup->getTotalLength(), true).c_str());
_e->_fileAllocationMan->markCurrentFileAllocationEntryDone();
_e->addCommand(_fileAllocationEntry->prepareForNextAction(_e));
return true;
} else {
_e->commands.push_back(this);
return false;
}
} catch(Exception* e) {
_e->_fileAllocationMan->markCurrentFileAllocationEntryDone();
throw;
} }
} }
bool FileAllocationCommand::handleException(Exception* e) bool FileAllocationCommand::handleException(Exception* e)
{ {
logger->error(MSG_FILE_ALLOCATION_FAILURE, e, cuid); logger->error(MSG_FILE_ALLOCATION_FAILURE, e, cuid);
delete e;
logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str()); logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str());
return true; return true;
} }

View File

@ -37,16 +37,19 @@
#include "RealtimeCommand.h" #include "RealtimeCommand.h"
#include "TimeA2.h" #include "TimeA2.h"
#include "FileAllocationEntry.h"
class FileAllocationEntry;
extern typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;
class Exception;
class FileAllocationCommand : public RealtimeCommand { class FileAllocationCommand : public RealtimeCommand {
private: private:
FileAllocationEntryHandle _fileAllocationEntry; FileAllocationEntryHandle _fileAllocationEntry;
Time _timer; Time _timer;
public: public:
FileAllocationCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const FileAllocationEntryHandle& fileAllocationEntry): FileAllocationCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const FileAllocationEntryHandle& fileAllocationEntry);
RealtimeCommand(cuid, requestGroup, e),
_fileAllocationEntry(fileAllocationEntry) {} virtual ~FileAllocationCommand();
virtual bool executeInternal(); virtual bool executeInternal();

View File

@ -33,22 +33,35 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "FileAllocationDispatcherCommand.h" #include "FileAllocationDispatcherCommand.h"
#include "DownloadEngine.h"
#include "RequestGroupMan.h"
#include "FileAllocationMan.h"
#include "FileAllocationEntry.h"
#include "FileAllocationCommand.h" #include "FileAllocationCommand.h"
#include "message.h" #include "message.h"
#include "CUIDCounter.h"
FileAllocationDispatcherCommand::FileAllocationDispatcherCommand(int32_t cuid, DownloadEngine* e):
Command(cuid), _e(e)
{
setStatusRealtime();
}
FileAllocationDispatcherCommand::~FileAllocationDispatcherCommand() {}
bool FileAllocationDispatcherCommand::execute() bool FileAllocationDispatcherCommand::execute()
{ {
if(_e->_requestGroupMan->downloadFinished()) { if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
return true; return true;
} }
if(!_e->_fileAllocationMan->isFileAllocationBeingExecuted() && if(!_e->_fileAllocationMan->isFileAllocationBeingExecuted() &&
_e->_fileAllocationMan->nextFileAllocationEntryExists()) { _e->_fileAllocationMan->nextFileAllocationEntryExists()) {
FileAllocationEntryHandle entry = _e->_fileAllocationMan->popNextFileAllocationEntry(); FileAllocationEntryHandle entry = _e->_fileAllocationMan->popNextFileAllocationEntry();
logger->info(MSG_FILE_ALLOCATION_DISPATCH, // TODO we have to change message
entry->getCUID()); int32_t newCUID = CUIDCounterSingletonHolder::instance()->newID();
logger->info(MSG_FILE_ALLOCATION_DISPATCH, newCUID);
FileAllocationCommand* command = FileAllocationCommand* command =
new FileAllocationCommand(entry->getCUID(), new FileAllocationCommand(newCUID,
entry->getRequestGroup(), entry->getRequestGroup(),
_e, _e,
entry); entry);

View File

@ -36,17 +36,16 @@
#define _D_FILE_ALLOCATION_DISPATCHER_COMMAND_H_ #define _D_FILE_ALLOCATION_DISPATCHER_COMMAND_H_
#include "Command.h" #include "Command.h"
#include "DownloadEngine.h"
class DownloadEngine;
class FileAllocationDispatcherCommand : public Command { class FileAllocationDispatcherCommand : public Command {
private: private:
DownloadEngine* _e; DownloadEngine* _e;
public: public:
FileAllocationDispatcherCommand(int cuid, DownloadEngine* e): FileAllocationDispatcherCommand(int32_t cuid, DownloadEngine* e);
Command(cuid), _e(e)
{ virtual ~FileAllocationDispatcherCommand();
setStatusRealtime();
}
virtual bool execute(); virtual bool execute();
}; };

View File

@ -33,22 +33,35 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "FileAllocationEntry.h" #include "FileAllocationEntry.h"
#include "FileAllocationIterator.h"
#include "DownloadEngine.h"
#include "RequestGroup.h"
#include "PieceStorage.h"
#include "DiskAdaptor.h"
#define BUFSIZE 16*1024 FileAllocationEntry::FileAllocationEntry(RequestGroup* requestGroup, Command* nextCommand):
RequestGroupEntry(requestGroup, nextCommand),
_fileAllocationIterator(requestGroup->getPieceStorage()->getDiskAdaptor()->fileAllocationIterator())
{}
FileAllocationEntry:: ~FileAllocationEntry() {}
int64_t FileAllocationEntry::getCurrentLength()
{
return _fileAllocationIterator->getCurrentLength();
}
int64_t FileAllocationEntry::getTotalLength()
{
return _fileAllocationIterator->getTotalLength();
}
bool FileAllocationEntry::finished()
{
return _fileAllocationIterator->finished();
}
void FileAllocationEntry::allocateChunk() void FileAllocationEntry::allocateChunk()
{ {
int32_t bufSize = BUFSIZE; _fileAllocationIterator->allocateChunk();
char buf[BUFSIZE];
memset(buf, 0, bufSize);
_requestGroup->getSegmentMan()->diskWriter->writeData(buf, bufSize, _offset);
_offset += bufSize;
int64_t totalLength = _requestGroup->getSegmentMan()->totalSize;
if(totalLength < _offset) {
_requestGroup->getSegmentMan()->diskWriter->truncate(totalLength);
_offset = totalLength;
}
} }

View File

@ -37,32 +37,29 @@
#include "RequestGroupEntry.h" #include "RequestGroupEntry.h"
class FileAllocationEntry : public RequestGroupEntry { class FileAllocationIterator;
extern typedef SharedHandle<FileAllocationIterator> FileAllocationIteratorHandle;
class Command;
extern typedef deque<Command*> Commands;
class DownloadEngine;
class FileAllocationEntry : public RequestGroupEntry, public ProgressAwareEntry {
private: private:
int64_t _offset; FileAllocationIteratorHandle _fileAllocationIterator;
public: public:
FileAllocationEntry(int cuid, FileAllocationEntry(RequestGroup* requestGroup, Command* nextCommand = 0);
const RequestHandle& currentRequest,
RequestGroup* requestGroup,
DownloadCommand* nextDownloadCommand = 0,
int64_t offset = 0):
RequestGroupEntry(cuid, currentRequest, requestGroup, nextDownloadCommand),
_offset(offset)
{}
virtual ~FileAllocationEntry() {} ~FileAllocationEntry();
virtual int64_t getCurrentLength() const virtual int64_t getCurrentLength();
{
return _offset;
}
virtual bool finished() const virtual int64_t getTotalLength();
{
return _requestGroup->getTotalLength() <= _offset; virtual bool finished();
}
void allocateChunk(); void allocateChunk();
virtual Commands prepareForNextAction(DownloadEngine* e) = 0;
}; };
typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle; typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;

View File

@ -0,0 +1,56 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_FILE_ALLOCATION_ITERATOR_H_
#define _D_FILE_ALLOCATION_ITERATOR_H_
#include "common.h"
class FileAllocationIterator
{
public:
virtual ~FileAllocationIterator() {}
virtual void allocateChunk() = 0;
virtual bool finished() = 0;
virtual int64_t getCurrentLength() = 0;
virtual int64_t getTotalLength() = 0;
};
typedef SharedHandle<FileAllocationIterator> FileAllocationIteratorHandle;
#endif // _D_FILE_ALLOCATION_ITERATOR_H_

View File

@ -32,40 +32,50 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#include "TorrentConsoleDownloadEngine.h" #include "FileAllocationMan.h"
#include "Util.h" #include "FileAllocationEntry.h"
#include <signal.h>
volatile sig_atomic_t btHaltRequested = 0; FileAllocationMan::FileAllocationMan():_currentFileAllocationEntry(0) {}
TorrentConsoleDownloadEngine::TorrentConsoleDownloadEngine() {} FileAllocationMan::~FileAllocationMan() {}
TorrentConsoleDownloadEngine::~TorrentConsoleDownloadEngine() {} bool FileAllocationMan::isFileAllocationBeingExecuted() const
{
void TorrentConsoleDownloadEngine::sendStatistics() { return _currentFileAllocationEntry.get() != 0;
printf("\r ");
printf("\r");
if(pieceStorage->downloadFinished()) {
printf("Download Completed.");
} else {
printf("%sB/%sB %d%% %s D:%.2f",
Util::abbrevSize(downloadLength).c_str(),
Util::abbrevSize(totalLength).c_str(),
(totalLength == 0 ?
0 : (int)((downloadLength*100)/totalLength)),
avgSpeed == 0 ? "-" : Util::secfmt(eta).c_str(),
downloadSpeed/1024.0);
}
printf(" U:%.2f(%sB) %d peers",
uploadSpeed/1024.0,
Util::abbrevSize(uploadLength).c_str(),
btRuntime->getConnections());
fflush(stdout);
} }
void TorrentConsoleDownloadEngine::afterEachIteration() { FileAllocationEntryHandle FileAllocationMan::getCurrentFileAllocationEntry()
if(btHaltRequested) { {
btRuntime->setHalt(true); return _currentFileAllocationEntry;
} }
TorrentDownloadEngine::afterEachIteration();
void FileAllocationMan::markCurrentFileAllocationEntryDone()
{
_currentFileAllocationEntry = 0;
}
bool FileAllocationMan::nextFileAllocationEntryExists() const
{
return !_fileAllocationEntries.empty();
}
FileAllocationEntryHandle FileAllocationMan::popNextFileAllocationEntry()
{
if(!nextFileAllocationEntryExists()) {
return 0;
}
FileAllocationEntryHandle entry = _fileAllocationEntries.front();
_fileAllocationEntries.pop_front();
_currentFileAllocationEntry = entry;
return entry;
}
void FileAllocationMan::pushFileAllocationEntry(const FileAllocationEntryHandle& entry)
{
_fileAllocationEntries.push_back(entry);
}
int32_t FileAllocationMan::countFileAllocationEntryInQueue() const
{
return _fileAllocationEntries.size();
} }

View File

@ -36,57 +36,33 @@
#define _D_FILE_ALLOCATION_MAN_H_ #define _D_FILE_ALLOCATION_MAN_H_
#include "common.h" #include "common.h"
#include "Request.h"
#include "RequestGroup.h" class FileAllocationEntry;
#include "FileAllocationEntry.h" extern typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;
extern typedef deque<FileAllocationEntryHandle> FileAllocationEntries;
class FileAllocationMan { class FileAllocationMan {
private: private:
FileAllocationEntries _fileAllocationEntries; FileAllocationEntries _fileAllocationEntries;
FileAllocationEntryHandle _currentFileAllocationEntry; FileAllocationEntryHandle _currentFileAllocationEntry;
public: public:
FileAllocationMan():_currentFileAllocationEntry(0) {} FileAllocationMan();
bool isFileAllocationBeingExecuted() const ~FileAllocationMan();
{
return _currentFileAllocationEntry.get() != 0;
}
FileAllocationEntryHandle getCurrentFileAllocationEntry() bool isFileAllocationBeingExecuted() const;
{
return _currentFileAllocationEntry;
}
void markCurrentFileAllocationEntryDone() FileAllocationEntryHandle getCurrentFileAllocationEntry();
{
_currentFileAllocationEntry = 0;
}
bool nextFileAllocationEntryExists() const void markCurrentFileAllocationEntryDone();
{
return !_fileAllocationEntries.empty();
}
FileAllocationEntryHandle popNextFileAllocationEntry() bool nextFileAllocationEntryExists() const;
{
if(!nextFileAllocationEntryExists()) {
return 0;
}
FileAllocationEntryHandle entry = _fileAllocationEntries.front();
_fileAllocationEntries.pop_front();
_currentFileAllocationEntry = entry;
return entry;
}
void pushFileAllocationEntry(const FileAllocationEntryHandle& entry) FileAllocationEntryHandle popNextFileAllocationEntry();
{
_fileAllocationEntries.push_back(entry);
}
int32_t countFileAllocationEntryInQueue() const void pushFileAllocationEntry(const FileAllocationEntryHandle& entry);
{
return _fileAllocationEntries.size(); int32_t countFileAllocationEntryInQueue() const;
}
}; };
typedef SharedHandle<FileAllocationMan> FileAllocationManHandle; typedef SharedHandle<FileAllocationMan> FileAllocationManHandle;

View File

@ -45,7 +45,8 @@ FileEntry::FileEntry(const string& path,
FileEntry::~FileEntry() {} FileEntry::~FileEntry() {}
void FileEntry::setupDir(const string& parentDir) { void FileEntry::setupDir(const string& parentDir)
{
string absPath = parentDir+"/"+path; string absPath = parentDir+"/"+path;
char* temp = strdup(absPath.c_str()); char* temp = strdup(absPath.c_str());
string dir = string(dirname(temp)); string dir = string(dirname(temp));
@ -62,3 +63,15 @@ void FileEntry::setupDir(const string& parentDir) {
throw new DlAbortEx("Failed to create directory %s.", dir.c_str()); throw new DlAbortEx("Failed to create directory %s.", dir.c_str());
} }
} }
FileEntry& FileEntry::operator=(const FileEntry& entry)
{
if(this != &entry) {
path = entry.path;
length = entry.length;
offset = entry.offset;
extracted = entry.extracted;
requested = entry.requested;
}
return *this;
}

View File

@ -50,20 +50,10 @@ public:
FileEntry(const string& path, int64_t length, int64_t offset); FileEntry(const string& path, int64_t length, int64_t offset);
FileEntry& operator=(const FileEntry& entry)
{
if(this != &entry) {
path = entry.path;
length = entry.length;
offset = entry.offset;
extracted = entry.extracted;
requested = entry.requested;
}
return *this;
}
~FileEntry(); ~FileEntry();
FileEntry& operator=(const FileEntry& entry);
string getBasename() const string getBasename() const
{ {
return File(path).getBasename(); return File(path).getBasename();

View File

@ -33,11 +33,33 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "FillRequestGroupCommand.h" #include "FillRequestGroupCommand.h"
#include "DownloadEngine.h"
#include "RequestGroupMan.h"
#include "RequestGroup.h"
#include "DlAbortEx.h"
#include "message.h"
FillRequestGroupCommand::FillRequestGroupCommand(int32_t cuid,
DownloadEngine* e,
int32_t interval):
Command(cuid),
_e(e),
_interval(interval)
{
setStatusRealtime();
}
FillRequestGroupCommand::~FillRequestGroupCommand() {}
bool FillRequestGroupCommand::execute() bool FillRequestGroupCommand::execute()
{ {
_e->_requestGroupMan->fillRequestGroupFromReserver(_e); try {
if(_e->_requestGroupMan->downloadFinished()) { _e->_requestGroupMan->fillRequestGroupFromReserver(_e);
} catch(DlAbortEx* ex) {
logger->error(EX_EXCEPTION_CAUGHT, ex);
delete ex;
}
if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
return true; return true;
} }
_e->commands.push_back(this); _e->commands.push_back(this);

View File

@ -37,8 +37,11 @@
#include "Command.h" #include "Command.h"
#include "TimeA2.h" #include "TimeA2.h"
#include "RequestGroup.h"
#include "DownloadEngine.h" class RequestGroup;
extern typedef SharedHandle<RequestGroup> RequestGroupHandle;
extern typedef deque<RequestGroupHandle> RequestGroups;
class DownloadEngine;
class FillRequestGroupCommand : public Command { class FillRequestGroupCommand : public Command {
private: private:
@ -47,13 +50,9 @@ private:
int32_t _interval; int32_t _interval;
Time _checkPoint; Time _checkPoint;
public: public:
FillRequestGroupCommand(int cuid, DownloadEngine* e, int32_t interval): FillRequestGroupCommand(int32_t cuid, DownloadEngine* e, int32_t interval);
Command(cuid),
_e(e), virtual ~FillRequestGroupCommand();
_interval(interval)
{
setStatusRealtime();
}
virtual bool execute(); virtual bool execute();

Some files were not shown because too many files have changed in this diff Show More