33 #include <QDirIterator>
45 NetworkDiskCacheGC::NetworkDiskCacheGC ()
47 const auto timer =
new QTimer {
this };
51 SLOT (handleCollect ()));
52 timer->start (60 * 60 * 1000);
63 struct SizeCollectInfo
65 QMultiMap<QDateTime, QString>
Items_;
69 SizeCollectInfo CollectSizes (
const QString& cacheDirectory)
71 SizeCollectInfo result;
73 const QDir::Filters filters = QDir::AllDirs | QDir:: Files | QDir::NoDotAndDotDot;
74 QDirIterator it { cacheDirectory, filters, QDirIterator::Subdirectories };
78 const auto& path = it.next ();
79 const auto& info = it.fileInfo ();
80 result.Items_.insert (info.created (), path);
81 result.TotalSize_ += info.size ();
90 return QtConcurrent::run ([path] {
return CollectSizes (path).TotalSize_; });
94 const std::function<
int ()>& sizeGetter)
96 auto& list = Directories_ [path];
97 list.push_front (sizeGetter);
98 const auto thisItem = list.begin ();
100 return Util::MakeScopeGuard ([
this, path, thisItem] { UnregisterDirectory (path, thisItem); }).EraseType ();
103 void NetworkDiskCacheGC::UnregisterDirectory (
const QString& path, CacheSizeGetters_t::iterator pos)
105 if (!Directories_.contains (path))
107 qWarning () << Q_FUNC_INFO
108 <<
"unknown directory"
113 auto& list = Directories_ [path];
116 if (!list.isEmpty ())
119 Directories_.remove (path);
120 LastSizes_.remove (path);
125 qint64 Collector (
const QString& cacheDirectory, qint64 goal)
127 if (cacheDirectory.isEmpty ())
130 qDebug () << Q_FUNC_INFO <<
"running..." << cacheDirectory << goal;
132 auto sizeInfoResult = CollectSizes (cacheDirectory);
134 for (
auto i = sizeInfoResult.Items_.constBegin ();
135 i != sizeInfoResult.Items_.constEnd () && sizeInfoResult.TotalSize_ > goal;
139 sizeInfoResult.TotalSize_ -= file.size ();
143 qDebug () <<
"collector finished" << sizeInfoResult.TotalSize_;
145 return sizeInfoResult.TotalSize_;
149 void NetworkDiskCacheGC::handleCollect ()
153 qWarning () << Q_FUNC_INFO
154 <<
"already collecting";
161 const auto& getters = pair.second;
162 const auto minSize = (*std::min_element (getters.begin (), getters.end (),
164 dirs.append ({ pair.first, minSize });
170 IsCollecting_ =
true;
174 return QtConcurrent::run ([dirs]
177 for (
const auto& pair : dirs)
178 sizes [pair.first] = Collector (pair.first, pair.second);
184 IsCollecting_ =
false;
186 LastSizes_ [pair.first] = pair.second;
QMultiMap< QDateTime, QString > Items_
QFuture< qint64 > GetCurrentSize(const QString &path) const
Schedules calculation of the path total size.
detail::ScopeGuard< F > MakeScopeGuard(const F &f)
Returns an object performing passed function on scope exit.
Garbage collection for a set of network disk caches.
static NetworkDiskCacheGC & Instance()
Returns a single global instance of the GC manager.
detail::ComparingByClosure< R > ComparingBy(R r)
auto Stlize(Assoc &&assoc) -> detail::StlAssocRange< decltype(assoc.begin()), Assoc, PairType >
Converts an Qt's associative sequence assoc to an STL-like iteratable range.
struct LeechCraft::Util::@0 Apply
Util::DefaultScopeGuard RegisterDirectory(const QString &path, const std::function< int()> &sizeGetter)
Registers the given cache path.
void ExecuteFuture(Executor f, ResultHandler rh, QObject *parent, Args...args)
Runs a QFuture-returning function and feeding the future to a handler when it is ready.