mirror of https://github.com/aria2/aria2
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.ccpull/1/head
parent
120e2de096
commit
2dfee3dc49
16
ChangeLog
16
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue