LeechCraft  0.6.70-13605-g8cd066ad6a
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  * Boost Software License - Version 1.0 - August 17th, 2003
6  *
7  * Permission is hereby granted, free of charge, to any person or organization
8  * obtaining a copy of the software and accompanying documentation covered by
9  * this license (the "Software") to use, reproduce, display, distribute,
10  * execute, and transmit the Software, and to prepare derivative works of the
11  * Software, and to permit third-parties to whom the Software is furnished to
12  * do so, all subject to the following:
13  *
14  * The copyright notices in the Software and this entire statement, including
15  * the above license grant, this restriction and the following disclaimer,
16  * must be included in all copies of the Software, in whole or in part, and
17  * all derivative works of the Software, unless such copies or derivative
18  * works are solely in the form of machine-executable object code generated by
19  * a source language processor.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  **********************************************************************/
29 
30 #include "networkdiskcachegc.h"
31 #include <QTimer>
32 #include <QDir>
33 #include <QDirIterator>
34 #include <QtConcurrentRun>
35 #include <QDateTime>
36 #include <QtDebug>
37 #include <util/compat/fileinfo.h>
38 #include <util/sll/qtutil.h>
39 #include <util/sll/prelude.h>
40 #include <util/sll/util.h>
41 #include <util/threads/futures.h>
42 
43 namespace LC
44 {
45 namespace Util
46 {
47  NetworkDiskCacheGC::NetworkDiskCacheGC ()
48  {
49  const auto timer = new QTimer { this };
50  connect (timer,
51  SIGNAL (timeout ()),
52  this,
53  SLOT (handleCollect ()));
54  timer->start (60 * 60 * 1000);
55  }
56 
57  NetworkDiskCacheGC& NetworkDiskCacheGC::Instance ()
58  {
59  static NetworkDiskCacheGC gc;
60  return gc;
61  }
62 
63  namespace
64  {
65  struct SizeCollectInfo
66  {
67  QMultiMap<QDateTime, QString> Items_;
68  qint64 TotalSize_ = 0;
69  };
70 
71  SizeCollectInfo CollectSizes (const QString& cacheDirectory)
72  {
73  SizeCollectInfo result;
74 
75  const QDir::Filters filters = QDir::AllDirs | QDir:: Files | QDir::NoDotAndDotDot;
76  QDirIterator it { cacheDirectory, filters, QDirIterator::Subdirectories };
77 
78  while (it.hasNext ())
79  {
80  const auto& path = it.next ();
81  const auto& info = it.fileInfo ();
82  result.Items_.insert (Compat::Created (info), path);
83  result.TotalSize_ += info.size ();
84  }
85 
86  return result;
87  }
88  }
89 
90  QFuture<qint64> NetworkDiskCacheGC::GetCurrentSize (const QString& path) const
91  {
92  return QtConcurrent::run ([path] { return CollectSizes (path).TotalSize_; });
93  }
94 
96  const std::function<int ()>& sizeGetter)
97  {
98  auto& list = Directories_ [path];
99  list.push_front (sizeGetter);
100  const auto thisItem = list.begin ();
101 
102  return Util::MakeScopeGuard ([this, path, thisItem] { UnregisterDirectory (path, thisItem); }).EraseType ();
103  }
104 
105  void NetworkDiskCacheGC::UnregisterDirectory (const QString& path, CacheSizeGetters_t::iterator pos)
106  {
107  if (!Directories_.contains (path))
108  {
109  qWarning () << Q_FUNC_INFO
110  << "unknown directory"
111  << path;
112  return;
113  }
114 
115  auto& list = Directories_ [path];
116  list.erase (pos);
117 
118  if (!list.isEmpty ())
119  return;
120 
121  Directories_.remove (path);
122  LastSizes_.remove (path);
123  }
124 
125  namespace
126  {
127  qint64 Collector (const QString& cacheDirectory, qint64 goal)
128  {
129  if (cacheDirectory.isEmpty ())
130  return 0;
131 
132  qDebug () << Q_FUNC_INFO << "running..." << cacheDirectory << goal;
133 
134  auto sizeInfoResult = CollectSizes (cacheDirectory);
135 
136  for (auto i = sizeInfoResult.Items_.constBegin ();
137  i != sizeInfoResult.Items_.constEnd () && sizeInfoResult.TotalSize_ > goal;
138  ++i)
139  {
140  QFile file { *i };
141  sizeInfoResult.TotalSize_ -= file.size ();
142  file.remove ();
143  }
144 
145  qDebug () << "collector finished" << sizeInfoResult.TotalSize_;
146 
147  return sizeInfoResult.TotalSize_;
148  }
149  };
150 
151  void NetworkDiskCacheGC::handleCollect ()
152  {
153  if (IsCollecting_)
154  {
155  qWarning () << Q_FUNC_INFO
156  << "already collecting";
157  return;
158  }
159 
161  for (const auto& pair : Util::Stlize (Directories_))
162  {
163  const auto& getters = pair.second;
164  const auto minSize = (*std::min_element (getters.begin (), getters.end (),
165  Util::ComparingBy (Apply))) ();
166  dirs.append ({ pair.first, minSize });
167  }
168 
169  if (dirs.isEmpty ())
170  return;
171 
172  IsCollecting_ = true;
173 
174  Util::Sequence (this,
175  QtConcurrent::run ([dirs]
176  {
177  QMap<QString, qint64> sizes;
178  for (const auto& pair : dirs)
179  sizes [pair.first] = Collector (pair.first, pair.second);
180  return sizes;
181  })) >>
182  [this] (const QMap<QString, qint64>& sizes)
183  {
184  IsCollecting_ = false;
185  for (const auto& pair : Util::Stlize (sizes))
186  LastSizes_ [pair.first] = pair.second;
187  };
188  }
189 }
190 }
fileinfo.h
LC::Util::Apply
constexpr auto Apply
Definition: prelude.h:252
LC::Util::Stlize
auto Stlize(Assoc &&assoc)
Converts an Qt's associative sequence assoc to an STL-like iteratable range.
Definition: qtutil.h:140
LC::Util::DefaultScopeGuard
detail::ScopeGuard< detail::DefaultScopeGuardDeleter > DefaultScopeGuard
Definition: util.h:185
LC::Util::ComparingBy
auto ComparingBy(R r)
Definition: prelude.h:241
QList
Definition: ianrulesstorage.h:34
Items_
QMultiMap< QDateTime, QString > Items_
Definition: networkdiskcachegc.cpp:118
TotalSize_
qint64 TotalSize_
Definition: networkdiskcachegc.cpp:119
LC::Util::NetworkDiskCacheGC::RegisterDirectory
Util::DefaultScopeGuard RegisterDirectory(const QString &path, const std::function< int()> &sizeGetter)
Registers the given cache path.
Definition: networkdiskcachegc.cpp:146
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:141
qtutil.h
LC::Util::MakeScopeGuard
detail::ScopeGuard< F > MakeScopeGuard(const F &f)
Returns an object performing passed function on scope exit.
Definition: util.h:208
prelude.h
LC
Definition: constants.h:34
LC::Util::NetworkDiskCacheGC::Instance
static NetworkDiskCacheGC & Instance()
Returns a single global instance of the GC manager.
Definition: networkdiskcachegc.cpp:108
QFuture
Definition: idownload.h:39
QMap< QString, qint64 >
LC::Util::Compat::Created
QDateTime Created(const QFileInfo &info)
Definition: fileinfo.h:61
networkdiskcachegc.h