mirror of https://github.com/aria2/aria2
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
parent
e26bbbb9ee
commit
048a2cf597
|
@ -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
7
TODO
|
@ -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
|
||||||
|
|
|
@ -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'`\\"
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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_
|
|
@ -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;
|
||||||
|
}
|
|
@ -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_
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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_
|
|
@ -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;
|
|
||||||
}
|
}
|
|
@ -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_
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
}
|
|
@ -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_
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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) \
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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_
|
|
|
@ -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();
|
||||||
|
|
|
@ -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) {}
|
||||||
|
|
|
@ -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_
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -79,6 +79,11 @@ public:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Strings& getChecksums() const
|
||||||
|
{
|
||||||
|
return _checksums;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t getChecksumLength() const
|
int32_t getChecksumLength() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -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();
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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_
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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_
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_
|
|
@ -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
|
||||||
|
|
|
@ -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_
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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_
|
||||||
|
|
23
src/File.cc
23
src/File.cc
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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_
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_
|
|
@ -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();
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue