From 2a84b9de43c759fb93aa7a0bb2d22d4b5f37af4e Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 16 Apr 2006 14:38:19 +0000 Subject: [PATCH] 2006-04-16 Tatsuhiro Tsujikawa * src/TorrentConsoleDownloadEngine.cc (onPartialDownloadingCompletes): Renamed as onSelectiveDownloadingCompletes. (onSelectiveDownloadingCompletes): Updated message. To add DiskAdaptor which abstract DiskWriter family: * src/PeerConnection.cc: Use diskAdaptor instead of diskWriter. * src/PeerInteractionCommand.cc: Use diskAdaptor instead of diskWriter. * src/BitfieldMan.cc (isAllBitSet): bug fix. * src/TorrentMan.cc : Included CopyDiskAdaptor.h, DirectDiskAdaptor.h, MultiDiskAdaptor.h. (readFileEntry): Changed its arguments. (setup): setupDiskWriter is merged into this function. (setupDiskWriter): Removed. (setFileFilter): New function. (readFileEntryFromMetaInfoFile): Updated according to the changes made in readFileEntry. (getFilePath): Removed. (getTempFilePath): Removed. (getSegmentFilePath): Updated due to the removal of getFilePath. (fixFilename): Removed. (copySingleFile): Removed. (splitMultiFile): Removed. (deleteTempFile): Removed. (setFileEntriesToDownload): Removed. (isPartialDownloadingMode): Renamed as isSelectiveDownloadingMode. (isSelectiveDownloadingMode): New function. (setAllMultiFileRequestedState): Removed. (finishPartialDownloadingMode): Renamed as finishSelectiveDownloadingMode. (finishSelectiveDownloadingMode): New function. (getPartialTotalLength): Renamed as getSelectedTotalLength. (getSelectedTotalLength): New function. (onDownloadComplete): Use diskAdaptor. * src/MultiDiskWriter.cc (Constructor): Added the argument pieceLength (Range): Removed. (setMultiFileEntries): Renamed as setFileEntries. (setFileEntries): New function. * src/MultiDiskWriter.h [DiskWriterEntry](enabled): Removed. (pieceLength): New variable. * src/main.cc (printDownloadCompeleteMessage): New function. (torrentHandler): Use diskAdaptor instead of diskWriter. (main): Renamed torrent-show-files to show-files. Rewritten file contents listing. * src/TorrentMan.h (FileEntry): Removed. (multiFileTopDir): Removed. (multiFileEntries): Removed. (diskWriter): Removed. (diskAdaptor): New variable. * src/DefaultDiskWriter.h (totalLength): New variable. * src/DefaultDiskWriter.cc (initAndOpenFile): Added ftruncate. * src/TorrentDownloadEngine.cc (onEndOfRun): Use diskAdaptor instead of diskWriter. * src/TorrentConsoleDownloadEngine.h (partialDownloadLengthDiff): Renamed as selectedDownloadLengthDiff. (partialTotalLength): Renamed as selectedTotalLength. * src/AbstractDiskWriter.cc (openFile): If file exists, call openExistingFile, otherwise call initAndOpenFile. (closeFile): fd > 0, not fd != 0. * src/prefs.h (PREF_TORRENT_SHOW_FILES): Renamed as PREF_SHOW_FILES (PREF_SHOW_FILES): New definition. --- ChangeLog | 68 +++++++++ TODO | 12 +- src/AbstractDiskWriter.cc | 13 +- src/BitfieldMan.cc | 2 +- src/DefaultDiskWriter.cc | 7 +- src/DefaultDiskWriter.h | 3 + src/FileEntry.h | 42 ++++++ src/Makefile.am | 7 +- src/Makefile.in | 15 +- src/MultiDiskWriter.cc | 70 ++------- src/MultiDiskWriter.h | 17 +-- src/PeerConnection.cc | 8 +- src/PeerInteractionCommand.cc | 12 +- src/PreAllocationDiskWriter.cc | 1 - src/TorrentConsoleDownloadEngine.cc | 17 +-- src/TorrentConsoleDownloadEngine.h | 15 +- src/TorrentDownloadEngine.cc | 6 +- src/TorrentDownloadEngine.h | 2 +- src/TorrentMan.cc | 214 ++++++++-------------------- src/TorrentMan.h | 43 ++---- src/main.cc | 49 +++---- src/prefs.h | 2 +- test/MultiDiskWriterTest.cc | 20 +-- 23 files changed, 302 insertions(+), 343 deletions(-) create mode 100644 src/FileEntry.h diff --git a/ChangeLog b/ChangeLog index 21feecef..a46ef60f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,71 @@ +2006-04-16 Tatsuhiro Tsujikawa + + * src/TorrentConsoleDownloadEngine.cc + (onPartialDownloadingCompletes): Renamed as + onSelectiveDownloadingCompletes. + (onSelectiveDownloadingCompletes): Updated message. + + To add DiskAdaptor which abstract DiskWriter family: + + * src/PeerConnection.cc: Use diskAdaptor instead of diskWriter. + * src/PeerInteractionCommand.cc: Use diskAdaptor instead of diskWriter. + * src/BitfieldMan.cc (isAllBitSet): bug fix. + * src/TorrentMan.cc : Included CopyDiskAdaptor.h, DirectDiskAdaptor.h, + MultiDiskAdaptor.h. + (readFileEntry): Changed its arguments. + (setup): setupDiskWriter is merged into this function. + (setupDiskWriter): Removed. + (setFileFilter): New function. + (readFileEntryFromMetaInfoFile): Updated according to the changes + made in readFileEntry. + (getFilePath): Removed. + (getTempFilePath): Removed. + (getSegmentFilePath): Updated due to the removal of getFilePath. + (fixFilename): Removed. + (copySingleFile): Removed. + (splitMultiFile): Removed. + (deleteTempFile): Removed. + (setFileEntriesToDownload): Removed. + (isPartialDownloadingMode): Renamed as isSelectiveDownloadingMode. + (isSelectiveDownloadingMode): New function. + (setAllMultiFileRequestedState): Removed. + (finishPartialDownloadingMode): Renamed as + finishSelectiveDownloadingMode. + (finishSelectiveDownloadingMode): New function. + (getPartialTotalLength): Renamed as getSelectedTotalLength. + (getSelectedTotalLength): New function. + (onDownloadComplete): Use diskAdaptor. + * src/MultiDiskWriter.cc (Constructor): Added the argument pieceLength + (Range): Removed. + (setMultiFileEntries): Renamed as setFileEntries. + (setFileEntries): New function. + * src/MultiDiskWriter.h [DiskWriterEntry](enabled): Removed. + (pieceLength): New variable. + * src/main.cc (printDownloadCompeleteMessage): New function. + (torrentHandler): Use diskAdaptor instead of diskWriter. + (main): Renamed torrent-show-files to show-files. + Rewritten file contents listing. + * src/TorrentMan.h (FileEntry): Removed. + (multiFileTopDir): Removed. + (multiFileEntries): Removed. + (diskWriter): Removed. + (diskAdaptor): New variable. + * src/DefaultDiskWriter.h (totalLength): New variable. + * src/DefaultDiskWriter.cc (initAndOpenFile): Added ftruncate. + * src/TorrentDownloadEngine.cc (onEndOfRun): Use diskAdaptor instead of + diskWriter. + * src/TorrentConsoleDownloadEngine.h + (partialDownloadLengthDiff): Renamed as selectedDownloadLengthDiff. + (partialTotalLength): Renamed as selectedTotalLength. + * src/AbstractDiskWriter.cc (openFile): If file exists, call + openExistingFile, otherwise call initAndOpenFile. + (closeFile): fd > 0, not fd != 0. + + * src/prefs.h (PREF_TORRENT_SHOW_FILES): Renamed as PREF_SHOW_FILES + (PREF_SHOW_FILES): New definition. + + + 2006-04-12 Tatsuhiro Tsujikawa To add the ability to download multi torrent into respective files diff --git a/TODO b/TODO index ccee211d..92870030 100644 --- a/TODO +++ b/TODO @@ -11,6 +11,14 @@ * Add port range command-line option * Add max peers command-line option * Distinguish seeder from leecher -* file selection in multi-file mode + +0.4.0 release +* Add selective downloading mode * try to use ftruncate to allocate file. -* fix TorrentMan::getFilePath() \ No newline at end of file +* test all download mode +* Add loggerfactory +* Add SIGTERM signal handler + +0.4.1 release +* Add port command-line option +* Add estimated remaining time to normal HTTP/FTP downloading status ouput diff --git a/src/AbstractDiskWriter.cc b/src/AbstractDiskWriter.cc index 4e7cd642..74b35b63 100644 --- a/src/AbstractDiskWriter.cc +++ b/src/AbstractDiskWriter.cc @@ -36,7 +36,7 @@ AbstractDiskWriter::AbstractDiskWriter():fd(0) { } AbstractDiskWriter::~AbstractDiskWriter() { - if(fd != 0) { + if(fd > 0) { close(fd); } #ifdef ENABLE_SHA1DIGEST @@ -45,13 +45,16 @@ AbstractDiskWriter::~AbstractDiskWriter() { } void AbstractDiskWriter::openFile(const string& filename) { - if((fd = open(filename.c_str(), O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { - throw new DlAbortEx(strerror(errno)); - } + File f(filename); + if(f.exists()) { + openExistingFile(filename); + } else { + initAndOpenFile(filename); + } } void AbstractDiskWriter::closeFile() { - if(fd != 0) { + if(fd > 0) { close(fd); fd = 0; } diff --git a/src/BitfieldMan.cc b/src/BitfieldMan.cc index b7e9aed6..9ae3276c 100644 --- a/src/BitfieldMan.cc +++ b/src/BitfieldMan.cc @@ -261,7 +261,7 @@ bool BitfieldMan::unsetBit(int index) { bool BitfieldMan::isAllBitSet() const { if(filterEnabled) { - for(int i = 0; i < bitfieldLength-1; i++) { + for(int i = 0; i < bitfieldLength; i++) { if((bitfield[i]&filterBitfield[i]) != filterBitfield[i]) { return false; } diff --git a/src/DefaultDiskWriter.cc b/src/DefaultDiskWriter.cc index be71fbfc..9b806db3 100644 --- a/src/DefaultDiskWriter.cc +++ b/src/DefaultDiskWriter.cc @@ -23,10 +23,15 @@ #include "DlAbortEx.h" #include -DefaultDiskWriter::DefaultDiskWriter():AbstractDiskWriter() {} +DefaultDiskWriter::DefaultDiskWriter():AbstractDiskWriter(), totalLength(0) {} + +DefaultDiskWriter::DefaultDiskWriter(long long int totalLength):AbstractDiskWriter(), totalLength(totalLength) {} DefaultDiskWriter::~DefaultDiskWriter() {} void DefaultDiskWriter::initAndOpenFile(string filename) { createFile(filename); + if(totalLength > 0) { + ftruncate(fd, totalLength); + } } diff --git a/src/DefaultDiskWriter.h b/src/DefaultDiskWriter.h index 91dc4814..dc8fc6a6 100644 --- a/src/DefaultDiskWriter.h +++ b/src/DefaultDiskWriter.h @@ -25,8 +25,11 @@ #include "AbstractDiskWriter.h" class DefaultDiskWriter:public AbstractDiskWriter { +private: + long long int totalLength; public: DefaultDiskWriter(); + DefaultDiskWriter(long long int totalLength); ~DefaultDiskWriter(); void initAndOpenFile(string filename); diff --git a/src/FileEntry.h b/src/FileEntry.h new file mode 100644 index 00000000..5ebac6e2 --- /dev/null +++ b/src/FileEntry.h @@ -0,0 +1,42 @@ +/* */ +#ifndef _D_FILE_ENTRY_H_ +#define _D_FILE_ENTRY_H_ + +#include "common.h" + +class FileEntry { +public: + string path; + long long int length; + long long int offset; + bool extracted; + bool requested; + FileEntry(string path, long long int length, long long int offset): + path(path), length(length), offset(offset), + extracted(false), requested(true) {} + ~FileEntry() {} +}; + +typedef deque FileEntries; + +#endif // _D_FILE_ENTRY_H_ diff --git a/src/Makefile.am b/src/Makefile.am index 8b51cc10..b22d7bb4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -79,7 +79,12 @@ SRCS = Socket.cc Socket.h\ TrackerWatcherCommand.cc TrackerWatcherCommand.h\ messageDigest.h\ SendMessageQueue.cc SendMessageQueue.h\ - MultiDiskWriter.cc MultiDiskWriter.h + MultiDiskWriter.cc MultiDiskWriter.h\ + DiskAdaptor.cc DiskAdaptor.h\ + CopyDiskAdaptor.cc CopyDiskAdaptor.h\ + DirectDiskAdaptor.cc DirectDiskAdaptor.h\ + MultiDiskAdaptor.cc MultiDiskAdaptor.h\ + FileEntry.h noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ diff --git a/src/Makefile.in b/src/Makefile.in index a4330fba..2a3e161c 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -98,7 +98,9 @@ am__objects_1 = Socket.$(OBJEXT) SocketCore.$(OBJEXT) \ PeerMessage.$(OBJEXT) Piece.$(OBJEXT) RequestSlot.$(OBJEXT) \ RequestSlotMan.$(OBJEXT) TorrentAutoSaveCommand.$(OBJEXT) \ Directory.$(OBJEXT) TrackerWatcherCommand.$(OBJEXT) \ - SendMessageQueue.$(OBJEXT) MultiDiskWriter.$(OBJEXT) + SendMessageQueue.$(OBJEXT) MultiDiskWriter.$(OBJEXT) \ + DiskAdaptor.$(OBJEXT) CopyDiskAdaptor.$(OBJEXT) \ + DirectDiskAdaptor.$(OBJEXT) MultiDiskAdaptor.$(OBJEXT) am_libaria2c_a_OBJECTS = $(am__objects_1) libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" @@ -327,7 +329,12 @@ SRCS = Socket.cc Socket.h\ TrackerWatcherCommand.cc TrackerWatcherCommand.h\ messageDigest.h\ SendMessageQueue.cc SendMessageQueue.h\ - MultiDiskWriter.cc MultiDiskWriter.h + MultiDiskWriter.cc MultiDiskWriter.h\ + DiskAdaptor.cc DiskAdaptor.h\ + CopyDiskAdaptor.cc CopyDiskAdaptor.h\ + DirectDiskAdaptor.cc DirectDiskAdaptor.h\ + MultiDiskAdaptor.cc MultiDiskAdaptor.h\ + FileEntry.h noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) @@ -420,10 +427,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChunkedEncoding.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConsoleDownloadEngine.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@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultDiskWriter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Dictionary.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DirectDiskAdaptor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Directory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DiskAdaptor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngine.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/File.Po@am__quote@ @@ -444,6 +454,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InitiateConnectionCommandFactory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/List.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetaFileUtil.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)/Option.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Peer.Po@am__quote@ diff --git a/src/MultiDiskWriter.cc b/src/MultiDiskWriter.cc index 7172b809..922eed8e 100644 --- a/src/MultiDiskWriter.cc +++ b/src/MultiDiskWriter.cc @@ -24,7 +24,7 @@ #include "Util.h" #include -MultiDiskWriter::MultiDiskWriter() { +MultiDiskWriter::MultiDiskWriter(int pieceLength):pieceLength(pieceLength) { #ifdef ENABLE_SHA1DIGEST sha1DigestInit(ctx); #endif // ENABLE_SHA1DIGEST @@ -37,63 +37,26 @@ MultiDiskWriter::~MultiDiskWriter() { #endif // ENABLE_SHA1DIGEST } -typedef struct { - long long int blockOffset; - long long int length; -} Range; - -typedef deque Ranges; - void MultiDiskWriter::clearEntries() { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); itr++) { - if((*itr)->enabled) { - (*itr)->diskWriter->closeFile(); - } delete *itr; } diskWriterEntries.clear(); } -void MultiDiskWriter::setMultiFileEntries(const MultiFileEntries& multiFileEntries, int pieceLength) { +void MultiDiskWriter::setFileEntries(const FileEntries& fileEntries) { clearEntries(); - Ranges ranges; - for(MultiFileEntries::const_iterator itr = multiFileEntries.begin(); - itr != multiFileEntries.end(); itr++) { - if(itr->requested) { - Range range; - range.blockOffset = (itr->offset/pieceLength)*pieceLength; - range.length = ((itr->offset+itr->length)/pieceLength+ - ((itr->offset+itr->length)%pieceLength ? 1 : 0))*pieceLength-range.blockOffset; - ranges.push_back(range); - } - } - Ranges::const_iterator ritr = ranges.begin(); - for(MultiFileEntries::const_iterator itr = multiFileEntries.begin(); - itr != multiFileEntries.end(); itr++) { - DiskWriterEntry* entry; - if(ritr != ranges.end() && - // !(ritr->blockOffset+ritr->length-1 < itr->offset || - // itr->offset+itr->length-1 < ritr->blockOffset)) { - itr->offset < ritr->blockOffset+ritr->length && - ritr->blockOffset < itr->offset+itr->length) { - - entry = new DiskWriterEntry(*itr, true); - for(;ritr->blockOffset+ritr->length <= itr->offset+itr->length && - ritr != ranges.end(); ritr++); - } else { - entry = new DiskWriterEntry(*itr, false); - } - diskWriterEntries.push_back(entry); + for(FileEntries::const_iterator itr = fileEntries.begin(); + itr != fileEntries.end(); itr++) { + diskWriterEntries.push_back(new DiskWriterEntry(*itr)); } } void MultiDiskWriter::openFile(const string& filename) { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); itr++) { - if((*itr)->enabled) { - (*itr)->diskWriter->openFile(filename+"/"+(*itr)->fileEntry.path); - } + (*itr)->diskWriter->openFile(filename+"/"+(*itr)->fileEntry.path); } } @@ -101,27 +64,21 @@ void MultiDiskWriter::openFile(const string& filename) { void MultiDiskWriter::initAndOpenFile(string filename) { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); itr++) { - if((*itr)->enabled) { - (*itr)->diskWriter->initAndOpenFile(filename+"/"+(*itr)->fileEntry.path); - } + (*itr)->diskWriter->initAndOpenFile(filename+"/"+(*itr)->fileEntry.path); } } void MultiDiskWriter::closeFile() { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); itr++) { - if((*itr)->enabled) { - (*itr)->diskWriter->closeFile(); - } + (*itr)->diskWriter->closeFile(); } } void MultiDiskWriter::openExistingFile(string filename) { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); itr++) { - if((*itr)->enabled) { - (*itr)->diskWriter->openExistingFile(filename+"/"+(*itr)->fileEntry.path); - } + (*itr)->diskWriter->openExistingFile(filename+"/"+(*itr)->fileEntry.path); } } @@ -133,9 +90,6 @@ void MultiDiskWriter::writeData(const char* data, int len, long long int positio for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end() && rem != 0; itr++) { if(isInRange(*itr, offset) || writing) { - if(!(*itr)->enabled) { - throw new DlAbortEx("invalid offset or length. offset = %lld", offset); - } int writeLength = calculateLength(*itr, fileOffset, rem); (*itr)->diskWriter->writeData(data+(len-rem), writeLength, fileOffset); rem -= writeLength; @@ -174,9 +128,6 @@ int MultiDiskWriter::readData(char* data, int len, long long int position) { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end() && rem != 0; itr++) { if(isInRange(*itr, offset) || reading) { - if(!(*itr)->enabled) { - throw new DlAbortEx("invalid offset or length. offset = %lld", offset); - } int readLength = calculateLength((*itr), fileOffset, rem); totalReadLength += (*itr)->diskWriter->readData(data+(len-rem), readLength, fileOffset); rem -= readLength; @@ -223,9 +174,6 @@ string MultiDiskWriter::sha1Sum(long long int offset, long long int length) { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end() && rem != 0; itr++) { if(isInRange(*itr, offset) || reading) { - if(!(*itr)->enabled) { - throw new DlAbortEx("invalid offset or length. offset = %lld", offset); - } int readLength = calculateLength((*itr), fileOffset, rem); hashUpdate(*itr, fileOffset, readLength); rem -= readLength; diff --git a/src/MultiDiskWriter.h b/src/MultiDiskWriter.h index fba08255..69a6f0e2 100644 --- a/src/MultiDiskWriter.h +++ b/src/MultiDiskWriter.h @@ -30,17 +30,12 @@ class DiskWriterEntry { public: FileEntry fileEntry; DiskWriter* diskWriter; - bool enabled; public: - DiskWriterEntry(const FileEntry& fileEntry, bool enabled):fileEntry(fileEntry), enabled(enabled) { - if(enabled) { - diskWriter = new DefaultDiskWriter(); - } + DiskWriterEntry(const FileEntry& fileEntry):fileEntry(fileEntry) { + diskWriter = new DefaultDiskWriter(this->fileEntry.length); } ~DiskWriterEntry() { - if(enabled) { - delete diskWriter; - } + delete diskWriter; } }; @@ -49,7 +44,7 @@ typedef deque DiskWriterEntries; class MultiDiskWriter : public DiskWriter { private: DiskWriterEntries diskWriterEntries; - + int pieceLength; bool isInRange(const DiskWriterEntry* entry, long long int offset) const; int calculateLength(const DiskWriterEntry* entry, long long int fileOffset, int rem) const; void clearEntries(); @@ -59,10 +54,10 @@ private: #endif // ENABLE_SHA1DIGEST public: - MultiDiskWriter(); + MultiDiskWriter(int pieceLength); virtual ~MultiDiskWriter(); - void setMultiFileEntries(const MultiFileEntries& multiFileEntries, int pieceLength); + void setFileEntries(const FileEntries& fileEntries); virtual void openFile(const string& filename); virtual void initAndOpenFile(string filename); diff --git a/src/PeerConnection.cc b/src/PeerConnection.cc index 4010a34f..82484d06 100644 --- a/src/PeerConnection.cc +++ b/src/PeerConnection.cc @@ -216,14 +216,14 @@ void PeerConnection::sendPiece(int index, int begin, int length) const { int iteration = length/BUF_SIZE; long long int pieceOffset = ((long long int)index*torrentMan->pieceLength)+begin; for(int i = 0; i < iteration; i++) { - if(torrentMan->diskWriter->readData(buf, BUF_SIZE, pieceOffset+i*BUF_SIZE) < BUF_SIZE) { + if(torrentMan->diskAdaptor->readData(buf, BUF_SIZE, pieceOffset+i*BUF_SIZE) < BUF_SIZE) { throw new DlAbortEx("piece reading failed."); } socket->writeData(buf, BUF_SIZE); } int rem = length%BUF_SIZE; if(rem > 0) { - if(torrentMan->diskWriter->readData(buf, rem, pieceOffset+iteration*BUF_SIZE) < rem) { + if(torrentMan->diskAdaptor->readData(buf, rem, pieceOffset+iteration*BUF_SIZE) < rem) { throw new DlAbortEx("piece reading failed."); } socket->writeData(buf, rem); @@ -259,7 +259,7 @@ int PeerConnection::sendPieceData(long long int offset, int length) const { if(!isWritable) { return writtenLength; } - if(torrentMan->diskWriter->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) { + if(torrentMan->diskAdaptor->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) { throw new DlAbortEx("piece reading failed."); } socket->writeData(buf, BUF_SIZE); @@ -268,7 +268,7 @@ int PeerConnection::sendPieceData(long long int offset, int length) const { if(socket->isWritable(0)) { int rem = length%BUF_SIZE; if(rem > 0) { - if(torrentMan->diskWriter->readData(buf, rem, offset+iteration*BUF_SIZE) < rem) { + if(torrentMan->diskAdaptor->readData(buf, rem, offset+iteration*BUF_SIZE) < rem) { throw new DlAbortEx("piece reading failed."); } socket->writeData(buf, rem); diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc index 691f9043..2015f21b 100644 --- a/src/PeerInteractionCommand.cc +++ b/src/PeerInteractionCommand.cc @@ -274,9 +274,9 @@ void PeerInteractionCommand::receiveMessage() { ((long long int)message->getIndex())*e->torrentMan->pieceLength+message->getBegin(); e->logger->debug("CUID#%d - write block length = %d, offset=%lld", cuid, message->getBlockLength(), offset); - e->torrentMan->diskWriter->writeData(message->getBlock(), - message->getBlockLength(), - offset); + e->torrentMan->diskAdaptor->writeData(message->getBlock(), + message->getBlockLength(), + offset); piece.completeBlock(slot.getBlockIndex()); sendMessageQueue->deleteRequestSlot(slot); e->torrentMan->updatePiece(piece); @@ -444,7 +444,7 @@ void PeerInteractionCommand::beforeSocketCheck() { bool PeerInteractionCommand::checkPieceHash(const Piece& piece) { long long int offset = ((long long int)piece.getIndex())*e->torrentMan->pieceLength; - return e->torrentMan->diskWriter->sha1Sum(offset, piece.getLength()) == + return e->torrentMan->diskAdaptor->sha1Sum(offset, piece.getLength()) == e->torrentMan->getPieceHash(piece.getIndex()); } @@ -454,11 +454,11 @@ void PeerInteractionCommand::erasePieceOnDisk(const Piece& piece) { memset(buf, 0, BUFSIZE); long long int offset = ((long long int)piece.getIndex())*e->torrentMan->pieceLength; for(int i = 0; i < piece.getLength()/BUFSIZE; i++) { - e->torrentMan->diskWriter->writeData(buf, BUFSIZE, offset); + e->torrentMan->diskAdaptor->writeData(buf, BUFSIZE, offset); offset += BUFSIZE; } int r = piece.getLength()%BUFSIZE; if(r > 0) { - e->torrentMan->diskWriter->writeData(buf, r, offset); + e->torrentMan->diskAdaptor->writeData(buf, r, offset); } } diff --git a/src/PreAllocationDiskWriter.cc b/src/PreAllocationDiskWriter.cc index 6f528b2e..cc538bf5 100644 --- a/src/PreAllocationDiskWriter.cc +++ b/src/PreAllocationDiskWriter.cc @@ -35,7 +35,6 @@ PreAllocationDiskWriter::~PreAllocationDiskWriter() {} void PreAllocationDiskWriter::initAndOpenFile(string filename) { createFile(filename); - int bufSize = 4096; char buf[4096]; diff --git a/src/TorrentConsoleDownloadEngine.cc b/src/TorrentConsoleDownloadEngine.cc index 7c3b68b6..13b76795 100644 --- a/src/TorrentConsoleDownloadEngine.cc +++ b/src/TorrentConsoleDownloadEngine.cc @@ -26,8 +26,9 @@ TorrentConsoleDownloadEngine::TorrentConsoleDownloadEngine() {} TorrentConsoleDownloadEngine::~TorrentConsoleDownloadEngine() {} -void TorrentConsoleDownloadEngine::onPartialDownloadingCompletes() { - printf("Download of specified files has completed. Continue normal download operation.\n"); +void TorrentConsoleDownloadEngine::onSelectiveDownloadingCompletes() { + printf("\nDownload of selected files has completed.\n"); + fflush(stdout); } void TorrentConsoleDownloadEngine::printStatistics() { @@ -68,9 +69,9 @@ void TorrentConsoleDownloadEngine::initStatistics() { sessionDownloadLength = 0; downloadLength = 0; totalLength = 0; - if(torrentMan->isPartialDownloadingMode()) { - partialDownloadLengthDiff = torrentMan->getDownloadLength()-torrentMan->getCompletedLength(); - partialTotalLength = torrentMan->getPartialTotalLength(); + if(torrentMan->isSelectiveDownloadingMode()) { + selectedDownloadLengthDiff = torrentMan->getDownloadLength()-torrentMan->getCompletedLength(); + selectedTotalLength = torrentMan->getSelectedTotalLength(); } } @@ -95,9 +96,9 @@ void TorrentConsoleDownloadEngine::calculateStatistics() { torrentMan->resetDeltaDownloadLength(); torrentMan->resetDeltaUploadLength(); - if(torrentMan->isPartialDownloadingMode()) { - downloadLength = torrentMan->getDownloadLength()-partialDownloadLengthDiff; - totalLength = partialTotalLength; + if(torrentMan->isSelectiveDownloadingMode()) { + downloadLength = torrentMan->getDownloadLength()-selectedDownloadLengthDiff; + totalLength = selectedTotalLength; } else { downloadLength = torrentMan->getDownloadLength(); totalLength = torrentMan->getTotalLength(); diff --git a/src/TorrentConsoleDownloadEngine.h b/src/TorrentConsoleDownloadEngine.h index 26f0fc23..865ee4b3 100644 --- a/src/TorrentConsoleDownloadEngine.h +++ b/src/TorrentConsoleDownloadEngine.h @@ -26,11 +26,6 @@ class TorrentConsoleDownloadEngine : public TorrentDownloadEngine { private: - /* - struct timeval cp; - long long int sessionDownloadSize; - long long int sessionUploadSize; - */ struct timeval cp[2]; long long int sessionDownloadLengthArray[2]; long long int sessionUploadLengthArray[2]; @@ -39,11 +34,15 @@ private: int downloadSpeed; int uploadSpeed; int lastElapsed; - long long int partialDownloadLengthDiff; - long long int partialTotalLength; + long long int selectedDownloadLengthDiff; + long long int selectedTotalLength; + // The time when startup struct timeval startup; + // The number of bytes downloaded since startup long long int sessionDownloadLength; + // The average speed(bytes per second) since startup int avgSpeed; + // The estimated remaining time to complete the download. int eta; long long int downloadLength; long long int totalLength; @@ -53,7 +52,7 @@ private: protected: void initStatistics(); void calculateStatistics(); - void onPartialDownloadingCompletes(); + void onSelectiveDownloadingCompletes(); public: TorrentConsoleDownloadEngine(); ~TorrentConsoleDownloadEngine(); diff --git a/src/TorrentDownloadEngine.cc b/src/TorrentDownloadEngine.cc index fe802bb9..008c0734 100644 --- a/src/TorrentDownloadEngine.cc +++ b/src/TorrentDownloadEngine.cc @@ -22,7 +22,7 @@ #include "TorrentDownloadEngine.h" void TorrentDownloadEngine::onEndOfRun() { - torrentMan->diskWriter->closeFile(); + torrentMan->diskAdaptor->closeFile(); if(filenameFixed && torrentMan->downloadComplete()) { torrentMan->remove(); } else { @@ -32,8 +32,8 @@ void TorrentDownloadEngine::onEndOfRun() { void TorrentDownloadEngine::afterEachIteration() { if(!filenameFixed && torrentMan->downloadComplete()) { - if(torrentMan->isPartialDownloadingMode()) { - onPartialDownloadingCompletes(); + if(torrentMan->isSelectiveDownloadingMode()) { + onSelectiveDownloadingCompletes(); } torrentMan->onDownloadComplete(); if(torrentMan->downloadComplete()) { diff --git a/src/TorrentDownloadEngine.h b/src/TorrentDownloadEngine.h index b8a8d47b..273c35f3 100644 --- a/src/TorrentDownloadEngine.h +++ b/src/TorrentDownloadEngine.h @@ -31,7 +31,7 @@ private: protected: void onEndOfRun(); void afterEachIteration(); - virtual void onPartialDownloadingCompletes() = 0; + virtual void onSelectiveDownloadingCompletes() = 0; public: TorrentDownloadEngine():filenameFixed(false) {} virtual ~TorrentDownloadEngine() {} diff --git a/src/TorrentMan.cc b/src/TorrentMan.cc index c03b3762..f076feb6 100644 --- a/src/TorrentMan.cc +++ b/src/TorrentMan.cc @@ -32,6 +32,9 @@ #include "DefaultDiskWriter.h" #include "MultiDiskWriter.h" #include "prefs.h" +#include "CopyDiskAdaptor.h" +#include "DirectDiskAdaptor.h" +#include "MultiDiskAdaptor.h" #include #include #include @@ -42,25 +45,21 @@ TorrentMan::TorrentMan():bitfield(NULL), preDownloadLength(0), preUploadLength(0), deltaDownloadLength(0), deltaUploadLength(0), storeDir("."), - multiFileTopDir(NULL), setupComplete(false), interval(DEFAULT_ANNOUNCE_INTERVAL), minInterval(DEFAULT_ANNOUNCE_MIN_INTERVAL), complete(0), incomplete(0), - connections(0), diskWriter(NULL) {} + connections(0), diskAdaptor(NULL) {} TorrentMan::~TorrentMan() { if(bitfield != NULL) { delete bitfield; } - if(multiFileTopDir != NULL) { - delete multiFileTopDir; - } for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) { delete *itr; } - if(diskWriter != NULL) { - delete diskWriter; + if(diskAdaptor != NULL) { + delete diskAdaptor; } } @@ -298,7 +297,7 @@ bool TorrentMan::downloadComplete() const { return bitfield->isAllBitSet(); } -void TorrentMan::readFileEntry(const Dictionary* infoDic, const string& defaultName) { +void TorrentMan::readFileEntry(FileEntries& fileEntries, Directory** pTopDir, const Dictionary* infoDic, const string& defaultName) { Data* topName = (Data*)infoDic->get("name"); if(topName != NULL) { name = topName->toString(); @@ -313,12 +312,14 @@ void TorrentMan::readFileEntry(const Dictionary* infoDic, const string& defaultN setFileMode(SINGLE); Data* length = (Data*)infoDic->get("length"); totalLength = length->toLLInt(); + FileEntry fileEntry(name, totalLength, 0); + fileEntries.push_back(fileEntry); } else { long long int length = 0; long long int offset = 0; // multi-file mode setFileMode(MULTI); - multiFileTopDir = new Directory(name); + *pTopDir = new Directory(name); const MetaList& metaList = files->getList(); for(MetaList::const_iterator itr = metaList.begin(); itr != metaList.end(); itr++) { @@ -327,7 +328,7 @@ void TorrentMan::readFileEntry(const Dictionary* infoDic, const string& defaultN length += lengthData->toLLInt(); List* path = (List*)fileDic->get("path"); const MetaList& paths = path->getList(); - Directory* parentDir = multiFileTopDir; + Directory* parentDir = *pTopDir; string filePath = name; for(int i = 0; i < (int)paths.size()-1; i++) { Data* subpath = (Data*)paths.at(i); @@ -339,14 +340,14 @@ void TorrentMan::readFileEntry(const Dictionary* infoDic, const string& defaultN Data* lastpath = (Data*)paths.back(); filePath.append("/").append(lastpath->toString()); FileEntry fileEntry(filePath, lengthData->toLLInt(), offset); - multiFileEntries.push_back(fileEntry); + fileEntries.push_back(fileEntry); offset += fileEntry.length; } totalLength = length; } } -void TorrentMan::setup(string metaInfoFile) { +void TorrentMan::setup(string metaInfoFile, const Strings& targetFilePaths) { peerId = "-A2****-"; for(int i = 0; i < 12; i++) { peerId += Util::itos((int)(((double)10)*random()/(RAND_MAX+1.0))); @@ -363,7 +364,9 @@ void TorrentMan::setup(string metaInfoFile) { v.getHash(md, len); setInfoHash(md); - readFileEntry(infoDic, metaInfoFile); + FileEntries fileEntries; + Directory* topDir = NULL; + readFileEntry(fileEntries, &topDir, infoDic, metaInfoFile); announce = ((Data*)topDic->get("announce"))->toString(); pieceLength = ((Data*)infoDic->get("piece length"))->toInt(); @@ -380,45 +383,54 @@ void TorrentMan::setup(string metaInfoFile) { initBitfield(); delete topDic; -} -void TorrentMan::setupDiskWriter() { if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) { - if(segmentFileExists()) { - load(); - } if(fileMode == SINGLE) { - diskWriter = new DefaultDiskWriter(); + diskAdaptor = new DirectDiskAdaptor(new DefaultDiskWriter(totalLength)); } else { - diskWriter = new MultiDiskWriter(); - ((MultiDiskWriter*)diskWriter)->setMultiFileEntries(multiFileEntries, pieceLength); - multiFileTopDir->createDir(storeDir, true); + diskAdaptor = new MultiDiskAdaptor(new MultiDiskWriter(pieceLength)); } - diskWriter->openFile(getFilePath()); } else { - if(option->get(PREF_NO_PREALLOCATION) == V_TRUE) { - diskWriter = new DefaultDiskWriter(); - } else { - diskWriter = new PreAllocationDiskWriter(totalLength); - } - if(segmentFileExists()) { - load(); - diskWriter->openExistingFile(getTempFilePath()); - } else { - diskWriter->initAndOpenFile(getTempFilePath()); - } + diskAdaptor = new CopyDiskAdaptor(new DefaultDiskWriter(totalLength)); + ((CopyDiskAdaptor*)diskAdaptor)->setTempFilename(name+".a2tmp"); + } + diskAdaptor->setStoreDir(storeDir); + diskAdaptor->setTopDir(topDir); + diskAdaptor->setFileEntries(fileEntries); + setFileFilter(targetFilePaths); + if(segmentFileExists()) { + load(); + diskAdaptor->openExistingFile(); + } else { + diskAdaptor->initAndOpenFile(); } setupComplete = true; } -const MultiFileEntries& TorrentMan::getMultiFileEntries() const { - return multiFileEntries; +void TorrentMan::setFileFilter(const Strings& filePaths) { + if(fileMode != MULTI || filePaths.empty()) { + return; + } + diskAdaptor->removeAllDownloadEntry(); + for(Strings::const_iterator pitr = filePaths.begin(); + pitr != filePaths.end(); pitr++) { + if(!diskAdaptor->addDownloadEntry(*pitr)) { + throw new DlAbortEx("no such file entry <%s>", (*pitr).c_str()); + } + FileEntry fileEntry = diskAdaptor->getFileEntryFromPath(*pitr); + bitfield->addFilter(fileEntry.offset, fileEntry.length); + } + bitfield->enableFilter(); } -void TorrentMan::readFileEntryFromMetaInfoFile(const string& metaInfoFile) { +FileEntries TorrentMan::readFileEntryFromMetaInfoFile(const string& metaInfoFile) { Dictionary* topDic = (Dictionary*)MetaFileUtil::parseMetaFile(metaInfoFile); const Dictionary* infoDic = (const Dictionary*)topDic->get("info"); - readFileEntry(infoDic, metaInfoFile); + FileEntries fileEntries; + Directory* topDir; + readFileEntry(fileEntries, &topDir, infoDic, metaInfoFile); + delete topDir; + return fileEntries; } string TorrentMan::getName() const { @@ -433,28 +445,8 @@ string TorrentMan::getPieceHash(int index) const { return pieceHashes.at(index); } -string TorrentMan::getFilePath() const { - if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE && fileMode == MULTI) { - return storeDir; - } else { - return storeDir+"/"+name; - } -} - -string TorrentMan::getTempFilePath() const { - if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) { - return getFilePath(); - } else { - return getFilePath()+".a2tmp"; - } -} - string TorrentMan::getSegmentFilePath() const { - if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE && fileMode == MULTI) { - return storeDir+"/"+name+".aria2"; - } else { - return getFilePath()+".aria2"; - } + return storeDir+"/"+name+".aria2"; } bool TorrentMan::segmentFileExists() const { @@ -546,117 +538,27 @@ void TorrentMan::remove() const { } } -void TorrentMan::fixFilename() { - if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) { - // nothing to do here - } else { - if(fileMode == SINGLE) { - copySingleFile(); - } else { - splitMultiFile(); - } - } -} - -void TorrentMan::copySingleFile() const { - logger->info("writing file %s", getFilePath().c_str()); - Util::fileCopy(getFilePath(), getTempFilePath()); -} - -void TorrentMan::splitMultiFile() { - logger->info("creating directories"); - multiFileTopDir->createDir(storeDir, true); - long long int offset = 0; - for(MultiFileEntries::iterator itr = multiFileEntries.begin(); - itr != multiFileEntries.end(); itr++) { - if(!itr->extracted && itr->requested) { - string dest = storeDir+"/"+itr->path; - logger->info("writing file %s", dest.c_str()); - Util::rangedFileCopy(dest, getTempFilePath(), offset, itr->length); - itr->extracted = true; - } - offset += itr->length; - } -} - -void TorrentMan::deleteTempFile() const { - if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) { - // nothing to do here - } else { - unlink(getTempFilePath().c_str()); - } -} - -// bool TorrentMan::unextractedFileEntryExists() const { -// if(fileMode == SINGLE) { -// return false; -// } -// for(MultiFileEntries::const_iterator itr = multiFileEntries.begin(); -// itr != multiFileEntries.end(); itr++) { -// if(!itr->extracted) { -// return true; -// } -// } -// } - -void TorrentMan::setFileEntriesToDownload(const Strings& filePaths) { - if(fileMode != MULTI) { - throw new DlAbortEx("only multi-mode supports partial downloading mode."); - } - // clear all requested flags in multiFileEntries. - setAllMultiFileRequestedState(false); - for(Strings::const_iterator pitr = filePaths.begin(); - pitr != filePaths.end(); pitr++) { - bool found = false; - for(MultiFileEntries::iterator itr = multiFileEntries.begin(); - itr != multiFileEntries.end(); itr++) { - if(*pitr == itr->path) { - itr->requested = true; - found = true; - bitfield->addFilter(itr->offset, itr->length); - break; - } - } - if(!found) { - throw new DlAbortEx("no such file entry <%s>", (*pitr).c_str()); - } - } - bitfield->enableFilter(); -} - -bool TorrentMan::isPartialDownloadingMode() const { +bool TorrentMan::isSelectiveDownloadingMode() const { return bitfield->isFilterEnabled(); } -void TorrentMan::setAllMultiFileRequestedState(bool state) { - for(MultiFileEntries::iterator itr = multiFileEntries.begin(); - itr != multiFileEntries.end(); itr++) { - itr->requested = state; - } -} - -void TorrentMan::finishPartialDownloadingMode() { +void TorrentMan::finishSelectiveDownloadingMode() { bitfield->clearFilter(); - setAllMultiFileRequestedState(true); - if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE && fileMode == MULTI) { - ((MultiDiskWriter*)diskWriter)->setMultiFileEntries(multiFileEntries, pieceLength); - } + diskAdaptor->addAllDownloadEntry(); } long long int TorrentMan::getCompletedLength() const { return bitfield->getCompletedLength(); } -long long int TorrentMan::getPartialTotalLength() const { +long long int TorrentMan::getSelectedTotalLength() const { return bitfield->getFilteredTotalLength(); } void TorrentMan::onDownloadComplete() { - diskWriter->closeFile(); save(); - fixFilename(); - if(isPartialDownloadingMode()) { - finishPartialDownloadingMode(); + diskAdaptor->onDownloadComplete(); + if(isSelectiveDownloadingMode()) { + finishSelectiveDownloadingMode(); } - diskWriter->openFile(getTempFilePath()); } diff --git a/src/TorrentMan.h b/src/TorrentMan.h index 24d4422c..9f6fe618 100644 --- a/src/TorrentMan.h +++ b/src/TorrentMan.h @@ -28,9 +28,10 @@ #include "BitfieldMan.h" #include "DiskWriter.h" #include "Piece.h" -#include "Directory.h" #include "Dictionary.h" #include "Option.h" +#include "FileEntry.h" +#include "DiskAdaptor.h" #include #include #include @@ -46,22 +47,8 @@ using namespace std; #define END_GAME_PIECE_NUM 20 #define MAX_PEER_ERROR 5 -class FileEntry { -public: - string path; - long long int length; - long long int offset; - bool extracted; - bool requested; - FileEntry(string path, long long int length, long long int offset): - path(path), length(length), offset(offset), - extracted(false), requested(true) {} - ~FileEntry() {} -}; - typedef deque Peers; typedef multimap Haves; -typedef deque MultiFileEntries; typedef deque UsedPieces; typedef deque PieceIndexes; @@ -85,8 +72,6 @@ private: int port; Haves haves; UsedPieces usedPieces; - Directory* multiFileTopDir; - MultiFileEntries multiFileEntries; bool setupComplete; FILE* openSegFile(string segFilename, string mode) const; @@ -97,7 +82,8 @@ private: void deleteUsedPiece(const Piece& piece); int deleteUsedPiecesByFillRate(int fillRate, int toDelete); void reduceUsedPieces(int max); - void readFileEntry(const Dictionary* infoDic, const string& defaultName); + void readFileEntry(FileEntries& fileEntries, Directory** pTopDir, const Dictionary* infoDic, const string& defaultName); + void setFileFilter(const Strings& filePaths); public: int pieceLength; int pieces; @@ -115,7 +101,7 @@ public: ~TorrentMan(); const Logger* logger; - DiskWriter* diskWriter; + DiskAdaptor* diskAdaptor; const Option* option; int getNewCuid() { return ++cuidCounter; } @@ -150,8 +136,7 @@ public: return infoHash; } - void setup(string metaInfoFile); - void setupDiskWriter(); + void setup(string metaInfoFile, const Strings& targetFilePaths); string getPieceHash(int index) const; @@ -213,8 +198,6 @@ public: string getStoreDir() const { return storeDir; } void setStoreDir(string dir) { storeDir = dir; } - string getFilePath() const; - string getTempFilePath() const; string getSegmentFilePath() const; bool segmentFileExists() const; @@ -233,20 +216,14 @@ public: int countUsedPiece() const { return usedPieces.size(); } int countAdvertisedPiece() const { return haves.size(); } - void readFileEntryFromMetaInfoFile(const string& metaInfoFile); - const MultiFileEntries& getMultiFileEntries() const; + FileEntries readFileEntryFromMetaInfoFile(const string& metaInfoFile); string getName() const; - //bool unextractedFileEntryExists() const; - - void setAllMultiFileRequestedState(bool state); - void finishPartialDownloadingMode(); - bool isPartialDownloadingMode() const; - - void setFileEntriesToDownload(const Strings& filePaths); + void finishSelectiveDownloadingMode(); + bool isSelectiveDownloadingMode() const; long long int getCompletedLength() const; - long long int getPartialTotalLength() const; + long long int getSelectedTotalLength() const; void onDownloadComplete(); diff --git a/src/main.cc b/src/main.cc index 5ee9011f..03d2e58f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -63,6 +63,10 @@ void printDownloadCompeleteMessage(string filename) { printf(_("\nThe download was complete. <%s>\n"), filename.c_str()); } +void printDownloadCompeleteMessage() { + printf("\nThe download was complete.\n"); +} + void printDownloadAbortMessage() { printf(_("\nThe download was not complete because of errors. Check the log.\n")); } @@ -85,13 +89,13 @@ void handler(int signal) { void torrentHandler(int signal) { cout << _("\nSIGINT signal received.") << endl; - if(te->torrentMan->diskWriter != NULL) { - te->torrentMan->diskWriter->closeFile(); + if(te->torrentMan->diskAdaptor != NULL) { + te->torrentMan->diskAdaptor->closeFile(); } if(te->torrentMan->downloadComplete() && te->isFilenameFixed()) { te->torrentMan->remove(); - te->torrentMan->deleteTempFile(); - printDownloadCompeleteMessage(te->torrentMan->getFilePath()); + //te->torrentMan->deleteTempFile(); + printDownloadCompeleteMessage(); } else { te->torrentMan->save(); } @@ -283,7 +287,7 @@ int main(int argc, char* argv[]) { #ifdef ENABLE_BITTORRENT { "torrent-file", required_argument, &lopt, 15 }, { "follow-torrent", required_argument, &lopt, 16 }, - { "torrent-show-files", no_argument, &lopt, 17 }, + { "show-files", no_argument, &lopt, 17 }, { "no-preallocation", no_argument, &lopt, 18 }, { "direct-file-mapping", required_argument, &lopt, 19 }, #endif // ENABLE_BITTORRENT @@ -414,7 +418,7 @@ int main(int argc, char* argv[]) { } break; case 17: - op->put(PREF_TORRENT_SHOW_FILES, V_TRUE); + op->put(PREF_SHOW_FILES, V_TRUE); break; case 18: op->put(PREF_NO_PREALLOCATION, V_TRUE); @@ -608,32 +612,21 @@ int main(int argc, char* argv[]) { te->torrentMan->option = op; string targetTorrentFile = torrentFile.empty() ? downloadedTorrentFile : torrentFile; - if(op->get(PREF_TORRENT_SHOW_FILES) == V_TRUE) { - te->torrentMan->readFileEntryFromMetaInfoFile(targetTorrentFile); + if(op->get(PREF_SHOW_FILES) == V_TRUE) { + FileEntries fileEntries = te->torrentMan->readFileEntryFromMetaInfoFile(targetTorrentFile); cout << "Files:" << endl; - switch(te->torrentMan->getFileMode()) { - case TorrentMan::SINGLE: - printf("%s %s Bytes\n", te->torrentMan->getName().c_str(), - Util::llitos(te->torrentMan->getTotalLength(), true).c_str()); - break; - case TorrentMan::MULTI: { - const MultiFileEntries& entries = te->torrentMan->getMultiFileEntries(); - for(MultiFileEntries::const_iterator itr = entries.begin(); - itr != entries.end(); itr++) { - printf("%s %s Bytes\n", itr->path.c_str(), - Util::llitos(itr->length, true).c_str()); - } - break; - } + for(FileEntries::const_iterator itr = fileEntries.begin(); + itr != fileEntries.end(); itr++) { + printf("%s %s Bytes\n", itr->path.c_str(), + Util::llitos(itr->length, true).c_str()); } exit(0); } else { - te->torrentMan->setup(targetTorrentFile); - if(!torrentFile.empty() && !args.empty() && - te->torrentMan->getFileMode() == TorrentMan::MULTI) { - te->torrentMan->setFileEntriesToDownload(args); + Strings targetFiles; + if(!torrentFile.empty() && !args.empty()) { + targetFiles = args; } - te->torrentMan->setupDiskWriter(); + te->torrentMan->setup(targetTorrentFile, targetFiles); } PeerListenCommand* listenCommand = new PeerListenCommand(te->torrentMan->getNewCuid(), te); @@ -652,7 +645,7 @@ int main(int argc, char* argv[]) { te->run(); if(te->torrentMan->downloadComplete()) { - printDownloadCompeleteMessage(te->torrentMan->getFilePath()); + printDownloadCompeleteMessage(); } else { printDownloadAbortMessage(); } diff --git a/src/prefs.h b/src/prefs.h index e513a404..f4173412 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -89,7 +89,7 @@ // values: 1*digit #define PREF_PEER_CONNECTION_TIMEOUT "peer_connection_timeout" // values: true | false -#define PREF_TORRENT_SHOW_FILES "torrent_show_files" +#define PREF_SHOW_FILES "show_files" // values: true | false #define PREF_NO_PREALLOCATION "no_preallocation" // values: true | false diff --git a/test/MultiDiskWriterTest.cc b/test/MultiDiskWriterTest.cc index cc442975..6cca9cb5 100644 --- a/test/MultiDiskWriterTest.cc +++ b/test/MultiDiskWriterTest.cc @@ -25,14 +25,14 @@ public: CPPUNIT_TEST_SUITE_REGISTRATION( MultiDiskWriterTest ); -MultiFileEntries createEntries() { +FileEntries createEntries() { FileEntry entry1("file1.txt", 15, 0); FileEntry entry2("file2.txt", 7, 15); FileEntry entry3("file3.txt", 3, 22); unlink("file1.txt"); unlink("file2.txt"); unlink("file3.txt"); - MultiFileEntries entries; + FileEntries entries; entries.push_back(entry1); entries.push_back(entry2); entries.push_back(entry3); @@ -52,8 +52,8 @@ void readFile(const string& filename, char* buf, int bufLength) { } void MultiDiskWriterTest::testWriteData() { - MultiDiskWriter dw; - dw.setMultiFileEntries(createEntries(), 2); + MultiDiskWriter dw(2); + dw.setFileEntries(createEntries()); dw.openFile("."); string msg = "12345"; @@ -97,12 +97,12 @@ void MultiDiskWriterTest::testReadData() { FileEntry entry1("file1r.txt", 15, 0); FileEntry entry2("file2r.txt", 7, 15); FileEntry entry3("file3r.txt", 3, 22); - MultiFileEntries entries; + FileEntries entries; entries.push_back(entry1); entries.push_back(entry2); entries.push_back(entry3); - MultiDiskWriter dw; - dw.setMultiFileEntries(entries, 2); + MultiDiskWriter dw(2); + dw.setFileEntries(entries); dw.openFile("."); char buf[128]; @@ -124,12 +124,12 @@ void MultiDiskWriterTest::testSha1Sum() { FileEntry entry1("file1r.txt", 15, 0); FileEntry entry2("file2r.txt", 7, 15); FileEntry entry3("file3r.txt", 3, 22); - MultiFileEntries entries; + FileEntries entries; entries.push_back(entry1); entries.push_back(entry2); entries.push_back(entry3); - MultiDiskWriter dw; - dw.setMultiFileEntries(entries, 2); + MultiDiskWriter dw(2); + dw.setFileEntries(entries); dw.openFile("."); string sha1sum = dw.sha1Sum(0, 25);