mirror of
https://github.com/aria2/aria2.git
synced 2025-01-04 09:03:46 +00:00
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.
This commit is contained in:
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>
|
||||
|
||||
Fixed the compilation error on 64bit platform.
|
||||
|
7
TODO
7
TODO
@ -47,4 +47,9 @@
|
||||
src/PeerChokeCommand.h
|
||||
src/TorrentAutoSaveCommand.h
|
||||
* Rewrite MetaFileUtil
|
||||
* Integrate FTP/HTTP/BitTorrent downloads from metalinks
|
||||
* Reconsider the use of RecoverableException and FatalException
|
||||
* Limit the number of opening file to,say,100 in MultiDiskAdaptor.
|
||||
|
||||
* Implement duplicate download checking in Bt
|
||||
* Implement the feature to treat http/ftp as auxuality download method for BitTorrent
|
||||
* Fixed the download error when sending "CWD //*" to the ftp server
|
||||
|
20
configure
vendored
20
configure
vendored
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# 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>.
|
||||
#
|
||||
@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='aria2c'
|
||||
PACKAGE_TARNAME='aria2c'
|
||||
PACKAGE_VERSION='0.11.3'
|
||||
PACKAGE_STRING='aria2c 0.11.3'
|
||||
PACKAGE_VERSION='0.12.0alpha'
|
||||
PACKAGE_STRING='aria2c 0.12.0alpha'
|
||||
PACKAGE_BUGREPORT='t-tujikawa@users.sourceforge.net'
|
||||
|
||||
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.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
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]...
|
||||
|
||||
@ -1369,7 +1369,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of aria2c 0.11.3:";;
|
||||
short | recursive ) echo "Configuration of aria2c 0.12.0alpha:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@ -1490,7 +1490,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
aria2c configure 0.11.3
|
||||
aria2c configure 0.12.0alpha
|
||||
generated by GNU Autoconf 2.61
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
$ $0 $@
|
||||
@ -2300,7 +2300,7 @@ fi
|
||||
|
||||
# Define the identity of the package.
|
||||
PACKAGE='aria2c'
|
||||
VERSION='0.11.3'
|
||||
VERSION='0.12.0alpha'
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
@ -14327,7 +14327,7 @@ exec 6>&1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
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
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@ -14380,7 +14380,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
||||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF
|
||||
ac_cs_version="\\
|
||||
aria2c config.status 0.11.3
|
||||
aria2c config.status 0.12.0alpha
|
||||
configured by $0, generated by GNU Autoconf 2.61,
|
||||
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
#
|
||||
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_SYSTEM
|
||||
AM_INIT_AUTOMAKE()
|
||||
|
@ -9,7 +9,7 @@
|
||||
# General Public License and is *not* in the public domain.
|
||||
|
||||
PACKAGE = aria2c
|
||||
VERSION = 0.11.3
|
||||
VERSION = 0.12.0alpha
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
../src/TorrentRequestInfo.cc \
|
||||
../src/UrlRequestInfo.cc \
|
||||
../src/main.cc \
|
||||
../src/version_usage.cc \
|
||||
../src/DefaultPieceStorage.cc \
|
||||
../src/DefaultBtAnnounce.cc \
|
||||
../src/DefaultBtProgressInfoFile.cc \
|
||||
|
@ -4,6 +4,7 @@ src/DownloadEngineFactory.cc
|
||||
src/TorrentRequestInfo.cc
|
||||
src/UrlRequestInfo.cc
|
||||
src/main.cc
|
||||
src/version_usage.cc
|
||||
src/DefaultPieceStorage.cc
|
||||
src/DefaultBtAnnounce.cc
|
||||
src/DefaultBtProgressInfoFile.cc
|
||||
|
@ -33,44 +33,64 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "AbstractCommand.h"
|
||||
#include "SegmentMan.h"
|
||||
#include "NameResolver.h"
|
||||
#include "CUIDCounter.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include "DlRetryEx.h"
|
||||
#include "FatalException.h"
|
||||
#include "InitiateConnectionCommandFactory.h"
|
||||
#include "Util.h"
|
||||
#include "message.h"
|
||||
#include "SleepCommand.h"
|
||||
#include "prefs.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,
|
||||
const RequestHandle& req,
|
||||
RequestGroup* requestGroup,
|
||||
DownloadEngine* e,
|
||||
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),
|
||||
nameResolverCheck(false) {
|
||||
|
||||
nameResolverCheck(false)
|
||||
{
|
||||
setReadCheckSocket(socket);
|
||||
timeout = this->e->option->getAsInt(PREF_TIMEOUT);
|
||||
++_requestGroup->numConnection;
|
||||
_requestGroup->increaseStreamConnection();
|
||||
}
|
||||
|
||||
AbstractCommand::~AbstractCommand() {
|
||||
disableReadCheckSocket();
|
||||
disableWriteCheckSocket();
|
||||
--_requestGroup->numConnection;
|
||||
_requestGroup->decreaseStreamConnection();
|
||||
}
|
||||
|
||||
bool AbstractCommand::execute() {
|
||||
try {
|
||||
if(_requestGroup->getSegmentMan()->finished()) {
|
||||
if(_requestGroup->downloadFinished() || _requestGroup->isHaltRequested()) {
|
||||
//logger->debug("CUID#%d - finished.", cuid);
|
||||
return true;
|
||||
}
|
||||
PeerStatHandle peerStat = _requestGroup->getSegmentMan()->getPeerStat(cuid);
|
||||
if(peerStat.get()) {
|
||||
PeerStatHandle peerStat = 0;
|
||||
if(!_requestGroup->getSegmentMan().isNull()) {
|
||||
peerStat = _requestGroup->getSegmentMan()->getPeerStat(cuid);
|
||||
}
|
||||
if(!peerStat.isNull()) {
|
||||
if(peerStat->getStatus() == PeerStat::REQUEST_IDLE) {
|
||||
logger->info(MSG_ABORT_REQUESTED, cuid);
|
||||
onAbort(0);
|
||||
@ -86,9 +106,8 @@ bool AbstractCommand::execute() {
|
||||
#endif // ENABLE_ASYNC_DNS
|
||||
!checkSocketIsReadable && !checkSocketIsWritable && !nameResolverCheck) {
|
||||
checkPoint.reset();
|
||||
if(_requestGroup->getSegmentMan()->downloadStarted) {
|
||||
// TODO Segment::isNull(), Change method name, it is very confusing.
|
||||
if(segment->isNull()) {
|
||||
if(!_requestGroup->getPieceStorage().isNull()) {
|
||||
if(segment.isNull()) {
|
||||
segment = _requestGroup->getSegmentMan()->getSegment(cuid);
|
||||
if(segment.isNull()) {
|
||||
logger->info(MSG_NO_SEGMENT_AVAILABLE, cuid);
|
||||
@ -98,26 +117,17 @@ bool AbstractCommand::execute() {
|
||||
}
|
||||
return executeInternal();
|
||||
} else {
|
||||
|
||||
if(checkPoint.elapsed(timeout)) {
|
||||
throw new DlRetryEx(EX_TIME_OUT);
|
||||
}
|
||||
e->commands.push_back(this);
|
||||
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) {
|
||||
logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
|
||||
onAbort(err);
|
||||
delete(err);
|
||||
req->resetUrl();
|
||||
_requestGroup->getSegmentMan()->errors++;
|
||||
tryReserved();
|
||||
return true;
|
||||
} catch(DlRetryEx* err) {
|
||||
@ -132,13 +142,16 @@ bool AbstractCommand::execute() {
|
||||
logger->info(MSG_MAX_TRY, cuid, req->getTryCount());
|
||||
logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
|
||||
delete(err);
|
||||
_requestGroup->getSegmentMan()->errors++;
|
||||
tryReserved();
|
||||
return true;
|
||||
} else {
|
||||
delete(err);
|
||||
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) {
|
||||
_requestGroup->getSegmentMan()->cancelSegment(cuid);
|
||||
if(!_requestGroup->getPieceStorage().isNull()) {
|
||||
_requestGroup->getSegmentMan()->cancelSegment(cuid);
|
||||
}
|
||||
Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, req, _requestGroup, e);
|
||||
if(wait == 0) {
|
||||
e->commands.push_back(command);
|
||||
@ -162,7 +177,9 @@ bool AbstractCommand::prepareForRetry(int32_t wait) {
|
||||
void AbstractCommand::onAbort(Exception* ex) {
|
||||
logger->debug(MSG_UNREGISTER_CUID, cuid);
|
||||
//_segmentMan->unregisterId(cuid);
|
||||
_requestGroup->getSegmentMan()->cancelSegment(cuid);
|
||||
if(!_requestGroup->getPieceStorage().isNull()) {
|
||||
_requestGroup->getSegmentMan()->cancelSegment(cuid);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractCommand::disableReadCheckSocket() {
|
||||
@ -272,3 +289,138 @@ bool AbstractCommand::nameResolveFinished() const {
|
||||
return false;
|
||||
}
|
||||
#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_
|
||||
|
||||
#include "Command.h"
|
||||
#include "Request.h"
|
||||
#include "DownloadEngine.h"
|
||||
#include "SegmentMan.h"
|
||||
#include "TimeA2.h"
|
||||
#include "RecoverableException.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "RequestGroupAware.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:
|
||||
Time checkPoint;
|
||||
int32_t timeout;
|
||||
protected:
|
||||
RequestHandle req;
|
||||
RequestGroup* _requestGroup;
|
||||
DownloadEngine* e;
|
||||
SocketHandle socket;
|
||||
SegmentHandle segment;
|
||||
@ -70,12 +74,26 @@ protected:
|
||||
virtual bool nameResolveFinished() const;
|
||||
#endif // ENABLE_ASYNC_DNS
|
||||
void setTimeout(int32_t timeout) { this->timeout = timeout; }
|
||||
|
||||
void loadAndOpenFile();
|
||||
|
||||
bool tryAutoFileRenaming();
|
||||
|
||||
void initPieceStorage();
|
||||
|
||||
bool downloadFinishedByFileLength();
|
||||
|
||||
void prepareForNextAction(Command* nextCommand = 0);
|
||||
|
||||
void shouldCancelDownloadForSafety();
|
||||
|
||||
private:
|
||||
bool checkSocketIsReadable;
|
||||
bool checkSocketIsWritable;
|
||||
SocketHandle readCheckTarget;
|
||||
SocketHandle writeCheckTarget;
|
||||
bool nameResolverCheck;
|
||||
|
||||
public:
|
||||
AbstractCommand(int32_t cuid, const RequestHandle& req, RequestGroup* requestGroup, DownloadEngine* e, const SocketHandle& s = SocketHandle());
|
||||
virtual ~AbstractCommand();
|
||||
|
@ -33,7 +33,6 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "AbstractDiskWriter.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include "File.h"
|
||||
#include "Util.h"
|
||||
#include "message.h"
|
||||
@ -47,8 +46,6 @@
|
||||
|
||||
AbstractDiskWriter::AbstractDiskWriter():
|
||||
fd(-1),
|
||||
fileAllocator(0),
|
||||
glowFileAllocator(0),
|
||||
logger(LogFactory::getInstance())
|
||||
{}
|
||||
|
||||
@ -57,7 +54,9 @@ AbstractDiskWriter::~AbstractDiskWriter()
|
||||
closeFile();
|
||||
}
|
||||
|
||||
void AbstractDiskWriter::openFile(const string& filename, int64_t totalLength) {
|
||||
void AbstractDiskWriter::openFile(const string& filename, int64_t totalLength)
|
||||
throw(DlAbortEx*)
|
||||
{
|
||||
File f(filename);
|
||||
if(f.exists()) {
|
||||
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) {
|
||||
close(fd);
|
||||
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;
|
||||
File f(filename);
|
||||
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) {
|
||||
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;
|
||||
// TODO proper filename handling needed
|
||||
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);
|
||||
}
|
||||
|
||||
int32_t AbstractDiskWriter::readDataInternal(char* data, int32_t len) {
|
||||
int32_t AbstractDiskWriter::readDataInternal(unsigned char* data, int32_t 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)) {
|
||||
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);
|
||||
if(writeDataInternal(data, len) < 0) {
|
||||
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;
|
||||
seek(offset);
|
||||
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)
|
||||
throw(DlAbortEx*)
|
||||
{
|
||||
if(fd == -1) {
|
||||
throw new DlAbortEx("File not opened.");
|
||||
}
|
||||
ftruncate(fd, length);
|
||||
}
|
||||
|
||||
// TODO the file descriptor fd must be opened before calling this function.
|
||||
int64_t AbstractDiskWriter::size() const
|
||||
throw(DlAbortEx*)
|
||||
{
|
||||
if(fd == -1) {
|
||||
throw new DlAbortEx("File not opened.");
|
||||
}
|
||||
struct stat fileStat;
|
||||
if(fstat(fd, &fileStat) < 0) {
|
||||
return 0;
|
||||
|
@ -36,52 +36,40 @@
|
||||
#define _D_ABSTRACT_DISK_WRITER_H_
|
||||
|
||||
#include "DiskWriter.h"
|
||||
#include "FileAllocator.h"
|
||||
#include "Logger.h"
|
||||
#include "DlAbortEx.h"
|
||||
|
||||
class AbstractDiskWriter : public DiskWriter {
|
||||
protected:
|
||||
string filename;
|
||||
int32_t fd;
|
||||
FileAllocatorHandle fileAllocator;
|
||||
FileAllocatorHandle glowFileAllocator;
|
||||
const Logger* logger;
|
||||
|
||||
void createFile(const string& filename, int32_t addFlags = 0);
|
||||
void createFile(const string& filename, int32_t addFlags = 0) throw(DlAbortEx*);
|
||||
|
||||
private:
|
||||
int32_t writeDataInternal(const char* data, int32_t len);
|
||||
int32_t readDataInternal(char* data, int32_t len);
|
||||
int32_t writeDataInternal(const unsigned 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:
|
||||
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 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)
|
||||
{
|
||||
this->fileAllocator = fileAllocator;
|
||||
}
|
||||
virtual void truncate(int64_t length) throw(DlAbortEx*);
|
||||
|
||||
void setGlowFileAllocator(const FileAllocatorHandle& fileAllocator)
|
||||
{
|
||||
this->glowFileAllocator = fileAllocator;
|
||||
}
|
||||
|
||||
virtual void truncate(int64_t length);
|
||||
|
||||
virtual int64_t size() const;
|
||||
virtual int64_t size() const throw(DlAbortEx*);
|
||||
};
|
||||
|
||||
#endif // _D_ABSTRACT_DISK_WRITER_H_
|
||||
|
@ -33,6 +33,9 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "AbstractProxyRequestCommand.h"
|
||||
#include "DownloadEngine.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "Request.h"
|
||||
#include "HttpConnection.h"
|
||||
#include "prefs.h"
|
||||
|
||||
|
@ -36,7 +36,9 @@
|
||||
#define _D_ABSTRACT_PROXY_REQUEST_COMMAND_H_
|
||||
|
||||
#include "AbstractCommand.h"
|
||||
#include "HttpConnection.h"
|
||||
|
||||
class HttpConnection;
|
||||
extern typedef SharedHandle<HttpConnection> HttpConnectionHandle;
|
||||
|
||||
class AbstractProxyRequestCommand : public AbstractCommand {
|
||||
protected:
|
||||
|
@ -33,6 +33,11 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "AbstractProxyResponseCommand.h"
|
||||
#include "HttpConnection.h"
|
||||
#include "Request.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "DownloadEngine.h"
|
||||
#include "HttpResponse.h"
|
||||
#include "HttpRequestCommand.h"
|
||||
#include "DlRetryEx.h"
|
||||
#include "message.h"
|
||||
|
@ -36,7 +36,9 @@
|
||||
#define _D_ABSTRACT_PROXY_RESPONSE_COMMAND_H_
|
||||
|
||||
#include "AbstractCommand.h"
|
||||
#include "HttpConnection.h"
|
||||
|
||||
class HttpConnection;
|
||||
extern typedef SharedHandle<HttpConnection> HttpConnectionHandle;
|
||||
|
||||
class AbstractProxyResponseCommand : public AbstractCommand {
|
||||
protected:
|
||||
|
@ -34,28 +34,40 @@
|
||||
/* copyright --> */
|
||||
#include "AbstractSingleDiskAdaptor.h"
|
||||
#include "File.h"
|
||||
#include "SingleFileAllocationIterator.h"
|
||||
|
||||
void AbstractSingleDiskAdaptor::initAndOpenFile() {
|
||||
void AbstractSingleDiskAdaptor::initAndOpenFile()
|
||||
throw(DlAbortEx*)
|
||||
{
|
||||
diskWriter->initAndOpenFile(getFilePath(), totalLength);
|
||||
}
|
||||
|
||||
void AbstractSingleDiskAdaptor::openFile() {
|
||||
void AbstractSingleDiskAdaptor::openFile()
|
||||
throw(DlAbortEx*)
|
||||
{
|
||||
diskWriter->openFile(getFilePath(), totalLength);
|
||||
}
|
||||
|
||||
void AbstractSingleDiskAdaptor::closeFile() {
|
||||
void AbstractSingleDiskAdaptor::closeFile()
|
||||
{
|
||||
diskWriter->closeFile();
|
||||
}
|
||||
|
||||
void AbstractSingleDiskAdaptor::openExistingFile() {
|
||||
void AbstractSingleDiskAdaptor::openExistingFile()
|
||||
throw(DlAbortEx*)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -63,3 +75,8 @@ bool AbstractSingleDiskAdaptor::fileExists()
|
||||
{
|
||||
return File(getFilePath()).exists();
|
||||
}
|
||||
|
||||
FileAllocationIteratorHandle AbstractSingleDiskAdaptor::fileAllocationIterator()
|
||||
{
|
||||
return new SingleFileAllocationIterator(this);
|
||||
}
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include "DiskAdaptor.h"
|
||||
#include "DiskWriter.h"
|
||||
#include "DlAbortEx.h"
|
||||
|
||||
class AbstractSingleDiskAdaptor : public DiskAdaptor {
|
||||
protected:
|
||||
@ -47,26 +48,33 @@ public:
|
||||
|
||||
virtual ~AbstractSingleDiskAdaptor() {}
|
||||
|
||||
virtual void initAndOpenFile();
|
||||
virtual void initAndOpenFile() throw(DlAbortEx*);
|
||||
|
||||
virtual void openFile();
|
||||
virtual void openFile() throw(DlAbortEx*);
|
||||
|
||||
virtual void closeFile();
|
||||
|
||||
virtual void openExistingFile();
|
||||
virtual void openExistingFile() throw(DlAbortEx*);
|
||||
|
||||
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 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) {
|
||||
this->diskWriter = diskWriter;
|
||||
}
|
||||
|
@ -37,6 +37,22 @@
|
||||
#include "CUIDCounter.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() {
|
||||
if(btRuntime->isHalt()) {
|
||||
return true;
|
||||
@ -63,7 +79,7 @@ void ActivePeerConnectionCommand::connectToPeer(const PeerHandle& peer)
|
||||
}
|
||||
peer->cuid = CUIDCounterSingletonHolder::instance()->newID();
|
||||
PeerInitiateConnectionCommand* command =
|
||||
new PeerInitiateConnectionCommand(peer->cuid, peer, e, btContext);
|
||||
new PeerInitiateConnectionCommand(peer->cuid, _requestGroup, peer, e, btContext);
|
||||
e->commands.push_back(command);
|
||||
logger->info(MSG_CONNECTING_TO_PEER,
|
||||
cuid, peer->ipaddr.c_str());
|
||||
|
@ -35,30 +35,30 @@
|
||||
#ifndef _D_ACTIVE_PEER_CONNECTION_COMMAND_H_
|
||||
#define _D_ACTIVE_PEER_CONNECTION_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "BtContextAwareCommand.h"
|
||||
#include "TorrentDownloadEngine.h"
|
||||
#include "DownloadEngine.h"
|
||||
#include "TimeA2.h"
|
||||
#include "RequestGroupAware.h"
|
||||
|
||||
class ActivePeerConnectionCommand : public BtContextAwareCommand {
|
||||
class ActivePeerConnectionCommand : public Command,
|
||||
public BtContextAwareCommand,
|
||||
public RequestGroupAware
|
||||
{
|
||||
private:
|
||||
int32_t interval; // UNIT: sec
|
||||
TorrentDownloadEngine* e;
|
||||
DownloadEngine* e;
|
||||
Time checkPoint;
|
||||
int32_t _lowestSpeedLimit; // UNIT: byte/sec
|
||||
int32_t _numNewConnection; // the number of the connection to establish.
|
||||
public:
|
||||
ActivePeerConnectionCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
RequestGroup* requestGroup,
|
||||
DownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
int32_t interval)
|
||||
:BtContextAwareCommand(cuid, btContext),
|
||||
interval(interval),
|
||||
e(e),
|
||||
_lowestSpeedLimit(20*1024),
|
||||
_numNewConnection(5)
|
||||
{}
|
||||
int32_t interval);
|
||||
|
||||
virtual ~ActivePeerConnectionCommand() {}
|
||||
virtual ~ActivePeerConnectionCommand();
|
||||
|
||||
virtual bool execute();
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
#define _D_ALPHA_NUMBER_DECORATOR_H_
|
||||
|
||||
#include "NumberDecorator.h"
|
||||
#include "FatalException.h"
|
||||
#include "DlAbortEx.h"
|
||||
|
||||
class AlphaNumberDecorator : public NumberDecorator
|
||||
{
|
||||
@ -64,7 +64,7 @@ public:
|
||||
virtual string decorate(int32_t number)
|
||||
{
|
||||
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) {
|
||||
return widen(_zero, _width);
|
||||
|
@ -33,10 +33,17 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#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()
|
||||
{
|
||||
if(_e->_requestGroupMan->downloadFinished()) {
|
||||
if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
|
||||
_exit = true;
|
||||
}
|
||||
}
|
||||
|
@ -40,10 +40,9 @@
|
||||
class AutoSaveCommand : public TimeBasedCommand
|
||||
{
|
||||
public:
|
||||
AutoSaveCommand(int32_t cuid, DownloadEngine* e, int32_t interval):
|
||||
TimeBasedCommand(cuid, e, interval) {}
|
||||
AutoSaveCommand(int32_t cuid, DownloadEngine* e, int32_t interval);
|
||||
|
||||
virtual ~AutoSaveCommand() {}
|
||||
virtual ~AutoSaveCommand();
|
||||
|
||||
virtual void preProcess();
|
||||
|
||||
|
52
src/BinaryStream.h
Normal file
52
src/BinaryStream.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_BINARY_STREAM_H_
|
||||
#define _D_BINARY_STREAM_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "DlAbortEx.h"
|
||||
|
||||
class BinaryStream {
|
||||
public:
|
||||
virtual ~BinaryStream() {}
|
||||
|
||||
virtual void writeData(const unsigned char* data, int32_t len, int64_t offset) = 0;
|
||||
|
||||
virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) = 0;
|
||||
};
|
||||
|
||||
typedef SharedHandle<BinaryStream> BinaryStreamHandle;
|
||||
|
||||
#endif // _D_BINARY_STREAM_H_
|
@ -32,37 +32,29 @@
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_CONSOLE_DOWNLOAD_ENGINE_H_
|
||||
#define _D_CONSOLE_DOWNLOAD_ENGINE_H_
|
||||
|
||||
#include "BtCheckIntegrityEntry.h"
|
||||
#include "BtSetup.h"
|
||||
#include "BtFileAllocationEntry.h"
|
||||
#include "CUIDCounter.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "DownloadEngine.h"
|
||||
#include "TimeA2.h"
|
||||
#include "FileAllocationMan.h"
|
||||
#include "DiskAdaptor.h"
|
||||
|
||||
class ConsoleDownloadEngine : public DownloadEngine {
|
||||
private:
|
||||
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();
|
||||
BtCheckIntegrityEntry::BtCheckIntegrityEntry(RequestGroup* requestGroup):
|
||||
CheckIntegrityEntry(requestGroup, 0) {}
|
||||
|
||||
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;
|
||||
}
|
51
src/BtCheckIntegrityEntry.h
Normal file
51
src/BtCheckIntegrityEntry.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_BT_CHECK_INTEGRITY_ENTRY_H_
|
||||
#define _D_BT_CHECK_INTEGRITY_ENTRY_H_
|
||||
|
||||
#include "CheckIntegrityEntry.h"
|
||||
|
||||
class BtCheckIntegrityEntry : public CheckIntegrityEntry {
|
||||
public:
|
||||
BtCheckIntegrityEntry(RequestGroup* requestGroup);
|
||||
|
||||
virtual ~BtCheckIntegrityEntry();
|
||||
|
||||
virtual Commands prepareForNextAction(DownloadEngine* e);
|
||||
};
|
||||
|
||||
typedef SharedHandle<BtCheckIntegrityEntry> BtCheckIntegrityEntryHandle;
|
||||
|
||||
#endif // _D_BT_FILE_ALLOCATION_ENTRY_H_
|
@ -35,57 +35,40 @@
|
||||
#ifndef _D_BT_CONTEXT_H_
|
||||
#define _D_BT_CONTEXT_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "FileEntry.h"
|
||||
#include "AnnounceTier.h"
|
||||
#include "DownloadContext.h"
|
||||
|
||||
#define INFO_HASH_LENGTH 20
|
||||
#define MAX_PEER_ERROR 5
|
||||
#define MAX_PEERS 55
|
||||
|
||||
class AnnounceTier;
|
||||
extern typedef SharedHandle<AnnounceTier> AnnounceTierHandle;
|
||||
typedef deque<AnnounceTierHandle> AnnounceTiers;
|
||||
|
||||
class BtContext {
|
||||
class RequestGroup;
|
||||
|
||||
class BtContext:public DownloadContext {
|
||||
public:
|
||||
virtual ~BtContext() {}
|
||||
|
||||
enum FILE_MODE {
|
||||
SINGLE,
|
||||
MULTI
|
||||
};
|
||||
|
||||
virtual const unsigned char* getInfoHash() const = 0;
|
||||
|
||||
virtual int32_t getInfoHashLength() 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 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
|
||||
*/
|
||||
virtual const unsigned char* getPeerId() = 0;
|
||||
|
||||
virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize) = 0;
|
||||
|
||||
virtual RequestGroup* getOwnerRequestGroup() = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -35,9 +35,7 @@
|
||||
#include "BtContextAwareCommand.h"
|
||||
#include "BtRegistry.h"
|
||||
|
||||
BtContextAwareCommand::BtContextAwareCommand(int cuid,
|
||||
const BtContextHandle& btContext):
|
||||
Command(cuid),
|
||||
BtContextAwareCommand::BtContextAwareCommand(const BtContextHandle& btContext):
|
||||
btContext(btContext),
|
||||
btRuntime(BT_RUNTIME(btContext)),
|
||||
pieceStorage(PIECE_STORAGE(btContext)),
|
||||
|
@ -35,7 +35,7 @@
|
||||
#ifndef _D_BT_CONTEXT_AWARE_COMMAND_H_
|
||||
#define _D_BT_CONTEXT_AWARE_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "common.h"
|
||||
#include "BtContext.h"
|
||||
#include "BtRuntime.h"
|
||||
#include "PieceStorage.h"
|
||||
@ -43,7 +43,8 @@
|
||||
#include "BtAnnounce.h"
|
||||
#include "BtProgressInfoFile.h"
|
||||
|
||||
class BtContextAwareCommand : public Command {
|
||||
class BtContextAwareCommand
|
||||
{
|
||||
protected:
|
||||
BtContextHandle btContext;
|
||||
BtRuntimeHandle btRuntime;
|
||||
@ -52,7 +53,7 @@ protected:
|
||||
BtAnnounceHandle btAnnounce;
|
||||
BtProgressInfoFileHandle btProgressInfoFile;
|
||||
public:
|
||||
BtContextAwareCommand(int cuid, const BtContextHandle& btContext);
|
||||
BtContextAwareCommand(const BtContextHandle& btContext);
|
||||
|
||||
virtual ~BtContextAwareCommand();
|
||||
};
|
||||
|
83
src/BtDependency.cc
Normal file
83
src/BtDependency.cc
Normal file
@ -0,0 +1,83 @@
|
||||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "BtDependency.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "Option.h"
|
||||
#include "LogFactory.h"
|
||||
#include "DefaultBtContext.h"
|
||||
#include "RecoverableException.h"
|
||||
#include "message.h"
|
||||
#include "prefs.h"
|
||||
|
||||
BtDependency::BtDependency(const RequestGroupWeakHandle& dependant,
|
||||
const RequestGroupWeakHandle& dependee,
|
||||
const Option* option):
|
||||
_dependant(dependant),
|
||||
_dependee(dependee),
|
||||
_option(option),
|
||||
_logger(LogFactory::getInstance()) {}
|
||||
|
||||
BtDependency::~BtDependency() {}
|
||||
|
||||
bool BtDependency::resolve()
|
||||
{
|
||||
if(_dependee->getNumCommand() == 0 && _dependee->downloadFinished()) {
|
||||
DefaultBtContextHandle btContext = new DefaultBtContext();
|
||||
try {
|
||||
btContext->load(_dependee->getFilePath());
|
||||
if(_option->defined(PREF_PEER_ID_PREFIX)) {
|
||||
btContext->setPeerIdPrefix(_option->get(PREF_PEER_ID_PREFIX));
|
||||
}
|
||||
btContext->setDir(_dependant->getDownloadContext()->getDir());
|
||||
} catch(RecoverableException* e) {
|
||||
_logger->error(EX_EXCEPTION_CAUGHT, e);
|
||||
delete e;
|
||||
_logger->debug("BtDependency for GID#%d failed. Go without Bt.",
|
||||
_dependant->getGID());
|
||||
return true;
|
||||
}
|
||||
_logger->debug("Dependency resolved for GID#%d", _dependant->getGID());
|
||||
_dependant->setDownloadContext(btContext);
|
||||
btContext->setOwnerRequestGroup(_dependant.get());
|
||||
return true;
|
||||
} else if(_dependee->getNumCommand() == 0) {
|
||||
// _dependee's download failed.
|
||||
_logger->debug("BtDependency for GID#%d failed. Go without Bt.",
|
||||
_dependant->getGID());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -32,30 +32,33 @@
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_TORRENT_REQUEST_INFO_H_
|
||||
#define _D_TORRENT_REQUEST_INFO_H_
|
||||
#ifndef _D_BT_DEPENDENCY_H_
|
||||
#define _D_BT_DEPENDENCY_H_
|
||||
|
||||
#include "RequestInfo.h"
|
||||
#include "TorrentDownloadEngine.h"
|
||||
#include "BtContext.h"
|
||||
#include "Dependency.h"
|
||||
|
||||
class TorrentRequestInfo : public RequestInfo {
|
||||
class RequestGroup;
|
||||
extern typedef WeakHandle<RequestGroup> RequestGroupWeakHandle;
|
||||
class Option;
|
||||
class Logger;
|
||||
|
||||
class BtDependency : public Dependency
|
||||
{
|
||||
private:
|
||||
string torrentFile;
|
||||
Strings targetFiles;
|
||||
|
||||
RequestGroupWeakHandle _dependant;
|
||||
RequestGroupWeakHandle _dependee;
|
||||
const Option* _option;
|
||||
const Logger* _logger;
|
||||
public:
|
||||
TorrentRequestInfo(const string& torrentFile, Option* op):
|
||||
RequestInfo(op),
|
||||
torrentFile(torrentFile) {}
|
||||
BtDependency(const RequestGroupWeakHandle& dependant,
|
||||
const RequestGroupWeakHandle& dependee,
|
||||
const Option* option);
|
||||
|
||||
virtual ~TorrentRequestInfo() {}
|
||||
virtual ~BtDependency();
|
||||
|
||||
virtual RequestInfos execute();
|
||||
|
||||
void setTargetFiles(const Strings& targetFiles) {
|
||||
this->targetFiles = targetFiles;
|
||||
}
|
||||
virtual bool resolve();
|
||||
};
|
||||
|
||||
#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.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "TorrentAutoSaveCommand.h"
|
||||
#include "Util.h"
|
||||
#include "BtFileAllocationEntry.h"
|
||||
#include "BtSetup.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "Command.h"
|
||||
#include "DownloadEngine.h"
|
||||
|
||||
TorrentAutoSaveCommand::TorrentAutoSaveCommand(int32_t cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
int32_t interval):
|
||||
BtContextAwareCommand(cuid, btContext),
|
||||
e(e),
|
||||
interval(interval) {}
|
||||
BtFileAllocationEntry::BtFileAllocationEntry(RequestGroup* requestGroup):
|
||||
FileAllocationEntry(requestGroup, 0) {}
|
||||
|
||||
TorrentAutoSaveCommand::~TorrentAutoSaveCommand() {}
|
||||
BtFileAllocationEntry::~BtFileAllocationEntry() {}
|
||||
|
||||
bool TorrentAutoSaveCommand::execute() {
|
||||
if(checkPoint.elapsed(interval) || btRuntime->isHalt()) {
|
||||
checkPoint.reset();
|
||||
btProgressInfoFile->save();
|
||||
if(btRuntime->isHalt()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
e->commands.push_back(this);
|
||||
return false;
|
||||
Commands BtFileAllocationEntry::prepareForNextAction(DownloadEngine* e)
|
||||
{
|
||||
Commands commands = BtSetup().setup(_requestGroup, e, e->option);
|
||||
// TODO don't integerate http/ftp when multi-file torrent
|
||||
Commands streamCommands = _requestGroup->createNextCommandWithAdj(e, 0);
|
||||
copy(streamCommands.begin(), streamCommands.end(), back_inserter(commands));
|
||||
return commands;
|
||||
}
|
56
src/BtFileAllocationEntry.h
Normal file
56
src/BtFileAllocationEntry.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_BT_FILE_ALLOCATION_ENTRY_H_
|
||||
#define _D_BT_FILE_ALLOCATION_ENTRY_H_
|
||||
|
||||
#include "FileAllocationEntry.h"
|
||||
|
||||
class RequestGroup;
|
||||
class DownloadEngine;
|
||||
class Command;
|
||||
extern typedef deque<Command*> Commands;
|
||||
|
||||
class BtFileAllocationEntry : public FileAllocationEntry {
|
||||
public:
|
||||
BtFileAllocationEntry(RequestGroup* requestGroup);
|
||||
|
||||
virtual ~BtFileAllocationEntry();
|
||||
|
||||
virtual Commands prepareForNextAction(DownloadEngine* e);
|
||||
};
|
||||
|
||||
typedef SharedHandle<BtFileAllocationEntry> BtFileAllocationEntryHandle;
|
||||
|
||||
#endif // _D_BT_FILE_ALLOCATION_ENTRY_H_
|
@ -39,8 +39,8 @@
|
||||
#include "DlAbortEx.h"
|
||||
#include "BtChokingEvent.h"
|
||||
#include "BtCancelSendingPieceEvent.h"
|
||||
#include "DiskAdaptorWriter.h"
|
||||
#include "MessageDigestHelper.h"
|
||||
#include "DiskAdaptor.h"
|
||||
|
||||
void BtPieceMessage::setBlock(const unsigned char* block, int32_t blockLength) {
|
||||
delete [] this->block;
|
||||
@ -193,7 +193,7 @@ bool BtPieceMessage::checkPieceHash(const PieceHandle& piece) {
|
||||
int64_t offset =
|
||||
((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());
|
||||
}
|
||||
|
||||
|
@ -32,28 +32,31 @@
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "ConsoleFileAllocationMonitor.h"
|
||||
#include "Util.h"
|
||||
#include "BtPostDownloadHandler.h"
|
||||
#include "DefaultBtContext.h"
|
||||
#include "prefs.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "Option.h"
|
||||
|
||||
void ConsoleFileAllocationMonitor::showProgress() {
|
||||
int32_t progressPercentage = (int32_t)(((current-min)*1.0/(max-min))*100);
|
||||
int32_t numOfStar = progressPercentage/10*2;
|
||||
BtPostDownloadHandler::BtPostDownloadHandler(const Option* option):
|
||||
PostDownloadHandler(".torrent", option)
|
||||
{}
|
||||
|
||||
cout << "\r ";
|
||||
cout << "\r";
|
||||
cout << "|";
|
||||
for(int32_t i = 0; i < numOfStar; ++i) {
|
||||
cout << "*";
|
||||
BtPostDownloadHandler::~BtPostDownloadHandler() {}
|
||||
|
||||
RequestGroups BtPostDownloadHandler::getNextRequestGroups(const string& path)
|
||||
{
|
||||
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) {
|
||||
cout << " ";
|
||||
}
|
||||
cout << "|";
|
||||
cout << progressPercentage << "%";
|
||||
cout << "(";
|
||||
cout << Util::ullitos(current, true) << "/" << Util::ullitos(max, true);
|
||||
cout << ")";
|
||||
cout << flush;
|
||||
// Example,
|
||||
// |******************* | 95%(1,333,3256/1,553,3232 bytes)
|
||||
btContext->setDir(_option->get(PREF_DIR));
|
||||
rg->setDownloadContext(btContext);
|
||||
btContext->setOwnerRequestGroup(rg.get());
|
||||
|
||||
RequestGroups groups;
|
||||
groups.push_back(rg);
|
||||
return groups;
|
||||
}
|
51
src/BtPostDownloadHandler.h
Normal file
51
src/BtPostDownloadHandler.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_BT_POST_DOWNLOAD_HANDLER_H_
|
||||
#define _D_BT_POST_DOWNLOAD_HANDLER_H_
|
||||
|
||||
#include "PostDownloadHandler.h"
|
||||
|
||||
class BtPostDownloadHandler:public PostDownloadHandler
|
||||
{
|
||||
public:
|
||||
BtPostDownloadHandler(const Option* option);
|
||||
|
||||
virtual ~BtPostDownloadHandler();
|
||||
|
||||
virtual RequestGroups getNextRequestGroups(const string& path);
|
||||
};
|
||||
|
||||
typedef SharedHandle<BtPostDownloadHandler> BtPostDownloadHandlerHandle;
|
||||
#endif // _D_BT_POST_DOWNLOAD_HANDLER_H_
|
@ -43,8 +43,6 @@ public:
|
||||
|
||||
virtual string getFilename() = 0;
|
||||
|
||||
virtual void setFilename(const string& filename) = 0;
|
||||
|
||||
virtual bool exists() = 0;
|
||||
|
||||
virtual void save() = 0;
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "BtRegistry.h"
|
||||
#include "DlAbortEx.h"
|
||||
|
||||
BtContextMap BtRegistry::btContextMap;
|
||||
PeerStorageMap BtRegistry::peerStorageMap;
|
||||
PieceStorageMap BtRegistry::pieceStorageMap;
|
||||
BtAnnounceMap BtRegistry::btAnnounceMap;
|
||||
@ -42,93 +43,77 @@ BtRuntimeMap BtRegistry::btRuntimeMap;
|
||||
BtProgressInfoFileMap BtRegistry::btProgressInfoFileMap;
|
||||
PeerObjectClusterRegistry BtRegistry::peerObjectClusterRegistry;
|
||||
|
||||
PeerStorageHandle BtRegistry::getPeerStorage(const string& key) {
|
||||
PeerStorageMap::iterator itr = peerStorageMap.find(key);
|
||||
if(itr == peerStorageMap.end()) {
|
||||
return PeerStorageHandle(0);
|
||||
} else {
|
||||
return itr->second;
|
||||
}
|
||||
PeerStorageHandle BtRegistry::getPeerStorage(const string& key)
|
||||
{
|
||||
return peerStorageMap.getHandle(key);
|
||||
}
|
||||
|
||||
bool BtRegistry::registerPeerStorage(const string& key,
|
||||
const PeerStorageHandle& peerStorage) {
|
||||
PeerStorageMap::value_type p(key, peerStorage);
|
||||
pair<PeerStorageMap::iterator, bool> retval = peerStorageMap.insert(p);
|
||||
return retval.second;
|
||||
void BtRegistry::registerPeerStorage(const string& key,
|
||||
const PeerStorageHandle& peerStorage)
|
||||
{
|
||||
peerStorageMap.registerHandle(key, peerStorage);
|
||||
}
|
||||
|
||||
PieceStorageHandle
|
||||
BtRegistry::getPieceStorage(const string& key) {
|
||||
PieceStorageMap::iterator itr = pieceStorageMap.find(key);
|
||||
if(itr == pieceStorageMap.end()) {
|
||||
return PieceStorageHandle(0);
|
||||
} else {
|
||||
return itr->second;
|
||||
}
|
||||
BtRegistry::getPieceStorage(const string& key)
|
||||
{
|
||||
return pieceStorageMap.getHandle(key);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BtRegistry::registerPieceStorage(const string& key,
|
||||
const PieceStorageHandle& pieceStorage) {
|
||||
pieceStorageMap.erase(key);
|
||||
PieceStorageMap::value_type p(key, pieceStorage);
|
||||
pair<PieceStorageMap::iterator, bool> retval = pieceStorageMap.insert(p);
|
||||
return retval.second;
|
||||
const PieceStorageHandle& pieceStorage)
|
||||
{
|
||||
pieceStorageMap.registerHandle(key, pieceStorage);
|
||||
}
|
||||
|
||||
BtRuntimeHandle BtRegistry::getBtRuntime(const string& key) {
|
||||
BtRuntimeMap::iterator itr = btRuntimeMap.find(key);
|
||||
if(itr == btRuntimeMap.end()) {
|
||||
return BtRuntimeHandle(0);
|
||||
} else {
|
||||
return itr->second;
|
||||
}
|
||||
BtRuntimeHandle BtRegistry::getBtRuntime(const string& key)
|
||||
{
|
||||
return btRuntimeMap.getHandle(key);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BtRegistry::registerBtRuntime(const string& key,
|
||||
const BtRuntimeHandle& btRuntime) {
|
||||
BtRuntimeMap::value_type p(key, btRuntime);
|
||||
pair<BtRuntimeMap::iterator, bool> retval =
|
||||
btRuntimeMap.insert(p);
|
||||
return retval.second;
|
||||
const BtRuntimeHandle& btRuntime)
|
||||
{
|
||||
btRuntimeMap.registerHandle(key, btRuntime);
|
||||
}
|
||||
|
||||
BtAnnounceHandle BtRegistry::getBtAnnounce(const string& key) {
|
||||
BtAnnounceMap::iterator itr = btAnnounceMap.find(key);
|
||||
if(itr == btAnnounceMap.end()) {
|
||||
return BtAnnounceHandle(0);
|
||||
} else {
|
||||
return itr->second;
|
||||
}
|
||||
BtAnnounceHandle BtRegistry::getBtAnnounce(const string& key)
|
||||
{
|
||||
return btAnnounceMap.getHandle(key);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BtRegistry::registerBtAnnounce(const string& key,
|
||||
const BtAnnounceHandle& btAnnounce) {
|
||||
BtAnnounceMap::value_type p(key, btAnnounce);
|
||||
pair<BtAnnounceMap::iterator, bool> retval =
|
||||
btAnnounceMap.insert(p);
|
||||
return retval.second;
|
||||
const BtAnnounceHandle& btAnnounce)
|
||||
{
|
||||
btAnnounceMap.registerHandle(key, btAnnounce);
|
||||
}
|
||||
|
||||
BtProgressInfoFileHandle BtRegistry::getBtProgressInfoFile(const string& key) {
|
||||
BtProgressInfoFileMap::iterator itr = btProgressInfoFileMap.find(key);
|
||||
if(itr == btProgressInfoFileMap.end()) {
|
||||
return BtProgressInfoFileHandle(0);
|
||||
} else {
|
||||
return itr->second;
|
||||
}
|
||||
BtProgressInfoFileHandle BtRegistry::getBtProgressInfoFile(const string& key)
|
||||
{
|
||||
return btProgressInfoFileMap.getHandle(key);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BtRegistry::registerBtProgressInfoFile(const string& key,
|
||||
const BtProgressInfoFileHandle& btProgressInfoFile) {
|
||||
BtProgressInfoFileMap::value_type p(key, btProgressInfoFile);
|
||||
pair<BtProgressInfoFileMap::iterator, bool> retval =
|
||||
btProgressInfoFileMap.insert(p);
|
||||
return retval.second;
|
||||
const BtProgressInfoFileHandle& btProgressInfoFile)
|
||||
{
|
||||
btProgressInfoFileMap.registerHandle(key, btProgressInfoFile);
|
||||
}
|
||||
|
||||
BtContextHandle
|
||||
BtRegistry::getBtContext(const string& key)
|
||||
{
|
||||
return btContextMap.getHandle(key);
|
||||
}
|
||||
|
||||
void
|
||||
BtRegistry::registerBtContext(const string& key,
|
||||
const BtContextHandle& btContext)
|
||||
{
|
||||
btContextMap.registerHandle(key, btContext);
|
||||
}
|
||||
|
||||
PeerObjectClusterHandle
|
||||
@ -150,7 +135,8 @@ BtRegistry::unregisterPeerObjectCluster(const string& key)
|
||||
peerObjectClusterRegistry.unregisterHandle(key);
|
||||
}
|
||||
|
||||
void BtRegistry::clear() {
|
||||
void BtRegistry::unregisterAll() {
|
||||
btContextMap.clear();
|
||||
peerStorageMap.clear();
|
||||
pieceStorageMap.clear();
|
||||
btAnnounceMap.clear();
|
||||
@ -158,3 +144,14 @@ void BtRegistry::clear() {
|
||||
btProgressInfoFileMap.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_
|
||||
|
||||
#include "common.h"
|
||||
#include "BtContext.h"
|
||||
#include "PeerStorage.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "BtAnnounce.h"
|
||||
@ -45,11 +46,12 @@
|
||||
#include "HandleRegistry.h"
|
||||
#include <map>
|
||||
|
||||
typedef map<string, PeerStorageHandle> PeerStorageMap;
|
||||
typedef map<string, PieceStorageHandle> PieceStorageMap;
|
||||
typedef map<string, BtAnnounceHandle> BtAnnounceMap;
|
||||
typedef map<string, BtRuntimeHandle> BtRuntimeMap;
|
||||
typedef map<string, BtProgressInfoFileHandle> BtProgressInfoFileMap;
|
||||
typedef HandleRegistry<string, PeerStorage> PeerStorageMap;
|
||||
typedef HandleRegistry<string, PieceStorage> PieceStorageMap;
|
||||
typedef HandleRegistry<string, BtAnnounce> BtAnnounceMap;
|
||||
typedef HandleRegistry<string, BtRuntime> BtRuntimeMap;
|
||||
typedef HandleRegistry<string, BtProgressInfoFile> BtProgressInfoFileMap;
|
||||
typedef HandleRegistry<string, BtContext> BtContextMap;
|
||||
|
||||
// for BtMessageFactory
|
||||
typedef HandleRegistry<string, PeerObject> PeerObjectCluster;
|
||||
@ -60,6 +62,7 @@ class BtRegistry {
|
||||
private:
|
||||
BtRegistry() {}
|
||||
|
||||
static BtContextMap btContextMap;
|
||||
static PeerStorageMap peerStorageMap;
|
||||
static PieceStorageMap pieceStorageMap;
|
||||
static BtAnnounceMap btAnnounceMap;
|
||||
@ -67,24 +70,28 @@ private:
|
||||
static BtProgressInfoFileMap btProgressInfoFileMap;
|
||||
static PeerObjectClusterRegistry peerObjectClusterRegistry;
|
||||
public:
|
||||
static BtContextHandle getBtContext(const string& key);
|
||||
static void registerBtContext(const string& key,
|
||||
const BtContextHandle& btContext);
|
||||
|
||||
static PeerStorageHandle getPeerStorage(const string& key);
|
||||
static bool registerPeerStorage(const string& key,
|
||||
static void registerPeerStorage(const string& key,
|
||||
const PeerStorageHandle& peer);
|
||||
|
||||
static PieceStorageHandle getPieceStorage(const string& key);
|
||||
static bool registerPieceStorage(const string& key,
|
||||
static void registerPieceStorage(const string& key,
|
||||
const PieceStorageHandle& pieceStorage);
|
||||
|
||||
static BtRuntimeHandle getBtRuntime(const string& key);
|
||||
static bool registerBtRuntime(const string& key,
|
||||
static void registerBtRuntime(const string& key,
|
||||
const BtRuntimeHandle& btRuntime);
|
||||
|
||||
static BtAnnounceHandle getBtAnnounce(const string& key);
|
||||
static bool registerBtAnnounce(const string& key,
|
||||
static void registerBtAnnounce(const string& key,
|
||||
const BtAnnounceHandle& btAnnounce);
|
||||
|
||||
static BtProgressInfoFileHandle getBtProgressInfoFile(const string& key);
|
||||
static bool registerBtProgressInfoFile(const string& key,
|
||||
static void registerBtProgressInfoFile(const string& key,
|
||||
const BtProgressInfoFileHandle& btProgressInfoFile);
|
||||
|
||||
// for PeerObject
|
||||
@ -98,7 +105,9 @@ public:
|
||||
static void
|
||||
unregisterPeerObjectCluster(const string& key);
|
||||
|
||||
static void clear();
|
||||
static void unregisterAll();
|
||||
|
||||
static void unregister(const string& key);
|
||||
};
|
||||
|
||||
#define PEER_STORAGE(btContext) \
|
||||
|
@ -46,12 +46,14 @@ private:
|
||||
int32_t port;
|
||||
bool halt;
|
||||
int32_t connections;
|
||||
bool _ready;
|
||||
public:
|
||||
BtRuntime():
|
||||
uploadLengthAtStartup(0),
|
||||
port(0),
|
||||
halt(false),
|
||||
connections(0)
|
||||
connections(0),
|
||||
_ready(false)
|
||||
{}
|
||||
~BtRuntime() {}
|
||||
|
||||
@ -83,7 +85,11 @@ public:
|
||||
|
||||
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;
|
||||
|
97
src/BtSetup.cc
Normal file
97
src/BtSetup.cc
Normal file
@ -0,0 +1,97 @@
|
||||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "BtSetup.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "DownloadEngine.h"
|
||||
#include "Option.h"
|
||||
#include "BtRegistry.h"
|
||||
#include "PeerListenCommand.h"
|
||||
#include "TrackerWatcherCommand.h"
|
||||
#include "SeedCheckCommand.h"
|
||||
#include "PeerChokeCommand.h"
|
||||
#include "ActivePeerConnectionCommand.h"
|
||||
#include "UnionSeedCriteria.h"
|
||||
#include "TimeSeedCriteria.h"
|
||||
#include "ShareRatioSeedCriteria.h"
|
||||
#include "DefaultPieceStorage.h"
|
||||
#include "DefaultBtProgressInfoFile.h"
|
||||
#include "CUIDCounter.h"
|
||||
#include "prefs.h"
|
||||
|
||||
Commands BtSetup::setup(RequestGroup* requestGroup,
|
||||
DownloadEngine* e,
|
||||
const Option* option)
|
||||
{
|
||||
Commands commands;
|
||||
BtContextHandle btContext = requestGroup->getDownloadContext();
|
||||
if(btContext.isNull()) {
|
||||
return commands;
|
||||
}
|
||||
// TODO following process is moved to BtSetup
|
||||
|
||||
// commands
|
||||
commands.push_back(new TrackerWatcherCommand(CUIDCounterSingletonHolder::instance()->newID(),
|
||||
requestGroup,
|
||||
e,
|
||||
btContext));
|
||||
commands.push_back(new PeerChokeCommand(CUIDCounterSingletonHolder::instance()->newID(),
|
||||
requestGroup,
|
||||
e,
|
||||
btContext,
|
||||
10));
|
||||
commands.push_back(new ActivePeerConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(),
|
||||
requestGroup,
|
||||
e,
|
||||
btContext,
|
||||
30));
|
||||
|
||||
SharedHandle<UnionSeedCriteria> unionCri = new UnionSeedCriteria();
|
||||
if(option->defined(PREF_SEED_TIME)) {
|
||||
unionCri->addSeedCriteria(new TimeSeedCriteria(option->getAsInt(PREF_SEED_TIME)*60));
|
||||
}
|
||||
if(option->defined(PREF_SEED_RATIO)) {
|
||||
unionCri->addSeedCriteria(new ShareRatioSeedCriteria(option->getAsDouble(PREF_SEED_RATIO), btContext));
|
||||
}
|
||||
if(unionCri->getSeedCriterion().size() > 0) {
|
||||
commands.push_back(new SeedCheckCommand(CUIDCounterSingletonHolder::instance()->newID(),
|
||||
requestGroup,
|
||||
e,
|
||||
btContext,
|
||||
unionCri));
|
||||
}
|
||||
|
||||
BT_RUNTIME(btContext)->setReady(true);
|
||||
return commands;
|
||||
}
|
@ -32,20 +32,22 @@
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_DEFAULT_FILE_ALLOCATOR_H_
|
||||
#define _D_DEFAULT_FILE_ALLOCATOR_H_
|
||||
#ifndef _D_BT_SETUP_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:
|
||||
DefaultFileAllocator() {}
|
||||
|
||||
virtual ~DefaultFileAllocator() {}
|
||||
|
||||
virtual void allocate(int fd, int64_t totalLength);
|
||||
Commands setup(RequestGroup* requestGroup,
|
||||
DownloadEngine* e,
|
||||
const Option* option);
|
||||
};
|
||||
|
||||
typedef SharedHandle<DefaultFileAllocator> DefaultFileAllocatorHandle;
|
||||
|
||||
#endif // _D_DEFAULT_FILE_ALLOCATOR_H_
|
||||
#endif // _D_BT_SETUP_H_
|
@ -38,34 +38,35 @@
|
||||
ByteArrayDiskWriter::ByteArrayDiskWriter() {
|
||||
}
|
||||
|
||||
ByteArrayDiskWriter::~ByteArrayDiskWriter() {
|
||||
closeFile();
|
||||
}
|
||||
ByteArrayDiskWriter::~ByteArrayDiskWriter() {}
|
||||
|
||||
void ByteArrayDiskWriter::clear() {
|
||||
void ByteArrayDiskWriter::clear()
|
||||
{
|
||||
buf.str("");
|
||||
}
|
||||
|
||||
void ByteArrayDiskWriter::initAndOpenFile(const string& filename,
|
||||
int64_t totalLength) {
|
||||
int64_t totalLength)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void ByteArrayDiskWriter::openFile(const string& filename,
|
||||
int64_t totalLength) {
|
||||
initAndOpenFile(filename);
|
||||
int64_t totalLength)
|
||||
{
|
||||
}
|
||||
|
||||
void ByteArrayDiskWriter::closeFile() {
|
||||
clear();
|
||||
}
|
||||
void ByteArrayDiskWriter::closeFile()
|
||||
{}
|
||||
|
||||
void ByteArrayDiskWriter::openExistingFile(const string& filename,
|
||||
int64_t totalLength) {
|
||||
int64_t totalLength)
|
||||
{
|
||||
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) {
|
||||
buf.seekg(0, ios::end);
|
||||
for(int32_t i = size(); i < position; ++i) {
|
||||
@ -74,12 +75,13 @@ void ByteArrayDiskWriter::writeData(const char* data, int32_t dataLength, int64_
|
||||
} else {
|
||||
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.read(data, len);
|
||||
buf.read(reinterpret_cast<char*>(data), len);
|
||||
// TODO we have to call buf.clear() here? YES
|
||||
buf.clear();
|
||||
return buf.gcount();
|
||||
|
@ -55,9 +55,8 @@ public:
|
||||
|
||||
virtual void openExistingFile(const string& filename, int64_t totalLength = 0);
|
||||
|
||||
// position is ignored
|
||||
virtual void writeData(const char* data, int32_t len, int64_t position = 0);
|
||||
virtual int32_t readData(char* data, int32_t len, int64_t position);
|
||||
virtual void writeData(const unsigned char* data, int32_t len, int64_t position);
|
||||
virtual int32_t readData(unsigned char* data, int32_t len, int64_t position);
|
||||
|
||||
// Not implemented yet
|
||||
virtual void truncate(int64_t length) {}
|
||||
|
52
src/ByteArrayDiskWriterFactory.h
Normal file
52
src/ByteArrayDiskWriterFactory.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_BYTE_ARRAY_DISK_WRITER_FACTORY_H_
|
||||
#define _D_BYTE_ARRAY_DISK_WRITER_FACTORY_H_
|
||||
|
||||
#include "DiskWriterFactory.h"
|
||||
#include "ByteArrayDiskWriter.h"
|
||||
|
||||
class ByteArrayDiskWriterFactory:public DiskWriterFactory
|
||||
{
|
||||
public:
|
||||
DiskWriterHandle newDiskWriter()
|
||||
{
|
||||
return new ByteArrayDiskWriter();
|
||||
}
|
||||
};
|
||||
|
||||
typedef SharedHandle<ByteArrayDiskWriterFactory> ByteArrayDiskWriterFactoryHandle;
|
||||
|
||||
#endif // _D_BYTE_ARRAY_DISK_WRITER_FACTORY_H_
|
@ -33,6 +33,9 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "CheckIntegrityCommand.h"
|
||||
#include "CheckIntegrityMan.h"
|
||||
#include "CheckIntegrityEntry.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "FileAllocationEntry.h"
|
||||
#include "InitiateConnectionCommandFactory.h"
|
||||
#include "DlAbortEx.h"
|
||||
@ -40,7 +43,7 @@
|
||||
#include "DownloadCommand.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),
|
||||
_entry(entry)
|
||||
{
|
||||
@ -54,25 +57,16 @@ CheckIntegrityCommand::~CheckIntegrityCommand()
|
||||
|
||||
bool CheckIntegrityCommand::executeInternal()
|
||||
{
|
||||
if(_requestGroup->isHaltRequested()) {
|
||||
return true;
|
||||
}
|
||||
_entry->validateChunk();
|
||||
if(_entry->finished()) {
|
||||
_entry->updatePieceStorage();
|
||||
if(_requestGroup->downloadFinished()) {
|
||||
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 {
|
||||
if(_timer.difference() <= _e->option->getAsInt(PREF_DIRECT_DOWNLOAD_TIMEOUT) &&
|
||||
_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);
|
||||
}
|
||||
_e->addCommand(_entry->prepareForNextAction(_e));
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
@ -84,12 +78,6 @@ bool CheckIntegrityCommand::executeInternal()
|
||||
bool CheckIntegrityCommand::handleException(Exception* e)
|
||||
{
|
||||
logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid);
|
||||
delete e;
|
||||
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;
|
||||
}
|
||||
|
@ -36,16 +36,17 @@
|
||||
#define _D_CHECK_INTEGRITY_COMMAND_H_
|
||||
|
||||
#include "RealtimeCommand.h"
|
||||
#include "IteratableChunkChecksumValidator.h"
|
||||
#include "CheckIntegrityEntry.h"
|
||||
#include "TimeA2.h"
|
||||
|
||||
class CheckIntegrityEntry;
|
||||
extern typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
|
||||
|
||||
class CheckIntegrityCommand : public RealtimeCommand {
|
||||
private:
|
||||
CheckIntegrityEntryHandle _entry;
|
||||
Time _timer;
|
||||
public:
|
||||
CheckIntegrityCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const CheckIntegrityEntryHandle& entry);
|
||||
CheckIntegrityCommand(int32_t cuid, RequestGroup* requestGroup, DownloadEngine* e, const CheckIntegrityEntryHandle& entry);
|
||||
|
||||
virtual ~CheckIntegrityCommand();
|
||||
|
||||
|
@ -34,33 +34,64 @@
|
||||
/* copyright --> */
|
||||
#include "CheckIntegrityEntry.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()
|
||||
{
|
||||
_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();
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
IteratableChunkChecksumValidatorHandle validator =
|
||||
new IteratableChunkChecksumValidator();
|
||||
validator->setChunkChecksum(_requestGroup->getChunkChecksum());
|
||||
validator->setDiskWriter(_requestGroup->getSegmentMan()->diskWriter);
|
||||
validator->setBitfield(_requestGroup->getSegmentMan()->getBitfield());
|
||||
if(!validator->canValidate()) {
|
||||
// insufficient checksums.
|
||||
throw new DlAbortEx("Insufficient checksums.");
|
||||
}
|
||||
validator->init();
|
||||
new IteratableChunkChecksumValidator(_requestGroup->getDownloadContext(),
|
||||
_requestGroup->getPieceStorage());
|
||||
_validator = validator;
|
||||
}
|
||||
|
||||
void CheckIntegrityEntry::updatePieceStorage()
|
||||
{
|
||||
_validator->updatePieceStorage();
|
||||
}
|
||||
|
@ -36,29 +36,37 @@
|
||||
#define _D_CHECK_INTEGRITY_ENTRY_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:
|
||||
IteratableChunkChecksumValidatorHandle _validator;
|
||||
public:
|
||||
CheckIntegrityEntry(int cuid,
|
||||
const RequestHandle& currentRequest,
|
||||
RequestGroup* requestGroup,
|
||||
DownloadCommand* nextDownloadCommand = 0):
|
||||
RequestGroupEntry(cuid, currentRequest, requestGroup, nextDownloadCommand),
|
||||
_validator(0)
|
||||
{}
|
||||
CheckIntegrityEntry(RequestGroup* requestGroup, Command* nextCommand = 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 validateChunk();
|
||||
|
||||
void updatePieceStorage();
|
||||
|
||||
virtual Commands prepareForNextAction(DownloadEngine* e) = 0;
|
||||
};
|
||||
|
||||
typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
|
||||
|
72
src/CheckIntegrityMan.cc
Normal file
72
src/CheckIntegrityMan.cc
Normal file
@ -0,0 +1,72 @@
|
||||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "CheckIntegrityMan.h"
|
||||
#include "CheckIntegrityEntry.h"
|
||||
|
||||
CheckIntegrityMan::CheckIntegrityMan() {}
|
||||
|
||||
CheckIntegrityMan::~CheckIntegrityMan() {}
|
||||
|
||||
void CheckIntegrityMan::addCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry)
|
||||
{
|
||||
_checkIntegrityEntries.push_back(entry);
|
||||
}
|
||||
|
||||
bool CheckIntegrityMan::removeCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry)
|
||||
{
|
||||
CheckIntegrityEntries::iterator itr = find(_checkIntegrityEntries.begin(),
|
||||
_checkIntegrityEntries.end(),
|
||||
entry);
|
||||
if(itr == _checkIntegrityEntries.end()) {
|
||||
return false;
|
||||
} else {
|
||||
_checkIntegrityEntries.erase(itr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CheckIntegrityEntryHandle CheckIntegrityMan::getFirstCheckIntegrityEntry() const
|
||||
{
|
||||
if(_checkIntegrityEntries.empty()) {
|
||||
return 0;
|
||||
} else {
|
||||
return _checkIntegrityEntries.front();
|
||||
}
|
||||
}
|
||||
|
||||
int32_t CheckIntegrityMan::countCheckIntegrityEntry() const
|
||||
{
|
||||
return _checkIntegrityEntries.size();
|
||||
}
|
@ -36,43 +36,26 @@
|
||||
#define _D_CHECK_INTEGRITY_MAN_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "CheckIntegrityEntry.h"
|
||||
|
||||
class CheckIntegrityEntry;
|
||||
extern typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
|
||||
extern typedef deque<CheckIntegrityEntryHandle> CheckIntegrityEntries;
|
||||
|
||||
class CheckIntegrityMan {
|
||||
private:
|
||||
CheckIntegrityEntries _checkIntegrityEntries;
|
||||
public:
|
||||
void addCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry)
|
||||
{
|
||||
_checkIntegrityEntries.push_back(entry);
|
||||
}
|
||||
CheckIntegrityMan();
|
||||
|
||||
bool 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;
|
||||
}
|
||||
}
|
||||
~CheckIntegrityMan();
|
||||
|
||||
CheckIntegrityEntryHandle getFirstCheckIntegrityEntry() const
|
||||
{
|
||||
if(_checkIntegrityEntries.empty()) {
|
||||
return 0;
|
||||
} else {
|
||||
return _checkIntegrityEntries.front();
|
||||
}
|
||||
}
|
||||
void addCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry);
|
||||
|
||||
int32_t countCheckIntegrityEntry() const
|
||||
{
|
||||
return _checkIntegrityEntries.size();
|
||||
}
|
||||
bool removeCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry);
|
||||
|
||||
CheckIntegrityEntryHandle getFirstCheckIntegrityEntry() const;
|
||||
|
||||
int32_t countCheckIntegrityEntry() const;
|
||||
};
|
||||
|
||||
typedef SharedHandle<CheckIntegrityMan> CheckIntegrityManHandle;
|
||||
|
@ -39,9 +39,11 @@
|
||||
void ChecksumCommand::initValidator()
|
||||
{
|
||||
_validator = new IteratableChecksumValidator();
|
||||
_validator->setChecksum(_requestGroup->getChecksum());
|
||||
_validator->setDiskWriter(_requestGroup->getSegmentMan()->diskWriter);
|
||||
_validator->setBitfield(_requestGroup->getSegmentMan()->getBitfield());
|
||||
// TODO checksum will be held by DownloadContext
|
||||
_validator->setChecksum(0);
|
||||
//_validator->setDiskWriter(new DiskAdaptorWriter(_requestGroup->getSegmentMan()->getDiskAdaptor()));
|
||||
// TODO we should use PieceStorage instead of BitfieldMan
|
||||
//_validator->setBitfield(_requestGroup->getSegmentMan()->getBitfield());
|
||||
if(!_validator->canValidate()) {
|
||||
// insufficient checksums.
|
||||
throw new DlAbortEx(EX_INSUFFICIENT_CHECKSUM);
|
||||
@ -51,6 +53,9 @@ void ChecksumCommand::initValidator()
|
||||
|
||||
bool ChecksumCommand::executeInternal()
|
||||
{
|
||||
if(_e->isHaltRequested()) {
|
||||
return true;
|
||||
}
|
||||
_validator->validateChunk();
|
||||
if(_validator->finished()) {
|
||||
if(_requestGroup->downloadFinished()) {
|
||||
@ -70,7 +75,6 @@ bool ChecksumCommand::executeInternal()
|
||||
bool ChecksumCommand::handleException(Exception* e)
|
||||
{
|
||||
logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid);
|
||||
delete e;
|
||||
logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str());
|
||||
// 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
|
||||
|
@ -47,12 +47,12 @@ public:
|
||||
RealtimeCommand(cuid, requestGroup, e),
|
||||
_validator(0)
|
||||
{
|
||||
++_requestGroup->numConnection;
|
||||
_requestGroup->increaseNumCommand();
|
||||
}
|
||||
|
||||
virtual ~ChecksumCommand()
|
||||
{
|
||||
--_requestGroup->numConnection;
|
||||
_requestGroup->decreaseNumCommand();
|
||||
}
|
||||
|
||||
void initValidator();
|
||||
|
@ -79,6 +79,11 @@ public:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
const Strings& getChecksums() const
|
||||
{
|
||||
return _checksums;
|
||||
}
|
||||
|
||||
int32_t getChecksumLength() const
|
||||
{
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
void ChunkChecksumValidator::validate()
|
||||
{
|
||||
/*
|
||||
if(!_validator->canValidate()) {
|
||||
// insufficient checksums.
|
||||
logger->error(MSG_INSUFFICIENT_CHECKSUM,
|
||||
@ -63,4 +64,5 @@ void ChunkChecksumValidator::validate()
|
||||
}
|
||||
fileAllocationMonitor->setCurrentValue(numChecksum);
|
||||
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));
|
||||
}
|
162
src/ConsoleStatCalc.cc
Normal file
162
src/ConsoleStatCalc.cc
Normal file
@ -0,0 +1,162 @@
|
||||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "ConsoleStatCalc.h"
|
||||
#include "RequestGroupMan.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "FileAllocationMan.h"
|
||||
#include "FileAllocationEntry.h"
|
||||
#include "CheckIntegrityMan.h"
|
||||
#include "CheckIntegrityEntry.h"
|
||||
#include "Util.h"
|
||||
#include <iomanip>
|
||||
|
||||
void
|
||||
ConsoleStatCalc::calculateStat(const RequestGroupManHandle& requestGroupMan,
|
||||
const FileAllocationManHandle& fileAllocationMan,
|
||||
const CheckIntegrityManHandle& checkIntegrityMan)
|
||||
{
|
||||
if(!_cp.elapsed(1)) {
|
||||
return;
|
||||
}
|
||||
_cp.reset();
|
||||
|
||||
cout << "\r ";
|
||||
cout << "\r";
|
||||
if(requestGroupMan->countRequestGroup() > 0) {
|
||||
RequestGroupHandle firstRequestGroup = requestGroupMan->getRequestGroup(0);
|
||||
TransferStat stat = firstRequestGroup->calculateStat();
|
||||
//int32_t dlSpeed = firstRequestGroup->calculateDownloadSpeed();
|
||||
int32_t eta = 0;
|
||||
if(firstRequestGroup->getTotalLength() > 0 && stat.getDownloadSpeed() > 0) {
|
||||
eta = (firstRequestGroup->getTotalLength()-firstRequestGroup->getCompletedLength())/stat.getDownloadSpeed();
|
||||
}
|
||||
|
||||
cout << "["
|
||||
<< "#" << firstRequestGroup->getGID() << " "
|
||||
<< "SIZE:"
|
||||
<< Util::abbrevSize(firstRequestGroup->getCompletedLength())
|
||||
<< "B"
|
||||
<< "/"
|
||||
<< Util::abbrevSize(firstRequestGroup->getTotalLength())
|
||||
<< "B";
|
||||
if(firstRequestGroup->getTotalLength() > 0) {
|
||||
cout << "("
|
||||
<< 100*firstRequestGroup->getCompletedLength()/firstRequestGroup->getTotalLength()
|
||||
<< "%)";
|
||||
}
|
||||
cout << " "
|
||||
<< "CN:"
|
||||
<< firstRequestGroup->getNumConnection();
|
||||
cout << " "
|
||||
<< "SPD:"
|
||||
<< fixed << setprecision(2) << stat.getDownloadSpeed()/1024.0 << "KiB/s";
|
||||
if(stat.getSessionUploadLength() > 0) {
|
||||
cout << " "
|
||||
<< "UP:"
|
||||
<< fixed << setprecision(2) << stat.getUploadSpeed()/1024.0 << "KiB/s"
|
||||
<< "(" << Util::abbrevSize(stat.getAllTimeUploadLength()) << ")";
|
||||
}
|
||||
if(eta > 0) {
|
||||
cout << " "
|
||||
<< "ETA:"
|
||||
<< Util::secfmt(eta);
|
||||
}
|
||||
cout << "]";
|
||||
if(requestGroupMan->countRequestGroup() > 1) {
|
||||
cout << "("
|
||||
<< requestGroupMan->countRequestGroup()-1
|
||||
<< "more...)";
|
||||
}
|
||||
}
|
||||
|
||||
if(requestGroupMan->countRequestGroup() > 1) {
|
||||
TransferStat stat = requestGroupMan->calculateStat();
|
||||
cout << " "
|
||||
<< "[TOTAL SPD:"
|
||||
<< fixed << setprecision(2) << stat.getDownloadSpeed()/1024.0 << "KiB/s" << "]";
|
||||
}
|
||||
|
||||
{
|
||||
FileAllocationEntryHandle entry = fileAllocationMan->getCurrentFileAllocationEntry();
|
||||
if(!entry.isNull()) {
|
||||
cout << " "
|
||||
<< "[FileAlloc:"
|
||||
<< "#" << entry->getRequestGroup()->getGID() << " "
|
||||
<< Util::abbrevSize(entry->getCurrentLength())
|
||||
<< "B"
|
||||
<< "/"
|
||||
<< Util::abbrevSize(entry->getTotalLength())
|
||||
<< "B"
|
||||
<< "(";
|
||||
if(entry->getTotalLength() > 0) {
|
||||
cout << 100*entry->getCurrentLength()/entry->getTotalLength();
|
||||
} else {
|
||||
cout << "--";
|
||||
}
|
||||
cout << "%)"
|
||||
<< "]";
|
||||
if(fileAllocationMan->countFileAllocationEntryInQueue() > 0) {
|
||||
cout << "("
|
||||
<< fileAllocationMan->countFileAllocationEntryInQueue()
|
||||
<< "waiting...)";
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_MESSAGE_DIGEST
|
||||
{
|
||||
CheckIntegrityEntryHandle entry = checkIntegrityMan->getFirstCheckIntegrityEntry();
|
||||
if(!entry.isNull()) {
|
||||
cout << " "
|
||||
<< "[Checksum:"
|
||||
<< "#" << entry->getRequestGroup()->getGID() << " "
|
||||
<< Util::abbrevSize(entry->getCurrentLength())
|
||||
<< "B"
|
||||
<< "/"
|
||||
<< Util::abbrevSize(entry->getTotalLength())
|
||||
<< "B"
|
||||
<< "("
|
||||
<< 100*entry->getCurrentLength()/entry->getTotalLength()
|
||||
<< "%)";
|
||||
cout << "]";
|
||||
if(checkIntegrityMan->countCheckIntegrityEntry() > 1) {
|
||||
cout << "("
|
||||
<< checkIntegrityMan->countCheckIntegrityEntry()-1
|
||||
<< "more...)";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_MESSAGE_DIGEST
|
||||
cout << flush;
|
||||
}
|
@ -32,20 +32,24 @@
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_TRACKER_SEGMENT_MAN_FACTORY_H_
|
||||
#define _D_TRACKER_SEGMENT_MAN_FACTORY_H_
|
||||
#ifndef _D_CONSOLE_STAT_CALC_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:
|
||||
TrackerSegmentManFactory(const Option* option):AbstractSegmentManFactory(option) {}
|
||||
virtual ~ConsoleStatCalc() {}
|
||||
|
||||
virtual ~TrackerSegmentManFactory() {}
|
||||
|
||||
virtual SegmentManHandle createNewInstance();
|
||||
virtual void calculateStat(const RequestGroupManHandle& requestGroupMan,
|
||||
const FileAllocationManHandle& fileAllocationMan,
|
||||
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 "message.h"
|
||||
|
||||
void CopyDiskAdaptor::onDownloadComplete() {
|
||||
void CopyDiskAdaptor::onDownloadComplete()
|
||||
throw(DlAbortEx*)
|
||||
{
|
||||
closeFile();
|
||||
fixFilename();
|
||||
openFile();
|
||||
}
|
||||
|
||||
void CopyDiskAdaptor::fixFilename() {
|
||||
void CopyDiskAdaptor::fixFilename()
|
||||
throw(DlAbortEx*)
|
||||
{
|
||||
int64_t offset = 0;
|
||||
for(FileEntries::iterator itr = fileEntries.begin();
|
||||
itr != fileEntries.end(); itr++) {
|
||||
@ -59,6 +63,7 @@ void CopyDiskAdaptor::fixFilename() {
|
||||
}
|
||||
}
|
||||
|
||||
string CopyDiskAdaptor::getFilePath() {
|
||||
string CopyDiskAdaptor::getFilePath()
|
||||
{
|
||||
return storeDir+"/"+tempFilename;
|
||||
}
|
||||
|
@ -36,13 +36,14 @@
|
||||
#define _D_COPY_DISK_ADAPTOR_H_
|
||||
|
||||
#include "AbstractSingleDiskAdaptor.h"
|
||||
#include "DlAbortEx.h"
|
||||
|
||||
class CopyDiskAdaptor : public AbstractSingleDiskAdaptor {
|
||||
private:
|
||||
string tempFilename;
|
||||
string topDir;
|
||||
|
||||
void fixFilename();
|
||||
void fixFilename() throw(DlAbortEx*);
|
||||
public:
|
||||
CopyDiskAdaptor() {}
|
||||
|
||||
@ -50,7 +51,7 @@ public:
|
||||
|
||||
virtual string getFilePath();
|
||||
|
||||
virtual void onDownloadComplete();
|
||||
virtual void onDownloadComplete() throw(DlAbortEx*);
|
||||
|
||||
// tempFilename is relative to storeDir
|
||||
void setTempFilename(const string& tempFilename) {
|
||||
|
@ -42,9 +42,10 @@
|
||||
#include "Util.h"
|
||||
#include "MessageDigestHelper.h"
|
||||
#include "a2netcompat.h"
|
||||
#include "AnnounceTier.h"
|
||||
#include <libgen.h>
|
||||
|
||||
DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-") {}
|
||||
DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-"), _ownerRequestGroup(0) {}
|
||||
|
||||
DefaultBtContext::~DefaultBtContext() {}
|
||||
|
||||
@ -248,6 +249,11 @@ int32_t DefaultBtContext::getNumPieces() const {
|
||||
return numPieces;
|
||||
}
|
||||
|
||||
string DefaultBtContext::getActualBasePath() const
|
||||
{
|
||||
return _dir+"/"+name;
|
||||
}
|
||||
|
||||
Integers DefaultBtContext::computeFastSet(const string& ipaddr, int32_t fastSetSize)
|
||||
{
|
||||
Integers fastSet;
|
||||
|
@ -59,6 +59,8 @@ private:
|
||||
string _peerIdPrefix;
|
||||
AnnounceTiers announceTiers;
|
||||
|
||||
RequestGroup* _ownerRequestGroup;
|
||||
|
||||
void clear();
|
||||
void extractPieceHash(const unsigned char* hashData,
|
||||
int32_t hashDataLength,
|
||||
@ -90,6 +92,11 @@ private:
|
||||
|
||||
virtual FileEntries getFileEntries() const;
|
||||
|
||||
virtual string getPieceHashAlgo() const
|
||||
{
|
||||
return "sha1";
|
||||
}
|
||||
|
||||
virtual AnnounceTiers getAnnounceTiers() const;
|
||||
|
||||
virtual void load(const string& torrentFile);
|
||||
@ -100,6 +107,8 @@ private:
|
||||
|
||||
virtual int32_t getNumPieces() const;
|
||||
|
||||
virtual string getActualBasePath() const;
|
||||
|
||||
virtual const unsigned char* getPeerId() {
|
||||
if(peerId == "") {
|
||||
peerId = generatePeerId();
|
||||
@ -109,6 +118,11 @@ private:
|
||||
|
||||
virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize);
|
||||
|
||||
virtual RequestGroup* getOwnerRequestGroup()
|
||||
{
|
||||
return _ownerRequestGroup;
|
||||
}
|
||||
|
||||
string generatePeerId() const;
|
||||
|
||||
void setPeerIdPrefix(const string& peerIdPrefix)
|
||||
@ -126,7 +140,11 @@ private:
|
||||
{
|
||||
this->numPieces = numPieces;
|
||||
}
|
||||
|
||||
|
||||
void setOwnerRequestGroup(RequestGroup* owner)
|
||||
{
|
||||
_ownerRequestGroup = owner;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SharedHandle<DefaultBtContext> DefaultBtContextHandle;
|
||||
|
@ -33,6 +33,9 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "DefaultBtProgressInfoFile.h"
|
||||
#include "DownloadContext.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "Option.h"
|
||||
#include "BtRegistry.h"
|
||||
#include "LogFactory.h"
|
||||
#include "prefs.h"
|
||||
@ -41,143 +44,245 @@
|
||||
#include "File.h"
|
||||
#include "Util.h"
|
||||
#include "a2io.h"
|
||||
#include <fstream>
|
||||
#include <errno.h>
|
||||
|
||||
DefaultBtProgressInfoFile::DefaultBtProgressInfoFile(const BtContextHandle& btContext,
|
||||
DefaultBtProgressInfoFile::DefaultBtProgressInfoFile(const DownloadContextHandle& dctx,
|
||||
const PieceStorageHandle& pieceStorage,
|
||||
const Option* option):
|
||||
btContext(btContext),
|
||||
option(option),
|
||||
pieceStorage(PIECE_STORAGE(btContext)),
|
||||
btRuntime(BT_RUNTIME(btContext)),
|
||||
peerStorage(PEER_STORAGE(btContext))
|
||||
_dctx(dctx),
|
||||
_pieceStorage(pieceStorage),
|
||||
_option(option),
|
||||
_logger(LogFactory::getInstance())
|
||||
{
|
||||
logger = LogFactory::getInstance();
|
||||
string storeDir = option->get(PREF_DIR);
|
||||
filename = storeDir+"/"+btContext->getName()+".aria2";
|
||||
_filename = _dctx->getActualBasePath()+".aria2";
|
||||
}
|
||||
|
||||
DefaultBtProgressInfoFile::~DefaultBtProgressInfoFile() {}
|
||||
|
||||
void DefaultBtProgressInfoFile::save() {
|
||||
logger->info(MSG_SAVING_SEGMENT_FILE, filename.c_str());
|
||||
string filenameTemp = filename+"__temp";
|
||||
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));
|
||||
}
|
||||
bool DefaultBtProgressInfoFile::isTorrentDownload()
|
||||
{
|
||||
return !BtContextHandle(_dctx).isNull();
|
||||
}
|
||||
|
||||
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,
|
||||
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() {
|
||||
logger->info(MSG_LOADING_SEGMENT_FILE, filename.c_str());
|
||||
FILE* file = openFile(filename, "r+b");
|
||||
void DefaultBtProgressInfoFile::load()
|
||||
{
|
||||
_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* savedBitfield = 0;
|
||||
try {
|
||||
savedInfoHash = new unsigned char[btContext->getInfoHashLength()];
|
||||
savedBitfield = new unsigned char[pieceStorage->getBitfieldLength()];
|
||||
if(fread(savedInfoHash, btContext->getInfoHashLength(), 1, file) < 1) {
|
||||
throw string("readError");
|
||||
unsigned char version[2];
|
||||
in.read((char*)version, sizeof(version));
|
||||
if(string("0000") != Util::toHex(version, sizeof(version))) {
|
||||
throw new DlAbortEx("Unsupported ctrl file version: %s",
|
||||
Util::toHex(version, sizeof(version)).c_str());
|
||||
}
|
||||
if(Util::toHex(savedInfoHash, btContext->getInfoHashLength()) !=
|
||||
btContext->getInfoHashAsString()) {
|
||||
throw string("infoHashMismatch");
|
||||
unsigned char extension[4];
|
||||
in.read((char*)extension, sizeof(extension));
|
||||
|
||||
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,
|
||||
pieceStorage->getBitfieldLength());
|
||||
// allTimeDownloadLength exists for only a compatibility reason.
|
||||
int64_t allTimeDownloadLength;
|
||||
if(fread(&allTimeDownloadLength,
|
||||
sizeof(allTimeDownloadLength), 1, file) < 1) {
|
||||
throw string("readError");
|
||||
if(infoHashLength > 0) {
|
||||
savedInfoHash = new unsigned char[infoHashLength];
|
||||
in.read(reinterpret_cast<char*>(savedInfoHash), infoHashLength);
|
||||
BtContextHandle btContext = _dctx;
|
||||
if(infoHashCheckEnabled &&
|
||||
Util::toHex(savedInfoHash, infoHashLength) != btContext->getInfoHashAsString()) {
|
||||
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,
|
||||
sizeof(allTimeUploadLength), 1, file) < 1) {
|
||||
throw string("readError");
|
||||
|
||||
// TODO implement the conversion mechanism between different piece length.
|
||||
int32_t pieceLength;
|
||||
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;
|
||||
savedBitfield = 0;
|
||||
delete [] savedInfoHash;
|
||||
savedInfoHash = 0;
|
||||
fclose(file);
|
||||
} catch(string ex) {
|
||||
if(savedBitfield) {
|
||||
|
||||
int32_t numInFlightPiece;
|
||||
in.read(reinterpret_cast<char*>(&numInFlightPiece), sizeof(numInFlightPiece));
|
||||
|
||||
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;
|
||||
savedBitfield = 0;
|
||||
|
||||
inFlightPieces.push_back(piece);
|
||||
}
|
||||
if(savedInfoHash) {
|
||||
delete [] savedInfoHash;
|
||||
}
|
||||
fclose(file);
|
||||
if(ex == "infoHashMismatch") {
|
||||
throw new DlAbortEx(EX_INFOHASH_MISMATCH_IN_SEGFILE);
|
||||
} else {
|
||||
throw new DlAbortEx(EX_SEGMENT_FILE_READ,
|
||||
filename.c_str(), strerror(errno));
|
||||
}
|
||||
}
|
||||
logger->info(MSG_LOADED_SEGMENT_FILE);
|
||||
_pieceStorage->addInFlightPiece(inFlightPieces);
|
||||
|
||||
_logger->info(MSG_LOADED_SEGMENT_FILE);
|
||||
} catch(ios::failure const& exception) {
|
||||
delete [] savedBitfield;
|
||||
delete [] savedInfoHash;
|
||||
// TODO ios::failure doesn't give us the reasons of failure...
|
||||
throw new DlAbortEx(EX_SEGMENT_FILE_READ,
|
||||
_filename.c_str(), strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultBtProgressInfoFile::removeFile() {
|
||||
if(exists()) {
|
||||
File f(filename);
|
||||
File f(_filename);
|
||||
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() {
|
||||
File f(filename);
|
||||
File f(_filename);
|
||||
if(f.isFile()) {
|
||||
logger->info(MSG_SEGMENT_FILE_EXISTS, filename.c_str());
|
||||
_logger->info(MSG_SEGMENT_FILE_EXISTS, _filename.c_str());
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -36,49 +36,33 @@
|
||||
#define _D_DEFAULT_BT_PROGRESS_INFO_FILE_H_
|
||||
|
||||
#include "BtProgressInfoFile.h"
|
||||
#include "BtContext.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "BtRuntime.h"
|
||||
#include "PeerStorage.h"
|
||||
#include "Logger.h"
|
||||
#include "Option.h"
|
||||
|
||||
class DownloadContext;
|
||||
extern typedef SharedHandle<DownloadContext> DownloadContextHandle;
|
||||
class PieceStorage;
|
||||
extern typedef SharedHandle<PieceStorage> PieceStorageHandle;
|
||||
class Logger;
|
||||
class Option;
|
||||
|
||||
class DefaultBtProgressInfoFile : public BtProgressInfoFile {
|
||||
private:
|
||||
BtContextHandle btContext;
|
||||
const Option* option;
|
||||
Logger* logger;
|
||||
PieceStorageHandle pieceStorage;
|
||||
BtRuntimeHandle btRuntime;
|
||||
PeerStorageHandle peerStorage;
|
||||
string filename;
|
||||
DownloadContextHandle _dctx;
|
||||
PieceStorageHandle _pieceStorage;
|
||||
const Option* _option;
|
||||
const Logger* _logger;
|
||||
string _filename;
|
||||
|
||||
bool isTorrentDownload();
|
||||
|
||||
FILE* openFile(const string& filename, const string& mode) const;
|
||||
public:
|
||||
DefaultBtProgressInfoFile(const BtContextHandle& btContext,
|
||||
DefaultBtProgressInfoFile(const DownloadContextHandle& btContext,
|
||||
const PieceStorageHandle& pieceStorage,
|
||||
const Option* option);
|
||||
|
||||
virtual ~DefaultBtProgressInfoFile();
|
||||
|
||||
void setBtRuntime(const BtRuntimeHandle& btRuntime) {
|
||||
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 string getFilename() { return _filename; }
|
||||
|
||||
virtual bool exists();
|
||||
|
||||
virtual void save();
|
||||
|
@ -33,10 +33,7 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "DefaultDiskWriter.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include "message.h"
|
||||
#include "DefaultFileAllocator.h"
|
||||
#include "GlowFileAllocator.h"
|
||||
#include "prefs.h"
|
||||
#include "Util.h"
|
||||
#include <errno.h>
|
||||
@ -48,38 +45,7 @@ DefaultDiskWriter::~DefaultDiskWriter() {}
|
||||
|
||||
void DefaultDiskWriter::initAndOpenFile(const string& filename,
|
||||
int64_t totalLength)
|
||||
throw(DlAbortEx*)
|
||||
{
|
||||
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 "Option.h"
|
||||
#include "DlAbortEx.h"
|
||||
|
||||
class DefaultDiskWriter:public AbstractDiskWriter {
|
||||
public:
|
||||
@ -45,9 +46,7 @@ public:
|
||||
virtual ~DefaultDiskWriter();
|
||||
|
||||
virtual void initAndOpenFile(const string& filename,
|
||||
int64_t totalLength = 0);
|
||||
|
||||
static DefaultDiskWriter* createNewDiskWriter(const Option* option);
|
||||
int64_t totalLength = 0) throw(DlAbortEx*);
|
||||
};
|
||||
|
||||
typedef SharedHandle<DefaultDiskWriter> DefaultDiskWriterHandle;
|
||||
|
52
src/DefaultDiskWriterFactory.h
Normal file
52
src/DefaultDiskWriterFactory.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_DEFAULT_DISK_WRITER_FACTORY_H_
|
||||
#define _D_DEFAULT_DISK_WRITER_FACTORY_H_
|
||||
|
||||
#include "DiskWriterFactory.h"
|
||||
#include "DefaultDiskWriter.h"
|
||||
|
||||
class DefaultDiskWriterFactory:public DiskWriterFactory
|
||||
{
|
||||
public:
|
||||
DiskWriterHandle newDiskWriter()
|
||||
{
|
||||
return new DefaultDiskWriter();
|
||||
}
|
||||
};
|
||||
|
||||
typedef SharedHandle<DefaultDiskWriterFactory> DefaultDiskWriterFactoryHandle;
|
||||
|
||||
#endif // _D_DEFAULT_DISK_WRITER_FACTORY_H_
|
@ -192,6 +192,8 @@ TransferStat DefaultPeerStorage::calculateStat() {
|
||||
TransferStat stat = calStat.getTransferStat();
|
||||
stat.sessionDownloadLength += removedPeerSessionDownloadLength;
|
||||
stat.sessionUploadLength += removedPeerSessionUploadLength;
|
||||
stat.setAllTimeUploadLength(btRuntime->getUploadLengthAtStartup()+
|
||||
stat.getSessionUploadLength());
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
@ -33,29 +33,31 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "DefaultPieceStorage.h"
|
||||
#include "DownloadContext.h"
|
||||
#include "Piece.h"
|
||||
#include "Peer.h"
|
||||
#include "LogFactory.h"
|
||||
#include "prefs.h"
|
||||
#include "DirectDiskAdaptor.h"
|
||||
#include "MultiDiskAdaptor.h"
|
||||
#include "CopyDiskAdaptor.h"
|
||||
#include "DefaultDiskWriter.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include "DiskWriter.h"
|
||||
#include "BitfieldManFactory.h"
|
||||
#include "FileAllocationMonitor.h"
|
||||
#include "DiskAdaptorWriter.h"
|
||||
#include "ChunkChecksumValidator.h"
|
||||
#include "message.h"
|
||||
#include "DefaultDiskWriterFactory.h"
|
||||
#include "DlAbortEx.h"
|
||||
|
||||
DefaultPieceStorage::DefaultPieceStorage(BtContextHandle btContext, const Option* option):
|
||||
btContext(btContext),
|
||||
DefaultPieceStorage::DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option):
|
||||
downloadContext(downloadContext),
|
||||
diskAdaptor(0),
|
||||
_diskWriterFactory(new DefaultDiskWriterFactory()),
|
||||
endGamePieceNum(END_GAME_PIECE_NUM),
|
||||
option(option)
|
||||
{
|
||||
bitfieldMan =
|
||||
BitfieldManFactory::getFactoryInstance()->
|
||||
createBitfieldMan(btContext->getPieceLength(),
|
||||
btContext->getTotalLength());
|
||||
createBitfieldMan(downloadContext->getPieceLength(),
|
||||
downloadContext->getTotalLength());
|
||||
logger = LogFactory::getInstance();
|
||||
}
|
||||
|
||||
@ -63,16 +65,19 @@ DefaultPieceStorage::~DefaultPieceStorage() {
|
||||
delete bitfieldMan;
|
||||
}
|
||||
|
||||
bool DefaultPieceStorage::hasMissingPiece(const PeerHandle& peer) {
|
||||
bool DefaultPieceStorage::hasMissingPiece(const PeerHandle& peer)
|
||||
{
|
||||
return bitfieldMan->hasMissingPiece(peer->getBitfield(),
|
||||
peer->getBitfieldLength());
|
||||
}
|
||||
|
||||
bool DefaultPieceStorage::isEndGame() {
|
||||
bool DefaultPieceStorage::isEndGame()
|
||||
{
|
||||
return bitfieldMan->countMissingBlock() <= endGamePieceNum;
|
||||
}
|
||||
|
||||
int32_t DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer) {
|
||||
int32_t DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer)
|
||||
{
|
||||
int32_t index = -1;
|
||||
if(isEndGame()) {
|
||||
index = bitfieldMan->getMissingIndex(peer->getBitfield(),
|
||||
@ -84,7 +89,8 @@ int32_t DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer) {
|
||||
return index;
|
||||
}
|
||||
|
||||
PieceHandle DefaultPieceStorage::checkOutPiece(int32_t index) {
|
||||
PieceHandle DefaultPieceStorage::checkOutPiece(int32_t index)
|
||||
{
|
||||
if(index == -1) {
|
||||
return 0;
|
||||
}
|
||||
@ -104,7 +110,8 @@ PieceHandle DefaultPieceStorage::checkOutPiece(int32_t index) {
|
||||
* Newly instantiated piece is not added to usedPieces.
|
||||
* 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()) {
|
||||
PieceHandle piece = findUsedPiece(index);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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(),
|
||||
usedPieces.end(),
|
||||
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);
|
||||
return checkOutPiece(index);
|
||||
}
|
||||
|
||||
int32_t DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer) {
|
||||
int32_t DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer)
|
||||
{
|
||||
int32_t index = -1;
|
||||
if(peer->isFastExtensionEnabled() && peer->countFastSet() > 0) {
|
||||
BitfieldMan tempBitfield(bitfieldMan->getBlockLength(),
|
||||
@ -172,12 +183,28 @@ int32_t DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer) {
|
||||
return index;
|
||||
}
|
||||
|
||||
PieceHandle DefaultPieceStorage::getMissingFastPiece(const PeerHandle& peer) {
|
||||
PieceHandle DefaultPieceStorage::getMissingFastPiece(const PeerHandle& peer)
|
||||
{
|
||||
int32_t index = getMissingFastPieceIndex(peer);
|
||||
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()) {
|
||||
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;
|
||||
if(toDelete <= 0) {
|
||||
return;
|
||||
@ -204,7 +232,8 @@ void DefaultPieceStorage::reduceUsedPieces(int32_t delMax) {
|
||||
}
|
||||
|
||||
int32_t DefaultPieceStorage::deleteUsedPiecesByFillRate(int32_t fillRate,
|
||||
int32_t toDelete) {
|
||||
int32_t toDelete)
|
||||
{
|
||||
int32_t deleted = 0;
|
||||
for(Pieces::iterator itr = usedPieces.begin();
|
||||
itr != usedPieces.end() && deleted < toDelete;) {
|
||||
@ -224,7 +253,8 @@ int32_t DefaultPieceStorage::deleteUsedPiecesByFillRate(int32_t fillRate,
|
||||
return deleted;
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::completePiece(const PieceHandle& piece) {
|
||||
void DefaultPieceStorage::completePiece(const PieceHandle& piece)
|
||||
{
|
||||
if(piece.isNull()) {
|
||||
return;
|
||||
}
|
||||
@ -250,17 +280,20 @@ void DefaultPieceStorage::completePiece(const PieceHandle& piece) {
|
||||
}
|
||||
}
|
||||
|
||||
bool DefaultPieceStorage::isSelectiveDownloadingMode() {
|
||||
bool DefaultPieceStorage::isSelectiveDownloadingMode()
|
||||
{
|
||||
return bitfieldMan->isFilterEnabled();
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::finishSelectiveDownloadingMode() {
|
||||
void DefaultPieceStorage::finishSelectiveDownloadingMode()
|
||||
{
|
||||
bitfieldMan->clearFilter();
|
||||
diskAdaptor->addAllDownloadEntry();
|
||||
}
|
||||
|
||||
// not unittested
|
||||
void DefaultPieceStorage::cancelPiece(const PieceHandle& piece) {
|
||||
void DefaultPieceStorage::cancelPiece(const PieceHandle& piece)
|
||||
{
|
||||
if(piece.isNull()) {
|
||||
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);
|
||||
}
|
||||
|
||||
int64_t DefaultPieceStorage::getTotalLength() {
|
||||
bool DefaultPieceStorage::isPieceUsed(int32_t index)
|
||||
{
|
||||
return bitfieldMan->isUseBitSet(index);
|
||||
}
|
||||
|
||||
int64_t DefaultPieceStorage::getTotalLength()
|
||||
{
|
||||
return bitfieldMan->getTotalLength();
|
||||
}
|
||||
|
||||
int64_t DefaultPieceStorage::getFilteredTotalLength() {
|
||||
int64_t DefaultPieceStorage::getFilteredTotalLength()
|
||||
{
|
||||
return bitfieldMan->getFilteredTotalLength();
|
||||
}
|
||||
|
||||
int64_t DefaultPieceStorage::getCompletedLength() {
|
||||
int64_t DefaultPieceStorage::getCompletedLength()
|
||||
{
|
||||
return bitfieldMan->getCompletedLength();
|
||||
}
|
||||
|
||||
int64_t DefaultPieceStorage::getFilteredCompletedLength() {
|
||||
int64_t DefaultPieceStorage::getFilteredCompletedLength()
|
||||
{
|
||||
return bitfieldMan->getFilteredCompletedLength();
|
||||
}
|
||||
|
||||
// not unittested
|
||||
void DefaultPieceStorage::setFileFilter(const Strings& filePaths) {
|
||||
if(btContext->getFileMode() != BtContext::MULTI || filePaths.empty()) {
|
||||
void DefaultPieceStorage::setFileFilter(const Strings& filePaths)
|
||||
{
|
||||
if(downloadContext->getFileMode() != DownloadContext::MULTI || filePaths.empty()) {
|
||||
return;
|
||||
}
|
||||
diskAdaptor->removeAllDownloadEntry();
|
||||
@ -309,7 +353,8 @@ void DefaultPieceStorage::setFileFilter(const Strings& filePaths) {
|
||||
bitfieldMan->enableFilter();
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes) {
|
||||
void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes)
|
||||
{
|
||||
Strings filePaths;
|
||||
const FileEntries& entries = diskAdaptor->getFileEntries();
|
||||
for(int32_t i = 0; i < (int32_t)entries.size(); i++) {
|
||||
@ -322,66 +367,77 @@ void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes) {
|
||||
}
|
||||
|
||||
// not unittested
|
||||
void DefaultPieceStorage::clearFileFilter() {
|
||||
void DefaultPieceStorage::clearFileFilter()
|
||||
{
|
||||
bitfieldMan->clearFilter();
|
||||
diskAdaptor->addAllDownloadEntry();
|
||||
}
|
||||
|
||||
// not unittested
|
||||
bool DefaultPieceStorage::downloadFinished() {
|
||||
bool DefaultPieceStorage::downloadFinished()
|
||||
{
|
||||
return bitfieldMan->isFilteredAllBitSet();
|
||||
}
|
||||
|
||||
// not unittested
|
||||
bool DefaultPieceStorage::allDownloadFinished() {
|
||||
bool DefaultPieceStorage::allDownloadFinished()
|
||||
{
|
||||
return bitfieldMan->isAllBitSet();
|
||||
}
|
||||
|
||||
// not unittested
|
||||
void DefaultPieceStorage::initStorage() {
|
||||
if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) {
|
||||
if(btContext->getFileMode() == BtContext::SINGLE) {
|
||||
DefaultDiskWriterHandle writer = DefaultDiskWriter::createNewDiskWriter(option);
|
||||
DirectDiskAdaptorHandle directDiskAdaptor = new DirectDiskAdaptor();
|
||||
directDiskAdaptor->setDiskWriter(writer);
|
||||
directDiskAdaptor->setTotalLength(btContext->getTotalLength());
|
||||
this->diskAdaptor = directDiskAdaptor;
|
||||
} else {
|
||||
void DefaultPieceStorage::initStorage()
|
||||
{
|
||||
if(downloadContext->getFileMode() == DownloadContext::SINGLE) {
|
||||
logger->debug("Instantiating DirectDiskAdaptor");
|
||||
DiskWriterHandle writer = _diskWriterFactory->newDiskWriter();
|
||||
DirectDiskAdaptorHandle directDiskAdaptor = new DirectDiskAdaptor();
|
||||
directDiskAdaptor->setDiskWriter(writer);
|
||||
directDiskAdaptor->setTotalLength(downloadContext->getTotalLength());
|
||||
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();
|
||||
multiDiskAdaptor->setPieceLength(btContext->getPieceLength());
|
||||
multiDiskAdaptor->setTopDir(btContext->getName());
|
||||
multiDiskAdaptor->setPieceLength(downloadContext->getPieceLength());
|
||||
multiDiskAdaptor->setTopDir(downloadContext->getName());
|
||||
multiDiskAdaptor->setOption(option);
|
||||
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->setFileEntries(btContext->getFileEntries());
|
||||
diskAdaptor->setFileEntries(downloadContext->getFileEntries());
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::setBitfield(const unsigned char* bitfield,
|
||||
int32_t bitfieldLength) {
|
||||
int32_t bitfieldLength)
|
||||
{
|
||||
bitfieldMan->setBitfield(bitfield, bitfieldLength);
|
||||
}
|
||||
|
||||
int32_t DefaultPieceStorage::getBitfieldLength() {
|
||||
int32_t DefaultPieceStorage::getBitfieldLength()
|
||||
{
|
||||
return bitfieldMan->getBitfieldLength();
|
||||
}
|
||||
|
||||
const unsigned char* DefaultPieceStorage::getBitfield() {
|
||||
const unsigned char* DefaultPieceStorage::getBitfield()
|
||||
{
|
||||
return bitfieldMan->getBitfield();
|
||||
}
|
||||
|
||||
@ -389,17 +445,20 @@ DiskAdaptorHandle DefaultPieceStorage::getDiskAdaptor() {
|
||||
return diskAdaptor;
|
||||
}
|
||||
|
||||
int32_t DefaultPieceStorage::getPieceLength(int32_t index) {
|
||||
int32_t DefaultPieceStorage::getPieceLength(int32_t 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);
|
||||
haves.push_front(entry);
|
||||
}
|
||||
|
||||
Integers DefaultPieceStorage::getAdvertisedPieceIndexes(int32_t myCuid,
|
||||
const Time& lastCheckTime) {
|
||||
const Time& lastCheckTime)
|
||||
{
|
||||
Integers indexes;
|
||||
for(Haves::const_iterator itr = haves.begin(); itr != haves.end(); 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 =
|
||||
find_if(haves.begin(), haves.end(), FindElapsedHave(elapsed));
|
||||
if(itr != haves.end()) {
|
||||
@ -444,19 +504,33 @@ void DefaultPieceStorage::markAllPiecesDone()
|
||||
bitfieldMan->setAllBit();
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::checkIntegrity()
|
||||
void DefaultPieceStorage::markPiecesDone(int64_t length)
|
||||
{
|
||||
logger->notice(MSG_VALIDATING_FILE,
|
||||
diskAdaptor->getFilePath().c_str());
|
||||
ChunkChecksumHandle chunkChecksum = new ChunkChecksum("sha1",
|
||||
btContext->getPieceHashes(),
|
||||
btContext->getPieceLength());
|
||||
IteratableChunkChecksumValidatorHandle iv = new IteratableChunkChecksumValidator();
|
||||
iv->setDiskWriter(new DiskAdaptorWriter(diskAdaptor));
|
||||
iv->setBitfield(bitfieldMan);
|
||||
iv->setChunkChecksum(chunkChecksum);
|
||||
|
||||
ChunkChecksumValidator v(iv);
|
||||
v.setFileAllocationMonitor(FileAllocationMonitorFactory::getFactory()->createNewMonitor());
|
||||
v.validate();
|
||||
// TODO implement this
|
||||
abort();
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::markPieceMissing(int32_t index)
|
||||
{
|
||||
bitfieldMan->unsetBit(index);
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::addInFlightPiece(const Pieces& pieces)
|
||||
{
|
||||
copy(pieces.begin(), pieces.end(), back_inserter(usedPieces));
|
||||
}
|
||||
|
||||
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_
|
||||
|
||||
#include "PieceStorage.h"
|
||||
#include "BtContext.h"
|
||||
#include "DiskAdaptor.h"
|
||||
#include "BitfieldMan.h"
|
||||
#include "Logger.h"
|
||||
#include "Option.h"
|
||||
#include "Piece.h"
|
||||
#include "FileAllocator.h"
|
||||
|
||||
class DownloadContext;
|
||||
extern typedef SharedHandle<DownloadContext> DownloadContextHandle;
|
||||
class BitfieldMan;
|
||||
class Logger;
|
||||
class Option;
|
||||
extern typedef deque<PieceHandle> Pieces;
|
||||
class DiskWriterFactory;
|
||||
extern typedef SharedHandle<DiskWriterFactory> DiskWriterFactoryHandle;
|
||||
|
||||
#define END_GAME_PIECE_NUM 20
|
||||
|
||||
@ -67,15 +69,15 @@ typedef deque<HaveEntry> Haves;
|
||||
|
||||
class DefaultPieceStorage : public PieceStorage {
|
||||
private:
|
||||
BtContextHandle btContext;
|
||||
DownloadContextHandle downloadContext;
|
||||
BitfieldMan* bitfieldMan;
|
||||
DiskAdaptorHandle diskAdaptor;
|
||||
DiskWriterFactoryHandle _diskWriterFactory;
|
||||
Pieces usedPieces;
|
||||
int32_t endGamePieceNum;
|
||||
Logger* logger;
|
||||
const Option* option;
|
||||
Haves haves;
|
||||
FileAllocatorHandle createFileAllocator();
|
||||
|
||||
int32_t getMissingPieceIndex(const PeerHandle& peer);
|
||||
int32_t getMissingFastPieceIndex(const PeerHandle& peer);
|
||||
@ -85,7 +87,7 @@ private:
|
||||
void deleteUsedPiece(const PieceHandle& piece);
|
||||
PieceHandle findUsedPiece(int32_t index) const;
|
||||
public:
|
||||
DefaultPieceStorage(BtContextHandle btContext, const Option* option);
|
||||
DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option);
|
||||
virtual ~DefaultPieceStorage();
|
||||
|
||||
virtual bool hasMissingPiece(const PeerHandle& peer);
|
||||
@ -94,6 +96,10 @@ public:
|
||||
|
||||
virtual PieceHandle getMissingFastPiece(const PeerHandle& peer);
|
||||
|
||||
virtual PieceHandle getMissingPiece();
|
||||
|
||||
virtual PieceHandle getMissingPiece(int32_t index);
|
||||
|
||||
virtual PieceHandle getPiece(int32_t index);
|
||||
|
||||
virtual void completePiece(const PieceHandle& piece);
|
||||
@ -102,6 +108,8 @@ public:
|
||||
|
||||
virtual bool hasPiece(int32_t index);
|
||||
|
||||
virtual bool isPieceUsed(int32_t index);
|
||||
|
||||
virtual int64_t getTotalLength();
|
||||
|
||||
virtual int64_t getFilteredTotalLength();
|
||||
@ -156,13 +164,24 @@ public:
|
||||
|
||||
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.
|
||||
*/
|
||||
void addUsedPiece(const PieceHandle& piece);
|
||||
|
||||
void setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory);
|
||||
};
|
||||
|
||||
typedef SharedHandle<DefaultPieceStorage> DefaultPieceStorageHandle;
|
||||
|
||||
#endif // _D_DEFAULT_PIECE_STORAGE_H_
|
||||
|
@ -36,13 +36,14 @@
|
||||
#include "prefs.h"
|
||||
#include "DefaultDiskWriter.h"
|
||||
|
||||
SegmentManHandle DefaultSegmentManFactory::createNewInstance()
|
||||
SegmentManHandle DefaultSegmentManFactory::createNewInstance(const DownloadContextHandle& dctx,
|
||||
const PieceStorageHandle& ps)
|
||||
{
|
||||
SegmentManHandle segmentMan = new SegmentMan();
|
||||
segmentMan->diskWriter = new DefaultDiskWriter();
|
||||
segmentMan->dir = _option->get(PREF_DIR);
|
||||
SegmentManHandle segmentMan = new SegmentMan(_option, dctx, ps);
|
||||
//segmentMan->diskWriter = new DefaultDiskWriter();
|
||||
//segmentMan->dir = _option->get(PREF_DIR);
|
||||
// TODO disable this in multi-simultaneous download mode.
|
||||
//segmentMan->ufilename = _option->get(PREF_OUT);
|
||||
segmentMan->option = _option;
|
||||
//segmentMan->option = _option;
|
||||
return segmentMan;
|
||||
}
|
||||
|
@ -43,7 +43,8 @@ public:
|
||||
|
||||
virtual ~DefaultSegmentManFactory() {}
|
||||
|
||||
virtual SegmentManHandle createNewInstance();
|
||||
virtual SegmentManHandle createNewInstance(const DownloadContextHandle& dc,
|
||||
const PieceStorageHandle& ps);
|
||||
};
|
||||
|
||||
typedef SharedHandle<DefaultSegmentManFactory> DefaultSegmentManFactoryHandle;
|
||||
|
@ -32,6 +32,18 @@
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* 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 --> */
|
||||
#include "DirectDiskAdaptor.h"
|
||||
|
||||
string DirectDiskAdaptor::getFilePath() {
|
||||
string DirectDiskAdaptor::getFilePath()
|
||||
{
|
||||
return storeDir+"/"+fileEntries.front()->getPath();
|
||||
}
|
||||
|
||||
void DirectDiskAdaptor::onDownloadComplete() {
|
||||
void DirectDiskAdaptor::onDownloadComplete()
|
||||
throw(DlAbortEx*)
|
||||
{
|
||||
closeFile();
|
||||
openFile();
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#define _D_DIRECT_DISK_ADAPTOR_H_
|
||||
|
||||
#include "AbstractSingleDiskAdaptor.h"
|
||||
#include "DlAbortEx.h"
|
||||
|
||||
class DirectDiskAdaptor : public AbstractSingleDiskAdaptor {
|
||||
public:
|
||||
@ -44,7 +45,7 @@ public:
|
||||
|
||||
virtual string getFilePath();
|
||||
|
||||
virtual void onDownloadComplete();
|
||||
virtual void onDownloadComplete() throw(DlAbortEx*);
|
||||
};
|
||||
|
||||
typedef SharedHandle<DirectDiskAdaptor> DirectDiskAdaptorHandle;
|
||||
|
@ -33,7 +33,6 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "DiskAdaptor.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include "LogFactory.h"
|
||||
#include "message.h"
|
||||
|
||||
@ -41,7 +40,9 @@ DiskAdaptor::DiskAdaptor():logger(LogFactory::getInstance()) {}
|
||||
|
||||
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();
|
||||
itr != fileEntries.end(); itr++) {
|
||||
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());
|
||||
}
|
||||
|
||||
bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath) {
|
||||
bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath)
|
||||
{
|
||||
for(FileEntries::iterator itr = fileEntries.begin();
|
||||
itr != fileEntries.end(); itr++) {
|
||||
if((*itr)->getPath() == fileEntryPath) {
|
||||
@ -62,7 +64,8 @@ bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DiskAdaptor::addDownloadEntry(int index) {
|
||||
bool DiskAdaptor::addDownloadEntry(int index)
|
||||
{
|
||||
if(fileEntries.size() <= (unsigned int)index) {
|
||||
return false;
|
||||
}
|
||||
@ -70,14 +73,16 @@ bool DiskAdaptor::addDownloadEntry(int index) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void DiskAdaptor::addAllDownloadEntry() {
|
||||
void DiskAdaptor::addAllDownloadEntry()
|
||||
{
|
||||
for(FileEntries::iterator itr = fileEntries.begin();
|
||||
itr != fileEntries.end(); itr++) {
|
||||
(*itr)->setRequested(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DiskAdaptor::removeAllDownloadEntry() {
|
||||
void DiskAdaptor::removeAllDownloadEntry()
|
||||
{
|
||||
for(FileEntries::iterator itr = fileEntries.begin();
|
||||
itr != fileEntries.end(); itr++) {
|
||||
(*itr)->setRequested(false);
|
||||
|
@ -35,11 +35,13 @@
|
||||
#ifndef _D_DISK_ADAPTOR_H_
|
||||
#define _D_DISK_ADAPTOR_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "BinaryStream.h"
|
||||
#include "FileEntry.h"
|
||||
#include "Logger.h"
|
||||
#include "FileAllocationIterator.h"
|
||||
#include "DlAbortEx.h"
|
||||
|
||||
class DiskAdaptor {
|
||||
class DiskAdaptor:public BinaryStream {
|
||||
protected:
|
||||
string storeDir;
|
||||
FileEntries fileEntries;
|
||||
@ -56,10 +58,6 @@ public:
|
||||
|
||||
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 bool fileExists() = 0;
|
||||
@ -68,11 +66,15 @@ public:
|
||||
|
||||
virtual int64_t size() const = 0;
|
||||
|
||||
// optional behavior
|
||||
virtual void truncate(int64_t length) {}
|
||||
|
||||
void setFileEntries(const 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; }
|
||||
|
||||
@ -87,6 +89,8 @@ public:
|
||||
void setStoreDir(const string& storeDir) { this->storeDir = storeDir; }
|
||||
|
||||
const string& getStoreDir() const { return this->storeDir; }
|
||||
|
||||
virtual FileAllocationIteratorHandle fileAllocationIterator() = 0;
|
||||
};
|
||||
|
||||
typedef SharedHandle<DiskAdaptor> DiskAdaptorHandle;
|
||||
|
@ -35,15 +35,14 @@
|
||||
#ifndef _D_DISK_WRITER_H_
|
||||
#define _D_DISK_WRITER_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
using namespace std;
|
||||
#include "BinaryStream.h"
|
||||
#include "DlAbortEx.h"
|
||||
|
||||
/**
|
||||
* Interface for writing to a binary stream of bytes.
|
||||
*
|
||||
*/
|
||||
class DiskWriter {
|
||||
class DiskWriter:public BinaryStream {
|
||||
public:
|
||||
virtual ~DiskWriter() {}
|
||||
/**
|
||||
@ -51,13 +50,14 @@ public:
|
||||
* If the file exists, then it is truncated to 0 length.
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* Closes this output stream.
|
||||
*/
|
||||
// TODO we have to examine the return value of close()
|
||||
virtual void closeFile() = 0;
|
||||
|
||||
/**
|
||||
@ -68,26 +68,6 @@ public:
|
||||
*/
|
||||
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;
|
||||
|
||||
// Returns file length
|
||||
|
@ -32,20 +32,19 @@
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_GLOW_FILE_ALLOCATOR_H_
|
||||
#define _D_GLOW_FILE_ALLOCATOR_H_
|
||||
#ifndef _D_DISK_WRITER_FACTORY_H_
|
||||
#define _D_DISK_WRITER_FACTORY_H_
|
||||
|
||||
#include "FileAllocator.h"
|
||||
#include "common.h"
|
||||
#include "DiskWriter.h"
|
||||
|
||||
class GlowFileAllocator : public FileAllocator {
|
||||
class DiskWriterFactory {
|
||||
public:
|
||||
GlowFileAllocator() {}
|
||||
virtual ~DiskWriterFactory() {}
|
||||
|
||||
virtual ~GlowFileAllocator() {}
|
||||
|
||||
virtual void allocate(int fd, int64_t totalLength);
|
||||
virtual DiskWriterHandle newDiskWriter() = 0;
|
||||
};
|
||||
|
||||
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 --> */
|
||||
#include "DownloadCommand.h"
|
||||
#include "SegmentMan.h"
|
||||
#include "PeerStat.h"
|
||||
#include "TransferEncoding.h"
|
||||
#include "DownloadContext.h"
|
||||
#include "Util.h"
|
||||
#include "DlRetryEx.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include "HttpInitiateConnectionCommand.h"
|
||||
#include "InitiateConnectionCommandFactory.h"
|
||||
#include "message.h"
|
||||
#include "prefs.h"
|
||||
#ifdef ENABLE_MESSAGE_DIGEST
|
||||
# include "ChecksumCommand.h"
|
||||
#endif // ENABLE_MESSAGE_DIGEST
|
||||
#include "DiskAdaptor.h"
|
||||
#include "Segment.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "Option.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
DownloadCommand::DownloadCommand(int cuid,
|
||||
@ -80,17 +84,23 @@ bool DownloadCommand::executeInternal() {
|
||||
socket->readData(buf, bufSize);
|
||||
|
||||
if(transferDecoder.isNull()) {
|
||||
_requestGroup->getSegmentMan()->diskWriter->writeData(buf, bufSize,
|
||||
segment->getPositionToWrite());
|
||||
segment->writtenLength += bufSize;
|
||||
_requestGroup->getPieceStorage()->getDiskAdaptor()->writeData((const unsigned char*)buf, bufSize,
|
||||
segment->getPositionToWrite());
|
||||
//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);
|
||||
} else {
|
||||
int32_t infbufSize = 16*1024;
|
||||
char infbuf[infbufSize];
|
||||
transferDecoder->inflate(infbuf, infbufSize, buf, bufSize);
|
||||
_requestGroup->getSegmentMan()->diskWriter->writeData(infbuf, infbufSize,
|
||||
segment->getPositionToWrite());
|
||||
segment->writtenLength += infbufSize;
|
||||
_requestGroup->getPieceStorage()->getDiskAdaptor()->writeData((const unsigned char*)infbuf, infbufSize,
|
||||
segment->getPositionToWrite());
|
||||
segment->updateWrittenLength(infbufSize);
|
||||
//segment->writtenLength += infbufSize;
|
||||
peerStat->updateDownloadLength(infbufSize);
|
||||
}
|
||||
// calculate downloading speed
|
||||
@ -103,7 +113,7 @@ bool DownloadCommand::executeInternal() {
|
||||
req->getHost().c_str());
|
||||
}
|
||||
}
|
||||
if(_requestGroup->getSegmentMan()->totalSize != 0 && bufSize == 0) {
|
||||
if(_requestGroup->getTotalLength() != 0 && bufSize == 0) {
|
||||
throw new DlRetryEx(EX_GOT_EOF);
|
||||
}
|
||||
if(!transferDecoder.isNull() && transferDecoder->finished()
|
||||
@ -112,11 +122,22 @@ bool DownloadCommand::executeInternal() {
|
||||
if(!transferDecoder.isNull()) transferDecoder->end();
|
||||
logger->info(MSG_SEGMENT_DOWNLOAD_COMPLETED, cuid);
|
||||
_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
|
||||
if(e->option->get(PREF_REALTIME_CHUNK_CHECKSUM) == V_TRUE) {
|
||||
_requestGroup->getSegmentMan()->tryChunkChecksumValidation(segment, _requestGroup->getChunkChecksum());
|
||||
}
|
||||
#endif // ENABLE_MESSAGE_DIGEST
|
||||
*/
|
||||
// this unit is going to download another segment.
|
||||
return prepareForNextSegment();
|
||||
} else {
|
||||
@ -127,7 +148,9 @@ bool DownloadCommand::executeInternal() {
|
||||
}
|
||||
|
||||
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
|
||||
if(!_requestGroup->getChecksum().isNull() &&
|
||||
!_requestGroup->getChecksum()->isEmpty()) {
|
||||
@ -136,6 +159,7 @@ bool DownloadCommand::prepareForNextSegment() {
|
||||
e->commands.push_back(command);
|
||||
}
|
||||
#endif // ENABLE_MESSAGE_DIGEST
|
||||
*/
|
||||
return true;
|
||||
} else {
|
||||
// Merge segment with next segment, if segment.index+1 == nextSegment.index
|
||||
@ -143,15 +167,15 @@ bool DownloadCommand::prepareForNextSegment() {
|
||||
while(1) {
|
||||
SegmentHandle nextSegment =
|
||||
_requestGroup->getSegmentMan()->getSegment(cuid,
|
||||
tempSegment->index+1);
|
||||
tempSegment->getIndex()+1);
|
||||
if(nextSegment.isNull()) {
|
||||
break;
|
||||
} else {
|
||||
if(nextSegment->writtenLength > 0) {
|
||||
if(nextSegment->getWrittenLength() > 0) {
|
||||
return prepareForRetry(0);
|
||||
}
|
||||
nextSegment->writtenLength =
|
||||
tempSegment->writtenLength-tempSegment->length;
|
||||
nextSegment->updateWrittenLength(tempSegment->getOverflowLength());
|
||||
//tempSegment->writtenLength-tempSegment->length;
|
||||
if(nextSegment->complete()) {
|
||||
_requestGroup->getSegmentMan()->completeSegment(cuid, nextSegment);
|
||||
tempSegment = nextSegment;
|
||||
@ -165,3 +189,8 @@ bool DownloadCommand::prepareForNextSegment() {
|
||||
return prepareForRetry(0);
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadCommand::setTransferDecoder(const TransferEncodingHandle& transferDecoder)
|
||||
{
|
||||
this->transferDecoder = transferDecoder;
|
||||
}
|
||||
|
@ -36,11 +36,11 @@
|
||||
#define _D_DOWNLOAD_COMMAND_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 {
|
||||
private:
|
||||
@ -62,10 +62,7 @@ public:
|
||||
const SocketHandle& s);
|
||||
virtual ~DownloadCommand();
|
||||
|
||||
void setTransferDecoder(const TransferEncodingHandle& transferDecoder)
|
||||
{
|
||||
this->transferDecoder = transferDecoder;
|
||||
}
|
||||
void setTransferDecoder(const TransferEncodingHandle& transferDecoder);
|
||||
|
||||
void setMaxDownloadSpeedLimit(int32_t maxDownloadSpeedLimit) {
|
||||
this->maxDownloadSpeedLimit = maxDownloadSpeedLimit;
|
||||
|
99
src/DownloadContext.h
Normal file
99
src/DownloadContext.h
Normal file
@ -0,0 +1,99 @@
|
||||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_DOWNLOAD_CONTEXT_H_
|
||||
#define _D_DOWNLOAD_CONTEXT_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "FileEntry.h"
|
||||
|
||||
class DownloadContext
|
||||
{
|
||||
protected:
|
||||
string _dir;
|
||||
|
||||
public:
|
||||
DownloadContext():_dir(".") {}
|
||||
|
||||
virtual ~DownloadContext() {}
|
||||
|
||||
|
||||
enum FILE_MODE {
|
||||
SINGLE,
|
||||
MULTI
|
||||
};
|
||||
|
||||
virtual string getPieceHash(int32_t index) const = 0;
|
||||
|
||||
virtual const Strings& getPieceHashes() const = 0;
|
||||
|
||||
virtual int64_t getTotalLength() const = 0;
|
||||
|
||||
virtual FILE_MODE getFileMode() const = 0;
|
||||
|
||||
virtual FileEntries getFileEntries() const = 0;
|
||||
|
||||
virtual string getName() const = 0;
|
||||
|
||||
virtual int32_t getPieceLength() const = 0;
|
||||
|
||||
virtual int32_t getNumPieces() const = 0;
|
||||
|
||||
virtual string getPieceHashAlgo() const = 0;
|
||||
|
||||
/**
|
||||
* Returns an actual file path.
|
||||
* If this contains a single file entry, then returns its file path,
|
||||
* for example, "/tmp/downloads/aria2.txt"
|
||||
* If this contains multiple file entries(i,e /tmp/downloads/aria2.txt,
|
||||
* /tmp/downloads/aria2.bin), then returns its base dir path,
|
||||
* for example, "/tmp/downloads"
|
||||
*/
|
||||
virtual string getActualBasePath() const = 0;
|
||||
|
||||
string getDir() const
|
||||
{
|
||||
return _dir;
|
||||
}
|
||||
|
||||
void setDir(const string& dir)
|
||||
{
|
||||
_dir = dir;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef SharedHandle<DownloadContext> DownloadContextHandle;
|
||||
|
||||
#endif // _D_DOWNLOAD_CONTEXT_H_
|
@ -33,6 +33,15 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#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 "LogFactory.h"
|
||||
#include "TimeA2.h"
|
||||
@ -41,11 +50,38 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#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()),
|
||||
_statCalc(0),
|
||||
_haltRequested(false),
|
||||
noWait(false),
|
||||
_requestGroupMan(0),
|
||||
_fileAllocationMan(0)
|
||||
@ -83,7 +119,6 @@ void DownloadEngine::executeCommand(Command::STATUS statusFilter)
|
||||
}
|
||||
|
||||
void DownloadEngine::run() {
|
||||
initStatistics();
|
||||
Time cp;
|
||||
cp.setTimeInSec(0);
|
||||
Commands activeCommands;
|
||||
@ -232,6 +267,38 @@ bool DownloadEngine::deleteSocketForWriteCheck(const SocketHandle& socket,
|
||||
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
|
||||
bool DownloadEngine::addNameResolverCheck(const NameResolverHandle& resolver,
|
||||
Command* command) {
|
||||
@ -262,4 +329,10 @@ bool DownloadEngine::deleteNameResolverCheck(const NameResolverHandle& resolver,
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadEngine::addCommand(const Commands& commands)
|
||||
{
|
||||
this->commands.insert(this->commands.end(), commands.begin(), commands.end());
|
||||
}
|
||||
|
||||
#endif // ENABLE_ASYNC_DNS
|
||||
|
@ -35,20 +35,26 @@
|
||||
#ifndef _D_DOWNLOAD_ENGINE_H_
|
||||
#define _D_DOWNLOAD_ENGINE_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "Socket.h"
|
||||
#include "SegmentMan.h"
|
||||
#include "common.h"
|
||||
#include "Logger.h"
|
||||
#include "Option.h"
|
||||
#include "NameResolver.h"
|
||||
#include "RequestGroupMan.h"
|
||||
#include "FileAllocationMan.h"
|
||||
#ifdef ENABLE_MESSAGE_DIGEST
|
||||
# include "CheckIntegrityMan.h"
|
||||
#endif // ENABLE_MESSAGE_DIGEST
|
||||
#include "Command.h"
|
||||
|
||||
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 {
|
||||
public:
|
||||
@ -63,15 +69,9 @@ public:
|
||||
public:
|
||||
SocketEntry(const SocketHandle& socket,
|
||||
Command* command,
|
||||
TYPE type):
|
||||
socket(socket), command(command), type(type) {}
|
||||
~SocketEntry() {}
|
||||
TYPE type);
|
||||
|
||||
bool operator==(const SocketEntry& entry) {
|
||||
return socket == entry.socket &&
|
||||
command == entry.command &&
|
||||
type == entry.type;
|
||||
}
|
||||
bool operator==(const SocketEntry& entry);
|
||||
};
|
||||
|
||||
typedef deque<SocketEntry> SocketEntries;
|
||||
@ -83,14 +83,9 @@ public:
|
||||
Command* command;
|
||||
public:
|
||||
NameResolverEntry(const NameResolverHandle& nameResolver,
|
||||
Command* command):
|
||||
nameResolver(nameResolver), command(command) {}
|
||||
~NameResolverEntry() {}
|
||||
Command* command);
|
||||
|
||||
bool operator==(const NameResolverEntry& entry) {
|
||||
return nameResolver == entry.nameResolver &&
|
||||
command == entry.command;
|
||||
}
|
||||
bool operator==(const NameResolverEntry& entry);
|
||||
};
|
||||
|
||||
typedef deque<NameResolverEntry> NameResolverEntries;
|
||||
@ -108,16 +103,26 @@ private:
|
||||
fd_set wfdset;
|
||||
int32_t fdmax;
|
||||
|
||||
const Logger* logger;
|
||||
|
||||
StatCalcHandle _statCalc;
|
||||
|
||||
bool _haltRequested;
|
||||
|
||||
void shortSleep() const;
|
||||
bool addSocket(const SocketEntry& socketEntry);
|
||||
bool deleteSocket(const SocketEntry& socketEntry);
|
||||
void executeCommand(Command::STATUS statusFilter);
|
||||
protected:
|
||||
const Logger* logger;
|
||||
virtual void initStatistics() = 0;
|
||||
virtual void calculateStatistics() = 0;
|
||||
virtual void onEndOfRun() = 0;
|
||||
virtual void afterEachIteration() {}
|
||||
|
||||
/**
|
||||
* Delegates to StatCalc
|
||||
*/
|
||||
void calculateStatistics();
|
||||
|
||||
void onEndOfRun();
|
||||
|
||||
void afterEachIteration();
|
||||
|
||||
public:
|
||||
bool noWait;
|
||||
Commands commands;
|
||||
@ -152,11 +157,19 @@ public:
|
||||
Command* command);
|
||||
#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_
|
||||
|
||||
|
@ -33,46 +33,31 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "DownloadEngineFactory.h"
|
||||
#include "prefs.h"
|
||||
#include "DefaultDiskWriter.h"
|
||||
#include "InitiateConnectionCommandFactory.h"
|
||||
#include "Util.h"
|
||||
#include "FileAllocator.h"
|
||||
#include "FileAllocationMonitor.h"
|
||||
#include "FillRequestGroupCommand.h"
|
||||
#include "CUIDCounter.h"
|
||||
#include "FileAllocationDispatcherCommand.h"
|
||||
#include "LogFactory.h"
|
||||
#include "Option.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "DownloadEngine.h"
|
||||
#include "RequestGroupMan.h"
|
||||
#include "FileAllocationMan.h"
|
||||
#include "AutoSaveCommand.h"
|
||||
#ifdef ENABLE_MESSAGE_DIGEST
|
||||
# include "CheckIntegrityMan.h"
|
||||
#endif // ENABLE_MESSAGE_DIGEST
|
||||
#ifdef ENABLE_BITTORRENT
|
||||
# include "PeerListenCommand.h"
|
||||
# include "TrackerWatcherCommand.h"
|
||||
# include "TrackerUpdateCommand.h"
|
||||
# include "TorrentAutoSaveCommand.h"
|
||||
# include "SeedCheckCommand.h"
|
||||
# include "PeerChokeCommand.h"
|
||||
# include "HaveEraseCommand.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
|
||||
#include "prefs.h"
|
||||
#include "Util.h"
|
||||
#include "CUIDCounter.h"
|
||||
#include "FillRequestGroupCommand.h"
|
||||
#include "FileAllocationDispatcherCommand.h"
|
||||
#include "AutoSaveCommand.h"
|
||||
#include "HaveEraseCommand.h"
|
||||
#include "PeerListenCommand.h"
|
||||
|
||||
ConsoleDownloadEngine*
|
||||
DownloadEngineFactory::newConsoleEngine(const Option* op,
|
||||
const RequestGroups& requestGroups)
|
||||
DownloadEngineFactory::DownloadEngineFactory():
|
||||
_logger(LogFactory::getInstance()) {}
|
||||
|
||||
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 reservedSet;
|
||||
if(op->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS) < (int32_t)requestGroups.size()) {
|
||||
@ -83,109 +68,24 @@ DownloadEngineFactory::newConsoleEngine(const Option* op,
|
||||
workingSet = requestGroups;
|
||||
}
|
||||
|
||||
ConsoleDownloadEngine* e = new ConsoleDownloadEngine();
|
||||
DownloadEngineHandle e = new DownloadEngine();
|
||||
e->option = op;
|
||||
RequestGroupManHandle requestGroupMan = new RequestGroupMan(workingSet,
|
||||
op->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS));
|
||||
RequestGroupManHandle requestGroupMan =
|
||||
new RequestGroupMan(workingSet,
|
||||
op->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS));
|
||||
requestGroupMan->addReservedGroup(reservedSet);
|
||||
e->_requestGroupMan = requestGroupMan;
|
||||
e->_fileAllocationMan = new FileAllocationMan();
|
||||
#ifdef ENABLE_MESSAGE_DIGEST
|
||||
e->_checkIntegrityMan = new CheckIntegrityMan();
|
||||
#endif // ENABLE_MESSAGE_DIGEST
|
||||
e->commands.push_back(new FillRequestGroupCommand(CUIDCounterSingletonHolder::instance()->newID(), e, 1));
|
||||
e->commands.push_back(new FileAllocationDispatcherCommand(CUIDCounterSingletonHolder::instance()->newID(), e));
|
||||
e->commands.push_back(new AutoSaveCommand(CUIDCounterSingletonHolder::instance()->newID(), e, op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
|
||||
return e;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
e->commands.push_back(new FillRequestGroupCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get(), 1));
|
||||
e->commands.push_back(new FileAllocationDispatcherCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get()));
|
||||
e->commands.push_back(new AutoSaveCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get(), op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
|
||||
e->commands.push_back(new HaveEraseCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get(), 10));
|
||||
|
||||
PeerListenCommand* listenCommand =
|
||||
new PeerListenCommand(CUIDCounterSingletonHolder::instance()->newID(),
|
||||
te, btContext);
|
||||
new PeerListenCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get());
|
||||
int32_t port;
|
||||
int32_t listenPort = op->getAsInt(PREF_LISTEN_PORT);
|
||||
if(listenPort == -1) {
|
||||
@ -194,48 +94,13 @@ DownloadEngineFactory::newTorrentConsoleEngine(const BtContextHandle& btContext,
|
||||
port = listenCommand->bindPort(listenPort, listenPort);
|
||||
}
|
||||
if(port == -1) {
|
||||
printf(_("Errors occurred while binding port.\n"));
|
||||
exit(EXIT_FAILURE);
|
||||
_logger->error(_("Errors occurred while binding port.\n"));
|
||||
delete listenCommand;
|
||||
} else {
|
||||
op->put(PREF_LISTEN_PORT, Util::itos(port).c_str());
|
||||
e->commands.push_back(listenCommand);
|
||||
}
|
||||
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));
|
||||
//btRuntime->setListenPort(port);
|
||||
|
||||
SharedHandle<UnionSeedCriteria> unionCri = new UnionSeedCriteria();
|
||||
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;
|
||||
return e;
|
||||
}
|
||||
#endif // ENABLE_BITTORRENT
|
||||
|
@ -36,28 +36,23 @@
|
||||
#define _D_DOWNLOAD_ENGINE_FACTORY_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "ConsoleDownloadEngine.h"
|
||||
#ifdef ENABLE_BITTORRENT
|
||||
# include "TorrentConsoleDownloadEngine.h"
|
||||
#endif // ENABLE_BITTORRENT
|
||||
|
||||
class Logger;
|
||||
class Option;
|
||||
class RequestGroup;
|
||||
extern typedef SharedHandle<RequestGroup> RequestGroupHandle;
|
||||
extern typedef deque<RequestGroupHandle> RequestGroups;
|
||||
class DownloadEngine;
|
||||
extern typedef SharedHandle<DownloadEngine> DownloadEngineHandle;
|
||||
|
||||
class DownloadEngineFactory {
|
||||
private:
|
||||
const Logger* _logger;
|
||||
public:
|
||||
static ConsoleDownloadEngine*
|
||||
newConsoleEngine(const Option* op,
|
||||
const RequestGroups& requestGroups);
|
||||
DownloadEngineFactory();
|
||||
|
||||
static ConsoleDownloadEngine*
|
||||
newConsoleEngine(const Option* option,
|
||||
const Requests& requests,
|
||||
const Requests& reserved);
|
||||
|
||||
#ifdef ENABLE_BITTORRENT
|
||||
static TorrentConsoleDownloadEngine*
|
||||
newTorrentConsoleEngine(const BtContextHandle& btContext,
|
||||
const Option* option,
|
||||
const Strings& targetFiles);
|
||||
#endif // ENABLE_BITTORRENT
|
||||
DownloadEngineHandle
|
||||
newDownloadEngine(Option* op, const RequestGroups& requestGroups);
|
||||
};
|
||||
|
||||
#endif // _D_DOWNLOAD_ENGINE_FACTORY_H_
|
||||
|
23
src/File.cc
23
src/File.cc
@ -37,6 +37,11 @@
|
||||
#include "a2io.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() {}
|
||||
@ -140,3 +145,21 @@ bool File::isDir(const string& filename)
|
||||
{
|
||||
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;
|
||||
|
||||
static bool isDir(const string& filename);
|
||||
|
||||
bool renameTo(const string& dest);
|
||||
};
|
||||
|
||||
#endif // _D_FILE_H_
|
||||
|
@ -33,45 +33,48 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "FileAllocationCommand.h"
|
||||
#include "InitiateConnectionCommandFactory.h"
|
||||
#include "FileAllocationMan.h"
|
||||
#include "FileAllocationEntry.h"
|
||||
#include "message.h"
|
||||
#include "DownloadCommand.h"
|
||||
#include "prefs.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()
|
||||
{
|
||||
_fileAllocationEntry->allocateChunk();
|
||||
|
||||
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);
|
||||
}
|
||||
if(_e->isHaltRequested()) {
|
||||
return true;
|
||||
} else {
|
||||
_e->commands.push_back(this);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
_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)
|
||||
{
|
||||
logger->error(MSG_FILE_ALLOCATION_FAILURE, e, cuid);
|
||||
delete e;
|
||||
logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str());
|
||||
return true;
|
||||
}
|
||||
|
@ -37,16 +37,19 @@
|
||||
|
||||
#include "RealtimeCommand.h"
|
||||
#include "TimeA2.h"
|
||||
#include "FileAllocationEntry.h"
|
||||
|
||||
class FileAllocationEntry;
|
||||
extern typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;
|
||||
class Exception;
|
||||
|
||||
class FileAllocationCommand : public RealtimeCommand {
|
||||
private:
|
||||
FileAllocationEntryHandle _fileAllocationEntry;
|
||||
Time _timer;
|
||||
public:
|
||||
FileAllocationCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const FileAllocationEntryHandle& fileAllocationEntry):
|
||||
RealtimeCommand(cuid, requestGroup, e),
|
||||
_fileAllocationEntry(fileAllocationEntry) {}
|
||||
FileAllocationCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const FileAllocationEntryHandle& fileAllocationEntry);
|
||||
|
||||
virtual ~FileAllocationCommand();
|
||||
|
||||
virtual bool executeInternal();
|
||||
|
||||
|
@ -33,22 +33,35 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "FileAllocationDispatcherCommand.h"
|
||||
#include "DownloadEngine.h"
|
||||
#include "RequestGroupMan.h"
|
||||
#include "FileAllocationMan.h"
|
||||
#include "FileAllocationEntry.h"
|
||||
#include "FileAllocationCommand.h"
|
||||
#include "message.h"
|
||||
#include "CUIDCounter.h"
|
||||
|
||||
FileAllocationDispatcherCommand::FileAllocationDispatcherCommand(int32_t cuid, DownloadEngine* e):
|
||||
Command(cuid), _e(e)
|
||||
{
|
||||
setStatusRealtime();
|
||||
}
|
||||
|
||||
FileAllocationDispatcherCommand::~FileAllocationDispatcherCommand() {}
|
||||
|
||||
bool FileAllocationDispatcherCommand::execute()
|
||||
{
|
||||
if(_e->_requestGroupMan->downloadFinished()) {
|
||||
if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!_e->_fileAllocationMan->isFileAllocationBeingExecuted() &&
|
||||
_e->_fileAllocationMan->nextFileAllocationEntryExists()) {
|
||||
FileAllocationEntryHandle entry = _e->_fileAllocationMan->popNextFileAllocationEntry();
|
||||
logger->info(MSG_FILE_ALLOCATION_DISPATCH,
|
||||
entry->getCUID());
|
||||
// TODO we have to change message
|
||||
int32_t newCUID = CUIDCounterSingletonHolder::instance()->newID();
|
||||
logger->info(MSG_FILE_ALLOCATION_DISPATCH, newCUID);
|
||||
FileAllocationCommand* command =
|
||||
new FileAllocationCommand(entry->getCUID(),
|
||||
new FileAllocationCommand(newCUID,
|
||||
entry->getRequestGroup(),
|
||||
_e,
|
||||
entry);
|
||||
|
@ -36,17 +36,16 @@
|
||||
#define _D_FILE_ALLOCATION_DISPATCHER_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "DownloadEngine.h"
|
||||
|
||||
class DownloadEngine;
|
||||
|
||||
class FileAllocationDispatcherCommand : public Command {
|
||||
private:
|
||||
DownloadEngine* _e;
|
||||
public:
|
||||
FileAllocationDispatcherCommand(int cuid, DownloadEngine* e):
|
||||
Command(cuid), _e(e)
|
||||
{
|
||||
setStatusRealtime();
|
||||
}
|
||||
FileAllocationDispatcherCommand(int32_t cuid, DownloadEngine* e);
|
||||
|
||||
virtual ~FileAllocationDispatcherCommand();
|
||||
|
||||
virtual bool execute();
|
||||
};
|
||||
|
@ -33,22 +33,35 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#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()
|
||||
{
|
||||
int32_t bufSize = BUFSIZE;
|
||||
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;
|
||||
}
|
||||
_fileAllocationIterator->allocateChunk();
|
||||
}
|
||||
|
||||
|
@ -37,32 +37,29 @@
|
||||
|
||||
#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:
|
||||
int64_t _offset;
|
||||
FileAllocationIteratorHandle _fileAllocationIterator;
|
||||
public:
|
||||
FileAllocationEntry(int cuid,
|
||||
const RequestHandle& currentRequest,
|
||||
RequestGroup* requestGroup,
|
||||
DownloadCommand* nextDownloadCommand = 0,
|
||||
int64_t offset = 0):
|
||||
RequestGroupEntry(cuid, currentRequest, requestGroup, nextDownloadCommand),
|
||||
_offset(offset)
|
||||
{}
|
||||
FileAllocationEntry(RequestGroup* requestGroup, Command* nextCommand = 0);
|
||||
|
||||
virtual ~FileAllocationEntry() {}
|
||||
~FileAllocationEntry();
|
||||
|
||||
virtual int64_t getCurrentLength() const
|
||||
{
|
||||
return _offset;
|
||||
}
|
||||
virtual int64_t getCurrentLength();
|
||||
|
||||
virtual bool finished() const
|
||||
{
|
||||
return _requestGroup->getTotalLength() <= _offset;
|
||||
}
|
||||
virtual int64_t getTotalLength();
|
||||
|
||||
virtual bool finished();
|
||||
|
||||
void allocateChunk();
|
||||
|
||||
virtual Commands prepareForNextAction(DownloadEngine* e) = 0;
|
||||
};
|
||||
|
||||
typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;
|
||||
|
56
src/FileAllocationIterator.h
Normal file
56
src/FileAllocationIterator.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_FILE_ALLOCATION_ITERATOR_H_
|
||||
#define _D_FILE_ALLOCATION_ITERATOR_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
class FileAllocationIterator
|
||||
{
|
||||
public:
|
||||
virtual ~FileAllocationIterator() {}
|
||||
|
||||
virtual void allocateChunk() = 0;
|
||||
|
||||
virtual bool finished() = 0;
|
||||
|
||||
virtual int64_t getCurrentLength() = 0;
|
||||
|
||||
virtual int64_t getTotalLength() = 0;
|
||||
};
|
||||
|
||||
typedef SharedHandle<FileAllocationIterator> FileAllocationIteratorHandle;
|
||||
|
||||
#endif // _D_FILE_ALLOCATION_ITERATOR_H_
|
@ -32,40 +32,50 @@
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "TorrentConsoleDownloadEngine.h"
|
||||
#include "Util.h"
|
||||
#include <signal.h>
|
||||
#include "FileAllocationMan.h"
|
||||
#include "FileAllocationEntry.h"
|
||||
|
||||
volatile sig_atomic_t btHaltRequested = 0;
|
||||
FileAllocationMan::FileAllocationMan():_currentFileAllocationEntry(0) {}
|
||||
|
||||
TorrentConsoleDownloadEngine::TorrentConsoleDownloadEngine() {}
|
||||
FileAllocationMan::~FileAllocationMan() {}
|
||||
|
||||
TorrentConsoleDownloadEngine::~TorrentConsoleDownloadEngine() {}
|
||||
|
||||
void TorrentConsoleDownloadEngine::sendStatistics() {
|
||||
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);
|
||||
bool FileAllocationMan::isFileAllocationBeingExecuted() const
|
||||
{
|
||||
return _currentFileAllocationEntry.get() != 0;
|
||||
}
|
||||
|
||||
void TorrentConsoleDownloadEngine::afterEachIteration() {
|
||||
if(btHaltRequested) {
|
||||
btRuntime->setHalt(true);
|
||||
}
|
||||
TorrentDownloadEngine::afterEachIteration();
|
||||
FileAllocationEntryHandle FileAllocationMan::getCurrentFileAllocationEntry()
|
||||
{
|
||||
return _currentFileAllocationEntry;
|
||||
}
|
||||
|
||||
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_
|
||||
|
||||
#include "common.h"
|
||||
#include "Request.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "FileAllocationEntry.h"
|
||||
|
||||
class FileAllocationEntry;
|
||||
extern typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;
|
||||
extern typedef deque<FileAllocationEntryHandle> FileAllocationEntries;
|
||||
|
||||
class FileAllocationMan {
|
||||
private:
|
||||
FileAllocationEntries _fileAllocationEntries;
|
||||
FileAllocationEntryHandle _currentFileAllocationEntry;
|
||||
public:
|
||||
FileAllocationMan():_currentFileAllocationEntry(0) {}
|
||||
FileAllocationMan();
|
||||
|
||||
bool isFileAllocationBeingExecuted() const
|
||||
{
|
||||
return _currentFileAllocationEntry.get() != 0;
|
||||
}
|
||||
~FileAllocationMan();
|
||||
|
||||
FileAllocationEntryHandle getCurrentFileAllocationEntry()
|
||||
{
|
||||
return _currentFileAllocationEntry;
|
||||
}
|
||||
bool isFileAllocationBeingExecuted() const;
|
||||
|
||||
void markCurrentFileAllocationEntryDone()
|
||||
{
|
||||
_currentFileAllocationEntry = 0;
|
||||
}
|
||||
FileAllocationEntryHandle getCurrentFileAllocationEntry();
|
||||
|
||||
bool nextFileAllocationEntryExists() const
|
||||
{
|
||||
return !_fileAllocationEntries.empty();
|
||||
}
|
||||
void markCurrentFileAllocationEntryDone();
|
||||
|
||||
FileAllocationEntryHandle popNextFileAllocationEntry()
|
||||
{
|
||||
if(!nextFileAllocationEntryExists()) {
|
||||
return 0;
|
||||
}
|
||||
FileAllocationEntryHandle entry = _fileAllocationEntries.front();
|
||||
_fileAllocationEntries.pop_front();
|
||||
_currentFileAllocationEntry = entry;
|
||||
return entry;
|
||||
}
|
||||
bool nextFileAllocationEntryExists() const;
|
||||
|
||||
void pushFileAllocationEntry(const FileAllocationEntryHandle& entry)
|
||||
{
|
||||
_fileAllocationEntries.push_back(entry);
|
||||
}
|
||||
FileAllocationEntryHandle popNextFileAllocationEntry();
|
||||
|
||||
int32_t countFileAllocationEntryInQueue() const
|
||||
{
|
||||
return _fileAllocationEntries.size();
|
||||
}
|
||||
void pushFileAllocationEntry(const FileAllocationEntryHandle& entry);
|
||||
|
||||
int32_t countFileAllocationEntryInQueue() const;
|
||||
};
|
||||
|
||||
typedef SharedHandle<FileAllocationMan> FileAllocationManHandle;
|
||||
|
@ -45,7 +45,8 @@ FileEntry::FileEntry(const string& path,
|
||||
|
||||
FileEntry::~FileEntry() {}
|
||||
|
||||
void FileEntry::setupDir(const string& parentDir) {
|
||||
void FileEntry::setupDir(const string& parentDir)
|
||||
{
|
||||
string absPath = parentDir+"/"+path;
|
||||
char* temp = strdup(absPath.c_str());
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
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& 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& operator=(const FileEntry& entry);
|
||||
|
||||
string getBasename() const
|
||||
{
|
||||
return File(path).getBasename();
|
||||
|
@ -33,11 +33,33 @@
|
||||
*/
|
||||
/* copyright --> */
|
||||
#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()
|
||||
{
|
||||
_e->_requestGroupMan->fillRequestGroupFromReserver(_e);
|
||||
if(_e->_requestGroupMan->downloadFinished()) {
|
||||
try {
|
||||
_e->_requestGroupMan->fillRequestGroupFromReserver(_e);
|
||||
} catch(DlAbortEx* ex) {
|
||||
logger->error(EX_EXCEPTION_CAUGHT, ex);
|
||||
delete ex;
|
||||
}
|
||||
if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
|
||||
return true;
|
||||
}
|
||||
_e->commands.push_back(this);
|
||||
|
@ -37,8 +37,11 @@
|
||||
|
||||
#include "Command.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 {
|
||||
private:
|
||||
@ -47,13 +50,9 @@ private:
|
||||
int32_t _interval;
|
||||
Time _checkPoint;
|
||||
public:
|
||||
FillRequestGroupCommand(int cuid, DownloadEngine* e, int32_t interval):
|
||||
Command(cuid),
|
||||
_e(e),
|
||||
_interval(interval)
|
||||
{
|
||||
setStatusRealtime();
|
||||
}
|
||||
FillRequestGroupCommand(int32_t cuid, DownloadEngine* e, int32_t interval);
|
||||
|
||||
virtual ~FillRequestGroupCommand();
|
||||
|
||||
virtual bool execute();
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user