From d734ff7d298d0abee4e6f75f94afd2d33e0c8fc6 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 12 Aug 2012 16:52:53 +0900 Subject: [PATCH] Added new file allocation method called 'trunc' --file-allocation option can now take new value 'trunc'. 'trunc' uses ftruncate() system call or platform-specific counterpart to truncate a file to a specified length. --- doc/manual-src/en/aria2c.rst | 6 ++- src/AbstractSingleDiskAdaptor.cc | 7 +++ src/DefaultPieceStorage.cc | 2 + src/DiskAdaptor.h | 3 +- src/Makefile.am | 1 + src/MultiFileAllocationIterator.cc | 7 +++ src/OptionHandlerFactory.cc | 11 +++-- src/TruncFileAllocationIterator.cc | 68 ++++++++++++++++++++++++++++++ src/TruncFileAllocationIterator.h | 66 +++++++++++++++++++++++++++++ src/prefs.cc | 1 + src/prefs.h | 1 + src/usage_text.h | 5 ++- 12 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 src/TruncFileAllocationIterator.cc create mode 100644 src/TruncFileAllocationIterator.h diff --git a/doc/manual-src/en/aria2c.rst b/doc/manual-src/en/aria2c.rst index 7adcf90d..a6b639d3 100644 --- a/doc/manual-src/en/aria2c.rst +++ b/doc/manual-src/en/aria2c.rst @@ -1078,7 +1078,11 @@ Advanced Options entirely until allocation finishes. ``falloc`` may not be available if your system doesn't have :manpage:`posix_fallocate(3)` function. - Possible Values: ``none``, ``prealloc``, ``falloc`` + ``trunc`` uses :manpage:`ftruncate(2)` system call or + platform-specific counterpart to truncate a file to a specified + length. + + Possible Values: ``none``, ``prealloc``, ``trunc``, ``falloc`` Default: ``prealloc`` .. option:: --hash-check-only[=true|false] diff --git a/src/AbstractSingleDiskAdaptor.cc b/src/AbstractSingleDiskAdaptor.cc index 2f92655c..f87a6e86 100644 --- a/src/AbstractSingleDiskAdaptor.cc +++ b/src/AbstractSingleDiskAdaptor.cc @@ -37,6 +37,7 @@ #include "AdaptiveFileAllocationIterator.h" #include "DiskWriter.h" #include "FileEntry.h" +#include "TruncFileAllocationIterator.h" #ifdef HAVE_SOME_FALLOCATE # include "FallocFileAllocationIterator.h" #endif // HAVE_SOME_FALLOCATE @@ -107,6 +108,12 @@ AbstractSingleDiskAdaptor::fileAllocationIterator() return h; } #endif // HAVE_SOME_FALLOCATE + case(DiskAdaptor::FILE_ALLOC_TRUNC): { + SharedHandle h + (new TruncFileAllocationIterator + (diskWriter_.get(), size(), totalLength_)); + return h; + } default: { SharedHandle h (new AdaptiveFileAllocationIterator diff --git a/src/DefaultPieceStorage.cc b/src/DefaultPieceStorage.cc index 036e9e10..9dcb154b 100644 --- a/src/DefaultPieceStorage.cc +++ b/src/DefaultPieceStorage.cc @@ -635,6 +635,8 @@ void DefaultPieceStorage::initStorage() } if(option_->get(PREF_FILE_ALLOCATION) == V_FALLOC) { diskAdaptor_->setFileAllocationMethod(DiskAdaptor::FILE_ALLOC_FALLOC); + } else if(option_->get(PREF_FILE_ALLOCATION) == V_TRUNC) { + diskAdaptor_->setFileAllocationMethod(DiskAdaptor::FILE_ALLOC_TRUNC); } } diff --git a/src/DiskAdaptor.h b/src/DiskAdaptor.h index f81c8894..9bf9ca11 100644 --- a/src/DiskAdaptor.h +++ b/src/DiskAdaptor.h @@ -51,7 +51,8 @@ class DiskAdaptor:public BinaryStream { public: enum FileAllocationMethod { FILE_ALLOC_ADAPTIVE, - FILE_ALLOC_FALLOC + FILE_ALLOC_FALLOC, + FILE_ALLOC_TRUNC }; DiskAdaptor(); diff --git a/src/Makefile.am b/src/Makefile.am index 9040ac5b..9b61f251 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -192,6 +192,7 @@ SRCS = Socket.h\ ContextAttribute.h\ TorrentAttribute.cc TorrentAttribute.h\ AdaptiveFileAllocationIterator.cc AdaptiveFileAllocationIterator.h\ + TruncFileAllocationIterator.cc TruncFileAllocationIterator.h\ StreamFilter.cc StreamFilter.h\ SinkStreamFilter.cc SinkStreamFilter.h\ ChunkedDecodingStreamFilter.cc ChunkedDecodingStreamFilter.h\ diff --git a/src/MultiFileAllocationIterator.cc b/src/MultiFileAllocationIterator.cc index f17115fe..24653335 100644 --- a/src/MultiFileAllocationIterator.cc +++ b/src/MultiFileAllocationIterator.cc @@ -36,6 +36,7 @@ #include "MultiDiskAdaptor.h" #include "FileEntry.h" #include "AdaptiveFileAllocationIterator.h" +#include "TruncFileAllocationIterator.h" #ifdef HAVE_SOME_FALLOCATE # include "FallocFileAllocationIterator.h" #endif // HAVE_SOME_FALLOCATE @@ -76,6 +77,12 @@ void MultiFileAllocationIterator::allocateChunk() fileEntry->getLength())); break; #endif // HAVE_SOME_FALLOCATE + case(DiskAdaptor::FILE_ALLOC_TRUNC): + fileAllocationIterator_.reset + (new TruncFileAllocationIterator(entry->getDiskWriter().get(), + entry->size(), + fileEntry->getLength())); + break; default: fileAllocationIterator_.reset (new AdaptiveFileAllocationIterator(entry->getDiskWriter().get(), diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 2c329a71..1910f81c 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -354,14 +354,17 @@ OptionHandlerFactory::createOptionHandlers() handlers.push_back(op); } { + const std::string params[] = { V_NONE, V_PREALLOC, V_TRUNC, +#ifdef HAVE_SOME_FALLOCATE + V_FALLOC +#endif // HAVE_SOME_FALLOCATE + }; SharedHandle op(new ParameterOptionHandler (PREF_FILE_ALLOCATION, TEXT_FILE_ALLOCATION, V_PREALLOC, - V_NONE, V_PREALLOC, -#ifdef HAVE_SOME_FALLOCATE - V_FALLOC, -#endif // HAVE_SOME_FALLOCATE + std::vector + (vbegin(params), vend(params)), 'a')); op->addTag(TAG_BASIC); op->addTag(TAG_FILE); diff --git a/src/TruncFileAllocationIterator.cc b/src/TruncFileAllocationIterator.cc new file mode 100644 index 00000000..e79467e4 --- /dev/null +++ b/src/TruncFileAllocationIterator.cc @@ -0,0 +1,68 @@ +/* */ +#include "TruncFileAllocationIterator.h" +#include "DlAbortEx.h" + +namespace aria2 { + +TruncFileAllocationIterator::TruncFileAllocationIterator +(BinaryStream* stream, int64_t offset, int64_t totalLength) + : stream_(stream), + offset_(offset), + totalLength_(totalLength) +{} + +void TruncFileAllocationIterator::allocateChunk() +{ + stream_->truncate(totalLength_); + offset_ = totalLength_; +} + +bool TruncFileAllocationIterator::finished() +{ + return offset_ == totalLength_; +} + +int64_t TruncFileAllocationIterator::getCurrentLength() +{ + return offset_; +} + +int64_t TruncFileAllocationIterator::getTotalLength() +{ + return totalLength_; +} + +} // namespace aria2 diff --git a/src/TruncFileAllocationIterator.h b/src/TruncFileAllocationIterator.h new file mode 100644 index 00000000..79c34d88 --- /dev/null +++ b/src/TruncFileAllocationIterator.h @@ -0,0 +1,66 @@ +/* */ +#ifndef D_TRUNC_FILE_ALLOCATION_ITERATOR_H +#define D_TRUNC_FILE_ALLOCATION_ITERATOR_H + +#include "FileAllocationIterator.h" +#include "BinaryStream.h" + +namespace aria2 { + +// Use ftruncate() system call or platform-specific counterpart to set +// file length. This allocator may not allocate file space, it just +// changes file length information. +class TruncFileAllocationIterator:public FileAllocationIterator { +private: + BinaryStream* stream_; + int64_t offset_; + int64_t totalLength_; +public: + TruncFileAllocationIterator(BinaryStream* stream, int64_t offset, + int64_t totalLength); + + virtual void allocateChunk(); + + virtual bool finished(); + + virtual int64_t getCurrentLength(); + + virtual int64_t getTotalLength(); +}; + +} // namespace aria2 + +#endif // D_TRUNC_FILE_ALLOCATION_ITERATOR_H diff --git a/src/prefs.cc b/src/prefs.cc index de459c5f..822a23bf 100644 --- a/src/prefs.cc +++ b/src/prefs.cc @@ -132,6 +132,7 @@ const std::string A2_V_FULL("full"); const std::string A2_V_GEOM("geom"); const std::string V_PREALLOC("prealloc"); const std::string V_FALLOC("falloc"); +const std::string V_TRUNC("trunc"); const std::string V_DEBUG("debug"); const std::string V_INFO("info"); const std::string V_NOTICE("notice"); diff --git a/src/prefs.h b/src/prefs.h index 31e0c165..9d9f8462 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -75,6 +75,7 @@ extern const std::string A2_V_FULL; extern const std::string A2_V_GEOM; extern const std::string V_PREALLOC; extern const std::string V_FALLOC; +extern const std::string V_TRUNC; extern const std::string V_DEBUG; extern const std::string V_INFO; extern const std::string V_NOTICE; diff --git a/src/usage_text.h b/src/usage_text.h index 21c31c66..de3f5a7e 100644 --- a/src/usage_text.h +++ b/src/usage_text.h @@ -137,7 +137,10 @@ " takes almost same time as 'prealloc' and it\n" \ " blocks aria2 entirely until allocation finishes.\n" \ " 'falloc' may not be available if your system\n" \ - " doesn't have posix_fallocate() function.") + " doesn't have posix_fallocate() function.\n" \ + " 'trunc' uses ftruncate() system call or\n" \ + " platform-specific counterpart to truncate a file\n" \ + " to a specified length.") #define TEXT_NO_FILE_ALLOCATION_LIMIT \ _(" --no-file-allocation-limit=SIZE No file allocation is made for files whose\n" \ " size is smaller than SIZE.\n" \