mirror of https://github.com/aria2/aria2
2007-12-06 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Rewritten direct I/O support routine * src/SingleFileAllocationIterator.cc * src/MultiDiskAdaptor.{h, cc} * src/ByteArrayDiskWriter.h * src/AbstractSingleDiskAdaptor.h * src/AbstractDiskWriter.cc * src/DefaultPieceStorage.cc * src/DiskWriter.h * src/BinaryStream.h * src/IteratableChunkChecksumValidator.cc * src/IteratableChecksumValidator.cc * src/CheckIntegrityEntry.cc * src/FileAllocationEntry.ccpull/1/head
parent
84e896eb09
commit
2850c16f8a
16
ChangeLog
16
ChangeLog
|
@ -1,3 +1,19 @@
|
||||||
|
2007-12-06 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
|
Rewritten direct I/O support routine
|
||||||
|
* src/SingleFileAllocationIterator.cc
|
||||||
|
* src/MultiDiskAdaptor.{h, cc}
|
||||||
|
* src/ByteArrayDiskWriter.h
|
||||||
|
* src/AbstractSingleDiskAdaptor.h
|
||||||
|
* src/AbstractDiskWriter.cc
|
||||||
|
* src/DefaultPieceStorage.cc
|
||||||
|
* src/DiskWriter.h
|
||||||
|
* src/BinaryStream.h
|
||||||
|
* src/IteratableChunkChecksumValidator.cc
|
||||||
|
* src/IteratableChecksumValidator.cc
|
||||||
|
* src/CheckIntegrityEntry.cc
|
||||||
|
* src/FileAllocationEntry.cc
|
||||||
|
|
||||||
2007-12-06 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
2007-12-06 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
Fixed typo
|
Fixed typo
|
||||||
|
|
|
@ -47,8 +47,7 @@
|
||||||
|
|
||||||
AbstractDiskWriter::AbstractDiskWriter():
|
AbstractDiskWriter::AbstractDiskWriter():
|
||||||
fd(-1),
|
fd(-1),
|
||||||
logger(LogFactory::getInstance())
|
logger(LogFactory::getInstance()) {}
|
||||||
{}
|
|
||||||
|
|
||||||
AbstractDiskWriter::~AbstractDiskWriter()
|
AbstractDiskWriter::~AbstractDiskWriter()
|
||||||
{
|
{
|
||||||
|
@ -167,9 +166,11 @@ int64_t AbstractDiskWriter::size() const
|
||||||
void AbstractDiskWriter::enableDirectIO()
|
void AbstractDiskWriter::enableDirectIO()
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_DIRECT_IO
|
#ifdef ENABLE_DIRECT_IO
|
||||||
int32_t flg;
|
if(_directIOAllowed) {
|
||||||
while((flg = fcntl(fd, F_GETFL)) == -1 && errno == EINTR);
|
int32_t flg;
|
||||||
while(fcntl(fd, F_SETFL, flg|O_DIRECT) == -1 && errno == EINTR);
|
while((flg = fcntl(fd, F_GETFL)) == -1 && errno == EINTR);
|
||||||
|
while(fcntl(fd, F_SETFL, flg|O_DIRECT) == -1 && errno == EINTR);
|
||||||
|
}
|
||||||
#endif // ENABLE_DIRECT_IO
|
#endif // ENABLE_DIRECT_IO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,12 @@ public:
|
||||||
virtual void enableDirectIO();
|
virtual void enableDirectIO();
|
||||||
|
|
||||||
virtual void disableDirectIO();
|
virtual void disableDirectIO();
|
||||||
|
|
||||||
|
virtual bool directIOAllowed() const
|
||||||
|
{
|
||||||
|
return diskWriter->directIOAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
void setDiskWriter(const DiskWriterHandle diskWriter) {
|
void setDiskWriter(const DiskWriterHandle diskWriter) {
|
||||||
this->diskWriter = diskWriter;
|
this->diskWriter = diskWriter;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,12 @@ public:
|
||||||
virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) = 0;
|
virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) = 0;
|
||||||
|
|
||||||
virtual void truncate(int64_t length) = 0;
|
virtual void truncate(int64_t length) = 0;
|
||||||
|
|
||||||
|
virtual void enableDirectIO() = 0;
|
||||||
|
|
||||||
|
virtual void disableDirectIO() = 0;
|
||||||
|
|
||||||
|
virtual bool directIOAllowed() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<BinaryStream> BinaryStreamHandle;
|
typedef SharedHandle<BinaryStream> BinaryStreamHandle;
|
||||||
|
|
|
@ -66,7 +66,5 @@ Commands BtCheckIntegrityEntry::onDownloadFinished(DownloadEngine* e)
|
||||||
// are valid, then aira2 goes to seeding mode. Sometimes it is better
|
// are valid, then aira2 goes to seeding mode. Sometimes it is better
|
||||||
// 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.
|
||||||
// TODO If FileAllocationEntry is not going to be used, call
|
|
||||||
// DiskAdaptor::disableDirectIO() manually here.
|
|
||||||
return onDownloadIncomplete(e);
|
return onDownloadIncomplete(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,11 @@ public:
|
||||||
|
|
||||||
virtual void disableDirectIO() {}
|
virtual void disableDirectIO() {}
|
||||||
|
|
||||||
|
virtual bool directIOAllowed() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void setString(const string& s)
|
void setString(const string& s)
|
||||||
{
|
{
|
||||||
buf.str(s);
|
buf.str(s);
|
||||||
|
|
|
@ -36,27 +36,14 @@
|
||||||
#include "Command.h"
|
#include "Command.h"
|
||||||
#include "RequestGroup.h"
|
#include "RequestGroup.h"
|
||||||
#include "IteratableValidator.h"
|
#include "IteratableValidator.h"
|
||||||
#include "prefs.h"
|
|
||||||
#include "PieceStorage.h"
|
|
||||||
#include "DownloadContext.h"
|
|
||||||
#include "DiskAdaptor.h"
|
|
||||||
#include "Option.h"
|
|
||||||
|
|
||||||
CheckIntegrityEntry::CheckIntegrityEntry(RequestGroup* requestGroup,
|
CheckIntegrityEntry::CheckIntegrityEntry(RequestGroup* requestGroup,
|
||||||
Command* nextCommand):
|
Command* nextCommand):
|
||||||
RequestGroupEntry(requestGroup, nextCommand),
|
RequestGroupEntry(requestGroup, nextCommand),
|
||||||
_validator(0)
|
_validator(0)
|
||||||
{
|
{}
|
||||||
if(_requestGroup->getOption()->getAsBool(PREF_ENABLE_DIRECT_IO) &&
|
|
||||||
_requestGroup->getDownloadContext()->getFileEntries().size() == 1) {
|
|
||||||
_requestGroup->getPieceStorage()->getDiskAdaptor()->enableDirectIO();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckIntegrityEntry::~CheckIntegrityEntry()
|
CheckIntegrityEntry::~CheckIntegrityEntry() {}
|
||||||
{
|
|
||||||
// TODO DiskAdaptor::disableIO() will be called from ~FileAllocationEntry
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckIntegrityEntry::validateChunk()
|
void CheckIntegrityEntry::validateChunk()
|
||||||
{
|
{
|
||||||
|
|
|
@ -434,6 +434,7 @@ void DefaultPieceStorage::initStorage()
|
||||||
if(downloadContext->getFileMode() == DownloadContext::SINGLE) {
|
if(downloadContext->getFileMode() == DownloadContext::SINGLE) {
|
||||||
logger->debug("Instantiating DirectDiskAdaptor");
|
logger->debug("Instantiating DirectDiskAdaptor");
|
||||||
DiskWriterHandle writer = _diskWriterFactory->newDiskWriter();
|
DiskWriterHandle writer = _diskWriterFactory->newDiskWriter();
|
||||||
|
writer->setDirectIOAllowed(option->getAsBool(PREF_ENABLE_DIRECT_IO));
|
||||||
DirectDiskAdaptorHandle directDiskAdaptor = new DirectDiskAdaptor();
|
DirectDiskAdaptorHandle directDiskAdaptor = new DirectDiskAdaptor();
|
||||||
directDiskAdaptor->setDiskWriter(writer);
|
directDiskAdaptor->setDiskWriter(writer);
|
||||||
directDiskAdaptor->setTotalLength(downloadContext->getTotalLength());
|
directDiskAdaptor->setTotalLength(downloadContext->getTotalLength());
|
||||||
|
@ -443,12 +444,14 @@ void DefaultPieceStorage::initStorage()
|
||||||
if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) {
|
if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) {
|
||||||
logger->debug("Instantiating MultiDiskAdaptor");
|
logger->debug("Instantiating MultiDiskAdaptor");
|
||||||
MultiDiskAdaptorHandle multiDiskAdaptor = new MultiDiskAdaptor();
|
MultiDiskAdaptorHandle multiDiskAdaptor = new MultiDiskAdaptor();
|
||||||
|
multiDiskAdaptor->setDirectIOAllowed(option->getAsBool(PREF_ENABLE_DIRECT_IO));
|
||||||
multiDiskAdaptor->setPieceLength(downloadContext->getPieceLength());
|
multiDiskAdaptor->setPieceLength(downloadContext->getPieceLength());
|
||||||
multiDiskAdaptor->setTopDir(downloadContext->getName());
|
multiDiskAdaptor->setTopDir(downloadContext->getName());
|
||||||
this->diskAdaptor = multiDiskAdaptor;
|
this->diskAdaptor = multiDiskAdaptor;
|
||||||
} else {
|
} else {
|
||||||
logger->debug("Instantiating CopyDiskAdaptor");
|
logger->debug("Instantiating CopyDiskAdaptor");
|
||||||
DiskWriterHandle writer = _diskWriterFactory->newDiskWriter();
|
DiskWriterHandle writer = _diskWriterFactory->newDiskWriter();
|
||||||
|
writer->setDirectIOAllowed(option->getAsBool(PREF_ENABLE_DIRECT_IO));
|
||||||
CopyDiskAdaptorHandle copyDiskAdaptor = new CopyDiskAdaptor();
|
CopyDiskAdaptorHandle copyDiskAdaptor = new CopyDiskAdaptor();
|
||||||
copyDiskAdaptor->setDiskWriter(writer);
|
copyDiskAdaptor->setDiskWriter(writer);
|
||||||
copyDiskAdaptor->setTempFilename(downloadContext->getName()+".a2tmp");
|
copyDiskAdaptor->setTempFilename(downloadContext->getName()+".a2tmp");
|
||||||
|
|
|
@ -90,9 +90,9 @@ public:
|
||||||
|
|
||||||
virtual FileAllocationIteratorHandle fileAllocationIterator() = 0;
|
virtual FileAllocationIteratorHandle fileAllocationIterator() = 0;
|
||||||
|
|
||||||
virtual void enableDirectIO() {};
|
virtual void enableDirectIO() {}
|
||||||
|
|
||||||
virtual void disableDirectIO() {};
|
virtual void disableDirectIO() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<DiskAdaptor> DiskAdaptorHandle;
|
typedef SharedHandle<DiskAdaptor> DiskAdaptorHandle;
|
||||||
|
|
|
@ -42,7 +42,12 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class DiskWriter:public BinaryStream {
|
class DiskWriter:public BinaryStream {
|
||||||
|
protected:
|
||||||
|
bool _directIOAllowed;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
DiskWriter():_directIOAllowed(false) {}
|
||||||
|
|
||||||
virtual ~DiskWriter() {}
|
virtual ~DiskWriter() {}
|
||||||
/**
|
/**
|
||||||
* Creates a file output stream to write to the file with the specified name.
|
* Creates a file output stream to write to the file with the specified name.
|
||||||
|
@ -75,6 +80,16 @@ public:
|
||||||
virtual void enableDirectIO() = 0;
|
virtual void enableDirectIO() = 0;
|
||||||
|
|
||||||
virtual void disableDirectIO() = 0;
|
virtual void disableDirectIO() = 0;
|
||||||
|
|
||||||
|
virtual bool directIOAllowed() const
|
||||||
|
{
|
||||||
|
return _directIOAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDirectIOAllowed(bool f)
|
||||||
|
{
|
||||||
|
_directIOAllowed = f;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<DiskWriter> DiskWriterHandle;
|
typedef SharedHandle<DiskWriter> DiskWriterHandle;
|
||||||
|
|
|
@ -38,24 +38,14 @@
|
||||||
#include "RequestGroup.h"
|
#include "RequestGroup.h"
|
||||||
#include "PieceStorage.h"
|
#include "PieceStorage.h"
|
||||||
#include "DiskAdaptor.h"
|
#include "DiskAdaptor.h"
|
||||||
#include "prefs.h"
|
|
||||||
#include "Option.h"
|
|
||||||
|
|
||||||
FileAllocationEntry::FileAllocationEntry(RequestGroup* requestGroup, Command* nextCommand):
|
FileAllocationEntry::FileAllocationEntry(RequestGroup* requestGroup, Command* nextCommand):
|
||||||
RequestGroupEntry(requestGroup, nextCommand),
|
RequestGroupEntry(requestGroup, nextCommand),
|
||||||
_fileAllocationIterator(requestGroup->getPieceStorage()->getDiskAdaptor()->fileAllocationIterator())
|
_fileAllocationIterator(requestGroup->getPieceStorage()->getDiskAdaptor()->fileAllocationIterator())
|
||||||
{
|
{}
|
||||||
if(_requestGroup->getOption()->getAsBool(PREF_ENABLE_DIRECT_IO)) {
|
|
||||||
_requestGroup->getPieceStorage()->getDiskAdaptor()->enableDirectIO();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FileAllocationEntry:: ~FileAllocationEntry()
|
FileAllocationEntry:: ~FileAllocationEntry()
|
||||||
{
|
{}
|
||||||
if(_requestGroup->getOption()->getAsBool(PREF_ENABLE_DIRECT_IO)) {
|
|
||||||
_requestGroup->getPieceStorage()->getDiskAdaptor()->disableDirectIO();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t FileAllocationEntry::getCurrentLength()
|
int64_t FileAllocationEntry::getCurrentLength()
|
||||||
{
|
{
|
||||||
|
|
|
@ -82,7 +82,12 @@ void IteratableChecksumValidator::validateChunk()
|
||||||
|
|
||||||
bool IteratableChecksumValidator::finished() const
|
bool IteratableChecksumValidator::finished() const
|
||||||
{
|
{
|
||||||
return _currentOffset >= _dctx->getTotalLength();
|
if(_currentOffset >= _dctx->getTotalLength()) {
|
||||||
|
_pieceStorage->getDiskAdaptor()->disableDirectIO();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t IteratableChecksumValidator::getTotalLength() const
|
int64_t IteratableChecksumValidator::getTotalLength() const
|
||||||
|
@ -97,6 +102,7 @@ void IteratableChecksumValidator::init()
|
||||||
#else
|
#else
|
||||||
_buffer = new unsigned char[BUFSIZE];
|
_buffer = new unsigned char[BUFSIZE];
|
||||||
#endif // HAVE_POSIX_MEMALIGN
|
#endif // HAVE_POSIX_MEMALIGN
|
||||||
|
_pieceStorage->getDiskAdaptor()->enableDirectIO();
|
||||||
_currentOffset = 0;
|
_currentOffset = 0;
|
||||||
_ctx = new MessageDigestContext();
|
_ctx = new MessageDigestContext();
|
||||||
_ctx->trySetAlgo(_dctx->getChecksumHashAlgo());
|
_ctx->trySetAlgo(_dctx->getChecksumHashAlgo());
|
||||||
|
|
|
@ -116,6 +116,9 @@ void IteratableChunkChecksumValidator::init()
|
||||||
#else
|
#else
|
||||||
_buffer = new unsigned char[BUFSIZE];
|
_buffer = new unsigned char[BUFSIZE];
|
||||||
#endif // HAVE_POSIX_MEMALIGN
|
#endif // HAVE_POSIX_MEMALIGN
|
||||||
|
if(_dctx->getFileEntries().size() == 1) {
|
||||||
|
_pieceStorage->getDiskAdaptor()->enableDirectIO();
|
||||||
|
}
|
||||||
_ctx = new MessageDigestContext();
|
_ctx = new MessageDigestContext();
|
||||||
_ctx->trySetAlgo(_dctx->getPieceHashAlgo());
|
_ctx->trySetAlgo(_dctx->getPieceHashAlgo());
|
||||||
_ctx->digestInit();
|
_ctx->digestInit();
|
||||||
|
@ -157,7 +160,12 @@ string IteratableChunkChecksumValidator::digest(int64_t offset, int32_t length)
|
||||||
|
|
||||||
bool IteratableChunkChecksumValidator::finished() const
|
bool IteratableChunkChecksumValidator::finished() const
|
||||||
{
|
{
|
||||||
return _currentIndex >= (uint32_t)_dctx->getNumPieces();
|
if(_currentIndex >= (uint32_t)_dctx->getNumPieces()) {
|
||||||
|
_pieceStorage->getDiskAdaptor()->disableDirectIO();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t IteratableChunkChecksumValidator::getCurrentOffset() const
|
int64_t IteratableChunkChecksumValidator::getCurrentOffset() const
|
||||||
|
|
|
@ -51,6 +51,7 @@ void MultiDiskAdaptor::resetDiskWriterEntries()
|
||||||
} else {
|
} else {
|
||||||
entry->setDiskWriter(new DefaultDiskWriter());
|
entry->setDiskWriter(new DefaultDiskWriter());
|
||||||
}
|
}
|
||||||
|
entry->getDiskWriter()->setDirectIOAllowed(_directIOAllowed);
|
||||||
diskWriterEntries.push_back(entry);
|
diskWriterEntries.push_back(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,8 @@ private:
|
||||||
int32_t pieceLength;
|
int32_t pieceLength;
|
||||||
DiskWriterEntries diskWriterEntries;
|
DiskWriterEntries diskWriterEntries;
|
||||||
|
|
||||||
|
bool _directIOAllowed;
|
||||||
|
|
||||||
void resetDiskWriterEntries();
|
void resetDiskWriterEntries();
|
||||||
|
|
||||||
void mkdir() const;
|
void mkdir() const;
|
||||||
|
@ -178,6 +180,16 @@ public:
|
||||||
int32_t getPieceLength() const {
|
int32_t getPieceLength() const {
|
||||||
return pieceLength;
|
return pieceLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool directIOAllowed() const
|
||||||
|
{
|
||||||
|
return _directIOAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDirectIOAllowed(bool b)
|
||||||
|
{
|
||||||
|
_directIOAllowed = b;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<MultiDiskAdaptor> MultiDiskAdaptorHandle;
|
typedef SharedHandle<MultiDiskAdaptor> MultiDiskAdaptorHandle;
|
||||||
|
|
|
@ -40,11 +40,16 @@
|
||||||
#define BUFSIZE (256*1024)
|
#define BUFSIZE (256*1024)
|
||||||
|
|
||||||
SingleFileAllocationIterator::SingleFileAllocationIterator(BinaryStream* stream, int64_t offset, int64_t totalLength):_stream(stream), _offset(offset), _totalLength(totalLength), _buffer(0)
|
SingleFileAllocationIterator::SingleFileAllocationIterator(BinaryStream* stream, int64_t offset, int64_t totalLength):_stream(stream), _offset(offset), _totalLength(totalLength), _buffer(0)
|
||||||
{}
|
{
|
||||||
|
if(_offset%512 == 0) {
|
||||||
|
_stream->enableDirectIO();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SingleFileAllocationIterator::~SingleFileAllocationIterator()
|
SingleFileAllocationIterator::~SingleFileAllocationIterator()
|
||||||
{
|
{
|
||||||
delete [] _buffer;
|
delete [] _buffer;
|
||||||
|
_stream->disableDirectIO();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleFileAllocationIterator::init()
|
void SingleFileAllocationIterator::init()
|
||||||
|
|
Loading…
Reference in New Issue