From f314719618d181036ceebcf45338ab76559daf55 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 27 Nov 2012 22:04:59 +0900 Subject: Added --disk-cache option This option enables disk cache. If SIZE is 0, the disk cache is disabled. This feature caches the downloaded data in memory, which grows to at most SIZE bytes. The cache storage is created for aria2 instance and shared by all downloads. The one advantage of the disk cache is reduce the disk seek time because the data is written in larger unit and it is reordered by the offset of the file. If the underlying file is heavily fragmented it is not the case. --- src/WrDiskCache.cc | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 src/WrDiskCache.cc (limited to 'src/WrDiskCache.cc') diff --git a/src/WrDiskCache.cc b/src/WrDiskCache.cc new file mode 100644 index 00000000..79af80e9 --- /dev/null +++ b/src/WrDiskCache.cc @@ -0,0 +1,129 @@ +/* */ +#include "WrDiskCache.h" +#include "WrDiskCacheEntry.h" +#include "LogFactory.h" +#include "fmt.h" + +namespace aria2 { + +WrDiskCache::WrDiskCache(size_t limit) + : limit_(limit), + total_(0), + clock_(0) +{} + +WrDiskCache::~WrDiskCache() +{ + if(total_) { + A2_LOG_WARN(fmt("Write disk cache is not empty size=%lu", + static_cast(total_))); + } +} + +bool WrDiskCache::add(WrDiskCacheEntry* ent) +{ + ent->setSizeKey(ent->getSize()); + ent->setLastUpdate(++clock_); + std::pair rv = set_.insert(ent); + if(rv.second) { + total_ += ent->getSize(); + ensureLimit(); + return true; + } else { + A2_LOG_WARN(fmt("Found duplicate cache entry a.{size=%lu,clock=%"PRId64 + "} b{size=%lu,clock=%"PRId64"}", + static_cast((*rv.first)->getSize()), + (*rv.first)->getLastUpdate(), + static_cast(ent->getSize()), + ent->getLastUpdate())); + return false; + } +} + +bool WrDiskCache::remove(WrDiskCacheEntry* ent) +{ + if(set_.erase(ent)) { + A2_LOG_DEBUG(fmt("Removed cache entry size=%lu, clock=%"PRId64, + static_cast(ent->getSize()), + ent->getLastUpdate())); + total_ -= ent->getSize(); + return true; + } else { + return false; + } +} + +bool WrDiskCache::update(WrDiskCacheEntry* ent, ssize_t delta) +{ + if(!set_.erase(ent)) { + return false; + } + A2_LOG_DEBUG(fmt("Update cache entry size=%lu, delta=%ld, clock=%"PRId64, + static_cast(ent->getSize()), + static_cast(delta), + ent->getLastUpdate())); + + ent->setSizeKey(ent->getSize()); + ent->setLastUpdate(++clock_); + set_.insert(ent); + + if(delta < 0) { + assert(total_ >= static_cast(-delta)); + } + total_ += delta; + ensureLimit(); + return true; +} + +void WrDiskCache::ensureLimit() +{ + while(total_ > limit_) { + EntrySet::iterator i = set_.begin(); + total_ -= (*i)->getSize(); + (*i)->writeToDisk(); + WrDiskCacheEntry* ent = *i; + A2_LOG_DEBUG(fmt("Force flush cache entry size=%lu, clock=%"PRId64, + static_cast(ent->getSizeKey()), + ent->getLastUpdate())); + set_.erase(i); + + ent->setSizeKey(ent->getSize()); + ent->setLastUpdate(++clock_); + set_.insert(ent); + } +} + +} // namespace aria2 -- cgit