Baloo

pendingfilequeue.cpp
1 /*
2  This file is part of the KDE Baloo project.
3  SPDX-FileCopyrightText: 2011 Sebastian Trueg <[email protected]>
4  SPDX-FileCopyrightText: 2013-2014 Vishesh Handa <[email protected]>
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 
15 using namespace Baloo;
16 
17 PendingFileQueue::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 
43 PendingFileQueue::~PendingFileQueue()
44 {
45 }
46 
47 void 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 
82 void 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 
128 void 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 
151 void 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 
182 void PendingFileQueue::setTrackingTime(int seconds)
183 {
184  m_trackingTime = seconds * 1000;
185 }
186 
187 void PendingFileQueue::setMinimumTimeout(int seconds)
188 {
189  m_minTimeout = seconds * 1000;
190 }
191 
192 void PendingFileQueue::setMaximumTimeout(int seconds)
193 {
194  m_maxTimeout = seconds * 1000;
195 }
196 
197 #include "moc_pendingfilequeue.cpp"
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
Represents a file which needs to be indexed.
Definition: pendingfile.h:19
QTime addMSecs(int ms) const const
QTime currentTime()
Implements storage for docIds without any associated data Instantiated for:
Definition: coding.cpp:11
void timeout()
int msecsTo(const QTime &t) const const
void merge(const PendingFile &file)
Takes a PendingFile file and merges its flags into the current PendingFile.
Definition: pendingfile.cpp:54
const QList< QKeySequence > & end()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Nov 29 2023 03:56:26 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.