• Skip to content
  • Skip to link menu
Brand

API Documentation

  1. KDE API Reference
  2. KDE PIM
  3. Akonadi
  • KDE Home
  • Contact Us

Quick Links

Skip menu "Akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • File List
  • Modules
  • Related Pages

Class Picker

About

PIM Storage Framework

Maintainer
Daniel Vrátil
Supported platforms
Linux
Community
IRC: #akonadi on Freenode
Mailing list: kde-pim
Use with CMake
find_package(KF5AkonadiCore)
target_link_libraries(yourapp KF5::AkonadiCore)
Use with QMake
QT += AkonadiCore 
Clone
git clone git://anongit.kde.org/akonadi.git
Browse source
Akonadi on cgit.kde.org

Akonadi

  • kde
  • pim
  • akonadi
  • src
  • server
aggregatedfetchscope.cpp
1 /*
2  Copyright (c) 2017 Daniel Vrátil <[email protected]>
3 
4  This library is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Library General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This library is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to the
16  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  02110-1301, USA.
18 */
19 
20 #include "aggregatedfetchscope.h"
21 #include <private/protocol_p.h>
22 #include <shared/akranges.h>
23 
24 #include <QMutex>
25 #include <QMutexLocker>
26 
27 #define LOCKED_D(name) \
28  Q_D(name); \
29  QMutexLocker lock(&d->lock);
30 
31 
32 namespace Akonadi {
33 namespace Server {
34 
35 class AggregatedFetchScopePrivate
36 {
37 public:
38  AggregatedFetchScopePrivate()
39  : lock(QMutex::Recursive) // recursive so that we can call our own getters/setters
40  {}
41 
42  inline void addToSet(const QByteArray &value, QSet<QByteArray> &set, QHash<QByteArray, int> &count)
43  {
44  auto it = count.find(value);
45  if (it == count.end()) {
46  it = count.insert(value, 0);
47  set.insert(value);
48  }
49  ++(*it);
50  }
51 
52  inline void removeFromSet(const QByteArray &value, QSet<QByteArray> &set, QHash<QByteArray, int> &count)
53  {
54  auto it = count.find(value);
55  if (it == count.end()) {
56  return;
57  }
58 
59  if (--(*it) == 0) {
60  count.erase(it);
61  set.remove(value);
62  }
63  }
64 
65  inline void updateBool(bool newValue, int &store)
66  {
67  store += newValue ? 1 : -1;
68  }
69 
70  inline void applySet(const QSet<QByteArray> &oldSet, const QSet<QByteArray> &newSet,
71  QSet<QByteArray> &set, QHash<QByteArray, int> &count)
72  {
73  const auto added = newSet - oldSet;
74  for (const auto &value : added) {
75  addToSet(value, set, count);
76  }
77  const auto removed = oldSet - newSet;
78  for (const auto &value : removed) {
79  removeFromSet(value, set, count);
80  }
81  }
82 
83 public:
84  mutable QMutex lock;
85 };
86 
87 class AggregatedCollectionFetchScopePrivate : public AggregatedFetchScopePrivate
88 {
89 public:
90  QSet<QByteArray> attrs;
91  QHash<QByteArray, int> attrsCount;
92  int subscribers = 0;
93  int fetchIdOnly = 0;
94  int fetchStats = 0;
95 };
96 
97 
98 class AggregatedTagFetchScopePrivate : public AggregatedFetchScopePrivate
99 {
100 public:
101  QSet<QByteArray> attrs;
102  QHash<QByteArray, int> attrsCount;
103  int subscribers = 0;
104  int fetchIdOnly = 0;
105  int fetchRemoteId = 0;
106  int doNotFetchAllAttributes = 0;
107 };
108 
109 class AggregatedItemFetchScopePrivate : public AggregatedFetchScopePrivate
110 {
111 public:
112  mutable Protocol::ItemFetchScope mCachedScope;
113  mutable bool mCachedScopeValid = false; // use std::optional for mCachedScope
114 
115  QSet<QByteArray> parts;
116  QHash<QByteArray, int> partsCount;
117  QSet<QByteArray> tags;
118  QHash<QByteArray, int> tagsCount;
119  int subscribers = 0;
120  int ancestors[3] = { 0, 0, 0 }; // 3 = size of AncestorDepth enum
121  int cacheOnly = 0;
122  int fullPayload = 0;
123  int allAttributes = 0;
124  int fetchSize = 0;
125  int fetchMTime = 0;
126  int fetchRRev = 0;
127  int ignoreErrors = 0;
128  int fetchFlags = 0;
129  int fetchRID = 0;
130  int fetchGID = 0;
131  int fetchTags = 0;
132  int fetchRelations = 0;
133  int fetchVRefs = 0;
134 };
135 
136 } // namespace Server
137 } // namespace Akonadi
138 
139 using namespace Akonadi;
140 using namespace Akonadi::Protocol;
141 using namespace Akonadi::Server;
142 
143 AggregatedCollectionFetchScope::AggregatedCollectionFetchScope()
144  : d_ptr(new AggregatedCollectionFetchScopePrivate)
145 {
146 }
147 
148 AggregatedCollectionFetchScope::~AggregatedCollectionFetchScope()
149 {
150  delete d_ptr;
151 }
152 
153 void AggregatedCollectionFetchScope::apply(const Protocol::CollectionFetchScope &oldScope,
154  const Protocol::CollectionFetchScope &newScope)
155 {
156  LOCKED_D(AggregatedCollectionFetchScope)
157 
158  if (newScope.includeStatistics() != oldScope.includeStatistics()) {
159  d->updateBool(newScope.includeStatistics(), d->fetchStats);
160  }
161  if (newScope.fetchIdOnly() != oldScope.fetchIdOnly()) {
162  d->updateBool(newScope.fetchIdOnly(), d->fetchIdOnly);
163  }
164  if (newScope.attributes() != oldScope.attributes()) {
165  d->applySet(oldScope.attributes(), newScope.attributes(), d->attrs, d->attrsCount);
166  }
167 }
168 
169 QSet<QByteArray> AggregatedCollectionFetchScope::attributes() const
170 {
171  LOCKED_D(const AggregatedCollectionFetchScope)
172  return d->attrs;
173 }
174 
175 bool AggregatedCollectionFetchScope::fetchIdOnly() const
176 {
177  LOCKED_D(const AggregatedCollectionFetchScope)
178  // Aggregation: we can return true only if everyone wants fetchIdOnly,
179  // otherwise there's at least one subscriber who wants everything
180  return d->fetchIdOnly == d->subscribers;
181 }
182 
183 bool AggregatedCollectionFetchScope::fetchStatistics() const
184 {
185  LOCKED_D(const AggregatedCollectionFetchScope);
186  // Aggregation: return true if at least one subscriber wants stats
187  return d->fetchStats > 0;
188 }
189 
190 void AggregatedCollectionFetchScope::addSubscriber()
191 {
192  LOCKED_D(AggregatedCollectionFetchScope)
193  ++d->subscribers;
194 }
195 
196 void AggregatedCollectionFetchScope::removeSubscriber()
197 {
198  LOCKED_D(AggregatedCollectionFetchScope)
199  --d->subscribers;
200 }
201 
202 
203 AggregatedItemFetchScope::AggregatedItemFetchScope()
204  : d_ptr(new AggregatedItemFetchScopePrivate)
205 {
206 }
207 
208 AggregatedItemFetchScope::~AggregatedItemFetchScope()
209 {
210  delete d_ptr;
211 }
212 
213 void AggregatedItemFetchScope::apply(const Protocol::ItemFetchScope &oldScope,
214  const Protocol::ItemFetchScope &newScope)
215 {
216  LOCKED_D(AggregatedItemFetchScope);
217 
218  const auto newParts = newScope.requestedParts() | AkRanges::Actions::toQSet;
219  const auto oldParts = oldScope.requestedParts() | AkRanges::Actions::toQSet;
220  if (newParts != oldParts) {
221  d->applySet(oldParts, newParts, d->parts, d->partsCount);
222  }
223  if (newScope.ancestorDepth() != oldScope.ancestorDepth()) {
224  updateAncestorDepth(oldScope.ancestorDepth(), newScope.ancestorDepth());
225  }
226  if (newScope.cacheOnly() != oldScope.cacheOnly()) {
227  d->updateBool(newScope.cacheOnly(), d->cacheOnly);
228  }
229  if (newScope.fullPayload() != oldScope.fullPayload()) {
230  d->updateBool(newScope.fullPayload(), d->fullPayload);
231  }
232  if (newScope.allAttributes() != oldScope.allAttributes()) {
233  d->updateBool(newScope.allAttributes(), d->allAttributes);
234  }
235  if (newScope.fetchSize() != oldScope.fetchSize()) {
236  d->updateBool(newScope.fetchSize(), d->fetchSize);
237  }
238  if (newScope.fetchMTime() != oldScope.fetchMTime()) {
239  d->updateBool(newScope.fetchMTime(), d->fetchMTime);
240  }
241  if (newScope.fetchRemoteRevision() != oldScope.fetchRemoteRevision()) {
242  d->updateBool(newScope.fetchRemoteRevision(), d->fetchRRev);
243  }
244  if (newScope.ignoreErrors() != oldScope.ignoreErrors()) {
245  d->updateBool(newScope.ignoreErrors(), d->ignoreErrors);
246  }
247  if (newScope.fetchFlags() != oldScope.fetchFlags()) {
248  d->updateBool(newScope.fetchFlags(), d->fetchFlags);
249  }
250  if (newScope.fetchRemoteId() != oldScope.fetchRemoteId()) {
251  d->updateBool(newScope.fetchRemoteId(), d->fetchRID);
252  }
253  if (newScope.fetchGID() != oldScope.fetchGID()) {
254  d->updateBool(newScope.fetchGID(), d->fetchGID);
255  }
256  if (newScope.fetchTags() != oldScope.fetchTags()) {
257  d->updateBool(newScope.fetchTags(), d->fetchTags);
258  }
259  if (newScope.fetchRelations() != oldScope.fetchRelations()) {
260  d->updateBool(newScope.fetchRelations(), d->fetchRelations);
261  }
262  if (newScope.fetchVirtualReferences() != oldScope.fetchVirtualReferences()) {
263  d->updateBool(newScope.fetchVirtualReferences(), d->fetchVRefs);
264  }
265 
266  d->mCachedScopeValid = false;
267 }
268 
269 ItemFetchScope AggregatedItemFetchScope::toFetchScope() const
270 {
271  LOCKED_D(const AggregatedItemFetchScope);
272  if (d->mCachedScopeValid) {
273  return d->mCachedScope;
274  }
275 
276  d->mCachedScope = ItemFetchScope();
277  d->mCachedScope.setRequestedParts(d->parts | AkRanges::Actions::toQVector);
278  d->mCachedScope.setAncestorDepth(ancestorDepth());
279 
280  d->mCachedScope.setFetch(ItemFetchScope::CacheOnly, cacheOnly());
281  d->mCachedScope.setFetch(ItemFetchScope::FullPayload, fullPayload());
282  d->mCachedScope.setFetch(ItemFetchScope::AllAttributes, allAttributes());
283  d->mCachedScope.setFetch(ItemFetchScope::Size, fetchSize());
284  d->mCachedScope.setFetch(ItemFetchScope::MTime, fetchMTime());
285  d->mCachedScope.setFetch(ItemFetchScope::RemoteRevision, fetchRemoteRevision());
286  d->mCachedScope.setFetch(ItemFetchScope::IgnoreErrors, ignoreErrors());
287  d->mCachedScope.setFetch(ItemFetchScope::Flags, fetchFlags());
288  d->mCachedScope.setFetch(ItemFetchScope::RemoteID, fetchRemoteId());
289  d->mCachedScope.setFetch(ItemFetchScope::GID, fetchGID());
290  d->mCachedScope.setFetch(ItemFetchScope::Tags, fetchTags());
291  d->mCachedScope.setFetch(ItemFetchScope::Relations, fetchRelations());
292  d->mCachedScope.setFetch(ItemFetchScope::VirtReferences, fetchVirtualReferences());
293  d->mCachedScopeValid = true;
294  return d->mCachedScope;
295 }
296 
297 QSet<QByteArray> AggregatedItemFetchScope::requestedParts() const
298 {
299  LOCKED_D(const AggregatedItemFetchScope)
300  return d->parts;
301 }
302 
303 ItemFetchScope::AncestorDepth AggregatedItemFetchScope::ancestorDepth() const
304 {
305  LOCKED_D(const AggregatedItemFetchScope)
306  // Aggregation: return the largest depth with at least one subscriber
307  if (d->ancestors[ItemFetchScope::AllAncestors] > 0) {
308  return ItemFetchScope::AllAncestors;
309  } else if (d->ancestors[ItemFetchScope::ParentAncestor] > 0) {
310  return ItemFetchScope::ParentAncestor;
311  } else {
312  return ItemFetchScope::NoAncestor;
313  }
314 }
315 
316 void AggregatedItemFetchScope::updateAncestorDepth(ItemFetchScope::AncestorDepth oldDepth,
317  ItemFetchScope::AncestorDepth newDepth)
318 {
319  LOCKED_D(AggregatedItemFetchScope)
320  if (d->ancestors[oldDepth] > 0) {
321  --d->ancestors[oldDepth];
322  }
323  ++d->ancestors[newDepth];
324 }
325 
326 bool AggregatedItemFetchScope::cacheOnly() const
327 {
328  LOCKED_D(const AggregatedItemFetchScope)
329  // Aggregation: we can return true only if everyone wants cached data only,
330  // otherwise there's at least one subscriber who wants uncached data
331  return d->cacheOnly == d->subscribers;
332 }
333 
334 bool AggregatedItemFetchScope::fullPayload() const
335 {
336  LOCKED_D(const AggregatedItemFetchScope)
337  // Aggregation: return true if there's at least one subscriber who wants the
338  // full payload
339  return d->fullPayload > 0;
340 }
341 
342 bool AggregatedItemFetchScope::allAttributes() const
343 {
344  LOCKED_D(const AggregatedItemFetchScope)
345  // Aggregation: return true if there's at least one subscriber who wants
346  // all attributes
347  return d->allAttributes > 0;
348 }
349 
350 bool AggregatedItemFetchScope::fetchSize() const
351 {
352  LOCKED_D(const AggregatedItemFetchScope)
353  // Aggregation: return true if there's at least one subscriber who wants size
354  return d->fetchSize > 0;
355 }
356 
357 bool AggregatedItemFetchScope::fetchMTime() const
358 {
359  LOCKED_D(const AggregatedItemFetchScope)
360  // Aggregation: return true if there's at least one subscriber who wants mtime
361  return d->fetchMTime > 0;
362 }
363 
364 bool AggregatedItemFetchScope::fetchRemoteRevision() const
365 {
366  LOCKED_D(const AggregatedItemFetchScope)
367  // Aggregation: return true if there's at least one subscriber who wants rrev
368  return d->fetchRRev > 0;
369 }
370 
371 bool AggregatedItemFetchScope::ignoreErrors() const
372 {
373  LOCKED_D(const AggregatedItemFetchScope)
374  // Aggregation: return true only if everyone wants to ignore errors, otherwise
375  // there's at least one subscriber who does not want to ignore them
376  return d->ignoreErrors == d->subscribers;
377 }
378 
379 bool AggregatedItemFetchScope::fetchFlags() const
380 {
381  LOCKED_D(const AggregatedItemFetchScope)
382  // Aggregation: return true if there's at least one subscriber who wants flags
383  return d->fetchFlags > 0;
384 }
385 
386 bool AggregatedItemFetchScope::fetchRemoteId() const
387 {
388  LOCKED_D(const AggregatedItemFetchScope)
389  // Aggregation: return true if there's at least one subscriber who wants RID
390  return d->fetchRID > 0;
391 }
392 
393 bool AggregatedItemFetchScope::fetchGID() const
394 {
395  LOCKED_D(const AggregatedItemFetchScope)
396  // Aggregation: return true if there's at least one subscriber who wants GID
397  return d->fetchGID > 0;
398 }
399 
400 bool AggregatedItemFetchScope::fetchTags() const
401 {
402  LOCKED_D(const AggregatedItemFetchScope)
403  // Aggregation: return true if there's at least one subscriber who wants tags
404  return d->fetchTags > 0;
405 }
406 
407 bool AggregatedItemFetchScope::fetchRelations() const
408 {
409  LOCKED_D(const AggregatedItemFetchScope)
410  // Aggregation: return true if there's at least one subscriber who wants relations
411  return d->fetchRelations > 0;
412 }
413 
414 bool AggregatedItemFetchScope::fetchVirtualReferences() const
415 {
416  LOCKED_D(const AggregatedItemFetchScope)
417  // Aggregation: return true if there's at least one subscriber who wants vrefs
418  return d->fetchVRefs > 0;
419 }
420 
421 void AggregatedItemFetchScope::addSubscriber()
422 {
423  LOCKED_D(AggregatedItemFetchScope)
424  ++d->subscribers;
425 }
426 
427 void AggregatedItemFetchScope::removeSubscriber()
428 {
429  LOCKED_D(AggregatedItemFetchScope)
430  --d->subscribers;
431 }
432 
433 
434 
435 
436 AggregatedTagFetchScope::AggregatedTagFetchScope()
437  : d_ptr(new AggregatedTagFetchScopePrivate)
438 {
439 }
440 
441 AggregatedTagFetchScope::~AggregatedTagFetchScope()
442 {
443  delete d_ptr;
444 }
445 
446 void AggregatedTagFetchScope::apply(const Protocol::TagFetchScope &oldScope,
447  const Protocol::TagFetchScope &newScope)
448 {
449  LOCKED_D(AggregatedTagFetchScope)
450 
451  if (newScope.fetchIdOnly() != oldScope.fetchIdOnly()) {
452  d->updateBool(newScope.fetchIdOnly(), d->fetchIdOnly);
453  }
454  if (newScope.fetchRemoteID() != oldScope.fetchRemoteID()) {
455  d->updateBool(newScope.fetchRemoteID(), d->fetchRemoteId);
456  }
457  if (newScope.fetchAllAttributes() != oldScope.fetchAllAttributes()) {
458  // Count the number of subscribers who call with false
459  d->updateBool(!newScope.fetchAllAttributes(), d->doNotFetchAllAttributes);
460  }
461  if (newScope.attributes() != oldScope.attributes()) {
462  d->applySet(oldScope.attributes(), newScope.attributes(), d->attrs, d->attrsCount);
463  }
464 }
465 
466 Protocol::TagFetchScope AggregatedTagFetchScope::toFetchScope() const
467 {
468  Protocol::TagFetchScope tfs;
469  tfs.setFetchIdOnly(fetchIdOnly());
470  tfs.setFetchRemoteID(fetchRemoteId());
471  tfs.setFetchAllAttributes(fetchAllAttributes());
472  tfs.setAttributes(attributes());
473  return tfs;
474 }
475 
476 bool AggregatedTagFetchScope::fetchIdOnly() const
477 {
478  LOCKED_D(const AggregatedTagFetchScope)
479  // Aggregation: we can return true only if everyone wants fetchIdOnly,
480  // otherwise there's at least one subscriber who wants everything
481  return d->fetchIdOnly == d->subscribers;
482 }
483 
484 bool AggregatedTagFetchScope::fetchRemoteId() const
485 {
486  LOCKED_D(const AggregatedTagFetchScope)
487  return d->fetchRemoteId > 0;
488 }
489 
490 bool AggregatedTagFetchScope::fetchAllAttributes() const
491 {
492  LOCKED_D(const AggregatedTagFetchScope)
493  // The default value for fetchAllAttributes is true, so we return false only if every subscriber said "do not fetch all attributes"
494  return d->doNotFetchAllAttributes != d->subscribers;
495 }
496 
497 QSet<QByteArray> AggregatedTagFetchScope::attributes() const
498 {
499  LOCKED_D(const AggregatedTagFetchScope)
500  return d->attrs;
501 }
502 
503 void AggregatedTagFetchScope::addSubscriber()
504 {
505  LOCKED_D(AggregatedTagFetchScope)
506  ++d->subscribers;
507 }
508 
509 void AggregatedTagFetchScope::removeSubscriber()
510 {
511  LOCKED_D(AggregatedTagFetchScope)
512  --d->subscribers;
513 }
514 
515 #undef LOCKED_D
QMutex
QHash::insert
iterator insert(const Key &key, const T &value)
Akonadi::Protocol
Definition: changenotification.h:32
QByteArray
Akonadi::Server
Definition: aggregatedfetchscope.cpp:33
QHash< QByteArray, int >
QSet< QByteArray >
QHash::erase
iterator erase(iterator pos)
Akonadi::ItemFetchScope
Specifies which parts of an item should be fetched from the Akonadi storage.
Definition: itemfetchscope.h:71
QHash::find
iterator find(const Key &key)
Akonadi
QHash::end
iterator end()
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Sun Dec 8 2019 03:45:39 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal