Baloo

pendingfilequeue.cpp
1/*
2 This file is part of the KDE Baloo project.
3 SPDX-FileCopyrightText: 2011 Sebastian Trueg <trueg@kde.org>
4 SPDX-FileCopyrightText: 2013-2014 Vishesh Handa <me@vhanda.in>
5
6 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7*/
8
9#include "pendingfilequeue.h"
10
11#include <memory>
12
13#include <QDateTime>
14
15using namespace Baloo;
16
17PendingFileQueue::PendingFileQueue(QObject* parent)
18 : QObject(parent)
19{
20 m_cacheTimer.setInterval(10);
21 m_cacheTimer.setSingleShot(true);
22 connect(&m_cacheTimer, &QTimer::timeout, [this] {
23 PendingFileQueue::processCache(QTime::currentTime());
24 });
25
26 m_trackingTime = 120 * 1000;
27
28 m_clearRecentlyEmittedTimer.setInterval(m_trackingTime);
29 m_clearRecentlyEmittedTimer.setSingleShot(true);
30 connect(&m_clearRecentlyEmittedTimer, &QTimer::timeout, [this] {
31 PendingFileQueue::clearRecentlyEmitted(QTime::currentTime());
32 });
33
34 m_minTimeout = 5 * 1000;
35 m_maxTimeout = 60 * 1000;
36 m_pendingFilesTimer.setInterval(m_minTimeout);
37 m_pendingFilesTimer.setSingleShot(true);
38 connect(&m_pendingFilesTimer, &QTimer::timeout, [this] {
39 PendingFileQueue::processPendingFiles(QTime::currentTime());
40 });
41}
42
43PendingFileQueue::~PendingFileQueue()
44{
45}
46
47void PendingFileQueue::enqueue(const PendingFile& file)
48{
49 // If we get an event to remove /home/A, remove all events for everything under /home/A/
50
51 if (file.shouldRemoveIndex() && file.path().endsWith(QLatin1Char('/'))) {
52 const auto keepFile = [&file](const PendingFile& pending) {
53 return !pending.path().startsWith(file.path());
54 };
55 const auto end = m_cache.end();
56 // std::partition moves all matching entries to the first partition
57 const auto droppedFilesBegin = std::partition(m_cache.begin(), end, keepFile);
58 for (auto it = droppedFilesBegin; it != end; it++) {
59 m_pendingFiles.remove(it->path());
60 m_recentlyEmitted.remove(it->path());
61 }
62 m_cache.erase(droppedFilesBegin, end);
63 }
64
65 if (file.shouldRemoveIndex()) {
66 m_cache.removeOne(file);
67 m_pendingFiles.remove(file.path());
68 Q_EMIT removeFileIndex(file.path());
69 return;
70 }
71
72 int i = m_cache.indexOf(file);
73 if (i == -1) {
74 m_cache << file;
75 } else {
76 m_cache[i].merge(file);
77 }
78
79 m_cacheTimer.start();
80}
81
82void PendingFileQueue::processCache(const QTime& currentTime)
83{
84 for (const PendingFile& file : std::as_const(m_cache)) {
85 if (file.shouldIndexXAttrOnly()) {
86 Q_EMIT indexXAttr(file.path());
87 }
88 else if (file.shouldIndexContents()) {
89 if (m_pendingFiles.contains(file.path())) {
90 QTime time = m_pendingFiles[file.path()];
91
92 int msecondsLeft = currentTime.msecsTo(time);
93 msecondsLeft = qBound(m_minTimeout, msecondsLeft * 2, m_maxTimeout);
94
95 time = currentTime.addMSecs(msecondsLeft);
96 m_pendingFiles[file.path()] = time;
97 }
98 else if (m_recentlyEmitted.contains(file.path())) {
99 QTime time = currentTime.addMSecs(m_minTimeout);
100 m_pendingFiles[file.path()] = time;
101 }
102 else {
103 if (file.isNewFile()) {
104 Q_EMIT indexNewFile(file.path());
105 } else {
106 Q_EMIT indexModifiedFile(file.path());
107 }
108 m_recentlyEmitted.insert(file.path(), currentTime);
109 }
110 } else {
111 Q_ASSERT_X(false, "FileWatch", "The PendingFile should always have some flags set");
112 }
113 }
114
115 m_cache.clear();
116
117 if (!m_pendingFiles.isEmpty() && !m_pendingFilesTimer.isActive()) {
118 m_pendingFilesTimer.setInterval(m_minTimeout);
119 m_pendingFilesTimer.start();
120 }
121
122 if (!m_recentlyEmitted.isEmpty() && !m_clearRecentlyEmittedTimer.isActive()) {
123 m_clearRecentlyEmittedTimer.setInterval(m_trackingTime);
124 m_clearRecentlyEmittedTimer.start();
125 }
126}
127
128void PendingFileQueue::clearRecentlyEmitted(const QTime& time)
129{
130 int nextUpdate = m_trackingTime;
131
132 QMutableHashIterator<QString, QTime> it(m_recentlyEmitted);
133 while (it.hasNext()) {
134 it.next();
135
136 int msecondsSinceEmitted = it.value().msecsTo(time);
137 if (msecondsSinceEmitted >= m_trackingTime) {
138 it.remove();
139 } else {
140 int timeLeft = m_trackingTime - msecondsSinceEmitted;
141 nextUpdate = qMin(nextUpdate, timeLeft);
142 }
143 }
144
145 if (!m_recentlyEmitted.isEmpty()) {
146 m_clearRecentlyEmittedTimer.setInterval(nextUpdate);
147 m_clearRecentlyEmittedTimer.start();
148 }
149}
150
151void PendingFileQueue::processPendingFiles(const QTime& currentTime)
152{
153 int nextUpdate = m_maxTimeout;
154
156 while (it.hasNext()) {
157 it.next();
158
159 int mSecondsLeft = currentTime.msecsTo(it.value());
160 if (mSecondsLeft <= 0) {
161 Q_EMIT indexModifiedFile(it.key());
162 m_recentlyEmitted.insert(it.key(), currentTime);
163
164 it.remove();
165 }
166 else {
167 nextUpdate = qMin(mSecondsLeft, nextUpdate);
168 }
169 }
170
171 if (!m_pendingFiles.isEmpty()) {
172 m_pendingFilesTimer.setInterval(nextUpdate);
173 m_pendingFilesTimer.start();
174 }
175
176 if (!m_recentlyEmitted.isEmpty() && !m_clearRecentlyEmittedTimer.isActive()) {
177 m_clearRecentlyEmittedTimer.setInterval(m_trackingTime);
178 m_clearRecentlyEmittedTimer.start();
179 }
180}
181
182void PendingFileQueue::setTrackingTime(int seconds)
183{
184 m_trackingTime = seconds * 1000;
185}
186
187void PendingFileQueue::setMinimumTimeout(int seconds)
188{
189 m_minTimeout = seconds * 1000;
190}
191
192void PendingFileQueue::setMaximumTimeout(int seconds)
193{
194 m_maxTimeout = seconds * 1000;
195}
196
197#include "moc_pendingfilequeue.cpp"
Represents a file which needs to be indexed.
Definition pendingfile.h:20
Implements storage for docIds without any associated data Instantiated for:
Definition coding.cpp:11
const QList< QKeySequence > & end()
bool contains(const Key &key) const const
iterator insert(const Key &key, const T &value)
bool isEmpty() const const
bool remove(const Key &key)
iterator begin()
void clear()
iterator end()
iterator erase(const_iterator begin, const_iterator end)
qsizetype indexOf(const AT &value, qsizetype from) const const
void remove(qsizetype i, qsizetype n)
bool removeOne(const AT &t)
bool startsWith(parameter_type value) const const
T value(qsizetype i) const const
Q_EMITQ_EMIT
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QTime addMSecs(int ms) const const
QTime currentTime()
int msecsTo(QTime t) const const
void setInterval(int msec)
bool isActive() const const
void start()
void timeout()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:16 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.