1 /*
2     SPDX-FileCopyrightText: 2007 Tobias Koenig <tokoe@kde.org>
3 
4     SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #pragma once
8 
9 #include "akonadicore_export.h"
10 #include "item.h"
11 #include "job.h"
12 
13 namespace Akonadi
14 {
15 class Collection;
16 class ItemSyncPrivate;
17 
18 /**
19  * @short Syncs between items known to a client (usually a resource) and the Akonadi storage.
20  *
21  * Remote Id must only be set by the resource storing the item, other clients
22  * should leave it empty, since the resource responsible for the target collection
23  * will be notified about the addition and then create a suitable remote Id.
24  *
25  * There are two different forms of ItemSync usage:
26  * - Full-Sync: meaning the client provides all valid items, i.e. any item not
27  *   part of the list but currently stored in Akonadi will be removed
28  * - Incremental-Sync: meaning the client provides two lists, one for items which
29  *   are new or modified and one for items which should be removed. Any item not
30  *   part of either list but currently stored in Akonadi will not be changed.
31  *
32  * @note This is provided for convenience to implement "save all" like behavior,
33  *       however it is strongly recommended to use single item jobs whenever
34  *       possible, e.g. ItemCreateJob, ItemModifyJob and ItemDeleteJob
35  *
36  * @author Tobias Koenig <tokoe@kde.org>
37  */
38 class AKONADICORE_EXPORT ItemSync : public Job
39 {
40     Q_OBJECT
41 
42 public:
43     enum MergeMode {
44         RIDMerge,
45         GIDMerge,
46     };
47 
48     /**
49      * Creates a new item synchronizer.
50      *
51      * @param collection The collection we are syncing.
52      * @param parent The parent object.
53      */
54     explicit ItemSync(const Collection &collection, QObject *parent = nullptr);
55 
56     /**
57      * Destroys the item synchronizer.
58      */
59     ~ItemSync() override;
60 
61     /**
62      * Sets the full item list for the collection.
63      *
64      * Usually the result of a full item listing.
65      *
66      * @warning If the client using this is a resource, all items must have
67      *          a valid remote identifier.
68      *
69      * @param items A list of items.
70      */
71     void setFullSyncItems(const Item::List &items);
72 
73     /**
74      * Set the amount of items which you are going to return in total
75      * by using the setFullSyncItems()/setIncrementalSyncItems() methods.
76      *
77      * @warning By default the item sync will automatically end once
78      * sufficient items have been provided.
79      * To disable this use setDisableAutomaticDeliveryDone
80      *
81      * @see setDisableAutomaticDeliveryDone
82      * @param amount The amount of items in total.
83      */
84     void setTotalItems(int amount);
85 
86     /**
87       Enable item streaming. Item streaming means that the items delivered by setXItems() calls
88       are delivered in chunks and you manually indicate when all items have been delivered
89       by calling deliveryDone().
90       @param enable @c true to enable item streaming
91     */
92     void setStreamingEnabled(bool enable);
93 
94     /**
95       Notify ItemSync that all remote items have been delivered.
96       Only call this in streaming mode.
97     */
98     void deliveryDone();
99 
100     /**
101      * Sets the item lists for incrementally syncing the collection.
102      *
103      * Usually the result of an incremental remote item listing.
104      *
105      * @warning If the client using this is a resource, all items must have
106      *          a valid remote identifier.
107      *
108      * @param changedItems A list of items added or changed by the client.
109      * @param removedItems A list of items deleted by the client.
110      */
111     void setIncrementalSyncItems(const Item::List &changedItems, const Item::List &removedItems);
112 
113     /**
114      * Aborts the sync process and rolls back all not yet committed transactions.
115      * Use this if an external error occurred during the sync process (such as the
116      * user canceling it).
117      * @since 4.5
118      */
119     void rollback();
120 
121     /**
122      * Transaction mode used by ItemSync.
123      * @since 4.6
124      */
125     enum TransactionMode {
126         SingleTransaction, ///< Use a single transaction for the entire sync process (default), provides maximum consistency ("all or nothing") and best
127                            ///< performance
128         MultipleTransactions, ///< Use one transaction per chunk of delivered items, good compromise between the other two when using streaming
129         NoTransaction ///< Use no transaction at all, provides highest responsiveness (might therefore feel faster even when actually taking slightly longer),
130                       ///< no consistency guaranteed (can fail anywhere in the sync process)
131     };
132 
133     /**
134      * Set the transaction mode to use for this sync.
135      * @note You must call this method before starting the sync, changes afterwards lead to undefined results.
136      * @param mode the transaction mode to use
137      * @since 4.6
138      */
139     void setTransactionMode(TransactionMode mode);
140 
141     /**
142      * Minimum number of items required to start processing in streaming mode.
143      * When MultipleTransactions is used, one transaction per batch will be created.
144      *
145      * @see setBatchSize()
146      * @since 4.14
147      */
148     Q_REQUIRED_RESULT int batchSize() const;
149 
150     /**
151      * Set the batch size.
152      *
153      * The default is 10.
154      *
155      * @note You must call this method before starting the sync, changes afterwards lead to undefined results.
156      * @see batchSize()
157      * @since 4.14
158      */
159     void setBatchSize(int);
160 
161     /**
162      * Disables the automatic completion of the item sync,
163      * based on the number of delivered items.
164      *
165      * This ensures that the item sync only finishes once deliveryDone()
166      * is called, while still making it possible to use the progress
167      * reporting of the ItemSync.
168      *
169      * @note You must call this method before starting the sync, changes afterwards lead to undefined results.
170      * @see setTotalItems
171      * @since 4.14
172      */
173     void setDisableAutomaticDeliveryDone(bool disable);
174 
175     /**
176      * Returns current merge mode
177      *
178      * @see setMergeMode()
179      * @since 5.1
180      */
181     Q_REQUIRED_RESULT MergeMode mergeMode() const;
182 
183     /**
184      * Set what merge method should be used for next ItemSync run
185      *
186      * By default ItemSync uses RIDMerge method.
187      *
188      * See ItemCreateJob for details on Item merging.
189      *
190      * @note You must call this method before starting the sync, changes afterwards lead to undefined results.
191      * @see mergeMode
192      * @since 4.14.11
193      */
194     void setMergeMode(MergeMode mergeMode);
195 
196 Q_SIGNALS:
197     /**
198      * Signals the resource that new items can be delivered.
199      * @param remainingBatchSize the number of items required to complete the batch (typically the same as batchSize())
200      *
201      * @since 4.14
202      */
203     void readyForNextBatch(int remainingBatchSize);
204 
205     /**
206      * @internal
207      * Emitted whenever a transaction is committed. This is for testing only.
208      *
209      * @since 4.14
210      */
211     void transactionCommitted();
212 
213 protected:
214     void doStart() override;
215     void slotResult(KJob *job) override;
216 
217 private:
218     /// @cond PRIVATE
219     Q_DECLARE_PRIVATE(ItemSync)
220 
221     Q_PRIVATE_SLOT(d_func(), void slotLocalListDone(KJob *))
222     Q_PRIVATE_SLOT(d_func(), void slotTransactionResult(KJob *))
223     Q_PRIVATE_SLOT(d_func(), void slotItemsReceived(const Akonadi::Item::List &))
224     /// @endcond
225 };
226 
227 }
228 
229