Akonadi

resourcebase.h
1/*
2 This file is part of akonadiresources.
3
4 SPDX-FileCopyrightText: 2006 Till Adam <adam@kde.org>
5 SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.0-or-later
8*/
9
10#pragma once
11
12#include "agentbase.h"
13#include "akonadiagentbase_export.h"
14// AkonadiCore
15#include "akonadi/collection.h"
16#include "akonadi/item.h"
17#include "akonadi/itemsync.h"
18
19class KJob;
20class Akonadi__ResourceAdaptor;
21class ResourceState;
22
23namespace Akonadi
24{
25class ResourceBasePrivate;
26
27/**
28 * @short The base class for all Akonadi resources.
29 *
30 * This class should be used as a base class by all resource agents,
31 * because it encapsulates large parts of the protocol between
32 * resource agent, agent manager and the Akonadi storage.
33 *
34 * It provides many convenience methods to make implementing a
35 * new Akonadi resource agent as simple as possible.
36 *
37 * <h4>How to write a resource</h4>
38 *
39 * The following provides an overview of what you need to do to implement
40 * your own Akonadi resource. In the following, the term 'backend' refers
41 * to the entity the resource connects with Akonadi, be it a single file
42 * or a remote server.
43 *
44 * @todo Complete this (online/offline state management)
45 *
46 * <h5>Basic %Resource Framework</h5>
47 *
48 * The following is needed to create a new resource:
49 * - A new class deriving from Akonadi::ResourceBase, implementing at least all
50 * pure-virtual methods, see below for further details.
51 * - call init() in your main() function.
52 * - a .desktop file similar to the following example
53 * \code
54 * [Desktop Entry]
55 * Name=My Akonadi Resource
56 * Type=AkonadiResource
57 * Exec=akonadi_my_resource
58 * Icon=my-icon
59 *
60 * X-Akonadi-MimeTypes=<supported-mimetypes>
61 * X-Akonadi-Capabilities=Resource
62 * X-Akonadi-Identifier=akonadi_my_resource
63 * \endcode
64 *
65 * <h5>Handling PIM Items</h5>
66 *
67 * To follow item changes in the backend, the following steps are necessary:
68 * - Implement retrieveItems() to synchronize all items in the given
69 * collection. If the backend supports incremental retrieval,
70 * implementing support for that is recommended to improve performance.
71 * - Convert the items provided by the backend to Akonadi items.
72 * This typically happens either in retrieveItems() if you retrieved
73 * the collection synchronously (not recommended for network backends) or
74 * in the result slot of the asynchronous retrieval job.
75 * Converting means to create Akonadi::Item objects for every retrieved
76 * item. It's very important that every object has its remote identifier set.
77 * - Call itemsRetrieved() or itemsRetrievedIncremental() respectively
78 * with the item objects created above. The Akonadi storage will then be
79 * updated automatically. Note that it is usually not necessary to manipulate
80 * any item in the Akonadi storage manually.
81 *
82 * To fetch item data on demand, the method retrieveItem() needs to be
83 * reimplemented. Fetch the requested data there and call itemRetrieved()
84 * with the result item.
85 *
86 * To write local changes back to the backend, you need to re-implement
87 * the following three methods:
88 * - itemAdded()
89 * - itemChanged()
90 * - itemRemoved()
91 *
92 * Note that these three functions don't get the full payload of the items by default,
93 * you need to change the item fetch scope of the change recorder to fetch the full
94 * payload. This can be expensive with big payloads, though.<br>
95 * Once you have handled changes in itemAdded() and itemChanged(), call changeCommitted().
96 * Once you have handled changes in itemRemoved(), call changeProcessed();
97 * These methods are called whenever a local item related to this resource is
98 * added, modified or deleted. They are only called if the resource is online, otherwise
99 * all changes are recorded and replayed as soon the resource is online again.
100 *
101 * <h5>Handling Collections</h5>
102 *
103 * To follow collection changes in the backend, the following steps are necessary:
104 * - Implement retrieveCollections() to retrieve collections from the backend.
105 * If the backend supports incremental collections updates, implementing
106 * support for that is recommended to improve performance.
107 * - Convert the collections of the backend to Akonadi collections.
108 * This typically happens either in retrieveCollections() if you retrieved
109 * the collection synchronously (not recommended for network backends) or
110 * in the result slot of the asynchronous retrieval job.
111 * Converting means to create Akonadi::Collection objects for every retrieved
112 * collection. It's very important that every object has its remote identifier
113 * and its parent remote identifier set.
114 * - Call collectionsRetrieved() or collectionsRetrievedIncremental() respectively
115 * with the collection objects created above. The Akonadi storage will then be
116 * updated automatically. Note that it is usually not necessary to manipulate
117 * any collection in the Akonadi storage manually.
118 *
119 *
120 * To write local collection changes back to the backend, you need to re-implement
121 * the following three methods:
122 * - collectionAdded()
123 * - collectionChanged()
124 * - collectionRemoved()
125 * Once you have handled changes in collectionAdded() and collectionChanged(), call changeCommitted().
126 * Once you have handled changes in collectionRemoved(), call changeProcessed();
127 * These methods are called whenever a local collection related to this resource is
128 * added, modified or deleted. They are only called if the resource is online, otherwise
129 * all changes are recorded and replayed as soon the resource is online again.
130 *
131 * @todo Convenience base class for collection-less resources
132 */
133// FIXME_API: API dox need to be updated for Observer approach (kevin)
134class AKONADIAGENTBASE_EXPORT ResourceBase : public AgentBase
135{
136 Q_OBJECT
137
138public:
139 /**
140 * Use this method in the main function of your resource
141 * application to initialize your resource subclass.
142 * This method also takes care of creating a KApplication
143 * object and parsing command line arguments.
144 *
145 * @note In case the given class is also derived from AgentBase::Observer
146 * it gets registered as its own observer (see AgentBase::Observer), e.g.
147 * <tt>resourceInstance->registerObserver( resourceInstance );</tt>
148 *
149 * @code
150 *
151 * class MyResource : public ResourceBase
152 * {
153 * ...
154 * };
155 *
156 * int main( int argc, char **argv )
157 * {
158 * return ResourceBase::init<MyResource>( argc, argv );
159 * }
160 *
161 * @endcode
162 *
163 * @param argc number of arguments
164 * @param argv string arguments
165 */
166 template<typename T>
167 static int init(int argc, char **argv)
168 {
169 // Disable session management
170 qunsetenv("SESSION_MANAGER");
171
172 QApplication app(argc, argv);
173 debugAgent(argc, argv);
174 const QString id = parseArguments(argc, argv);
175 T r(id);
176
177 // check if T also inherits AgentBase::Observer and
178 // if it does, automatically register it on itself
179 auto observer = dynamic_cast<Observer *>(&r);
180 if (observer != nullptr) {
181 r.registerObserver(observer);
182 }
183
184 return init(r);
185 }
186
187 /**
188 * This method is used to set the name of the resource.
189 */
190 void setName(const QString &name);
191
192 /**
193 * Returns the name of the resource.
194 */
195 [[nodiscard]] QString name() const;
196
197 /**
198 * This method sets list of activities.
199 */
200 void setActivities(const QStringList &activities);
201
202 /**
203 * return list of activities.
204 */
205 [[nodiscard]] QStringList activities() const;
206
207 /**
208 * This method enables or not activities support.
209 */
210 void setActivitiesEnabled(bool enable);
211
212 /**
213 * Returns true if activities is enabled.
214 */
215 [[nodiscard]] bool activitiesEnabled() const;
216
217 /**
218 * Enable or disable automatic progress reporting. By default, it is enabled.
219 * When enabled, the resource will automatically emit the signals percent() and status()
220 * while syncing items or collections.
221 *
222 * The automatic progress reporting is done on a per item / per collection basis, so if a
223 * finer granularity is desired, automatic reporting should be disabled and the subclass should
224 * emit the percent() and status() signals itself.
225 *
226 * @param enabled Whether or not automatic emission of the signals is enabled.
227 * @since 4.7
228 */
229 void setAutomaticProgressReporting(bool enabled);
230
231Q_SIGNALS:
232 /**
233 * This signal is emitted whenever the name of the resource has changed.
234 *
235 * @param name The new name of the resource.
236 */
237 void nameChanged(const QString &name);
238
239 /**
240 * Emitted when a full synchronization has been completed.
241 */
242 void synchronized();
243
244 /**
245 * Emitted when a collection attributes synchronization has been completed.
246 *
247 * @param collectionId The identifier of the collection whose attributes got synchronized.
248 * @since 4.6
249 */
250 void attributesSynchronized(qlonglong collectionId);
251
252 /**
253 * Emitted when a collection tree synchronization has been completed.
254 *
255 * @since 4.8
256 */
258
259 /**
260 * Emitted when the item synchronization processed the current batch and is ready for a new one.
261 * Use this to throttle the delivery to not overload Akonadi.
262 *
263 * Throttling can be used during item retrieval (retrieveItems(Akonadi::Collection)) in streaming mode.
264 * To throttle only deliver itemSyncBatchSize() items, and wait for this signal, then again deliver
265 * @param remainingBatchSize items.
266 *
267 * By always only providing the number of items required to process the batch, the items don't pile
268 * up in memory and items are only provided as fast as Akonadi can process them.
269 *
270 * @see batchSize()
271 *
272 * @since 4.14
273 */
274 void retrieveNextItemSyncBatch(int remainingBatchSize);
275
276protected Q_SLOTS:
277 /**
278 * Retrieve the collection tree from the remote server and supply it via
279 * collectionsRetrieved() or collectionsRetrievedIncremental().
280 * @see collectionsRetrieved(), collectionsRetrievedIncremental()
281 */
282 virtual void retrieveCollections() = 0;
283
284 /**
285 * Retrieve all tags from the backend
286 * @see tagsRetrieved()
287 */
288 virtual void retrieveTags();
289
290 /**
291 * Retrieve the attributes of a single collection from the backend. The
292 * collection to retrieve attributes for is provided as @p collection.
293 * Add the attributes parts and call collectionAttributesRetrieved()
294 * when done.
295 *
296 * @param collection The collection whose attributes should be retrieved.
297 * @see collectionAttributesRetrieved()
298 * @since 4.6
299 */
300 virtual void retrieveCollectionAttributes(const Akonadi::Collection &collection);
301
302 /**
303 * Retrieve all (new/changed) items in collection @p collection.
304 * It is recommended to use incremental retrieval if the backend supports that
305 * and provide the result by calling itemsRetrievedIncremental().
306 * If incremental retrieval is not possible, provide the full listing by calling
307 * itemsRetrieved( const Item::List& ).
308 * In any case, ensure that all items have a correctly set remote identifier
309 * to allow synchronizing with items already existing locally.
310 * In case you don't want to use the built-in item syncing code, store the retrieved
311 * items manually and call itemsRetrieved() once you are done.
312 * @param collection The collection whose items to retrieve.
313 * @see itemsRetrieved( const Item::List& ), itemsRetrievedIncremental(), itemsRetrieved(), currentCollection(), batchSize()
314 */
315 virtual void retrieveItems(const Akonadi::Collection &collection) = 0;
316
317 /**
318 * Returns the batch size used during the item sync.
319 *
320 * This can be used to throttle the item delivery.
321 *
322 * @see retrieveNextItemSyncBatch(int), retrieveItems(Akonadi::Collection)
323 * @since 4.14
324 */
325 [[nodiscard]] int itemSyncBatchSize() const;
326
327 /**
328 * Set the batch size used during the item sync.
329 * The default is 10.
330 *
331 * @see retrieveNextItemSyncBatch(int)
332 * @since 4.14
333 */
334 void setItemSyncBatchSize(int batchSize);
335
336 /**
337 * Set to true to schedule an attribute sync before every item sync.
338 * The default is false.
339 *
340 * @since 4.15
341 */
342 void setScheduleAttributeSyncBeforeItemSync(bool);
343
344 /**
345 * Retrieve a single item from the backend. The item to retrieve is provided as @p item.
346 * Add the requested payload parts and call itemRetrieved() when done.
347 * @param item The empty item whose payload should be retrieved. Use this object when delivering
348 * the result instead of creating a new item to ensure conflict detection will work.
349 * @param parts The item parts that should be retrieved.
350 * @return false if there is an immediate error when retrieving the item.
351 * @see itemRetrieved()
352 * @deprecated Use retrieveItems(const Akonadi::Item::List &, const QSet<QByteArray> &) instead.
353 */
354 AKONADIAGENTBASE_DEPRECATED virtual bool retrieveItem(const Akonadi::Item &item, const QSet<QByteArray> &parts);
355
356 /**
357 * Retrieve given @p items from the backend.
358 * Add the requested payload parts and call itemsRetrieved() when done.
359 * It is guaranteed that all @p items in the list belong to the same Collection.
360 *
361 * If the items are retrieved synchronously in this method, in case of an error
362 * emit error(const QString &) and return @c false, which will cancel the current task.
363 * If the items are retrieved asynchronously, in case of an non-immediate error you need
364 * to call cancelTask() or cancelTask(const QString&) in the respective handler methods
365 * explicitly.
366 *
367 * @param items The items whose payload should be retrieved. Use those objects
368 * when delivering the result instead of creating new items to ensure conflict
369 * detection will work.
370 * @param parts The item parts that should be retrieved.
371 * @return false if there is an immediate error when retrieving the items.
372 * @see itemsRetrieved()
373 * @since 5.4
374 *
375 * @todo: Make this method pure virtual once retrieveItem() is gone
376 */
377 virtual bool retrieveItems(const Akonadi::Item::List &items, const QSet<QByteArray> &parts);
378
379 /**
380 * Abort any activity in progress in the backend. By default this method does nothing.
381 *
382 * @since 4.6
383 */
384 virtual void abortActivity();
385
386 /**
387 * Dump resource internals, for debugging.
388 * @since 4.9
389 */
391 {
392 return QString();
393 }
394
395protected:
396 /**
397 * Creates a base resource.
398 *
399 * @param id The instance id of the resource.
400 */
401 ResourceBase(const QString &id);
402
403 /**
404 * Destroys the base resource.
405 */
406 ~ResourceBase() override;
407
408 /**
409 * Call this method from retrieveItem() once the result is available.
410 *
411 * @param item The retrieved item.
412 */
413 void itemRetrieved(const Item &item);
414
415 /**
416 * Call this method from retrieveCollectionAttributes() once the result is available.
417 *
418 * @param collection The collection whose attributes got retrieved.
419 * @since 4.6
420 */
421 void collectionAttributesRetrieved(const Collection &collection);
422
423 /**
424 * Resets the dirty flag of the given item and updates the remote id.
425 *
426 * Call whenever you have successfully written changes back to the server.
427 * This implicitly calls changeProcessed().
428 * @param item The changed item.
429 */
430 void changeCommitted(const Item &item);
431
432 /**
433 * Resets the dirty flag of all given items and updates remote ids.
434 *
435 * Call whenever you have successfully written changes back to the server.
436 * This implicitly calls changeProcessed().
437 * @param items Changed items
438 *
439 * @since 4.11
440 */
441 void changesCommitted(const Item::List &items);
442
443 /**
444 * Resets the dirty flag of the given tag and updates the remote id.
445 *
446 * Call whenever you have successfully written changes back to the server.
447 * This implicitly calls changeProcessed().
448 * @param tag Changed tag.
449 *
450 * @since 4.13
451 */
452 void changeCommitted(const Tag &tag);
453
454 /**
455 * Call whenever you have successfully handled or ignored a collection
456 * change notification.
457 *
458 * This will update the remote identifier of @p collection if necessary,
459 * as well as any other collection attributes.
460 * This implicitly calls changeProcessed().
461 * @param collection The collection which changes have been handled.
462 */
463 void changeCommitted(const Collection &collection);
464
465 /**
466 * Call this to supply the full folder tree retrieved from the remote server.
467 *
468 * @param collections A list of collections.
469 * @see collectionsRetrievedIncremental()
470 */
471 void collectionsRetrieved(const Collection::List &collections);
472
473 void tagsRetrieved(const Tag::List &tags, const QHash<QString, Item::List> &tagMembers);
474
475 /**
476 * Call this to supply incrementally retrieved collections from the remote server.
477 *
478 * @param changedCollections Collections that have been added or changed.
479 * @param removedCollections Collections that have been deleted.
480 * @see collectionsRetrieved()
481 */
482 void collectionsRetrievedIncremental(const Collection::List &changedCollections, const Collection::List &removedCollections);
483
484 /**
485 * Enable collection streaming, that is collections don't have to be delivered at once
486 * as result of a retrieveCollections() call but can be delivered by multiple calls
487 * to collectionsRetrieved() or collectionsRetrievedIncremental(). When all collections
488 * have been retrieved, call collectionsRetrievalDone().
489 * @param enable @c true if collection streaming should be enabled, @c false by default
490 */
491 void setCollectionStreamingEnabled(bool enable);
492
493 /**
494 * Call this method to indicate you finished synchronizing the collection tree.
495 *
496 * This is not needed if you use the built in syncing without collection streaming
497 * and call collectionsRetrieved() or collectionRetrievedIncremental() instead.
498 * If collection streaming is enabled, call this method once all collections have been delivered
499 * using collectionsRetrieved() or collectionsRetrievedIncremental().
500 */
501 void collectionsRetrievalDone();
502
503 /**
504 * Allows to keep locally changed collection parts during the collection sync.
505 *
506 * This is useful for resources to be able to provide default values during the collection
507 * sync, while preserving eventual more up-to date values.
508 *
509 * Valid values are attribute types and "CONTENTMIMETYPE" for the collections content mimetypes.
510 *
511 * By default this is enabled for the EntityDisplayAttribute.
512 *
513 * @param parts A set parts for which local changes should be preserved.
514 * @since 4.14
515 */
516 void setKeepLocalCollectionChanges(const QSet<QByteArray> &parts);
517
518 /**
519 * Call this method to supply the full collection listing from the remote server. Items not present in the list
520 * will be dropped from the Akonadi database.
521 *
522 * If the remote server supports incremental listing, it's strongly
523 * recommended to use itemsRetrievedIncremental() instead.
524 * @param items A list of items.
525 * @see itemsRetrievedIncremental().
526 */
527 void itemsRetrieved(const Item::List &items);
528
529 /**
530 * Call this method when you want to use the itemsRetrieved() method
531 * in streaming mode and indicate the amount of items that will arrive
532 * that way.
533 *
534 * @warning By default this will end the item sync automatically once
535 * sufficient items were delivered. To disable this and only make use
536 * of the progress reporting, use setDisableAutomaticItemDeliveryDone()
537 *
538 * @note The recommended way is therefore:
539 * @code
540 * setDisableAutomaticItemDeliveryDone(true);
541 * setItemStreamingEnabled(true);
542 * setTotalItems(X); // X = sum of all items in all batches
543 * while (...) {
544 * itemsRetrievedIncremental(...);
545 * // or itemsRetrieved(...);
546 * }
547 * itemsRetrievalDone();
548 * @endcode
549 *
550 * @param amount number of items that will arrive in streaming mode
551 * @see setDisableAutomaticItemDeliveryDone(bool)
552 * @see setItemStreamingEnabled(bool)
553 */
554 void setTotalItems(int amount);
555
556 /**
557 * Disables the automatic completion of the item sync,
558 * based on the number of delivered items.
559 *
560 * This ensures that the item sync only finishes once itemsRetrieved()
561 * is called, while still making it possible to use the automatic progress
562 * reporting based on setTotalItems().
563 *
564 * @note This needs to be called once, before the item sync is started.
565 *
566 * @see setTotalItems(int)
567 * @since 4.14
568 */
569 void setDisableAutomaticItemDeliveryDone(bool disable);
570
571 /**
572 * Enable item streaming, which is disabled by default.
573 * Item streaming means that the resource can call setTotalItems(),
574 * and then itemsRetrieved() or itemsRetrievedIncremental() multiple times,
575 * in chunks. When all is done, the resource should call itemsRetrievalDone().
576 * @param enable @c true if items are delivered in chunks rather in one big block.
577 * @see setTotalItems(int)
578 */
579 void setItemStreamingEnabled(bool enable);
580
581 /**
582 * Set transaction mode for item sync'ing.
583 * @param mode item transaction mode
584 * @see Akonadi::ItemSync::TransactionMode
585 * @since 4.6
586 */
587 void setItemTransactionMode(ItemSync::TransactionMode mode);
588
589 /**
590 * Set merge mode for item sync'ing.
591 *
592 * Default merge mode is RIDMerge.
593 *
594 * @note This method must be called before first call to itemRetrieved(),
595 * itemsRetrieved() or itemsRetrievedIncremental().
596 *
597 * @param mode Item merging mode (see ItemCreateJob for details on item merging)
598 * @see Akonadi::ItemSync::MergeMode
599 * @since 4.14.11
600 */
601 void setItemMergingMode(ItemSync::MergeMode mode);
602
603 /**
604 * Call this method to supply incrementally retrieved items from the remote server.
605 *
606 * @param changedItems Items changed in the backend.
607 * @param removedItems Items removed from the backend.
608 */
609 void itemsRetrievedIncremental(const Item::List &changedItems, const Item::List &removedItems);
610
611 /**
612 * Call this method to indicate you finished synchronizing the current collection.
613 *
614 * This is not needed if you use the built in syncing without item streaming
615 * and call itemsRetrieved() or itemsRetrievedIncremental() instead.
616 * If item streaming is enabled, call this method once all items have been delivered
617 * using itemsRetrieved() or itemsRetrievedIncremental().
618 * @see retrieveItems()
619 */
620 void itemsRetrievalDone();
621
622 /**
623 * Call this method to remove all items and collections of the resource from the
624 * server cache.
625 *
626 * The method should not be used anymore
627 *
628 * @see invalidateCache()
629 * @since 4.3
630 */
631 void clearCache();
632
633 /**
634 * Call this method to invalidate all cached content in @p collection.
635 *
636 * The method should be used when the backend indicated that the cached content
637 * is no longer valid.
638 *
639 * @param collection parent of the content to be invalidated in cache
640 * @since 4.8
641 */
642 void invalidateCache(const Collection &collection);
643
644 /**
645 * Returns the collection that is currently synchronized.
646 * @note Calling this method is only allowed during a collection synchronization task, that
647 * is directly or indirectly from retrieveItems().
648 */
649 [[nodiscard]] Collection currentCollection() const;
650
651 /**
652 * Returns the item that is currently retrieved.
653 * @note Calling this method is only allowed during fetching a single item, that
654 * is directly or indirectly from retrieveItem().
655 */
656 AKONADIAGENTBASE_DEPRECATED Item currentItem() const;
657
658 /**
659 * Returns the items that are currently retrieved.
660 * @note Calling this method is only allowed during item fetch, that is
661 * directly or indirectly from retrieveItems(Akonadi::Item::List,QSet<QByteArray>)
662 */
663 [[nodiscard]] Item::List currentItems() const;
664
665 /**
666 * This method is called whenever the resource should start synchronize all data.
667 */
668 void synchronize();
669
670 /**
671 * This method is called whenever the collection with the given @p id
672 * shall be synchronized.
673 */
674 void synchronizeCollection(qint64 id);
675
676 /**
677 * This method is called whenever the collection with the given @p id
678 * shall be synchronized.
679 * @param recursive if true, a recursive synchronization is done
680 */
681 void synchronizeCollection(qint64 id, bool recursive);
682
683 /**
684 * This method is called whenever the collection with the given @p id
685 * shall have its attributes synchronized.
686 *
687 * @param id The id of the collection to synchronize
688 * @since 4.6
689 */
690 void synchronizeCollectionAttributes(qint64 id);
691
692 /**
693 * Synchronizes the collection attributes.
694 *
695 * @param col The id of the collection to synchronize
696 * @since 4.15
697 */
698 void synchronizeCollectionAttributes(const Akonadi::Collection &col);
699
700 /**
701 * Refetches the Collections.
702 */
703 void synchronizeCollectionTree();
704
705 /**
706 * Refetches Tags.
707 */
708 void synchronizeTags();
709
710 /**
711 * Stops the execution of the current task and continues with the next one.
712 */
713 void cancelTask();
714
715 /**
716 * Stops the execution of the current task and continues with the next one.
717 * Additionally an error message is emitted.
718 * @param error additional error message to be emitted
719 */
720 void cancelTask(const QString &error);
721
722 /**
723 * Suspends the execution of the current task and tries again to execute it.
724 *
725 * This can be used to delay the task processing until the resource has reached a safe
726 * state, e.g. login to a server succeeded.
727 *
728 * @note This does not change the order of tasks so if there is no task with higher priority
729 * e.g. a custom task added with #Prepend the deferred task will be processed again.
730 *
731 * @since 4.3
732 */
733 void deferTask();
734
735 /**
736 * Inherited from AgentBase.
737 *
738 * When going offline, the scheduler aborts the current task, so you should
739 * do the same in your resource, if the task implementation is asynchronous.
740 */
741 void doSetOnline(bool online) override;
742
743 /**
744 * Indicate the use of hierarchical remote identifiers.
745 *
746 * This means that it is possible to have two different items with the same
747 * remoteId in different Collections.
748 *
749 * This should be called in the resource constructor as needed.
750 *
751 * @param enable whether to enable use of hierarchical remote identifiers
752 * @since 4.4
753 */
754 void setHierarchicalRemoteIdentifiersEnabled(bool enable);
755
756 friend class ResourceScheduler;
757 friend class ::ResourceState;
758
759 /**
760 * Describes the scheduling priority of a task that has been queued
761 * for execution.
762 *
763 * @see scheduleCustomTask
764 * @since 4.4
765 */
767 Prepend, ///< The task will be executed as soon as the current task has finished.
768 AfterChangeReplay, ///< The task is scheduled after the last ChangeReplay task in the queue
769 Append ///< The task will be executed after all tasks currently in the queue are finished
770 };
771
772 /**
773 * Schedules a custom task in the internal scheduler. It will be queued with
774 * all other tasks such as change replays and retrieval requests and eventually
775 * executed by calling the specified method. With the priority parameter the
776 * time of execution of the Task can be influenced. @see SchedulePriority
777 * @param receiver The object the slot should be called on.
778 * @param method The name of the method (and only the name, not signature, not SLOT(...) macro),
779 * that should be called to execute this task. The method has to be a slot and take a QVariant as
780 * argument.
781 * @param argument A QVariant argument passed to the method specified above. Use this to pass task
782 * parameters.
783 * @param priority Priority of the task. Use this to influence the position in
784 * the execution queue.
785 * @since 4.4
786 */
787 void scheduleCustomTask(QObject *receiver, const char *method, const QVariant &argument, SchedulePriority priority = Append);
788
789 /**
790 * Indicate that the current task is finished. Use this method from the slot called via scheduleCustomTaks().
791 * As with all the other callbacks, make sure to either call taskDone() or cancelTask()/deferTask() on all
792 * exit paths, otherwise the resource will hang.
793 * @since 4.4
794 */
795 void taskDone();
796
797 /**
798 * Dump the contents of the current ChangeReplay
799 * @since 4.8.1
800 */
801 [[nodiscard]] QString dumpNotificationListToString() const;
802
803 /**
804 * Dumps memory usage information to stdout.
805 * For now it outputs the result of glibc's mallinfo().
806 * This is useful to check if your memory problems are due to poor management by glibc.
807 * Look for a high value on fsmblks when interpreting results.
808 * man mallinfo for more details.
809 * @since 4.11
810 */
811 void dumpMemoryInfo() const;
812
813 /**
814 * Returns a string with memory usage information.
815 * @see dumpMemoryInfo()
816 *
817 * @since 4.11
818 */
819 [[nodiscard]] QString dumpMemoryInfoToString() const;
820
821 /**
822 * Dump the state of the scheduler
823 * @since 4.8.1
824 */
825 [[nodiscard]] QString dumpSchedulerToString() const;
826
827private:
828 static QString parseArguments(int argc, char **argv);
829 static int init(ResourceBase &r);
830
831 // dbus resource interface
832 friend class ::Akonadi__ResourceAdaptor;
833
834 void requestItemDelivery(const QList<qint64> &uids, const QByteArrayList &parts);
835
836private:
837 Q_DECLARE_PRIVATE(ResourceBase)
838
839 Q_PRIVATE_SLOT(d_func(), void slotAbortRequested())
840 Q_PRIVATE_SLOT(d_func(), void slotDeliveryDone(KJob *))
841 Q_PRIVATE_SLOT(d_func(), void slotCollectionSyncDone(KJob *))
842 Q_PRIVATE_SLOT(d_func(), void slotDeleteResourceCollection())
843 Q_PRIVATE_SLOT(d_func(), void slotDeleteResourceCollectionDone(KJob *))
844 Q_PRIVATE_SLOT(d_func(), void slotCollectionDeletionDone(KJob *))
845 Q_PRIVATE_SLOT(d_func(), void slotInvalidateCache(const Akonadi::Collection &))
846 Q_PRIVATE_SLOT(d_func(), void slotLocalListDone(KJob *))
847 Q_PRIVATE_SLOT(d_func(), void slotSynchronizeCollection(const Akonadi::Collection &))
848 Q_PRIVATE_SLOT(d_func(), void slotCollectionListDone(KJob *))
849 Q_PRIVATE_SLOT(d_func(), void slotSynchronizeCollectionAttributes(const Akonadi::Collection &))
850 Q_PRIVATE_SLOT(d_func(), void slotCollectionListForAttributesDone(KJob *))
851 Q_PRIVATE_SLOT(d_func(), void slotCollectionAttributesSyncDone(KJob *))
852 Q_PRIVATE_SLOT(d_func(), void slotItemSyncDone(KJob *))
853 Q_PRIVATE_SLOT(d_func(), void slotPercent(KJob *, quint64))
854 Q_PRIVATE_SLOT(d_func(), void slotDelayedEmitProgress())
855 Q_PRIVATE_SLOT(d_func(), void slotPrepareItemRetrieval(const Akonadi::Item &items))
856 Q_PRIVATE_SLOT(d_func(), void slotPrepareItemRetrievalResult(KJob *))
857 Q_PRIVATE_SLOT(d_func(), void slotPrepareItemsRetrieval(const QList<Akonadi::Item> &items))
858 Q_PRIVATE_SLOT(d_func(), void slotPrepareItemsRetrievalResult(KJob *))
859 Q_PRIVATE_SLOT(d_func(), void changeCommittedResult(KJob *))
860 Q_PRIVATE_SLOT(d_func(), void slotSessionReconnected())
861 Q_PRIVATE_SLOT(d_func(), void slotRecursiveMoveReplay(RecursiveMover *))
862 Q_PRIVATE_SLOT(d_func(), void slotRecursiveMoveReplayResult(KJob *))
863 Q_PRIVATE_SLOT(d_func(), void slotTagSyncDone(KJob *))
864 Q_PRIVATE_SLOT(d_func(), void slotSynchronizeTags())
865 Q_PRIVATE_SLOT(d_func(), void slotItemRetrievalCollectionFetchDone(KJob *))
866 Q_PRIVATE_SLOT(d_func(), void slotAttributeRetrievalCollectionFetchDone(KJob *))
867};
868
869}
870
871#ifndef AKONADI_RESOURCE_MAIN
872/**
873 * Convenience Macro for the most common main() function for Akonadi resources.
874 */
875#define AKONADI_RESOURCE_MAIN(resourceClass) \
876 int main(int argc, char **argv) \
877 { \
878 return Akonadi::ResourceBase::init<resourceClass>(argc, argv); \
879 }
880#endif
The interface for reacting on monitored or replayed changes.
Definition agentbase.h:179
The base class for all Akonadi agents and resources.
Definition agentbase.h:73
Represents a collection of PIM items.
Definition collection.h:62
TransactionMode
Transaction mode used by ItemSync.
Definition itemsync.h:129
Represents a PIM item stored in Akonadi storage.
Definition item.h:100
The base class for all Akonadi resources.
static int init(int argc, char **argv)
Use this method in the main function of your resource application to initialize your resource subclas...
virtual void retrieveCollections()=0
Retrieve the collection tree from the remote server and supply it via collectionsRetrieved() or colle...
SchedulePriority
Describes the scheduling priority of a task that has been queued for execution.
@ Prepend
The task will be executed as soon as the current task has finished.
@ AfterChangeReplay
The task is scheduled after the last ChangeReplay task in the queue.
void retrieveNextItemSyncBatch(int remainingBatchSize)
Emitted when the item synchronization processed the current batch and is ready for a new one.
void attributesSynchronized(qlonglong collectionId)
Emitted when a collection attributes synchronization has been completed.
virtual QString dumpResourceToString() const
Dump resource internals, for debugging.
void nameChanged(const QString &name)
This signal is emitted whenever the name of the resource has changed.
virtual void retrieveItems(const Akonadi::Collection &collection)=0
Retrieve all (new/changed) items in collection collection.
void collectionTreeSynchronized()
Emitted when a collection tree synchronization has been completed.
~ResourceBase() override
Destroys the base resource.
An Akonadi Tag.
Definition tag.h:26
Helper integration between Akonadi and Qt.
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:08:29 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.