From 3a412f89b24edf25579d3904e85687373eeb2172 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Mon, 8 Jan 2007 00:13:25 +0000 Subject: [PATCH] 2007-01-08 Tatsuhiro Tsujikawa To add an ability to pre-allocate file space: * src/DirectDiskAdaptor.h: Rewritten. * src/PieceStorage.h: DiskAdaptor -> DiskAdaptorHandle * src/MultiDiskAdaptor.h: Rewritten. * src/DefaultPieceStorage.cc (MultiDiskWriter.h): Removed include. (PreAllocationDiskWriter.h): Removed include. (FileAllocationMonitor.h): New include. (~DefaultPieceStorage): Removed deletion of diskAdaptor. (initStorage): Rewritten. (getDiskAdaptor): DiskAdaptor -> DiskAdaptorHandle * src/FileAllocator.h: New class. * src/FileAllocator.cc: New class. * src/FileAllocationMonitor.h: New class. * src/FileAllocationMonitor.cc: New class. * src/ConsoleFileAllocationMonitor.h: New class. * src/ConsoleFileAllocationMonitor.cc: New class. * src/AbstractSingleDiskAdaptor.h: New class. * src/AbstractSingleDiskAdaptor.cc: New class. * src/DiskAdaptor.h (Directory.h): Removed include. (DiskWriter.h): Removed include. (FileEntry.h): Removed include. (diskWriter): Removed. (DiskAdaptor): Removed diskWriter. (openFile): Made pure virtual. (closeFile): Made pure virtual. (openExistingFile): Made pure virtual. (initAndOpenFile): Made pure virtual. (writeData): Made pure virtual. (readData): Made pure virtual. (sha1Sum): Made pure virtual. (getStoreDir): Returns const reference of storeDir. (DiskAdaptorHandle): New type definition. * src/main.cc (ConsoleFileAllocationMonitor.h): New include. (showUsage): Added default value description of -s option. Added the description of --file-allocation option. (main): Set default value of --file-allocation option to 'none'. Added --file-allocation command-line option. Setup FileAllocationMonitorFactory. * src/FtpInitiateConnectionCommand.cc (executeInternal): Removed diskWriter related processing, which was moved to FtpNegotiationCommand.cc. * src/DirectDiskAdaptor.cc (getFilePath): Made non-const. * src/CopyDiskAdaptor.h (DiskAdaptor.h): Removed include. (DiskWriter.h): Removed include. (AbstractSingleDiskAdaptor.h): New include. (getFilePath): Made non-const. Added virtual keyword. (CopyDiskAdaptor): Removed diskWriter. (getTempFile): Returns const reference. (CopyDiskAdaptorHandle): New type definition. * src/ByteArrayDiskWriter.cc (clear): Simplified. (initAndOpenFile): Rewritten. (openFile): Call initAndOpenFile() * src/MultiDiskAdaptor.cc: Rewritten. * src/DownloadEngineFactory.cc (FileAllocator.h): New include. (FileAllocationMonitor.h): New include. (newConsoleEngine): Call DefaultDiskWriter::createNewDiskWriter() to create DefaultDiskWriter with file allocator. * src/DiskWriter.h (initAndOpenFile): Added totalLength argument. (openFile): Added totalLength argument. * src/prefs.h (PREF_FILE_ALLOCATION): New definition. (V_PREALLOC): New definition. (V_NONE): New definition. * src/HttpResponseCommand.cc (handleDefaultEncoding): Call DefaultDiskWriter::initAndOpenFile with size. * src/FtpNegotiateCommand.cc (Util.h): New include. (recvSize): Open file here. * src/Util.h (ullitos): New function. * src/CopyDiskWriter.h (getFilePath): Made non-const. * src/DefaultDiskWriter.h (Option.h): New include. (totalLength): Removed. (DefaultDiskWriter): Removed totalLength. (initAndOpenFile): Added totalLength argument. (DefaultDiskWriterHandle): New type definition. (createNewDiskWriter): New function. * src/Util.cc (ullitos): New function. * src/DefaultDiskWriter.cc (message.h): New include. (FileAllocator.h): New include. (prefs.h): New include. (Util.h): New include. (DefaultDiskWriter): Removed totalLength. (initAndOpenFile): Added file allocation. (createNewDiskWriter): New function. Just for temporary solution. It will be rewritten later. * src/DiskAdaptor.cc (DiskAdaptor): Removed diskWriter. * src/AbstractDiskWriter.cc (LogFactory.h): New include. (AbstractDiskWriter): Added fileAllocator, logger. (openFile): Added totalLength argument. * src/AbstractDiskWriter.h (FileAllocator.h): New include. (Logger.h): New include. (fileAllocator): New variable. (logger): New variable. (openFile): Added totalLength argument. Added virtual keyword explicitly. (openExistingFile): Added totalLength argument. Added virtual keyword explicitly. (closeFile): Added virtual keyword explicitly. (sha1Sum): Added virtual keyword explicitly. (writeData): Added virtual keyword explicitly. (readData): Added virtual keyword explicitly. (setFileAllocator): New function. * src/DefaultPieceStorage.h (FileAllocator.h): New include. (diskAdaptor): DiskAdaptor -> DiskAdaptorHandle (getDiskAdaptor): DiskAdaptor -> DiskAdaptorHandle * src/FileProgressMonitor.h: New class. To compile aria2 on PC-BSD: * src/DefaultBtContext.cc (libgen.h): New include. To fix memory leak: * src/Exception.h (~Exception): Delete cause. Fixed memory leak. --- ChangeLog | 138 ++++++++++++++++++ TODO | 3 - src/AbstractDiskWriter.cc | 65 ++++----- src/AbstractDiskWriter.h | 32 +++-- src/AbstractSingleDiskAdaptor.cc | 63 +++++++++ src/AbstractSingleDiskAdaptor.h | 80 +++++++++++ src/BitfieldMan.cc | 3 +- src/ByteArrayDiskWriter.cc | 25 ++-- src/ByteArrayDiskWriter.h | 14 +- src/ConsoleFileAllocationMonitor.cc | 58 ++++++++ src/ConsoleFileAllocationMonitor.h | 105 ++++++++++++++ src/CopyDiskAdaptor.cc | 6 +- src/CopyDiskAdaptor.h | 17 ++- src/DefaultBtContext.cc | 1 + src/DefaultDiskWriter.cc | 40 +++++- src/DefaultDiskWriter.h | 14 +- src/DefaultPieceStorage.cc | 33 +++-- src/DefaultPieceStorage.h | 6 +- src/DirectDiskAdaptor.cc | 6 +- src/DirectDiskAdaptor.h | 12 +- src/DiskAdaptor.cc | 36 +---- src/DiskAdaptor.h | 39 +++--- src/DiskWriter.h | 19 +-- src/DownloadEngineFactory.cc | 4 +- src/Exception.h | 4 +- src/FileAllocationMonitor.cc | 37 +++++ src/FileAllocationMonitor.h | 67 +++++++++ src/FileAllocator.cc | 69 +++++++++ src/FileAllocator.h | 59 ++++++++ src/FileProgressMonitor.h | 56 ++++++++ src/FtpInitiateConnectionCommand.cc | 11 -- src/FtpNegotiationCommand.cc | 10 ++ src/HttpResponseCommand.cc | 3 +- src/Makefile.am | 10 +- src/Makefile.in | 70 +++++----- src/MultiDiskAdaptor.cc | 169 +++++++++++++++++++++-- src/MultiDiskAdaptor.h | 122 ++++++++++++++-- src/MultiDiskWriter.cc | 14 +- src/MultiDiskWriter.h | 13 +- src/PieceStorage.h | 2 +- src/PreAllocationDiskWriter.cc | 7 +- src/PreAllocationDiskWriter.h | 9 +- src/Util.cc | 4 + src/Util.h | 1 + src/main.cc | 27 +++- src/prefs.h | 4 + test/ConsoleFileAllocationMonitorTest.cc | 38 +++++ test/Makefile.am | 5 +- test/Makefile.in | 13 +- test/MockPieceStorage.h | 8 +- test/MultiDiskAdaptorTest.cc | 156 +++++++++++++++++++++ 51 files changed, 1527 insertions(+), 280 deletions(-) create mode 100644 src/AbstractSingleDiskAdaptor.cc create mode 100644 src/AbstractSingleDiskAdaptor.h create mode 100644 src/ConsoleFileAllocationMonitor.cc create mode 100644 src/ConsoleFileAllocationMonitor.h create mode 100644 src/FileAllocationMonitor.cc create mode 100644 src/FileAllocationMonitor.h create mode 100644 src/FileAllocator.cc create mode 100644 src/FileAllocator.h create mode 100644 src/FileProgressMonitor.h create mode 100644 test/ConsoleFileAllocationMonitorTest.cc create mode 100644 test/MultiDiskAdaptorTest.cc diff --git a/ChangeLog b/ChangeLog index 2c2a26b3..06dc853e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,141 @@ +2007-01-08 Tatsuhiro Tsujikawa + + To add an ability to pre-allocate file space: + + * src/DirectDiskAdaptor.h: Rewritten. + * src/PieceStorage.h: DiskAdaptor -> DiskAdaptorHandle + * src/MultiDiskAdaptor.h: Rewritten. + * src/DefaultPieceStorage.cc + (MultiDiskWriter.h): Removed include. + (PreAllocationDiskWriter.h): Removed include. + (FileAllocationMonitor.h): New include. + (~DefaultPieceStorage): Removed deletion of diskAdaptor. + (initStorage): Rewritten. + (getDiskAdaptor): DiskAdaptor -> DiskAdaptorHandle + * src/FileAllocator.h: New class. + * src/FileAllocator.cc: New class. + * src/FileAllocationMonitor.h: New class. + * src/FileAllocationMonitor.cc: New class. + * src/ConsoleFileAllocationMonitor.h: New class. + * src/ConsoleFileAllocationMonitor.cc: New class. + * src/AbstractSingleDiskAdaptor.h: New class. + * src/AbstractSingleDiskAdaptor.cc: New class. + * src/DiskAdaptor.h + (Directory.h): Removed include. + (DiskWriter.h): Removed include. + (FileEntry.h): Removed include. + (diskWriter): Removed. + (DiskAdaptor): Removed diskWriter. + (openFile): Made pure virtual. + (closeFile): Made pure virtual. + (openExistingFile): Made pure virtual. + (initAndOpenFile): Made pure virtual. + (writeData): Made pure virtual. + (readData): Made pure virtual. + (sha1Sum): Made pure virtual. + (getStoreDir): Returns const reference of storeDir. + (DiskAdaptorHandle): New type definition. + * src/main.cc + (ConsoleFileAllocationMonitor.h): New include. + (showUsage): Added default value description of -s option. + Added the description of --file-allocation option. + (main): Set default value of --file-allocation option to 'none'. + Added --file-allocation command-line option. + Setup FileAllocationMonitorFactory. + * src/FtpInitiateConnectionCommand.cc + (executeInternal): Removed diskWriter related processing, which was + moved to FtpNegotiationCommand.cc. + * src/DirectDiskAdaptor.cc + (getFilePath): Made non-const. + * src/CopyDiskAdaptor.h + (DiskAdaptor.h): Removed include. + (DiskWriter.h): Removed include. + (AbstractSingleDiskAdaptor.h): New include. + (getFilePath): Made non-const. Added virtual keyword. + (CopyDiskAdaptor): Removed diskWriter. + (getTempFile): Returns const reference. + (CopyDiskAdaptorHandle): New type definition. + * src/ByteArrayDiskWriter.cc + (clear): Simplified. + (initAndOpenFile): Rewritten. + (openFile): Call initAndOpenFile() + * src/MultiDiskAdaptor.cc: Rewritten. + * src/DownloadEngineFactory.cc + (FileAllocator.h): New include. + (FileAllocationMonitor.h): New include. + (newConsoleEngine): Call DefaultDiskWriter::createNewDiskWriter() to + create DefaultDiskWriter with file allocator. + * src/DiskWriter.h + (initAndOpenFile): Added totalLength argument. + (openFile): Added totalLength argument. + * src/prefs.h + (PREF_FILE_ALLOCATION): New definition. + (V_PREALLOC): New definition. + (V_NONE): New definition. + * src/HttpResponseCommand.cc + (handleDefaultEncoding): Call DefaultDiskWriter::initAndOpenFile with + size. + * src/FtpNegotiateCommand.cc + (Util.h): New include. + (recvSize): Open file here. + * src/Util.h + (ullitos): New function. + * src/CopyDiskWriter.h + (getFilePath): Made non-const. + * src/DefaultDiskWriter.h + (Option.h): New include. + (totalLength): Removed. + (DefaultDiskWriter): Removed totalLength. + (initAndOpenFile): Added totalLength argument. + (DefaultDiskWriterHandle): New type definition. + (createNewDiskWriter): New function. + * src/Util.cc + (ullitos): New function. + * src/DefaultDiskWriter.cc + (message.h): New include. + (FileAllocator.h): New include. + (prefs.h): New include. + (Util.h): New include. + (DefaultDiskWriter): Removed totalLength. + (initAndOpenFile): Added file allocation. + (createNewDiskWriter): New function. Just for temporary solution. + It will be rewritten later. + * src/DiskAdaptor.cc + (DiskAdaptor): Removed diskWriter. + * src/AbstractDiskWriter.cc + (LogFactory.h): New include. + (AbstractDiskWriter): Added fileAllocator, logger. + (openFile): Added totalLength argument. + * src/AbstractDiskWriter.h + (FileAllocator.h): New include. + (Logger.h): New include. + (fileAllocator): New variable. + (logger): New variable. + (openFile): Added totalLength argument. Added virtual keyword + explicitly. + (openExistingFile): Added totalLength argument. Added virtual keyword + explicitly. + (closeFile): Added virtual keyword explicitly. + (sha1Sum): Added virtual keyword explicitly. + (writeData): Added virtual keyword explicitly. + (readData): Added virtual keyword explicitly. + (setFileAllocator): New function. + * src/DefaultPieceStorage.h + (FileAllocator.h): New include. + (diskAdaptor): DiskAdaptor -> DiskAdaptorHandle + (getDiskAdaptor): DiskAdaptor -> DiskAdaptorHandle + * src/FileProgressMonitor.h: New class. + + To compile aria2 on PC-BSD: + + * src/DefaultBtContext.cc + (libgen.h): New include. + + To fix memory leak: + + * src/Exception.h + (~Exception): Delete cause. Fixed memory leak. + 2006-12-24 Tatsuhiro Tsujikawa Rewritten a portion of bittorrent implementation: diff --git a/TODO b/TODO index 710712ca..50b02c74 100644 --- a/TODO +++ b/TODO @@ -25,8 +25,5 @@ do not start downloading and print some useful message to the user. * Fix Segfaults in BitfieldMan.cc:71 https://sourceforge.net/tracker/index.php?func=detail&aid=1606060&group_id=159897&atid=813673 -* Prevent the file to be fragmented. Use PreAllocationDiskWriter -https://sourceforge.net/tracker/index.php?func=detail&aid=1611886&group_id=159897&atid=813673 -* Add #include to DefaultBtContext.h * int32_t * remove blockIndex diff --git a/src/AbstractDiskWriter.cc b/src/AbstractDiskWriter.cc index 6240dd00..e0d958bf 100644 --- a/src/AbstractDiskWriter.cc +++ b/src/AbstractDiskWriter.cc @@ -37,6 +37,7 @@ #include "File.h" #include "Util.h" #include "message.h" +#include "LogFactory.h" #include #include #include @@ -44,7 +45,9 @@ #include AbstractDiskWriter::AbstractDiskWriter(): - fd(0) + fd(0), + fileAllocator(0), + logger(LogFactory::getInstance()) #ifdef ENABLE_MESSAGE_DIGEST ,ctx(DIGEST_ALGO_SHA1) #endif // ENABLE_MESSAGE_DIGEST @@ -61,12 +64,12 @@ AbstractDiskWriter::~AbstractDiskWriter() { #endif // ENABLE_MESSAGE_DIGEST } -void AbstractDiskWriter::openFile(const string& filename) { +void AbstractDiskWriter::openFile(const string& filename, uint64_t totalLength) { File f(filename); if(f.exists()) { openExistingFile(filename); } else { - initAndOpenFile(filename); + initAndOpenFile(filename, totalLength); } } @@ -89,7 +92,7 @@ void AbstractDiskWriter::openExistingFile(const string& filename) { } } -void AbstractDiskWriter::createFile(const string& filename, int addFlags) { +void AbstractDiskWriter::createFile(const string& filename, int32_t addFlags) { this->filename = filename; // TODO proper filename handling needed assert(filename.size()); @@ -101,63 +104,61 @@ void AbstractDiskWriter::createFile(const string& filename, int addFlags) { } } -void AbstractDiskWriter::writeDataInternal(const char* data, int len) { +void AbstractDiskWriter::writeDataInternal(const char* data, uint32_t len) { if(write(fd, data, len) < 0) { throw new DlAbortEx(EX_FILE_WRITE, filename.c_str(), strerror(errno)); } } -int AbstractDiskWriter::readDataInternal(char* data, int len) { - int ret; +int AbstractDiskWriter::readDataInternal(char* data, uint32_t len) { + int32_t ret; if((ret = read(fd, data, len)) < 0) { throw new DlAbortEx(EX_FILE_READ, filename.c_str(), strerror(errno)); } return ret; } -string AbstractDiskWriter::sha1Sum(long long int offset, long long int length) { +string AbstractDiskWriter::sha1Sum(int64_t offset, uint64_t length) { #ifdef ENABLE_MESSAGE_DIGEST ctx.digestReset(); - try { - int BUFSIZE = 16*1024; - char buf[BUFSIZE]; - for(int i = 0; i < length/BUFSIZE; i++) { - if(BUFSIZE != readData(buf, BUFSIZE, offset)) { - throw string("error"); - } - ctx.digestUpdate(buf, BUFSIZE); - offset += BUFSIZE; + + uint32_t BUFSIZE = 16*1024; + char buf[BUFSIZE]; + for(uint64_t i = 0; i < length/BUFSIZE; i++) { + if((int32_t)BUFSIZE != readData(buf, BUFSIZE, offset)) { + throw new DlAbortEx(EX_FILE_SHA1SUM, filename.c_str(), strerror(errno)); } - int r = length%BUFSIZE; - if(r > 0) { - if(r != readData(buf, r, offset)) { - throw string("error"); - } - ctx.digestUpdate(buf, r); - } - unsigned char hashValue[20]; - ctx.digestFinal(hashValue); - return Util::toHex(hashValue, 20); - } catch(string ex) { - throw new DlAbortEx(EX_FILE_SHA1SUM, filename.c_str(), strerror(errno)); + ctx.digestUpdate(buf, BUFSIZE); + offset += BUFSIZE; } + uint32_t r = length%BUFSIZE; + if(r > 0) { + if((int32_t)r != readData(buf, r, offset)) { + throw new DlAbortEx(EX_FILE_SHA1SUM, filename.c_str(), strerror(errno)); + } + ctx.digestUpdate(buf, r); + } + unsigned char hashValue[20]; + ctx.digestFinal(hashValue); + return Util::toHex(hashValue, 20); #else return ""; #endif // ENABLE_MESSAGE_DIGEST } -void AbstractDiskWriter::seek(long long int offset) { +void AbstractDiskWriter::seek(int64_t offset) { if(offset != lseek(fd, offset, SEEK_SET)) { throw new DlAbortEx(EX_FILE_SEEK, filename.c_str(), strerror(errno)); } } -void AbstractDiskWriter::writeData(const char* data, int len, long long int offset) { +void AbstractDiskWriter::writeData(const char* data, uint32_t len, int64_t offset) { seek(offset); writeDataInternal(data, len); } -int AbstractDiskWriter::readData(char* data, int len, long long int offset) { +int AbstractDiskWriter::readData(char* data, uint32_t len, int64_t offset) { seek(offset); return readDataInternal(data, len); } + diff --git a/src/AbstractDiskWriter.h b/src/AbstractDiskWriter.h index 02104f01..2019bc76 100644 --- a/src/AbstractDiskWriter.h +++ b/src/AbstractDiskWriter.h @@ -39,37 +39,45 @@ #ifdef ENABLE_MESSAGE_DIGEST #include "messageDigest.h" #endif // ENABLE_MESSAGE_DIGEST +#include "FileAllocator.h" +#include "Logger.h" -class AbstractDiskWriter:public DiskWriter { +class AbstractDiskWriter : public DiskWriter { protected: string filename; - int fd; + int32_t fd; + FileAllocatorHandle fileAllocator; + const Logger* logger; #ifdef ENABLE_MESSAGE_DIGEST MessageDigestContext ctx; #endif // ENABLE_MESSAGE_DIGEST - void createFile(const string& filename, int addFlags = 0); + void createFile(const string& filename, int32_t addFlags = 0); - void writeDataInternal(const char* data, int len); - int readDataInternal(char* data, int len); + void writeDataInternal(const char* data, uint32_t len); + int readDataInternal(char* data, uint32_t len); - void seek(long long int offset); + void seek(int64_t offset); public: AbstractDiskWriter(); virtual ~AbstractDiskWriter(); - void openFile(const string& filename); + virtual void openFile(const string& filename, uint64_t totalLength = 0); - void closeFile(); + virtual void closeFile(); - void openExistingFile(const string& filename); + virtual void openExistingFile(const string& filename); - string sha1Sum(long long int offset, long long int length); + virtual string sha1Sum(int64_t offset, uint64_t length); - void writeData(const char* data, int len, long long int offset); + virtual void writeData(const char* data, uint32_t len, int64_t offset); - int readData(char* data, int len, long long int offset); + virtual int readData(char* data, uint32_t len, int64_t offset); + + void setFileAllocator(const FileAllocatorHandle& fileAllocator) { + this->fileAllocator = fileAllocator; + } }; #endif // _D_ABSTRACT_DISK_WRITER_H_ diff --git a/src/AbstractSingleDiskAdaptor.cc b/src/AbstractSingleDiskAdaptor.cc new file mode 100644 index 00000000..5691fdf8 --- /dev/null +++ b/src/AbstractSingleDiskAdaptor.cc @@ -0,0 +1,63 @@ +/* */ +#include "AbstractSingleDiskAdaptor.h" + +void AbstractSingleDiskAdaptor::initAndOpenFile() { + diskWriter->initAndOpenFile(getFilePath(), totalLength); +} + +void AbstractSingleDiskAdaptor::openFile() { + diskWriter->openFile(getFilePath(), totalLength); +} + +void AbstractSingleDiskAdaptor::closeFile() { + diskWriter->closeFile(); +} + +void AbstractSingleDiskAdaptor::openExistingFile() { + diskWriter->openExistingFile(getFilePath()); +} + +void AbstractSingleDiskAdaptor::writeData(const unsigned char* data, uint32_t len, int64_t offset) { + diskWriter->writeData(data, len, offset); +} + +int AbstractSingleDiskAdaptor::readData(unsigned char* data, uint32_t len, int64_t offset) { + return diskWriter->readData(data, len, offset); +} + +string AbstractSingleDiskAdaptor::sha1Sum(int64_t offset, uint64_t length) { + return diskWriter->sha1Sum(offset, length); +} diff --git a/src/AbstractSingleDiskAdaptor.h b/src/AbstractSingleDiskAdaptor.h new file mode 100644 index 00000000..17211c61 --- /dev/null +++ b/src/AbstractSingleDiskAdaptor.h @@ -0,0 +1,80 @@ +/* */ +#ifndef _D_ABSTRACT_SINGLE_DISK_ADAPTOR_H_ +#define _D_ABSTRACT_SINGLE_DISK_ADAPTOR_H_ + +#include "DiskAdaptor.h" +#include "DiskWriter.h" + +class AbstractSingleDiskAdaptor : public DiskAdaptor { +protected: + DiskWriterHandle diskWriter; + uint64_t totalLength; + + virtual string getFilePath() = 0; +public: + AbstractSingleDiskAdaptor():diskWriter(0), totalLength(0) {} + + virtual ~AbstractSingleDiskAdaptor() {} + + virtual void initAndOpenFile(); + + virtual void openFile(); + + virtual void closeFile(); + + virtual void openExistingFile(); + + virtual void writeData(const unsigned char* data, uint32_t len, + int64_t offset); + + virtual int readData(unsigned char* data, uint32_t len, int64_t offset); + + virtual string sha1Sum(int64_t offset, uint64_t length); + + void setDiskWriter(const DiskWriterHandle diskWriter) { + this->diskWriter = diskWriter; + } + + DiskWriterHandle getDiskWriter() const { return diskWriter; } + + void setTotalLength(const uint64_t& totalLength) { + this->totalLength = totalLength; + } + + uint64_t getTotalLength() const { return totalLength; } +}; + +#endif // _D_ABSTRACT_SINGLE_DISK_ADAPTOR_H_ diff --git a/src/BitfieldMan.cc b/src/BitfieldMan.cc index 37365534..64e4dc60 100644 --- a/src/BitfieldMan.cc +++ b/src/BitfieldMan.cc @@ -110,9 +110,10 @@ BitfieldMan::getMissingIndexRandomly(const unsigned char* bitfield, (randomizer->getMaxRandomNumber()+1.0)); unsigned char lastMask = 0; + // the number of bytes in the last byte of bitfield uint32_t lastByteLength = totalLength%(blockLength*8); + // the number of block in the last byte of bitfield uint32_t lastBlockCount = DIV_FLOOR(lastByteLength, blockLength); - // TODO test this for(uint32_t i = 0; i < lastBlockCount; i++) { lastMask >>= 1; lastMask |= 0x80; diff --git a/src/ByteArrayDiskWriter.cc b/src/ByteArrayDiskWriter.cc index e916197d..63236014 100644 --- a/src/ByteArrayDiskWriter.cc +++ b/src/ByteArrayDiskWriter.cc @@ -35,7 +35,7 @@ #include "ByteArrayDiskWriter.h" #include "Util.h" -ByteArrayDiskWriter::ByteArrayDiskWriter():buf(NULL) { +ByteArrayDiskWriter::ByteArrayDiskWriter():buf(0) { } ByteArrayDiskWriter::~ByteArrayDiskWriter() { @@ -43,10 +43,7 @@ ByteArrayDiskWriter::~ByteArrayDiskWriter() { } void ByteArrayDiskWriter::clear() { - if(buf != NULL) { - delete [] buf; - buf = NULL; - } + delete [] buf; } void ByteArrayDiskWriter::init() { @@ -55,15 +52,17 @@ void ByteArrayDiskWriter::init() { bufLength = 0; } -void ByteArrayDiskWriter::initAndOpenFile(const string& filename) { - openFile(filename); -} - -void ByteArrayDiskWriter::openFile(const string& filename) { +void ByteArrayDiskWriter::initAndOpenFile(const string& filename, + uint64_t totalLength) { clear(); init(); } +void ByteArrayDiskWriter::openFile(const string& filename, + uint64_t totalLength) { + initAndOpenFile(filename); +} + void ByteArrayDiskWriter::closeFile() { clear(); } @@ -72,7 +71,7 @@ void ByteArrayDiskWriter::openExistingFile(const string& filename) { openFile(filename); } -void ByteArrayDiskWriter::writeData(const char* data, int dataLength, long long int position) { +void ByteArrayDiskWriter::writeData(const char* data, uint32_t dataLength, int64_t position) { if(bufLength+dataLength >= maxBufLength) { maxBufLength = Util::expandBuffer(&buf, bufLength, bufLength+dataLength); } @@ -80,11 +79,11 @@ void ByteArrayDiskWriter::writeData(const char* data, int dataLength, long long bufLength += dataLength; } -int ByteArrayDiskWriter::readData(char* data, int len, long long int position) { +int ByteArrayDiskWriter::readData(char* data, uint32_t len, int64_t position) { if(position >= bufLength) { return 0; } - int readLength; + uint32_t readLength; if(position+len <= bufLength) { readLength = len; } else { diff --git a/src/ByteArrayDiskWriter.h b/src/ByteArrayDiskWriter.h index d4f6e7d3..4abdd256 100644 --- a/src/ByteArrayDiskWriter.h +++ b/src/ByteArrayDiskWriter.h @@ -40,8 +40,8 @@ class ByteArrayDiskWriter : public DiskWriter { private: char* buf; - int maxBufLength; - int bufLength; + uint32_t maxBufLength; + uint32_t bufLength; void init(); void clear(); @@ -49,19 +49,19 @@ public: ByteArrayDiskWriter(); virtual ~ByteArrayDiskWriter(); - virtual void initAndOpenFile(const string& filename); + virtual void initAndOpenFile(const string& filename, uint64_t totalLength = 0); - virtual void openFile(const string& filename); + virtual void openFile(const string& filename, uint64_t totalLength = 0); virtual void closeFile(); virtual void openExistingFile(const string& filename); // position is ignored - virtual void writeData(const char* data, int len, long long int position = 0); - virtual int readData(char* data, int len, long long int position); + virtual void writeData(const char* data, uint32_t len, int64_t position = 0); + virtual int readData(char* data, uint32_t len, int64_t position); // not implemented yet - virtual string sha1Sum(long long int offset, long long int length) { return ""; } + virtual string sha1Sum(int64_t offset, uint64_t length) { return ""; } const char* getByteArray() const { return buf; diff --git a/src/ConsoleFileAllocationMonitor.cc b/src/ConsoleFileAllocationMonitor.cc new file mode 100644 index 00000000..6db18821 --- /dev/null +++ b/src/ConsoleFileAllocationMonitor.cc @@ -0,0 +1,58 @@ +/* */ +#include "ConsoleFileAllocationMonitor.h" +#include "Util.h" + +void ConsoleFileAllocationMonitor::showProgress() { + uint32_t progressPercentage = (uint32_t)(((current-min)*1.0/(max-min))*100); + uint32_t numOfStar = progressPercentage/10*2; + + cout << "\r "; + cout << "\r"; + cout << "|"; + for(uint32_t i = 0; i < numOfStar; i++) { + cout << "*"; + } + for(uint32_t i = 0; i < 20-numOfStar; i++) { + cout << " "; + } + cout << "|"; + cout << progressPercentage << "%"; + cout << "("; + cout << Util::ullitos(current, true) << "/" << Util::ullitos(max, true); + cout << ") done"; + cout << flush; + // |******************* | 95%(1,333,3256/1,553,3232 bytes) done +} diff --git a/src/ConsoleFileAllocationMonitor.h b/src/ConsoleFileAllocationMonitor.h new file mode 100644 index 00000000..940adeb7 --- /dev/null +++ b/src/ConsoleFileAllocationMonitor.h @@ -0,0 +1,105 @@ +/* */ +#ifndef _D_CONSOLE_FILE_ALLOCATION_MONITOR_H_ +#define _D_CONSOLE_FILE_ALLOCATION_MONITOR_H_ + +#include "FileAllocationMonitor.h" + +class ConsoleFileAllocationMonitor : public FileAllocationMonitor { +private: + string filename; + uint64_t min; + uint64_t max; + uint64_t current; +public: + ConsoleFileAllocationMonitor():min(0), max(0), current(0) {} + + virtual ~ConsoleFileAllocationMonitor() {} + + virtual void setFilename(const string& filename) { + this->filename = filename; + } + + virtual void setMinValue(const uint64_t& min) { + if(max < min) { + this->min = max; + } else { + this->min = min; + } + } + + uint64_t getMinValue() const { + return min; + } + + virtual void setMaxValue(const uint64_t& max) { + if(max < min) { + this->max = min; + } else { + this->max = max; + } + } + + uint64_t getMaxValue() const { + return max; + } + + virtual void setCurrentValue(const uint64_t& current) { + if(current > max) { + this->current = max; + } else { + this->current = current; + } + } + + uint64_t getCurrentValue() const { + return current; + } + + virtual void showProgress(); +}; + +class ConsoleFileAllocationMonitorFactory : public FileAllocationMonitorFactory { +public: + ConsoleFileAllocationMonitorFactory() {} + + virtual FileAllocationMonitorHandle createNewMonitor() { + return new ConsoleFileAllocationMonitor(); + } +}; + +typedef SharedHandle ConsoleFileAllocationMonitorFactoryHandle; + +#endif // _D_CONSOLE_FILE_ALLOCATION_MONITOR_H_ diff --git a/src/CopyDiskAdaptor.cc b/src/CopyDiskAdaptor.cc index f33eb94d..d8bb9e18 100644 --- a/src/CopyDiskAdaptor.cc +++ b/src/CopyDiskAdaptor.cc @@ -35,10 +35,6 @@ #include "CopyDiskAdaptor.h" #include "Util.h" -CopyDiskAdaptor::CopyDiskAdaptor(DiskWriter* diskWriter):DiskAdaptor(diskWriter) {} - -CopyDiskAdaptor::~CopyDiskAdaptor() {} - void CopyDiskAdaptor::onDownloadComplete() { closeFile(); fixFilename(); @@ -62,6 +58,6 @@ void CopyDiskAdaptor::fixFilename() { } } -string CopyDiskAdaptor::getFilePath() const { +string CopyDiskAdaptor::getFilePath() { return storeDir+"/"+tempFilename; } diff --git a/src/CopyDiskAdaptor.h b/src/CopyDiskAdaptor.h index 00b7453b..84acd3c2 100644 --- a/src/CopyDiskAdaptor.h +++ b/src/CopyDiskAdaptor.h @@ -35,20 +35,20 @@ #ifndef _D_COPY_DISK_ADAPTOR_H_ #define _D_COPY_DISK_ADAPTOR_H_ -#include "DiskAdaptor.h" -#include "DiskWriter.h" +#include "AbstractSingleDiskAdaptor.h" -class CopyDiskAdaptor : public DiskAdaptor { +class CopyDiskAdaptor : public AbstractSingleDiskAdaptor { private: string tempFilename; string topDir; void fixFilename(); protected: - string getFilePath() const; + virtual string getFilePath(); public: - CopyDiskAdaptor(DiskWriter* diskWriter); - ~CopyDiskAdaptor(); + CopyDiskAdaptor() {} + + virtual ~CopyDiskAdaptor() {} virtual void onDownloadComplete(); @@ -56,7 +56,8 @@ public: void setTempFilename(const string& tempFilename) { this->tempFilename = tempFilename; } - string getTempFile() const { return this->tempFilename; } + + const string& getTempFile() const { return this->tempFilename; } void setTopDir(const string& topDir) { this->topDir = topDir; @@ -67,4 +68,6 @@ public: } }; +typedef SharedHandle CopyDiskAdaptorHandle; + #endif // _D_COPY_DISK_ADAPTOR_H_ diff --git a/src/DefaultBtContext.cc b/src/DefaultBtContext.cc index 0235f410..f3487ee3 100644 --- a/src/DefaultBtContext.cc +++ b/src/DefaultBtContext.cc @@ -40,6 +40,7 @@ #include "DlAbortEx.h" #include "ShaVisitor.h" #include "Util.h" +#include DefaultBtContext::DefaultBtContext() {} diff --git a/src/DefaultDiskWriter.cc b/src/DefaultDiskWriter.cc index cf127c6f..6301e745 100644 --- a/src/DefaultDiskWriter.cc +++ b/src/DefaultDiskWriter.cc @@ -34,18 +34,46 @@ /* copyright --> */ #include "DefaultDiskWriter.h" #include "DlAbortEx.h" +#include "message.h" +#include "FileAllocator.h" +#include "prefs.h" +#include "Util.h" #include #include -DefaultDiskWriter::DefaultDiskWriter():AbstractDiskWriter(), totalLength(0) {} - -DefaultDiskWriter::DefaultDiskWriter(long long int totalLength):AbstractDiskWriter(), totalLength(totalLength) {} +DefaultDiskWriter::DefaultDiskWriter():AbstractDiskWriter() {} DefaultDiskWriter::~DefaultDiskWriter() {} -void DefaultDiskWriter::initAndOpenFile(const string& filename) { +void DefaultDiskWriter::initAndOpenFile(const string& filename, + uint64_t totalLength) +{ createFile(filename); - if(totalLength > 0) { - ftruncate(fd, totalLength); + try { + if(totalLength > 0) { + if(fileAllocator.isNull()) { + ftruncate(fd, totalLength); + } else { + logger->notice("Allocating file %s, %s bytes", + filename.c_str(), + Util::ullitos(totalLength).c_str()); + fileAllocator->allocate(fd, totalLength); + } + } + } catch(Exception *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) { + FileAllocatorHandle allocator = new FileAllocator(); + allocator->setFileAllocationMonitor(FileAllocationMonitorFactory::getFactory()->createNewMonitor()); + diskWriter->setFileAllocator(allocator); + } else { + diskWriter->setFileAllocator(0); + } + return diskWriter; +} diff --git a/src/DefaultDiskWriter.h b/src/DefaultDiskWriter.h index 008e1d5e..6c160bce 100644 --- a/src/DefaultDiskWriter.h +++ b/src/DefaultDiskWriter.h @@ -36,16 +36,20 @@ #define _D_DEFAULT_DISK_WRITER_H_ #include "AbstractDiskWriter.h" +#include "Option.h" class DefaultDiskWriter:public AbstractDiskWriter { -private: - long long int totalLength; public: DefaultDiskWriter(); - DefaultDiskWriter(long long int totalLength); - ~DefaultDiskWriter(); - void initAndOpenFile(const string& filename); + virtual ~DefaultDiskWriter(); + + virtual void initAndOpenFile(const string& filename, + uint64_t totalLength = 0); + + static DefaultDiskWriter* createNewDiskWriter(const Option* option); }; +typedef SharedHandle DefaultDiskWriterHandle; + #endif // _D_DEFAULT_DISK_WRITER_H_ diff --git a/src/DefaultPieceStorage.cc b/src/DefaultPieceStorage.cc index 58f9d455..3d47759d 100644 --- a/src/DefaultPieceStorage.cc +++ b/src/DefaultPieceStorage.cc @@ -39,10 +39,9 @@ #include "MultiDiskAdaptor.h" #include "CopyDiskAdaptor.h" #include "DefaultDiskWriter.h" -#include "MultiDiskWriter.h" -#include "PreAllocationDiskWriter.h" #include "DlAbortEx.h" #include "BitfieldManFactory.h" +#include "FileAllocationMonitor.h" DefaultPieceStorage::DefaultPieceStorage(BtContextHandle btContext, const Option* option): btContext(btContext), @@ -59,7 +58,6 @@ DefaultPieceStorage::DefaultPieceStorage(BtContextHandle btContext, const Option DefaultPieceStorage::~DefaultPieceStorage() { delete bitfieldMan; - delete diskAdaptor; } bool DefaultPieceStorage::hasMissingPiece(const PeerHandle& peer) { @@ -331,23 +329,30 @@ bool DefaultPieceStorage::downloadFinished() { // not unittested void DefaultPieceStorage::initStorage() { - if(diskAdaptor) { - delete diskAdaptor; - diskAdaptor = 0; - } if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) { if(btContext->getFileMode() == BtContext::SINGLE) { - diskAdaptor = new DirectDiskAdaptor(new DefaultDiskWriter(btContext->getTotalLength())); + DefaultDiskWriterHandle writer = DefaultDiskWriter::createNewDiskWriter(option); + DirectDiskAdaptorHandle directDiskAdaptor = new DirectDiskAdaptor(); + directDiskAdaptor->setDiskWriter(writer); + directDiskAdaptor->setTotalLength(btContext->getTotalLength()); + this->diskAdaptor = directDiskAdaptor; } else { - diskAdaptor = new MultiDiskAdaptor(new MultiDiskWriter(btContext->getPieceLength())); - ((MultiDiskAdaptor*)diskAdaptor)->setTopDir(btContext->getName()); + MultiDiskAdaptorHandle multiDiskAdaptor = new MultiDiskAdaptor(); + multiDiskAdaptor->setPieceLength(btContext->getPieceLength()); + multiDiskAdaptor->setTopDir(btContext->getName()); + multiDiskAdaptor->setOption(option); + this->diskAdaptor = multiDiskAdaptor; } } else { - diskAdaptor = new CopyDiskAdaptor(new PreAllocationDiskWriter(btContext->getTotalLength())); - ((CopyDiskAdaptor*)diskAdaptor)->setTempFilename(btContext->getName()+".a2tmp"); + 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*)diskAdaptor)->setTopDir(btContext->getName()); + copyDiskAdaptor->setTopDir(btContext->getName()); } + this->diskAdaptor = copyDiskAdaptor; } string storeDir = option->get(PREF_DIR); if(storeDir == "") { @@ -370,7 +375,7 @@ const unsigned char* DefaultPieceStorage::getBitfield() { return bitfieldMan->getBitfield(); } -DiskAdaptor* DefaultPieceStorage::getDiskAdaptor() { +DiskAdaptorHandle DefaultPieceStorage::getDiskAdaptor() { return diskAdaptor; } diff --git a/src/DefaultPieceStorage.h b/src/DefaultPieceStorage.h index 4821b899..da68fc80 100644 --- a/src/DefaultPieceStorage.h +++ b/src/DefaultPieceStorage.h @@ -42,6 +42,7 @@ #include "Logger.h" #include "Option.h" #include "Piece.h" +#include "FileAllocator.h" #define END_GAME_PIECE_NUM 20 @@ -68,12 +69,13 @@ class DefaultPieceStorage : public PieceStorage { private: BtContextHandle btContext; BitfieldMan* bitfieldMan; - DiskAdaptor* diskAdaptor; + DiskAdaptorHandle diskAdaptor; Pieces usedPieces; uint32_t endGamePieceNum; Logger* logger; const Option* option; Haves haves; + FileAllocatorHandle createFileAllocator(); int getMissingPieceIndex(const PeerHandle& peer); int getMissingFastPieceIndex(const PeerHandle& peer); @@ -139,7 +141,7 @@ public: virtual bool isEndGame(); - virtual DiskAdaptor* getDiskAdaptor(); + virtual DiskAdaptorHandle getDiskAdaptor(); virtual int getPieceLength(int index); diff --git a/src/DirectDiskAdaptor.cc b/src/DirectDiskAdaptor.cc index 290516e7..46941558 100644 --- a/src/DirectDiskAdaptor.cc +++ b/src/DirectDiskAdaptor.cc @@ -34,11 +34,7 @@ /* copyright --> */ #include "DirectDiskAdaptor.h" -DirectDiskAdaptor::DirectDiskAdaptor(DiskWriter* diskWriter):DiskAdaptor(diskWriter) {} - -DirectDiskAdaptor::~DirectDiskAdaptor() {} - -string DirectDiskAdaptor::getFilePath() const { +string DirectDiskAdaptor::getFilePath() { return storeDir+"/"+fileEntries.front()->getPath(); } diff --git a/src/DirectDiskAdaptor.h b/src/DirectDiskAdaptor.h index fc6788b7..ea4ce849 100644 --- a/src/DirectDiskAdaptor.h +++ b/src/DirectDiskAdaptor.h @@ -35,16 +35,18 @@ #ifndef _D_DIRECT_DISK_ADAPTOR_H_ #define _D_DIRECT_DISK_ADAPTOR_H_ -#include "DiskAdaptor.h" +#include "AbstractSingleDiskAdaptor.h" -class DirectDiskAdaptor : public DiskAdaptor { +class DirectDiskAdaptor : public AbstractSingleDiskAdaptor { protected: - string getFilePath() const; + virtual string getFilePath(); public: - DirectDiskAdaptor(DiskWriter* diskWriter); - virtual ~DirectDiskAdaptor(); + DirectDiskAdaptor() {}; + virtual ~DirectDiskAdaptor() {}; virtual void onDownloadComplete(); }; +typedef SharedHandle DirectDiskAdaptorHandle; + #endif // _D_DIRECT_DISK_ADAPTOR_H_ diff --git a/src/DiskAdaptor.cc b/src/DiskAdaptor.cc index 557a2f65..167628f8 100644 --- a/src/DiskAdaptor.cc +++ b/src/DiskAdaptor.cc @@ -36,41 +36,9 @@ #include "DlAbortEx.h" #include "LogFactory.h" -DiskAdaptor::DiskAdaptor(DiskWriter* diskWriter):diskWriter(diskWriter) { - logger = LogFactory::getInstance(); -} +DiskAdaptor::DiskAdaptor():logger(LogFactory::getInstance()) {} -DiskAdaptor::~DiskAdaptor() { - delete diskWriter; -} - -void DiskAdaptor::openFile() { - diskWriter->openFile(getFilePath()); -} - -void DiskAdaptor::closeFile() { - diskWriter->closeFile(); -} - -void DiskAdaptor::openExistingFile() { - diskWriter->openExistingFile(getFilePath()); -} - -void DiskAdaptor::initAndOpenFile() { - diskWriter->initAndOpenFile(getFilePath()); -} - -void DiskAdaptor::writeData(const unsigned char* data, uint32_t len, int64_t offset) { - diskWriter->writeData(data, len, offset); -} - -int DiskAdaptor::readData(unsigned char* data, uint32_t len, int64_t offset) { - return diskWriter->readData(data, len, offset); -} - -string DiskAdaptor::sha1Sum(int64_t offset, uint64_t length) { - return diskWriter->sha1Sum(offset, length); -} +DiskAdaptor::~DiskAdaptor() {} FileEntryHandle DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) const { for(FileEntries::const_iterator itr = fileEntries.begin(); diff --git a/src/DiskAdaptor.h b/src/DiskAdaptor.h index d0ddac47..2b9182e7 100644 --- a/src/DiskAdaptor.h +++ b/src/DiskAdaptor.h @@ -37,36 +37,30 @@ #include "common.h" #include "FileEntry.h" -#include "Directory.h" -#include "DiskWriter.h" #include "Logger.h" -#include "FileEntry.h" class DiskAdaptor { protected: - DiskWriter* diskWriter; string storeDir; FileEntries fileEntries; const Logger* logger; - virtual string getFilePath() const = 0; public: - DiskAdaptor(DiskWriter* diskWriter); + DiskAdaptor(); virtual ~DiskAdaptor(); - virtual void openFile(); - virtual void closeFile(); - virtual void openExistingFile(); - virtual void initAndOpenFile(); - void writeData(const unsigned char* data, uint32_t len, int64_t offset); - void writeData(const char* data, uint32_t len, int64_t offset) { - writeData((const unsigned char*)data, len, offset); - } - int readData(unsigned char* data, uint32_t len, int64_t offset); - int readData(char* data, uint32_t len, int64_t offset) { - return readData((unsigned char*)data, len, offset); - } + virtual void openFile() = 0; - string sha1Sum(int64_t offset, uint64_t length); + virtual void closeFile() = 0; + + virtual void openExistingFile() = 0; + + virtual void initAndOpenFile() = 0; + + virtual void writeData(const unsigned char* data, uint32_t len, int64_t offset) = 0; + + virtual int readData(unsigned char* data, uint32_t len, int64_t offset) = 0; + + virtual string sha1Sum(int64_t offset, uint64_t length) = 0; virtual void onDownloadComplete() = 0; @@ -79,13 +73,18 @@ public: const FileEntries& getFileEntries() const { return fileEntries; } bool addDownloadEntry(const string& fileEntryPath); + bool addDownloadEntry(int index); + void addAllDownloadEntry(); + void removeAllDownloadEntry(); void setStoreDir(const string& storeDir) { this->storeDir = storeDir; } - string getStoreDir() const { return this->storeDir; } + const string& getStoreDir() const { return this->storeDir; } }; +typedef SharedHandle DiskAdaptorHandle; + #endif // _D_DISK_ADAPTOR_H_ diff --git a/src/DiskWriter.h b/src/DiskWriter.h index 924b2fb0..73d5a9a3 100644 --- a/src/DiskWriter.h +++ b/src/DiskWriter.h @@ -52,9 +52,9 @@ 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) = 0; - - virtual void openFile(const string& filename) = 0; + virtual void initAndOpenFile(const string& filename, uint64_t totalLength = 0) = 0; + + virtual void openFile(const string& filename, uint64_t totalLength = 0) = 0; /** * Closes this output stream. @@ -78,19 +78,20 @@ public: * @param len the number of bytes to write * @param position the offset of this binary stream */ - virtual void writeData(const char* data, int len, long long int position = 0) = 0; - virtual void writeData(const unsigned char* data, int len, long long int position = 0) + virtual void writeData(const char* data, uint32_t len, int64_t position = 0) = 0; + virtual void writeData(const unsigned char* data, uint32_t len, int64_t position = 0) { writeData((const char*)data, len, position); } - virtual int readData(char* data, int len, long long int position) = 0; - virtual int readData(unsigned char* data, int len, long long int position) { + virtual int readData(char* data, uint32_t len, int64_t position) = 0; + virtual int readData(unsigned char* data, uint32_t len, int64_t position) { return readData((char*)data, len, position); } - virtual string sha1Sum(long long int offset, long long int length) = 0; - + virtual string sha1Sum(int64_t offset, uint64_t length) = 0; }; +typedef SharedHandle DiskWriterHandle; + #endif // _D_DISK_WRITER_H_ diff --git a/src/DownloadEngineFactory.cc b/src/DownloadEngineFactory.cc index c688b03c..bdc93733 100644 --- a/src/DownloadEngineFactory.cc +++ b/src/DownloadEngineFactory.cc @@ -38,6 +38,8 @@ #include "InitiateConnectionCommandFactory.h" #include "ByteArrayDiskWriter.h" #include "Util.h" +#include "FileAllocator.h" +#include "FileAllocationMonitor.h" #ifdef ENABLE_BITTORRENT # include "PeerListenCommand.h" # include "TrackerWatcherCommand.h" @@ -63,7 +65,7 @@ DownloadEngineFactory::newConsoleEngine(const Option* op, ConsoleDownloadEngine* e = new ConsoleDownloadEngine(); e->option = op; e->segmentMan = new SegmentMan(); - e->segmentMan->diskWriter = new DefaultDiskWriter(); + e->segmentMan->diskWriter = DefaultDiskWriter::createNewDiskWriter(op); e->segmentMan->dir = op->get(PREF_DIR); e->segmentMan->ufilename = op->get(PREF_OUT); e->segmentMan->option = op; diff --git a/src/Exception.h b/src/Exception.h index 69c16df6..a584fb91 100644 --- a/src/Exception.h +++ b/src/Exception.h @@ -56,7 +56,9 @@ protected: public: Exception(Exception* cause = 0):cause(cause) {} - virtual ~Exception() {} + virtual ~Exception() { + delete cause; + } const string& getMsg() const { return msg; } diff --git a/src/FileAllocationMonitor.cc b/src/FileAllocationMonitor.cc new file mode 100644 index 00000000..7a68df7b --- /dev/null +++ b/src/FileAllocationMonitor.cc @@ -0,0 +1,37 @@ +/* */ +#include "FileAllocationMonitor.h" + +FileAllocationMonitorFactoryHandle FileAllocationMonitorFactory::factory = 0; diff --git a/src/FileAllocationMonitor.h b/src/FileAllocationMonitor.h new file mode 100644 index 00000000..6f09899d --- /dev/null +++ b/src/FileAllocationMonitor.h @@ -0,0 +1,67 @@ +/* */ +#ifndef _D_FILE_ALLOCATION_MONITOR_H_ +#define _D_FILE_ALLOCATION_MONITOR_H_ + +#include "FileProgressMonitor.h" + +typedef FileProgressMonitor FileAllocationMonitor; +typedef SharedHandle FileAllocationMonitorHandle; + +class FileAllocationMonitorFactory; + +typedef SharedHandle FileAllocationMonitorFactoryHandle; + +class FileAllocationMonitorFactory { +private: + static FileAllocationMonitorFactoryHandle factory; + +protected: + FileAllocationMonitorFactory() {} +public: + static FileAllocationMonitorFactoryHandle getFactory() { + return factory; + } + + virtual ~FileAllocationMonitorFactory() {} + + static void setFactory(const FileAllocationMonitorFactoryHandle& factory) { + FileAllocationMonitorFactory::factory = factory; + } + + virtual FileAllocationMonitorHandle createNewMonitor() = 0; +}; + +#endif // _D_FILE_ALLOCATION_MONITOR_H_ diff --git a/src/FileAllocator.cc b/src/FileAllocator.cc new file mode 100644 index 00000000..b76af6a9 --- /dev/null +++ b/src/FileAllocator.cc @@ -0,0 +1,69 @@ + +/* */ +#include "FileAllocator.h" +#include "DlAbortEx.h" +#include "TimeA2.h" +#include +#include +#include + +void FileAllocator::allocate(int fd, uint64_t totalLength) +{ + if(0 != lseek(fd, 0, SEEK_SET)) { + throw new DlAbortEx("Seek failed: %s", strerror(errno)); + } + uint32_t bufSize = 4096; + char buf[4096]; + memset(buf, 0, bufSize); + uint64_t x = (totalLength+bufSize-1)/bufSize; + fileAllocationMonitor->setMinValue(0); + fileAllocationMonitor->setMaxValue(totalLength); + fileAllocationMonitor->setCurrentValue(0); + fileAllocationMonitor->showProgress(); + Time cp; + for(uint64_t i = 0; i < x; i++) { + if(write(fd, buf, bufSize) < 0) { + throw new DlAbortEx("Allocation failed: %s", strerror(errno)); + } + if(cp.elapsedInMillis(500)) { + fileAllocationMonitor->setCurrentValue(x*bufSize); + fileAllocationMonitor->showProgress(); + } + } + fileAllocationMonitor->setCurrentValue(totalLength); + fileAllocationMonitor->showProgress(); + ftruncate(fd, totalLength); +} diff --git a/src/FileAllocator.h b/src/FileAllocator.h new file mode 100644 index 00000000..267160d9 --- /dev/null +++ b/src/FileAllocator.h @@ -0,0 +1,59 @@ +/* */ +#ifndef _D_FILE_ALLOCATOR_H_ +#define _D_FILE_ALLOCATOR_H_ + +#include "common.h" +#include "FileAllocationMonitor.h" + +class FileAllocator { +private: + FileAllocationMonitorHandle fileAllocationMonitor; +public: + FileAllocator():fileAllocationMonitor(0) {} + + ~FileAllocator() {} + + void allocate(int fd, uint64_t totalLength); + + void setFileAllocationMonitor(const FileAllocationMonitorHandle& monitor) + { + this->fileAllocationMonitor = monitor; + } +}; + +typedef SharedHandle FileAllocatorHandle; + +#endif // _D_FILE_ALLOCATOR_H_ diff --git a/src/FileProgressMonitor.h b/src/FileProgressMonitor.h new file mode 100644 index 00000000..72d5bf14 --- /dev/null +++ b/src/FileProgressMonitor.h @@ -0,0 +1,56 @@ +/* */ +#ifndef _D_FILE_PROGRESS_MONITOR_H_ +#define _D_FILE_PROGRESS_MONITOR_H_ + +#include "common.h" + +template +class FileProgressMonitor { +public: + virtual ~FileProgressMonitor() {} + + virtual void setFilename(const string& filename) = 0; + + virtual void setMinValue(const T& min) = 0; + + virtual void setMaxValue(const T& max) = 0; + + virtual void setCurrentValue(const T& current) = 0; + + virtual void showProgress() = 0; +}; + +#endif // _D_FILE_PROGRESS_MONITOR_H_ diff --git a/src/FtpInitiateConnectionCommand.cc b/src/FtpInitiateConnectionCommand.cc index 456c369c..f8a3fcec 100644 --- a/src/FtpInitiateConnectionCommand.cc +++ b/src/FtpInitiateConnectionCommand.cc @@ -74,17 +74,6 @@ bool FtpInitiateConnectionCommand::executeInternal(Segment& segment) { } } #endif // ENABLE_ASYNC_DNS - if(!e->segmentMan->downloadStarted) { - e->segmentMan->filename = Util::urldecode(req->getFile()); - bool segFileExists = e->segmentMan->segmentFileExists(); - if(segFileExists) { - e->segmentMan->load(); - e->segmentMan->diskWriter->openExistingFile(e->segmentMan->getFilePath()); - e->segmentMan->downloadStarted = true; - } else { - e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath()); - } - } Command* command; if(useHttpProxy()) { logger->info(MSG_CONNECTING_TO_SERVER, cuid, diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc index 407aa438..49578887 100644 --- a/src/FtpNegotiationCommand.cc +++ b/src/FtpNegotiationCommand.cc @@ -38,6 +38,7 @@ #include "DlRetryEx.h" #include "message.h" #include "prefs.h" +#include "Util.h" FtpNegotiationCommand::FtpNegotiationCommand(int cuid, const RequestHandle req, DownloadEngine* e, @@ -185,6 +186,15 @@ bool FtpNegotiationCommand::recvSize() { e->segmentMan->totalSize = size; e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE), e->segmentMan->totalSize); + + e->segmentMan->filename = Util::urldecode(req->getFile()); + bool segFileExists = e->segmentMan->segmentFileExists(); + if(segFileExists) { + e->segmentMan->load(); + e->segmentMan->diskWriter->openExistingFile(e->segmentMan->getFilePath()); + } else { + e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath(), size); + } } else if(e->segmentMan->totalSize != size) { throw new DlAbortEx(EX_SIZE_MISMATCH, e->segmentMan->totalSize, size); } diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc index 618cbbbf..f7b6aecc 100644 --- a/src/HttpResponseCommand.cc +++ b/src/HttpResponseCommand.cc @@ -162,7 +162,8 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) { e->segmentMan->totalSize = size; e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE), e->segmentMan->totalSize); - e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath()); + e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath(), + size); return prepareForRetry(0); } } diff --git a/src/Makefile.am b/src/Makefile.am index 99fe0d53..59226b52 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,9 +37,8 @@ SRCS = Socket.h\ TransferEncoding.h\ ChunkedEncoding.cc ChunkedEncoding.h\ DiskWriter.h\ - DefaultDiskWriter.cc DefaultDiskWriter.h\ - PreAllocationDiskWriter.cc PreAllocationDiskWriter.h\ AbstractDiskWriter.cc AbstractDiskWriter.h\ + DefaultDiskWriter.cc DefaultDiskWriter.h\ File.cc File.h\ Option.cc Option.h\ Base64.cc Base64.h\ @@ -59,7 +58,10 @@ SRCS = Socket.h\ BitfieldMan.cc BitfieldMan.h\ BitfieldManFactory.cc BitfieldManFactory.h\ Randomizer.h\ - SimpleRandomizer.cc SimpleRandomizer.h + SimpleRandomizer.cc SimpleRandomizer.h\ + FileAllocator.cc FileAllocator.h\ + FileAllocationMonitor.cc FileAllocationMonitor.h\ + ConsoleFileAllocationMonitor.cc ConsoleFileAllocationMonitor.h # debug_new.cpp if ENABLE_ASYNC_DNS @@ -88,8 +90,8 @@ SRCS += MetaEntry.h\ TorrentAutoSaveCommand.cc TorrentAutoSaveCommand.h\ Directory.cc Directory.h\ TrackerWatcherCommand.cc TrackerWatcherCommand.h\ - MultiDiskWriter.cc MultiDiskWriter.h\ DiskAdaptor.cc DiskAdaptor.h\ + AbstractSingleDiskAdaptor.cc AbstractSingleDiskAdaptor.h\ CopyDiskAdaptor.cc CopyDiskAdaptor.h\ DirectDiskAdaptor.cc DirectDiskAdaptor.h\ MultiDiskAdaptor.cc MultiDiskAdaptor.h\ diff --git a/src/Makefile.in b/src/Makefile.in index d4bea19f..a30bd9ee 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -61,8 +61,8 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_BITTORRENT_TRUE@ TorrentAutoSaveCommand.cc TorrentAutoSaveCommand.h\ @ENABLE_BITTORRENT_TRUE@ Directory.cc Directory.h\ @ENABLE_BITTORRENT_TRUE@ TrackerWatcherCommand.cc TrackerWatcherCommand.h\ -@ENABLE_BITTORRENT_TRUE@ MultiDiskWriter.cc MultiDiskWriter.h\ @ENABLE_BITTORRENT_TRUE@ DiskAdaptor.cc DiskAdaptor.h\ +@ENABLE_BITTORRENT_TRUE@ AbstractSingleDiskAdaptor.cc AbstractSingleDiskAdaptor.h\ @ENABLE_BITTORRENT_TRUE@ CopyDiskAdaptor.cc CopyDiskAdaptor.h\ @ENABLE_BITTORRENT_TRUE@ DirectDiskAdaptor.cc DirectDiskAdaptor.h\ @ENABLE_BITTORRENT_TRUE@ MultiDiskAdaptor.cc MultiDiskAdaptor.h\ @@ -199,9 +199,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ message.h Exception.h DlAbortEx.h DlRetryEx.h Logger.h \ SimpleLogger.cc SimpleLogger.h TransferEncoding.h \ ChunkedEncoding.cc ChunkedEncoding.h DiskWriter.h \ - DefaultDiskWriter.cc DefaultDiskWriter.h \ - PreAllocationDiskWriter.cc PreAllocationDiskWriter.h \ - AbstractDiskWriter.cc AbstractDiskWriter.h File.cc File.h \ + AbstractDiskWriter.cc AbstractDiskWriter.h \ + DefaultDiskWriter.cc DefaultDiskWriter.h File.cc File.h \ Option.cc Option.h Base64.cc Base64.h CookieBox.cc CookieBox.h \ messageDigest.h LogFactory.cc LogFactory.h NullLogger.h \ TimeA2.cc TimeA2.h SharedHandle.h HandleRegistry.h \ @@ -210,12 +209,15 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ UrlRequestInfo.h SpeedCalc.cc SpeedCalc.h PeerStat.h \ BitfieldMan.cc BitfieldMan.h BitfieldManFactory.cc \ BitfieldManFactory.h Randomizer.h SimpleRandomizer.cc \ - SimpleRandomizer.h NameResolver.cc NameResolver.h MetaEntry.h \ - Data.cc Data.h Dictionary.cc Dictionary.h List.cc List.h \ - MetaFileUtil.cc MetaFileUtil.h MetaEntryVisitor.h \ - ShaVisitor.cc ShaVisitor.h PeerConnection.cc PeerConnection.h \ - PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \ - PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \ + SimpleRandomizer.h FileAllocator.cc FileAllocator.h \ + FileAllocationMonitor.cc FileAllocationMonitor.h \ + ConsoleFileAllocationMonitor.cc ConsoleFileAllocationMonitor.h \ + NameResolver.cc NameResolver.h MetaEntry.h Data.cc Data.h \ + Dictionary.cc Dictionary.h List.cc List.h MetaFileUtil.cc \ + MetaFileUtil.h MetaEntryVisitor.h ShaVisitor.cc ShaVisitor.h \ + PeerConnection.cc PeerConnection.h PeerMessageUtil.cc \ + PeerMessageUtil.h PeerAbstractCommand.cc PeerAbstractCommand.h \ + PeerInitiateConnectionCommand.cc \ PeerInitiateConnectionCommand.h PeerInteractionCommand.cc \ PeerInteractionCommand.h Peer.cc Peer.h \ TorrentDownloadEngine.cc TorrentDownloadEngine.h \ @@ -224,11 +226,11 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ RequestSlot.cc RequestSlot.h TorrentAutoSaveCommand.cc \ TorrentAutoSaveCommand.h Directory.cc Directory.h \ TrackerWatcherCommand.cc TrackerWatcherCommand.h \ - MultiDiskWriter.cc MultiDiskWriter.h DiskAdaptor.cc \ - DiskAdaptor.h CopyDiskAdaptor.cc CopyDiskAdaptor.h \ - DirectDiskAdaptor.cc DirectDiskAdaptor.h MultiDiskAdaptor.cc \ - MultiDiskAdaptor.h FileEntry.cc FileEntry.h \ - TrackerUpdateCommand.cc TrackerUpdateCommand.h \ + DiskAdaptor.cc DiskAdaptor.h AbstractSingleDiskAdaptor.cc \ + AbstractSingleDiskAdaptor.h CopyDiskAdaptor.cc \ + CopyDiskAdaptor.h DirectDiskAdaptor.cc DirectDiskAdaptor.h \ + MultiDiskAdaptor.cc MultiDiskAdaptor.h FileEntry.cc \ + FileEntry.h TrackerUpdateCommand.cc TrackerUpdateCommand.h \ ByteArrayDiskWriter.cc ByteArrayDiskWriter.h \ PeerChokeCommand.cc PeerChokeCommand.h HaveEraseCommand.cc \ HaveEraseCommand.h TorrentRequestInfo.cc TorrentRequestInfo.h \ @@ -297,8 +299,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ @ENABLE_BITTORRENT_TRUE@ TorrentAutoSaveCommand.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ Directory.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ TrackerWatcherCommand.$(OBJEXT) \ -@ENABLE_BITTORRENT_TRUE@ MultiDiskWriter.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DiskAdaptor.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ AbstractSingleDiskAdaptor.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ CopyDiskAdaptor.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DirectDiskAdaptor.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ MultiDiskAdaptor.$(OBJEXT) \ @@ -365,15 +367,16 @@ am__objects_4 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ DownloadEngine.$(OBJEXT) ConsoleDownloadEngine.$(OBJEXT) \ Segment.$(OBJEXT) SegmentMan.$(OBJEXT) Util.$(OBJEXT) \ Request.$(OBJEXT) SimpleLogger.$(OBJEXT) \ - ChunkedEncoding.$(OBJEXT) DefaultDiskWriter.$(OBJEXT) \ - PreAllocationDiskWriter.$(OBJEXT) AbstractDiskWriter.$(OBJEXT) \ - File.$(OBJEXT) Option.$(OBJEXT) Base64.$(OBJEXT) \ - CookieBox.$(OBJEXT) LogFactory.$(OBJEXT) TimeA2.$(OBJEXT) \ - FeatureConfig.$(OBJEXT) DownloadEngineFactory.$(OBJEXT) \ - UrlRequestInfo.$(OBJEXT) SpeedCalc.$(OBJEXT) \ - BitfieldMan.$(OBJEXT) BitfieldManFactory.$(OBJEXT) \ - SimpleRandomizer.$(OBJEXT) $(am__objects_1) $(am__objects_2) \ - $(am__objects_3) + ChunkedEncoding.$(OBJEXT) AbstractDiskWriter.$(OBJEXT) \ + DefaultDiskWriter.$(OBJEXT) File.$(OBJEXT) Option.$(OBJEXT) \ + Base64.$(OBJEXT) CookieBox.$(OBJEXT) LogFactory.$(OBJEXT) \ + TimeA2.$(OBJEXT) FeatureConfig.$(OBJEXT) \ + DownloadEngineFactory.$(OBJEXT) UrlRequestInfo.$(OBJEXT) \ + SpeedCalc.$(OBJEXT) BitfieldMan.$(OBJEXT) \ + BitfieldManFactory.$(OBJEXT) SimpleRandomizer.$(OBJEXT) \ + FileAllocator.$(OBJEXT) FileAllocationMonitor.$(OBJEXT) \ + ConsoleFileAllocationMonitor.$(OBJEXT) $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) am_libaria2c_a_OBJECTS = $(am__objects_4) libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" @@ -566,9 +569,8 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \ message.h Exception.h DlAbortEx.h DlRetryEx.h Logger.h \ SimpleLogger.cc SimpleLogger.h TransferEncoding.h \ ChunkedEncoding.cc ChunkedEncoding.h DiskWriter.h \ - DefaultDiskWriter.cc DefaultDiskWriter.h \ - PreAllocationDiskWriter.cc PreAllocationDiskWriter.h \ - AbstractDiskWriter.cc AbstractDiskWriter.h File.cc File.h \ + AbstractDiskWriter.cc AbstractDiskWriter.h \ + DefaultDiskWriter.cc DefaultDiskWriter.h File.cc File.h \ Option.cc Option.h Base64.cc Base64.h CookieBox.cc CookieBox.h \ messageDigest.h LogFactory.cc LogFactory.h NullLogger.h \ TimeA2.cc TimeA2.h SharedHandle.h HandleRegistry.h \ @@ -577,8 +579,10 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \ UrlRequestInfo.h SpeedCalc.cc SpeedCalc.h PeerStat.h \ BitfieldMan.cc BitfieldMan.h BitfieldManFactory.cc \ BitfieldManFactory.h Randomizer.h SimpleRandomizer.cc \ - SimpleRandomizer.h $(am__append_1) $(am__append_2) \ - $(am__append_3) + SimpleRandomizer.h FileAllocator.cc FileAllocator.h \ + FileAllocationMonitor.cc FileAllocationMonitor.h \ + ConsoleFileAllocationMonitor.cc ConsoleFileAllocationMonitor.h \ + $(am__append_1) $(am__append_2) $(am__append_3) noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ @@ -668,6 +672,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/alloca.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbstractCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbstractDiskWriter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbstractSingleDiskAdaptor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AnnounceList.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Base64.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldMan.Po@am__quote@ @@ -696,6 +701,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Command.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompactPeerListProcessor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConsoleDownloadEngine.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConsoleFileAllocationMonitor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBox.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CopyDiskAdaptor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Data.Po@am__quote@ @@ -721,6 +727,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngineFactory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfig.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/File.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileAllocationMonitor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileAllocator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileEntry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpConnection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpDownloadCommand.Po@am__quote@ @@ -746,7 +754,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkResource.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Metalinker.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultiDiskAdaptor.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultiDiskWriter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NameResolver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Option.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Peer.Po@am__quote@ @@ -758,7 +765,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerListenCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerMessageUtil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Piece.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PreAllocationDiskWriter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Request.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestSlot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SeedCheckCommand.Po@am__quote@ diff --git a/src/MultiDiskAdaptor.cc b/src/MultiDiskAdaptor.cc index 3efed1f6..8293e9b4 100644 --- a/src/MultiDiskAdaptor.cc +++ b/src/MultiDiskAdaptor.cc @@ -33,44 +33,185 @@ */ /* copyright --> */ #include "MultiDiskAdaptor.h" +#include "DefaultDiskWriter.h" +#include "DlAbortEx.h" +#include "message.h" +#include "Util.h" +#include -MultiDiskAdaptor::MultiDiskAdaptor(MultiDiskWriter* diskWriter):DiskAdaptor(diskWriter) {} - -MultiDiskAdaptor::~MultiDiskAdaptor() {} - -void MultiDiskAdaptor::setDiskWriterFileEntries() { - ((MultiDiskWriter*)diskWriter)->setFileEntries(fileEntries); +void MultiDiskAdaptor::resetDiskWriterEntries() { + diskWriterEntries.clear(); + for(FileEntries::const_iterator itr = fileEntries.begin(); + itr != fileEntries.end(); itr++) { + DiskWriterEntryHandle entry = new DiskWriterEntry(*itr); + if((*itr)->isRequested()) { + entry->setDiskWriter(DefaultDiskWriter::createNewDiskWriter(option)); + } else { + entry->setDiskWriter(new DefaultDiskWriter()); + } + diskWriterEntries.push_back(entry); + } } -string MultiDiskAdaptor::getFilePath() const { +string MultiDiskAdaptor::getTopDirPath() const { return storeDir+"/"+topDir; } void MultiDiskAdaptor::mkdir() const { for(FileEntries::const_iterator itr = fileEntries.begin(); itr != fileEntries.end(); itr++) { - (*itr)->setupDir(getFilePath()); + (*itr)->setupDir(getTopDirPath()); } } void MultiDiskAdaptor::openFile() { mkdir(); - setDiskWriterFileEntries(); - DiskAdaptor::openFile(); + resetDiskWriterEntries(); + for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); + itr != diskWriterEntries.end(); itr++) { + (*itr)->openFile(getTopDirPath()); + } } void MultiDiskAdaptor::initAndOpenFile() { mkdir(); - setDiskWriterFileEntries(); - DiskAdaptor::initAndOpenFile(); + resetDiskWriterEntries(); + for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); + itr != diskWriterEntries.end(); itr++) { + (*itr)->initAndOpenFile(getTopDirPath()); + } } void MultiDiskAdaptor::openExistingFile() { - setDiskWriterFileEntries(); - DiskAdaptor::openExistingFile(); + resetDiskWriterEntries(); + for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); + itr != diskWriterEntries.end(); itr++) { + (*itr)->openExistingFile(getTopDirPath()); + } +} + +void MultiDiskAdaptor::closeFile() { + for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); + itr != diskWriterEntries.end(); itr++) { + (*itr)->closeFile(); + } } void MultiDiskAdaptor::onDownloadComplete() { closeFile(); openFile(); } + +void MultiDiskAdaptor::writeData(const unsigned char* data, uint32_t len, + int64_t offset) +{ + int64_t fileOffset = offset; + bool writing = false; + uint32_t rem = len; + for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); + itr != diskWriterEntries.end() && rem != 0; itr++) { + if(isInRange(*itr, offset) || writing) { + uint32_t writeLength = calculateLength(*itr, fileOffset, rem); + (*itr)->getDiskWriter()->writeData(data+(len-rem), writeLength, fileOffset); + rem -= writeLength; + writing = true; + fileOffset = 0; + } else { + fileOffset -= (*itr)->fileEntry->getLength(); + } + } + if(!writing) { + throw new DlAbortEx(EX_FILE_OFFSET_OUT_OF_RANGE, offset); + } +} + +bool MultiDiskAdaptor::isInRange(const DiskWriterEntryHandle entry, + int64_t offset) const +{ + return entry->fileEntry->getOffset() <= offset && + offset < entry->fileEntry->getOffset()+entry->fileEntry->getLength(); +} + +uint32_t MultiDiskAdaptor::calculateLength(const DiskWriterEntryHandle entry, + int64_t fileOffset, + uint32_t rem) const +{ + uint32_t length; + if(entry->fileEntry->getLength() < fileOffset+rem) { + length = entry->fileEntry->getLength()-fileOffset; + } else { + length = rem; + } + return length; +} + +int MultiDiskAdaptor::readData(unsigned char* data, uint32_t len, int64_t offset) +{ + int64_t fileOffset = offset; + bool reading = false; + uint32_t rem = len; + uint32_t totalReadLength = 0; + for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); + itr != diskWriterEntries.end() && rem != 0; itr++) { + if(isInRange(*itr, offset) || reading) { + uint32_t readLength = calculateLength((*itr), fileOffset, rem); + totalReadLength += (*itr)->getDiskWriter()->readData(data+(len-rem), readLength, fileOffset); + rem -= readLength; + reading = true; + fileOffset = 0; + } else { + fileOffset -= (*itr)->fileEntry->getLength(); + } + } + if(!reading) { + throw new DlAbortEx(EX_FILE_OFFSET_OUT_OF_RANGE, offset); + } + return totalReadLength; +} + +void MultiDiskAdaptor::hashUpdate(const DiskWriterEntryHandle entry, + int64_t offset, uint64_t length) +{ + uint32_t BUFSIZE = 16*1024; + unsigned char buf[BUFSIZE]; + for(uint64_t i = 0; i < length/BUFSIZE; i++) { + if((int32_t)BUFSIZE != entry->getDiskWriter()->readData(buf, BUFSIZE, offset)) { + throw new DlAbortEx(EX_FILE_SHA1SUM, "", strerror(errno)); + } + ctx.digestUpdate(buf, BUFSIZE); + offset += BUFSIZE; + } + uint32_t r = length%BUFSIZE; + if(r > 0) { + if((int32_t)r != entry->getDiskWriter()->readData(buf, r, offset)) { + throw new DlAbortEx(EX_FILE_SHA1SUM, "", strerror(errno)); + } + ctx.digestUpdate(buf, r); + } +} + +string MultiDiskAdaptor::sha1Sum(int64_t offset, uint64_t length) { + int64_t fileOffset = offset; + bool reading = false; + uint32_t rem = length; + ctx.digestReset(); + + for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); + itr != diskWriterEntries.end() && rem != 0; itr++) { + if(isInRange(*itr, offset) || reading) { + uint32_t readLength = calculateLength((*itr), fileOffset, rem); + hashUpdate(*itr, fileOffset, readLength); + rem -= readLength; + reading = true; + fileOffset = 0; + } else { + fileOffset -= (*itr)->fileEntry->getLength(); + } + } + if(!reading) { + throw new DlAbortEx(EX_FILE_OFFSET_OUT_OF_RANGE, offset); + } + unsigned char hashValue[20]; + ctx.digestFinal(hashValue); + return Util::toHex(hashValue, 20); +} diff --git a/src/MultiDiskAdaptor.h b/src/MultiDiskAdaptor.h index 5c556126..e33a840d 100644 --- a/src/MultiDiskAdaptor.h +++ b/src/MultiDiskAdaptor.h @@ -36,19 +36,108 @@ #define _D_MULTI_DISK_ADAPTOR_H_ #include "DiskAdaptor.h" -#include "MultiDiskWriter.h" +#include "Option.h" +#include "DiskWriter.h" +#include "messageDigest.h" + +class DiskWriterEntry { +public: + FileEntryHandle fileEntry; +private: + DiskWriterHandle diskWriter; +public: + DiskWriterEntry(const FileEntryHandle& fileEntry): + fileEntry(fileEntry), + diskWriter(0) {} + + ~DiskWriterEntry() {} + + string getFilePath(const string& topDir) const + { + return topDir+"/"+fileEntry->getPath(); + } + + void initAndOpenFile(const string& topDir) + { + diskWriter->initAndOpenFile(getFilePath(topDir), fileEntry->getLength()); + } + + void openFile(const string& topDir) + { + diskWriter->openFile(getFilePath(topDir), fileEntry->getLength()); + } + + void openExistingFile(const string& topDir) + { + diskWriter->openExistingFile(getFilePath(topDir)); + } + + void closeFile() + { + diskWriter->closeFile(); + } + + void setDiskWriter(const DiskWriterHandle& diskWriter) { + this->diskWriter = diskWriter; + } + + DiskWriterHandle getDiskWriter() const { + return diskWriter; + } +}; + +typedef SharedHandle DiskWriterEntryHandle; + +typedef deque DiskWriterEntries; class MultiDiskAdaptor : public DiskAdaptor { private: string topDir; + uint32_t pieceLength; + MessageDigestContext ctx; + DiskWriterEntries diskWriterEntries; + const Option* option; + + void resetDiskWriterEntries(); - void setDiskWriterFileEntries(); void mkdir() const; -protected: - virtual string getFilePath() const; + + bool isInRange(const DiskWriterEntryHandle entry, int64_t offset) const; + + uint32_t calculateLength(const DiskWriterEntryHandle entry, + int64_t fileOffset, + uint32_t rem) const; + + void hashUpdate(const DiskWriterEntryHandle entry, + int64_t offset, uint64_t length); + + string getTopDirPath() const; public: - MultiDiskAdaptor(MultiDiskWriter* diskWriter); - virtual ~MultiDiskAdaptor(); + MultiDiskAdaptor():pieceLength(0), + ctx(DIGEST_ALGO_SHA1), + option(0) + { + ctx.digestInit(); + } + + virtual ~MultiDiskAdaptor() {} + + virtual void initAndOpenFile(); + + virtual void openFile(); + + virtual void openExistingFile(); + + virtual void closeFile(); + + virtual void onDownloadComplete(); + + virtual void writeData(const unsigned char* data, uint32_t len, + int64_t offset); + + virtual int readData(unsigned char* data, uint32_t len, int64_t offset); + + virtual string sha1Sum(int64_t offset, uint64_t length); void setTopDir(const string& topDir) { this->topDir = topDir; @@ -58,10 +147,23 @@ public: return topDir; } - virtual void openFile(); - virtual void initAndOpenFile(); - virtual void openExistingFile(); - virtual void onDownloadComplete(); + void setPieceLength(uint32_t pieceLength) { + this->pieceLength = pieceLength; + } + + uint32_t getPieceLength() const { + return pieceLength; + } + + void setOption(const Option* option) { + this->option = option; + } + + const Option* getOption() const { + return option; + } }; +typedef SharedHandle MultiDiskAdaptorHandle; + #endif // _D_MULTI_DISK_ADAPTOR_H_ diff --git a/src/MultiDiskWriter.cc b/src/MultiDiskWriter.cc index b231d564..ff3b03ae 100644 --- a/src/MultiDiskWriter.cc +++ b/src/MultiDiskWriter.cc @@ -40,7 +40,8 @@ MultiDiskWriter::MultiDiskWriter(int pieceLength): pieceLength(pieceLength), - ctx(DIGEST_ALGO_SHA1) { + ctx(DIGEST_ALGO_SHA1), + fileAllocator(0) { ctx.digestInit(); } @@ -65,9 +66,18 @@ void MultiDiskWriter::setFileEntries(const FileEntries& fileEntries) { } } +void MultiDiskWriter::configureFileAllocator(DiskWriterEntry* entry) { + if(entry->fileEntry->isRequested()) { + entry->diskWriter->setFileAllocator(fileAllocator); + } else { + entry->diskWriter->setFileAllocator(0); + } +} + void MultiDiskWriter::openFile(const string& filename) { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); itr++) { + configureFileAllocator(*itr); (*itr)->diskWriter->openFile(filename+"/"+(*itr)->fileEntry->getPath()); } } @@ -76,6 +86,7 @@ void MultiDiskWriter::openFile(const string& filename) { void MultiDiskWriter::initAndOpenFile(const string& filename) { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); itr++) { + configureFileAllocator(*itr); (*itr)->diskWriter->initAndOpenFile(filename+"/"+(*itr)->fileEntry->getPath()); } } @@ -90,6 +101,7 @@ void MultiDiskWriter::closeFile() { void MultiDiskWriter::openExistingFile(const string& filename) { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); itr++) { + (*itr)->diskWriter->setFileAllocator(0); (*itr)->diskWriter->openExistingFile(filename+"/"+(*itr)->fileEntry->getPath()); } } diff --git a/src/MultiDiskWriter.h b/src/MultiDiskWriter.h index c7e5d26c..6fa229a2 100644 --- a/src/MultiDiskWriter.h +++ b/src/MultiDiskWriter.h @@ -38,11 +38,12 @@ #include "DefaultDiskWriter.h" #include "messageDigest.h" #include "FileEntry.h" +#include "FileAllocator.h" class DiskWriterEntry { public: FileEntryHandle fileEntry; - DiskWriter* diskWriter; + DefaultDiskWriter* diskWriter; public: DiskWriterEntry(const FileEntryHandle& fileEntry):fileEntry(fileEntry) { diskWriter = new DefaultDiskWriter(this->fileEntry->getLength()); @@ -58,12 +59,14 @@ class MultiDiskWriter : public DiskWriter { private: DiskWriterEntries diskWriterEntries; int pieceLength; + MessageDigestContext ctx; + FileAllocatorHandle fileAllocator; + bool isInRange(const DiskWriterEntry* entry, long long int offset) const; int calculateLength(const DiskWriterEntry* entry, long long int fileOffset, int rem) const; void clearEntries(); - MessageDigestContext ctx; void hashUpdate(DiskWriterEntry* entry, long long int offset, long long int length); - + void configureFileAllocator(DiskWriterEntry* entry); public: MultiDiskWriter(int pieceLength); virtual ~MultiDiskWriter(); @@ -77,6 +80,10 @@ public: virtual void writeData(const char* data, int len, long long int position = 0); virtual int readData(char* data, int len, long long int position); virtual string sha1Sum(long long int offset, long long int length); + + void setFileAllocator(const FileAllocatorHandle& fileAllocator) { + this->fileAllocator = fileAllocator; + } }; #endif // _D_MULTI_DISK_WRITER_H_ diff --git a/src/PieceStorage.h b/src/PieceStorage.h index 892ffa8e..c53f3aa8 100644 --- a/src/PieceStorage.h +++ b/src/PieceStorage.h @@ -123,7 +123,7 @@ public: virtual bool isEndGame() = 0; - virtual DiskAdaptor* getDiskAdaptor() = 0; + virtual DiskAdaptorHandle getDiskAdaptor() = 0; virtual int getPieceLength(int index) = 0; diff --git a/src/PreAllocationDiskWriter.cc b/src/PreAllocationDiskWriter.cc index 461adee3..c8ea198b 100644 --- a/src/PreAllocationDiskWriter.cc +++ b/src/PreAllocationDiskWriter.cc @@ -42,12 +42,13 @@ #include #include -PreAllocationDiskWriter::PreAllocationDiskWriter(long long int totalLength) - :AbstractDiskWriter(),totalLength(totalLength) {} +PreAllocationDiskWriter::PreAllocationDiskWriter(uint64_t totalLength) + :AbstractDiskWriter(totalLength) {} PreAllocationDiskWriter::~PreAllocationDiskWriter() {} -void PreAllocationDiskWriter::initAndOpenFile(const string& filename) { +void PreAllocationDiskWriter::initAndOpenFile(const string& filename) +{ createFile(filename); int bufSize = 4096; char buf[4096]; diff --git a/src/PreAllocationDiskWriter.h b/src/PreAllocationDiskWriter.h index 08c5a2e5..e7554e3c 100644 --- a/src/PreAllocationDiskWriter.h +++ b/src/PreAllocationDiskWriter.h @@ -38,13 +38,12 @@ #include "AbstractDiskWriter.h" class PreAllocationDiskWriter:public AbstractDiskWriter { -private: - long long int totalLength; public: - PreAllocationDiskWriter(long long int totalLength); - ~PreAllocationDiskWriter(); + PreAllocationDiskWriter(uint64_t totalLength); - void initAndOpenFile(const string& filename); + virtual ~PreAllocationDiskWriter(); + + virtual void initAndOpenFile(const string& filename); }; #endif // _D_PRE_ALLOCATION_DISK_WRITER_H_ diff --git a/src/Util.cc b/src/Util.cc index 86d1e80e..9da2c5fc 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -101,6 +101,10 @@ string Util::itos(int32_t value, bool comma) { return int2str(value, comma); } +string Util::ullitos(uint64_t value, bool comma) { + return uint2str(value, comma); +} + string Util::llitos(int64_t value, bool comma) { return int2str(value, comma); diff --git a/src/Util.h b/src/Util.h index e6369c54..630b1b52 100644 --- a/src/Util.h +++ b/src/Util.h @@ -53,6 +53,7 @@ class Util { public: static void split(pair& hp, const string& src, char delim); static string llitos(int64_t value, bool comma = false); + static string ullitos(uint64_t value, bool comma = false); static string itos(int32_t value, bool comma = false); static string uitos(uint32_t value, bool comma = false); static string itos(int16_t value, bool comma = false); diff --git a/src/main.cc b/src/main.cc index 610f6dd6..b41ab8a9 100644 --- a/src/main.cc +++ b/src/main.cc @@ -47,6 +47,7 @@ #include "TorrentRequestInfo.h" #include "BitfieldManFactory.h" #include "SimpleRandomizer.h" +#include "ConsoleFileAllocationMonitor.h" #include #include #include @@ -119,7 +120,8 @@ void showUsage() { cout << _(" -s, --split=N Download a file using N connections. N must be\n" " between 1 and 5. This option affects all URLs.\n" " Thus, aria2 connects to each URL with\n" - " N connections.") << endl; + " N connections.\n" + " Default: 1") << endl; cout << _(" --retry-wait=SEC Set amount of time in second between requests\n" " for errors. Specify a value between 0 and 60.\n" " Default: 5") << endl; @@ -167,6 +169,13 @@ void showUsage() { " 0 means unrestricted.\n" " You can append K or M(1K = 1024, 1M = 1024K).\n" " Default: 0") << endl; + cout << _(" --file-allocation=METHOD Specify file allocation method. METHOD is either\n" + " 'none' or 'prealloc'.\n" + " 'none' doesn't pre-allocate file space. 'prealloc'\n" + " pre-allocates file space before download begins.\n" + " This may take some time depending on the size of\n" + " file.\n" + " Default: 'none'") << endl; #ifdef ENABLE_BITTORRENT cout << _(" -T, --torrent-file=TORRENT_FILE The file path to .torrent file.") << endl; cout << _(" --follow-torrent=true|false Setting this option to false prevents aria2 to\n" @@ -327,6 +336,7 @@ int main(int argc, char* argv[]) { op->put(PREF_MAX_UPLOAD_LIMIT, "0"); op->put(PREF_STARTUP_IDLE_TIME, "10"); op->put(PREF_TRACKER_MAX_TRIES, "10"); + op->put(PREF_FILE_ALLOCATION, V_NONE); while(1) { int optIndex = 0; int lopt; @@ -355,6 +365,7 @@ int main(int argc, char* argv[]) { { "http-proxy-method", required_argument, &lopt, 14 }, { "lowest-speed-limit", required_argument, &lopt, 200 }, { "max-download-limit", required_argument, &lopt, 201 }, + { "file-allocation", required_argument, 0, 'a' }, #ifdef ENABLE_BITTORRENT { "torrent-file", required_argument, NULL, 'T' }, { "listen-port", required_argument, &lopt, 15 }, @@ -382,7 +393,7 @@ int main(int argc, char* argv[]) { { "help", no_argument, NULL, 'h' }, { 0, 0, 0, 0 } }; - c = getopt_long(argc, argv, "Dd:o:l:s:pt:m:vhST:M:C:", longOpts, &optIndex); + c = getopt_long(argc, argv, "Dd:o:l:s:pt:m:vhST:M:C:a:", longOpts, &optIndex); if(c == -1) { break; } @@ -677,6 +688,17 @@ int main(int argc, char* argv[]) { op->put(PREF_METALINK_SERVERS, Util::itos(metalinkServers)); break; } + case 'a': { + string value = string(optarg); + if(value == V_NONE || value == V_PREALLOC) { + op->put(PREF_FILE_ALLOCATION, value); + } else { + cerr << _("file-allocation must be either 'none' or 'prealloc'.") << endl; + showUsage(); + exit(EXIT_FAILURE); + } + break; + } case 'v': showVersion(); exit(EXIT_SUCCESS); @@ -716,6 +738,7 @@ int main(int argc, char* argv[]) { #endif // ENABLE_METALINK SimpleRandomizer::init(); BitfieldManFactory::setDefaultRandomizer(SimpleRandomizer::getInstance()); + FileAllocationMonitorFactory::setFactory(new ConsoleFileAllocationMonitorFactory()); if(op->getAsBool(PREF_STDOUT_LOG)) { LogFactory::setLogFile("/dev/stdout"); } else if(op->get(PREF_LOG).size()) { diff --git a/src/prefs.h b/src/prefs.h index 6a0c05fe..35bdfcad 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -42,6 +42,7 @@ */ #define V_TRUE "true" #define V_FALSE "false" +#define V_NONE "none" /** * General preferences @@ -80,6 +81,9 @@ #define PREF_MAX_DOWNLOAD_LIMIT "max_download_limit" // value: 1*digit #define PREF_STARTUP_IDLE_TIME "startup_idle_time" +// value: prealloc | none +#define PREF_FILE_ALLOCATION "file_allocation" +# define V_PREALLOC "prealloc" /** * FTP related preferences diff --git a/test/ConsoleFileAllocationMonitorTest.cc b/test/ConsoleFileAllocationMonitorTest.cc new file mode 100644 index 00000000..cef4e6b9 --- /dev/null +++ b/test/ConsoleFileAllocationMonitorTest.cc @@ -0,0 +1,38 @@ +#include "ConsoleFileAllocationMonitor.h" +#include +#include + +using namespace std; + +class ConsoleFileAllocationMonitorTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(ConsoleFileAllocationMonitorTest); + CPPUNIT_TEST(testShowProgress); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testShowProgress(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION( ConsoleFileAllocationMonitorTest ); + +void ConsoleFileAllocationMonitorTest::testShowProgress() { + ConsoleFileAllocationMonitor monitor; + monitor.setMinValue(0); + monitor.setMaxValue(1000000000); + monitor.setCurrentValue(0); + + cout << endl; + for(uint64_t i = monitor.getMinValue(); i <= monitor.getMaxValue(); i += 1234343) { + monitor.setCurrentValue(i); + monitor.showProgress(); + usleep(5); + } + monitor.setCurrentValue(monitor.getMaxValue()); + monitor.showProgress(); +} diff --git a/test/Makefile.am b/test/Makefile.am index 7c458631..22570cda 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -15,7 +15,7 @@ aria2c_SOURCES = AllTest.cc\ ShaVisitorTest.cc\ PeerMessageUtilTest.cc\ DefaultDiskWriterTest.cc\ - MultiDiskWriterTest.cc\ + MultiDiskAdaptorTest.cc\ BitfieldManTest.cc\ Xml2MetalinkProcessorTest.cc\ MetalinkerTest.cc\ @@ -57,7 +57,8 @@ aria2c_SOURCES = AllTest.cc\ MockBtMessageDispatcher.h\ FixedNumberRandomizer.h\ MockBtMessageFactory.h\ - MockBtMessage.h + MockBtMessage.h\ + ConsoleFileAllocationMonitorTest.cc #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64 #aria2c_LDFLAGS = ${CPPUNIT_LIBS} diff --git a/test/Makefile.in b/test/Makefile.in index ef459e53..649dee7e 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -64,7 +64,7 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) RequestTest.$(OBJEXT) \ DictionaryTest.$(OBJEXT) ListTest.$(OBJEXT) \ MetaFileUtilTest.$(OBJEXT) ShaVisitorTest.$(OBJEXT) \ PeerMessageUtilTest.$(OBJEXT) DefaultDiskWriterTest.$(OBJEXT) \ - MultiDiskWriterTest.$(OBJEXT) BitfieldManTest.$(OBJEXT) \ + MultiDiskAdaptorTest.$(OBJEXT) BitfieldManTest.$(OBJEXT) \ Xml2MetalinkProcessorTest.$(OBJEXT) MetalinkerTest.$(OBJEXT) \ MetalinkEntryTest.$(OBJEXT) FeatureConfigTest.$(OBJEXT) \ ShareRatioSeedCriteriaTest.$(OBJEXT) \ @@ -88,7 +88,8 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) RequestTest.$(OBJEXT) \ BtRejectMessageTest.$(OBJEXT) BtRequestMessageTest.$(OBJEXT) \ BtSuggestPieceMessageTest.$(OBJEXT) \ BtUnchokeMessageTest.$(OBJEXT) \ - BtHandshakeMessageTest.$(OBJEXT) + BtHandshakeMessageTest.$(OBJEXT) \ + ConsoleFileAllocationMonitorTest.$(OBJEXT) aria2c_OBJECTS = $(am_aria2c_OBJECTS) am__DEPENDENCIES_1 = aria2c_DEPENDENCIES = ../src/libaria2c.a $(am__DEPENDENCIES_1) @@ -267,7 +268,7 @@ aria2c_SOURCES = AllTest.cc\ ShaVisitorTest.cc\ PeerMessageUtilTest.cc\ DefaultDiskWriterTest.cc\ - MultiDiskWriterTest.cc\ + MultiDiskAdaptorTest.cc\ BitfieldManTest.cc\ Xml2MetalinkProcessorTest.cc\ MetalinkerTest.cc\ @@ -309,7 +310,8 @@ aria2c_SOURCES = AllTest.cc\ MockBtMessageDispatcher.h\ FixedNumberRandomizer.h\ MockBtMessageFactory.h\ - MockBtMessage.h + MockBtMessage.h\ + ConsoleFileAllocationMonitorTest.cc #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64 #aria2c_LDFLAGS = ${CPPUNIT_LIBS} @@ -395,6 +397,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtSuggestPieceMessageTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtUnchokeMessageTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChunkedEncodingTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConsoleFileAllocationMonitorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBoxTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DataTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtAnnounceTest.Po@am__quote@ @@ -412,7 +415,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetaFileUtilTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkEntryTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkerTest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultiDiskWriterTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultiDiskAdaptorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OptionTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerMessageUtilTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerTest.Po@am__quote@ diff --git a/test/MockPieceStorage.h b/test/MockPieceStorage.h index 7c8f341d..76929d3a 100644 --- a/test/MockPieceStorage.h +++ b/test/MockPieceStorage.h @@ -13,10 +13,10 @@ private: BitfieldMan* bitfieldMan; bool selectiveDownloadingMode; bool endGame; - DiskAdaptor* diskAdaptor; + DiskAdaptorHandle diskAdaptor; Integers pieceLengthList; public: - MockPieceStorage() {} + MockPieceStorage():diskAdaptor(0) {} virtual ~MockPieceStorage() {} virtual bool hasMissingPiece(const PeerHandle& peer) { @@ -122,11 +122,11 @@ public: this->endGame = flag; } - virtual DiskAdaptor* getDiskAdaptor() { + virtual DiskAdaptorHandle getDiskAdaptor() { return diskAdaptor; } - void setDiskAdaptor(DiskAdaptor* adaptor) { + void setDiskAdaptor(const DiskAdaptorHandle adaptor) { this->diskAdaptor = adaptor; } diff --git a/test/MultiDiskAdaptorTest.cc b/test/MultiDiskAdaptorTest.cc new file mode 100644 index 00000000..5f9437f7 --- /dev/null +++ b/test/MultiDiskAdaptorTest.cc @@ -0,0 +1,156 @@ +#include "MultiDiskAdaptor.h" +#include +#include + +using namespace std; + +class MultiDiskAdaptorTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(MultiDiskAdaptorTest); + CPPUNIT_TEST(testWriteData); + CPPUNIT_TEST(testReadData); + CPPUNIT_TEST(testSha1Sum); + CPPUNIT_TEST_SUITE_END(); +private: + Option* option; + MultiDiskAdaptorHandle adaptor; +public: + MultiDiskAdaptorTest():option(0), adaptor(0) {} + + void setUp() { + delete option; + option = new Option(); + + adaptor = new MultiDiskAdaptor(); + adaptor->setPieceLength(2); + adaptor->setOption(new Option()); + adaptor->setStoreDir("."); + adaptor->setTopDir("."); + } + + void testWriteData(); + void testReadData(); + void testSha1Sum(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION( MultiDiskAdaptorTest ); + +FileEntries createEntries() { + FileEntryHandle entry1(new FileEntry("file1.txt", 15, 0)); + FileEntryHandle entry2(new FileEntry("file2.txt", 7, 15)); + FileEntryHandle entry3(new FileEntry("file3.txt", 3, 22)); + unlink("file1.txt"); + unlink("file2.txt"); + unlink("file3.txt"); + FileEntries entries; + entries.push_back(entry1); + entries.push_back(entry2); + entries.push_back(entry3); + return entries; +} + +void readFile(const string& filename, char* buf, int bufLength) { + FILE* f = fopen(filename.c_str(), "r"); + if(f == NULL) { + abort(); + } + int retval = fread(buf, bufLength, 1, f); + fclose(f); + if(retval != 1) { + abort(); + } +} + +void MultiDiskAdaptorTest::testWriteData() { + try { + adaptor->setFileEntries(createEntries()); + + adaptor->openFile(); + string msg = "12345"; + adaptor->writeData((const unsigned char*)msg.c_str(), msg.size(), 0); + adaptor->closeFile(); + + char buf[128]; + readFile("file1.txt", buf, 5); + buf[5] = '\0'; + CPPUNIT_ASSERT_EQUAL(msg, string(buf)); + + adaptor->openFile(); + string msg2 = "67890ABCDEF"; + adaptor->writeData((const unsigned char*)msg2.c_str(), msg2.size(), 5); + adaptor->closeFile(); + + readFile("file1.txt", buf, 15); + buf[15] = '\0'; + CPPUNIT_ASSERT_EQUAL(string("1234567890ABCDE"), string(buf)); + readFile("file2.txt", buf, 1); + buf[1] = '\0'; + CPPUNIT_ASSERT_EQUAL(string("F"), string(buf)); + + adaptor->openFile(); + string msg3 = "12345123456712"; + adaptor->writeData((const unsigned char*)msg3.c_str(), msg3.size(), 10); + adaptor->closeFile(); + + readFile("file1.txt", buf, 15); + buf[15] = '\0'; + CPPUNIT_ASSERT_EQUAL(string("123456789012345"), string(buf)); + readFile("file2.txt", buf, 7); + buf[7] = '\0'; + CPPUNIT_ASSERT_EQUAL(string("1234567"), string(buf)); + readFile("file3.txt", buf, 2); + buf[2] = '\0'; + CPPUNIT_ASSERT_EQUAL(string("12"), string(buf)); + } catch(Exception* e) { + CPPUNIT_FAIL(e->getMsg()); + } +} + +void MultiDiskAdaptorTest::testReadData() { + FileEntryHandle entry1(new FileEntry("file1r.txt", 15, 0)); + FileEntryHandle entry2(new FileEntry("file2r.txt", 7, 15)); + FileEntryHandle entry3(new FileEntry("file3r.txt", 3, 22)); + FileEntries entries; + entries.push_back(entry1); + entries.push_back(entry2); + entries.push_back(entry3); + + adaptor->setFileEntries(entries); + + adaptor->openFile(); + unsigned char buf[128]; + adaptor->readData(buf, 15, 0); + buf[15] = '\0'; + CPPUNIT_ASSERT_EQUAL(string("1234567890ABCDE"), string((char*)buf)); + adaptor->readData(buf, 10, 6); + buf[10] = '\0'; + CPPUNIT_ASSERT_EQUAL(string("7890ABCDEF"), string((char*)buf)); + adaptor->readData(buf, 4, 20); + buf[4] = '\0'; + CPPUNIT_ASSERT_EQUAL(string("KLMN"), string((char*)buf)); + adaptor->readData(buf, 25, 0); + buf[25] = '\0'; + CPPUNIT_ASSERT_EQUAL(string("1234567890ABCDEFGHIJKLMNO"), string((char*)buf)); +} + +void MultiDiskAdaptorTest::testSha1Sum() { + FileEntryHandle entry1(new FileEntry("file1r.txt", 15, 0)); + FileEntryHandle entry2(new FileEntry("file2r.txt", 7, 15)); + FileEntryHandle entry3(new FileEntry("file3r.txt", 3, 22)); + FileEntries entries; + entries.push_back(entry1); + entries.push_back(entry2); + entries.push_back(entry3); + + adaptor->setFileEntries(entries); + + adaptor->openFile(); + string sha1sum = adaptor->sha1Sum(0, 25); + CPPUNIT_ASSERT_EQUAL(string("76495faf71ca63df66dce99547d2c58da7266d9e"), sha1sum); + sha1sum = adaptor->sha1Sum(15, 7); + CPPUNIT_ASSERT_EQUAL(string("737660d816fb23c2d5bc74f62d9b01b852b2aaca"), sha1sum); + sha1sum = adaptor->sha1Sum(10, 14); + CPPUNIT_ASSERT_EQUAL(string("6238bf61dd8df8f77156b2378e9e39cd3939680c"), sha1sum); + adaptor->closeFile(); +}