LeechCraft  0.6.70-15082-g543737046d
Modular cross-platform feature rich live environment.
networkdiskcachegc.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * LeechCraft - modular cross-platform feature rich internet client.
3  * Copyright (C) 2006-2014 Georg Rudoy
4  *
5  * Distributed under the Boost Software License, Version 1.0.
6  * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7  **********************************************************************/
8 
9 #include "networkdiskcachegc.h"
10 #include <QTimer>
11 #include <QDir>
12 #include <QDirIterator>
13 #include <QtConcurrentRun>
14 #include <QDateTime>
15 #include <QtDebug>
16 #include <util/sll/qtutil.h>
17 #include <util/sll/prelude.h>
18 #include <util/sll/util.h>
19 #include <util/threads/futures.h>
20 
21 namespace LC::Util
22 {
23  NetworkDiskCacheGC::NetworkDiskCacheGC ()
24  {
25  const auto timer = new QTimer { this };
26  connect (timer,
27  &QTimer::timeout,
28  this,
29  &NetworkDiskCacheGC::HandleCollect);
30  timer->start (60 * 60 * 1000);
31  }
32 
33  NetworkDiskCacheGC& NetworkDiskCacheGC::Instance ()
34  {
35  static NetworkDiskCacheGC gc;
36  return gc;
37  }
38 
39  namespace
40  {
41  struct SizeCollectInfo
42  {
43  QMultiMap<QDateTime, QString> Items_;
44  qint64 TotalSize_ = 0;
45  };
46 
47  SizeCollectInfo CollectSizes (const QString& cacheDirectory)
48  {
49  SizeCollectInfo result;
50 
51  const QDir::Filters filters = QDir::AllDirs | QDir:: Files | QDir::NoDotAndDotDot;
52  QDirIterator it { cacheDirectory, filters, QDirIterator::Subdirectories };
53 
54  while (it.hasNext ())
55  {
56  const auto& path = it.next ();
57  const auto& info = it.fileInfo ();
58  result.Items_.insert (info.birthTime (), path);
59  result.TotalSize_ += info.size ();
60  }
61 
62  return result;
63  }
64  }
65 
66  QFuture<qint64> NetworkDiskCacheGC::GetCurrentSize (const QString& path) const
67  {
68  return QtConcurrent::run ([path] { return CollectSizes (path).TotalSize_; });
69  }
70 
72  const std::function<int ()>& sizeGetter)
73  {
74  auto& list = Directories_ [path];
75  list.push_front (sizeGetter);
76  const auto thisItem = list.begin ();
77 
78  return Util::MakeScopeGuard ([this, path, thisItem] { UnregisterDirectory (path, thisItem); }).EraseType ();
79  }
80 
81  void NetworkDiskCacheGC::UnregisterDirectory (const QString& path, CacheSizeGetters_t::iterator pos)
82  {
83  if (!Directories_.contains (path))
84  {
85  qWarning () << Q_FUNC_INFO
86  << "unknown directory"
87  << path;
88  return;
89  }
90 
91  auto& list = Directories_ [path];
92  list.erase (pos);
93 
94  if (!list.empty ())
95  return;
96 
97  Directories_.remove (path);
98  LastSizes_.remove (path);
99  }
100 
101  namespace
102  {
103  qint64 Collector (const QString& cacheDirectory, qint64 goal)
104  {
105  if (cacheDirectory.isEmpty ())
106  return 0;
107 
108  qDebug () << Q_FUNC_INFO << "running..." << cacheDirectory << goal;
109 
110  auto sizeInfoResult = CollectSizes (cacheDirectory);
111 
112  for (auto i = sizeInfoResult.Items_.constBegin ();
113  i != sizeInfoResult.Items_.constEnd () && sizeInfoResult.TotalSize_ > goal;
114  ++i)
115  {
116  QFile file { *i };
117  sizeInfoResult.TotalSize_ -= file.size ();
118  file.remove ();
119  }
120 
121  qDebug () << "collector finished" << sizeInfoResult.TotalSize_;
122 
123  return sizeInfoResult.TotalSize_;
124  }
125  };
126 
127  void NetworkDiskCacheGC::HandleCollect ()
128  {
129  if (IsCollecting_)
130  {
131  qWarning () << Q_FUNC_INFO
132  << "already collecting";
133  return;
134  }
135 
137  for (const auto& pair : Util::Stlize (Directories_))
138  {
139  const auto& getters = pair.second;
140  const auto minSize = (*std::min_element (getters.begin (), getters.end (),
141  Util::ComparingBy (Apply))) ();
142  dirs.append ({ pair.first, minSize });
143  }
144 
145  if (dirs.isEmpty ())
146  return;
147 
148  IsCollecting_ = true;
149 
150  Util::Sequence (this,
151  QtConcurrent::run ([dirs]
152  {
153  QMap<QString, qint64> sizes;
154  for (const auto& pair : dirs)
155  sizes [pair.first] = Collector (pair.first, pair.second);
156  return sizes;
157  })) >>
158  [this] (const QMap<QString, qint64>& sizes)
159  {
160  IsCollecting_ = false;
161  for (const auto& pair : Util::Stlize (sizes))
162  LastSizes_ [pair.first] = pair.second;
163  };
164  }
165 }
LC::Util::Apply
constexpr auto Apply
Definition: prelude.h:238
LC::Util::DefaultScopeGuard
detail::ScopeGuard< detail::DefaultScopeGuardDeleter > DefaultScopeGuard
Definition: util.h:125
LC::Util::ComparingBy
auto ComparingBy(R r)
Definition: prelude.h:227
QList
Definition: ianrulesstorage.h:14
Items_
QMultiMap< QDateTime, QString > Items_
Definition: networkdiskcachegc.cpp:49
LC::Util
Definition: icoreproxy.h:33
TotalSize_
qint64 TotalSize_
Definition: networkdiskcachegc.cpp:50
LC::Util::Stlize
auto Stlize(Assoc &&assoc) noexcept
Converts an Qt's associative sequence assoc to an STL-like iteratable range.
Definition: qtutil.h:49
LC::Util::NetworkDiskCacheGC::RegisterDirectory
Util::DefaultScopeGuard RegisterDirectory(const QString &path, const std::function< int()> &sizeGetter)
Registers the given cache path.
Definition: networkdiskcachegc.cpp:77
futures.h
util.h
LC::Util::NetworkDiskCacheGC::GetCurrentSize
QFuture< qint64 > GetCurrentSize(const QString &path) const
Schedules calculation of the path total size.
Definition: networkdiskcachegc.cpp:72
qtutil.h
LC::Util::MakeScopeGuard
detail::ScopeGuard< F > MakeScopeGuard(const F &f)
Returns an object performing passed function on scope exit.
Definition: util.h:148
prelude.h
LC::Util::NetworkDiskCacheGC::Instance
static NetworkDiskCacheGC & Instance()
Returns a single global instance of the GC manager.
Definition: networkdiskcachegc.cpp:39
QFuture
Definition: idownload.h:17
QMap< QString, qint64 >
networkdiskcachegc.h