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>
Added --http-auth-challenge option. If it is set to true(by

View File

@ -58,6 +58,7 @@ namespace aria2 {
AbstractDiskWriter::AbstractDiskWriter():
fd(-1),
_readOnly(false),
logger(LogFactory::getInstance()) {}
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());
}
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
(StringFormat(EX_FILE_OPEN, filename.c_str(), strerror(errno)).str());
}
@ -217,4 +225,14 @@ void AbstractDiskWriter::disableDirectIO()
#endif // ENABLE_DIRECT_IO
}
void AbstractDiskWriter::enableReadOnly()
{
_readOnly = true;
}
void AbstractDiskWriter::disableReadOnly()
{
_readOnly = false;
}
} // namespace aria2

View File

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

View File

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

View File

@ -77,7 +77,13 @@ public:
virtual void disableDirectIO();
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();
void setDiskWriter(const SharedHandle<DiskWriter>& diskWriter);

View File

@ -49,17 +49,28 @@ BtCheckIntegrityEntry::BtCheckIntegrityEntry(RequestGroup* requestGroup):
BtCheckIntegrityEntry::~BtCheckIntegrityEntry() {}
void BtCheckIntegrityEntry::onDownloadIncomplete(std::deque<Command*>& commands,
DownloadEngine* e)
static void proceedFileAllocation
(std::deque<Command*>& commands, DownloadEngine* e, RequestGroup* requestGroup)
{
FileAllocationEntryHandle entry(new BtFileAllocationEntry(_requestGroup));
if(_requestGroup->needsFileAllocation()) {
FileAllocationEntryHandle entry(new BtFileAllocationEntry(requestGroup));
if(requestGroup->needsFileAllocation()) {
e->_fileAllocationMan->pushEntry(entry);
} else {
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,
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
// behavior.
if(e->option->getAsBool(PREF_BT_HASH_CHECK_SEED)) {
onDownloadIncomplete(commands, e);
proceedFileAllocation(commands, e, _requestGroup);
}
}
} // namespace aria2

View File

@ -98,6 +98,10 @@ public:
virtual void disableDirectIO() {}
virtual void enableReadOnly() {}
virtual void disableReadOnly() {}
// 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
// length.

View File

@ -92,6 +92,16 @@ public:
{
_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;

View File

@ -169,7 +169,8 @@ void DiskWriterEntry::needsFileAllocation(bool f)
MultiDiskAdaptor::MultiDiskAdaptor():
pieceLength(0),
_maxOpenFiles(DEFAULT_MAX_OPEN_FILES),
_directIOAllowed(false) {}
_directIOAllowed(false),
_readOnly(false) {}
MultiDiskAdaptor::~MultiDiskAdaptor() {}
@ -273,6 +274,9 @@ void MultiDiskAdaptor::resetDiskWriterEntries()
(*i)->getFilePath(getTopDirPath()).c_str());
(*i)->setDiskWriter(dwFactory.newDiskWriter());
(*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()
{
for(std::deque<SharedHandle<DiskWriterEntry> >::const_iterator i =

View File

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

View File

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