2009-02-23 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

In BitTorrent, Open files in read-only mode for hash check.
	After that, re-open file in read/write mode only when the
	download is not finished.	
	* src/AbstractDiskWriter.cc
	* src/AbstractDiskWriter.h
	* src/AbstractSingleDiskAdaptor.cc
	* src/AbstractSingleDiskAdaptor.h
	* src/BtCheckIntegrityEntry.cc
	* src/DiskAdaptor.h
	* src/DiskWriter.h
	* src/MultiDiskAdaptor.cc
	* src/MultiDiskAdaptor.h
	* src/RequestGroup.cc
pull/1/head
Tatsuhiro Tsujikawa 2009-02-23 13:27:08 +00:00
parent 120e2de096
commit 2dfee3dc49
11 changed files with 114 additions and 9 deletions

View File

@ -1,3 +1,19 @@
2009-02-23 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
In BitTorrent, Open files in read-only mode for hash check. After
that, re-open file in read/write mode only when the download is
not finished.
* src/AbstractDiskWriter.cc
* src/AbstractDiskWriter.h
* src/AbstractSingleDiskAdaptor.cc
* src/AbstractSingleDiskAdaptor.h
* src/BtCheckIntegrityEntry.cc
* src/DiskAdaptor.h
* src/DiskWriter.h
* src/MultiDiskAdaptor.cc
* src/MultiDiskAdaptor.h
* src/RequestGroup.cc
2009-02-19 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net> 2009-02-19 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added --http-auth-challenge option. If it is set to true(by Added --http-auth-challenge option. If it is set to true(by

View File

@ -58,6 +58,7 @@ namespace aria2 {
AbstractDiskWriter::AbstractDiskWriter(): AbstractDiskWriter::AbstractDiskWriter():
fd(-1), fd(-1),
_readOnly(false),
logger(LogFactory::getInstance()) {} logger(LogFactory::getInstance()) {}
AbstractDiskWriter::~AbstractDiskWriter() AbstractDiskWriter::~AbstractDiskWriter()
@ -93,7 +94,14 @@ void AbstractDiskWriter::openExistingFile(const std::string& filename,
(StringFormat(EX_FILE_OPEN, filename.c_str(), MSG_FILE_NOT_FOUND).str()); (StringFormat(EX_FILE_OPEN, filename.c_str(), MSG_FILE_NOT_FOUND).str());
} }
if((fd = open(filename.c_str(), O_RDWR|O_BINARY, OPEN_MODE)) < 0) { int flags = O_BINARY;
if(_readOnly) {
flags |= O_RDONLY;
} else {
flags |= O_RDWR;
}
if((fd = open(filename.c_str(), flags, OPEN_MODE)) < 0) {
throw DlAbortEx throw DlAbortEx
(StringFormat(EX_FILE_OPEN, filename.c_str(), strerror(errno)).str()); (StringFormat(EX_FILE_OPEN, filename.c_str(), strerror(errno)).str());
} }
@ -217,4 +225,14 @@ void AbstractDiskWriter::disableDirectIO()
#endif // ENABLE_DIRECT_IO #endif // ENABLE_DIRECT_IO
} }
void AbstractDiskWriter::enableReadOnly()
{
_readOnly = true;
}
void AbstractDiskWriter::disableReadOnly()
{
_readOnly = false;
}
} // namespace aria2 } // namespace aria2

View File

@ -46,6 +46,9 @@ class AbstractDiskWriter : public DiskWriter {
protected: protected:
std::string filename; std::string filename;
int fd; int fd;
bool _readOnly;
Logger* logger; Logger* logger;
void createFile(const std::string& filename, int addFlags = 0); void createFile(const std::string& filename, int addFlags = 0);
@ -55,7 +58,6 @@ private:
ssize_t readDataInternal(unsigned char* data, size_t len); ssize_t readDataInternal(unsigned char* data, size_t len);
void seek(off_t offset); void seek(off_t offset);
public: public:
AbstractDiskWriter(); AbstractDiskWriter();
virtual ~AbstractDiskWriter(); virtual ~AbstractDiskWriter();
@ -77,6 +79,10 @@ public:
virtual void enableDirectIO(); virtual void enableDirectIO();
virtual void disableDirectIO(); virtual void disableDirectIO();
virtual void enableReadOnly();
virtual void disableReadOnly();
}; };
} // namespace aria2 } // namespace aria2

View File

@ -111,6 +111,16 @@ bool AbstractSingleDiskAdaptor::directIOAllowed() const
return diskWriter->directIOAllowed(); return diskWriter->directIOAllowed();
} }
void AbstractSingleDiskAdaptor::enableReadOnly()
{
diskWriter->enableReadOnly();
}
void AbstractSingleDiskAdaptor::disableReadOnly()
{
diskWriter->disableReadOnly();
}
void AbstractSingleDiskAdaptor::cutTrailingGarbage() void AbstractSingleDiskAdaptor::cutTrailingGarbage()
{ {
if(File(getFilePath()).size() > totalLength) { if(File(getFilePath()).size() > totalLength) {

View File

@ -78,6 +78,12 @@ public:
virtual bool directIOAllowed() const; virtual bool directIOAllowed() const;
// Make sure that DiskWriter is set before calling this function.
virtual void enableReadOnly();
// Make sure that DiskWriter is set before calling this function.
virtual void disableReadOnly();
virtual void cutTrailingGarbage(); virtual void cutTrailingGarbage();
void setDiskWriter(const SharedHandle<DiskWriter>& diskWriter); void setDiskWriter(const SharedHandle<DiskWriter>& diskWriter);

View File

@ -49,17 +49,28 @@ BtCheckIntegrityEntry::BtCheckIntegrityEntry(RequestGroup* requestGroup):
BtCheckIntegrityEntry::~BtCheckIntegrityEntry() {} BtCheckIntegrityEntry::~BtCheckIntegrityEntry() {}
void BtCheckIntegrityEntry::onDownloadIncomplete(std::deque<Command*>& commands, static void proceedFileAllocation
DownloadEngine* e) (std::deque<Command*>& commands, DownloadEngine* e, RequestGroup* requestGroup)
{ {
FileAllocationEntryHandle entry(new BtFileAllocationEntry(_requestGroup)); FileAllocationEntryHandle entry(new BtFileAllocationEntry(requestGroup));
if(_requestGroup->needsFileAllocation()) { if(requestGroup->needsFileAllocation()) {
e->_fileAllocationMan->pushEntry(entry); e->_fileAllocationMan->pushEntry(entry);
} else { } else {
entry->prepareForNextAction(commands, e); entry->prepareForNextAction(commands, e);
} }
} }
void BtCheckIntegrityEntry::onDownloadIncomplete(std::deque<Command*>& commands,
DownloadEngine* e)
{
// Now reopen DiskAdaptor with read only disabled.
_requestGroup->getPieceStorage()->getDiskAdaptor()->closeFile();
_requestGroup->getPieceStorage()->getDiskAdaptor()->disableReadOnly();
_requestGroup->getPieceStorage()->getDiskAdaptor()->openFile();
proceedFileAllocation(commands, e, _requestGroup);
}
void BtCheckIntegrityEntry::onDownloadFinished(std::deque<Command*>& commands, void BtCheckIntegrityEntry::onDownloadFinished(std::deque<Command*>& commands,
DownloadEngine* e) DownloadEngine* e)
{ {
@ -69,8 +80,9 @@ void BtCheckIntegrityEntry::onDownloadFinished(std::deque<Command*>& commands,
// to exit rather than doing seeding. So, it would be good to toggle this // to exit rather than doing seeding. So, it would be good to toggle this
// behavior. // behavior.
if(e->option->getAsBool(PREF_BT_HASH_CHECK_SEED)) { if(e->option->getAsBool(PREF_BT_HASH_CHECK_SEED)) {
onDownloadIncomplete(commands, e); proceedFileAllocation(commands, e, _requestGroup);
} }
} }
} // namespace aria2 } // namespace aria2

View File

@ -98,6 +98,10 @@ public:
virtual void disableDirectIO() {} virtual void disableDirectIO() {}
virtual void enableReadOnly() {}
virtual void disableReadOnly() {}
// Assumed each file length is stored in fileEntries or DiskAdaptor knows it. // Assumed each file length is stored in fileEntries or DiskAdaptor knows it.
// If each actual file's length is larger than that, truncate file to that // If each actual file's length is larger than that, truncate file to that
// length. // length.

View File

@ -92,6 +92,16 @@ public:
{ {
_directIOAllowed = f; _directIOAllowed = f;
} }
// Enables read-only mode. After this call, openExistingFile() opens
// file in read-only mode. This is an optional functionality. The
// default implementation is do nothing.
virtual void enableReadOnly() {}
// Disables read-only mode. After this call, openExistingFile()
// opens file in read/write mode. This is an optional
// functionality. The default implementation is do noting.
virtual void disableReadOnly() {}
}; };
typedef SharedHandle<DiskWriter> DiskWriterHandle; typedef SharedHandle<DiskWriter> DiskWriterHandle;

View File

@ -169,7 +169,8 @@ void DiskWriterEntry::needsFileAllocation(bool f)
MultiDiskAdaptor::MultiDiskAdaptor(): MultiDiskAdaptor::MultiDiskAdaptor():
pieceLength(0), pieceLength(0),
_maxOpenFiles(DEFAULT_MAX_OPEN_FILES), _maxOpenFiles(DEFAULT_MAX_OPEN_FILES),
_directIOAllowed(false) {} _directIOAllowed(false),
_readOnly(false) {}
MultiDiskAdaptor::~MultiDiskAdaptor() {} MultiDiskAdaptor::~MultiDiskAdaptor() {}
@ -273,6 +274,9 @@ void MultiDiskAdaptor::resetDiskWriterEntries()
(*i)->getFilePath(getTopDirPath()).c_str()); (*i)->getFilePath(getTopDirPath()).c_str());
(*i)->setDiskWriter(dwFactory.newDiskWriter()); (*i)->setDiskWriter(dwFactory.newDiskWriter());
(*i)->getDiskWriter()->setDirectIOAllowed(_directIOAllowed); (*i)->getDiskWriter()->setDirectIOAllowed(_directIOAllowed);
if(_readOnly) {
(*i)->getDiskWriter()->enableReadOnly();
}
} }
} }
} }
@ -518,6 +522,16 @@ void MultiDiskAdaptor::disableDirectIO()
} }
} }
void MultiDiskAdaptor::enableReadOnly()
{
_readOnly = true;
}
void MultiDiskAdaptor::disableReadOnly()
{
_readOnly = false;
}
void MultiDiskAdaptor::cutTrailingGarbage() void MultiDiskAdaptor::cutTrailingGarbage()
{ {
for(std::deque<SharedHandle<DiskWriterEntry> >::const_iterator i = for(std::deque<SharedHandle<DiskWriterEntry> >::const_iterator i =

View File

@ -113,6 +113,8 @@ private:
bool _directIOAllowed; bool _directIOAllowed;
bool _readOnly;
void resetDiskWriterEntries(); void resetDiskWriterEntries();
void mkdir(const std::string& topDirPath) const; void mkdir(const std::string& topDirPath) const;
@ -160,6 +162,10 @@ public:
virtual void disableDirectIO(); virtual void disableDirectIO();
virtual void enableReadOnly();
virtual void disableReadOnly();
void setTopDir(const std::string& topDir) { void setTopDir(const std::string& topDir) {
this->topDir = topDir; this->topDir = topDir;
} }

View File

@ -266,6 +266,9 @@ void RequestGroup::createInitialCommand(std::deque<Command*>& commands,
progressInfoFile->getFilename().c_str(), progressInfoFile->getFilename().c_str(),
_pieceStorage->getDiskAdaptor()->getFilePath().c_str()); _pieceStorage->getDiskAdaptor()->getFilePath().c_str());
} }
// First, make DiskAdaptor read-only mode.
_pieceStorage->getDiskAdaptor()->enableReadOnly();
// Call Load, Save and file allocation command here // Call Load, Save and file allocation command here
if(progressInfoFile->exists()) { if(progressInfoFile->exists()) {
// load .aria2 file if it exists. // load .aria2 file if it exists.