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
155 QMutableHashIterator<QString, QTime> it(m_pendingFiles);
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()
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 timeout()
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:50:57 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.