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:
Tatsuhiro Tsujikawa 2007-10-11 16:58:24 +00:00
parent e26bbbb9ee
commit 048a2cf597
252 changed files with 8646 additions and 5343 deletions

View File

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

7
TODO
View File

@ -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
View File

@ -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'`\\"

View File

@ -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()

View File

@ -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

View File

@ -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 \

View File

@ -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

View File

@ -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));
}
}

View File

@ -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();

View File

@ -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;

View File

@ -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_

View File

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

View File

@ -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:

View File

@ -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"

View File

@ -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:

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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());

View File

@ -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();

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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
View File

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

View File

@ -32,37 +32,29 @@
* files in the program, then also delete it here.
*/
/* 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;
}

View File

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

View File

@ -35,57 +35,40 @@
#ifndef _D_BT_CONTEXT_H_
#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;
};

View File

@ -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)),

View File

@ -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
View File

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

View File

@ -32,30 +32,33 @@
* files in the program, then also delete it here.
*/
/* 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_

View File

@ -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;
}

View File

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

View File

@ -39,8 +39,8 @@
#include "DlAbortEx.h"
#include "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());
}

View File

@ -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;
}

View File

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

View File

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

View File

@ -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);
}

View File

@ -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) \

View File

@ -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
View File

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

View File

@ -32,20 +32,22 @@
* files in the program, then also delete it here.
*/
/* 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_

View File

@ -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();

View File

@ -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) {}

View File

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

View File

@ -33,6 +33,9 @@
*/
/* copyright --> */
#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;
}

View File

@ -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();

View File

@ -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();
}

View File

@ -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
View File

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

View File

@ -36,43 +36,26 @@
#define _D_CHECK_INTEGRITY_MAN_H_
#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;

View File

@ -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

View File

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

View File

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

View File

@ -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();
*/
}

View File

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

162
src/ConsoleStatCalc.cc Normal file
View File

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

View File

@ -32,20 +32,24 @@
* files in the program, then also delete it here.
*/
/* 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_

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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;

View File

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

View File

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

View File

@ -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;
}

View File

@ -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_

View File

@ -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;
}

View File

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

View File

@ -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_

View File

@ -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();
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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_

View File

@ -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;
}

View File

@ -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
View File

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

View File

@ -33,6 +33,15 @@
*/
/* copyright --> */
#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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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;
}
}

View File

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

View File

@ -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;
}

View File

@ -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();

View File

@ -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);

View File

@ -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();
};

View File

@ -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();
}

View File

@ -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;

View File

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

View File

@ -32,40 +32,50 @@
* files in the program, then also delete it here.
*/
/* 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();
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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();

View File

@ -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);

View File

@ -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