From a5cc350dcf6cf83a84b5845e0f61230f1f42e7c7 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 4 Jul 2010 15:03:35 +0000 Subject: 2010-07-04 Tatsuhiro Tsujikawa When allocating disk space, for Linux system with fallocate() system call, first check file system supports fallocate. This just run fallocate with small chunk and see it succeeds or fails. If it succeeds, use fallocate() to allocate entire file otherwise fall back to traditional slower method: writing zeros. This behavior is enabled in --file-allocation=prealloc, so this is enabled by default for most modern Linux. * configure.ac * src/AbstractDiskWriter.cc * src/AbstractDiskWriter.h * src/AbstractSingleDiskAdaptor.cc * src/AdaptiveFileAllocationIterator.cc * src/AdaptiveFileAllocationIterator.h * src/DefaultPieceStorage.cc * src/DiskAdaptor.cc * src/DiskAdaptor.h * src/FallocFileAllocationIterator.cc * src/Makefile.am * src/MultiFileAllocationIterator.cc * src/OptionHandlerFactory.cc * test/FallocFileAllocationIteratorTest.cc * test/Makefile.am --- src/AdaptiveFileAllocationIterator.cc | 102 ++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 src/AdaptiveFileAllocationIterator.cc (limited to 'src/AdaptiveFileAllocationIterator.cc') diff --git a/src/AdaptiveFileAllocationIterator.cc b/src/AdaptiveFileAllocationIterator.cc new file mode 100644 index 00000000..3ec80fb6 --- /dev/null +++ b/src/AdaptiveFileAllocationIterator.cc @@ -0,0 +1,102 @@ +/* */ +#include "AdaptiveFileAllocationIterator.h" +#include "BinaryStream.h" +#ifdef HAVE_FALLOCATE +# include "FallocFileAllocationIterator.h" +#endif // HAVE_FALLOCATE +#include "SingleFileAllocationIterator.h" +#include "RecoverableException.h" +#include "LogFactory.h" +#include "Logger.h" + +namespace aria2 { + +AdaptiveFileAllocationIterator::AdaptiveFileAllocationIterator +(BinaryStream* stream, off_t offset, uint64_t totalLength): + stream_(stream), offset_(offset), totalLength_(totalLength), + logger_(LogFactory::getInstance()) {} + +AdaptiveFileAllocationIterator::~AdaptiveFileAllocationIterator() {} + +void AdaptiveFileAllocationIterator::allocateChunk() +{ + if(allocator_.isNull()) { +#ifdef HAVE_FALLOCATE + try { + if(logger_->debug()) { + logger_->debug("Testing file system supports fallocate."); + } + if(static_cast(offset_) < totalLength_) { + off_t len = std::min(totalLength_-offset_, static_cast(4096)); + stream_->allocate(offset_, len); + offset_ += len; + } + if(logger_->debug()) { + logger_->debug("File system supports fallocate."); + } + allocator_.reset + (new FallocFileAllocationIterator(stream_, offset_, totalLength_)); + } catch(RecoverableException& e) { + if(logger_->debug()) { + logger_->debug("File system does not support fallocate."); + } + SharedHandle salloc + (new SingleFileAllocationIterator(stream_, offset_, totalLength_)); + salloc->init(); + allocator_ = salloc; + } +#else // !HAVE_FALLOCATE + SharedHandle salloc + (new SingleFileAllocationIterator(stream_, offset_, totalLength_)); + salloc->init(); + allocator_ = salloc; +#endif // !HAVE_FALLOCATE + allocator_->allocateChunk(); + } else { + allocator_->allocateChunk(); + } +} + +bool AdaptiveFileAllocationIterator::finished() +{ + if(allocator_.isNull()) { + return false; + } else { + return allocator_->finished(); + } +} + +} // namespace aria2 -- cgit