File indexing completed on 2024-06-16 04:50:14

0001 /*
0002     SPDX-FileCopyrightText: 2007 Tobias Koenig <tokoe@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "akonadicore_export.h"
0010 #include "item.h"
0011 #include "job.h"
0012 
0013 #include <QDateTime>
0014 
0015 namespace Akonadi
0016 {
0017 class Collection;
0018 class ItemSyncPrivate;
0019 
0020 /**
0021  * @short Syncs between items known to a client (usually a resource) and the Akonadi storage.
0022  *
0023  * Remote Id must only be set by the resource storing the item, other clients
0024  * should leave it empty, since the resource responsible for the target collection
0025  * will be notified about the addition and then create a suitable remote Id.
0026  *
0027  * There are two different forms of ItemSync usage:
0028  * - Full-Sync: meaning the client provides all valid items, i.e. any item not
0029  *   part of the list but currently stored in Akonadi will be removed
0030  * - Incremental-Sync: meaning the client provides two lists, one for items which
0031  *   are new or modified and one for items which should be removed. Any item not
0032  *   part of either list but currently stored in Akonadi will not be changed.
0033  *
0034  * @note This is provided for convenience to implement "save all" like behavior,
0035  *       however it is strongly recommended to use single item jobs whenever
0036  *       possible, e.g. ItemCreateJob, ItemModifyJob and ItemDeleteJob
0037  *
0038  * @author Tobias Koenig <tokoe@kde.org>
0039  */
0040 class AKONADICORE_EXPORT ItemSync : public Job
0041 {
0042     Q_OBJECT
0043 
0044 public:
0045     enum MergeMode {
0046         RIDMerge,
0047         GIDMerge,
0048     };
0049 
0050     /**
0051      * Creates a new item synchronizer.
0052      *
0053      * @param collection The collection we are syncing.
0054      * @param timestamp Optional timestamp of itemsync start. Will be used to detect local changes that happen
0055                         while the ItemSync is running.
0056      * @param parent The parent object.
0057      */
0058     explicit ItemSync(const Collection &collection, const QDateTime &timestamp = {}, QObject *parent = nullptr);
0059 
0060     /**
0061      * Destroys the item synchronizer.
0062      */
0063     ~ItemSync() override;
0064 
0065     /**
0066      * Sets the full item list for the collection.
0067      *
0068      * Usually the result of a full item listing.
0069      *
0070      * @warning If the client using this is a resource, all items must have
0071      *          a valid remote identifier.
0072      *
0073      * @param items A list of items.
0074      */
0075     void setFullSyncItems(const Item::List &items);
0076 
0077     /**
0078      * Set the amount of items which you are going to return in total
0079      * by using the setFullSyncItems()/setIncrementalSyncItems() methods.
0080      *
0081      * @warning By default the item sync will automatically end once
0082      * sufficient items have been provided.
0083      * To disable this use setDisableAutomaticDeliveryDone
0084      *
0085      * @see setDisableAutomaticDeliveryDone
0086      * @param amount The amount of items in total.
0087      */
0088     void setTotalItems(int amount);
0089 
0090     /**
0091       Enable item streaming. Item streaming means that the items delivered by setXItems() calls
0092       are delivered in chunks and you manually indicate when all items have been delivered
0093       by calling deliveryDone().
0094       @param enable @c true to enable item streaming
0095     */
0096     void setStreamingEnabled(bool enable);
0097 
0098     /**
0099       Notify ItemSync that all remote items have been delivered.
0100       Only call this in streaming mode.
0101     */
0102     void deliveryDone();
0103 
0104     /**
0105      * Sets the item lists for incrementally syncing the collection.
0106      *
0107      * Usually the result of an incremental remote item listing.
0108      *
0109      * @warning If the client using this is a resource, all items must have
0110      *          a valid remote identifier.
0111      *
0112      * @param changedItems A list of items added or changed by the client.
0113      * @param removedItems A list of items deleted by the client.
0114      */
0115     void setIncrementalSyncItems(const Item::List &changedItems, const Item::List &removedItems);
0116 
0117     /**
0118      * Aborts the sync process and rolls back all not yet committed transactions.
0119      * Use this if an external error occurred during the sync process (such as the
0120      * user canceling it).
0121      * @since 4.5
0122      */
0123     void rollback();
0124 
0125     /**
0126      * Transaction mode used by ItemSync.
0127      * @since 4.6
0128      */
0129     enum TransactionMode {
0130         SingleTransaction, ///< Use a single transaction for the entire sync process (default), provides maximum consistency ("all or nothing") and best
0131                            ///< performance
0132         MultipleTransactions, ///< Use one transaction per chunk of delivered items, good compromise between the other two when using streaming
0133         NoTransaction ///< Use no transaction at all, provides highest responsiveness (might therefore feel faster even when actually taking slightly longer),
0134                       ///< no consistency guaranteed (can fail anywhere in the sync process)
0135     };
0136 
0137     /**
0138      * Set the transaction mode to use for this sync.
0139      * @note You must call this method before starting the sync, changes afterwards lead to undefined results.
0140      * @param mode the transaction mode to use
0141      * @since 4.6
0142      */
0143     void setTransactionMode(TransactionMode mode);
0144 
0145     /**
0146      * Minimum number of items required to start processing in streaming mode.
0147      * When MultipleTransactions is used, one transaction per batch will be created.
0148      *
0149      * @see setBatchSize()
0150      * @since 4.14
0151      */
0152     [[nodiscard]] int batchSize() const;
0153 
0154     /**
0155      * Set the batch size.
0156      *
0157      * The default is 10.
0158      *
0159      * @note You must call this method before starting the sync, changes afterwards lead to undefined results.
0160      * @see batchSize()
0161      * @since 4.14
0162      */
0163     void setBatchSize(int);
0164 
0165     /**
0166      * Disables the automatic completion of the item sync,
0167      * based on the number of delivered items.
0168      *
0169      * This ensures that the item sync only finishes once deliveryDone()
0170      * is called, while still making it possible to use the progress
0171      * reporting of the ItemSync.
0172      *
0173      * @note You must call this method before starting the sync, changes afterwards lead to undefined results.
0174      * @see setTotalItems
0175      * @since 4.14
0176      */
0177     void setDisableAutomaticDeliveryDone(bool disable);
0178 
0179     /**
0180      * Returns current merge mode
0181      *
0182      * @see setMergeMode()
0183      * @since 5.1
0184      */
0185     [[nodiscard]] MergeMode mergeMode() const;
0186 
0187     /**
0188      * Set what merge method should be used for next ItemSync run
0189      *
0190      * By default ItemSync uses RIDMerge method.
0191      *
0192      * See ItemCreateJob for details on Item merging.
0193      *
0194      * @note You must call this method before starting the sync, changes afterwards lead to undefined results.
0195      * @see mergeMode
0196      * @since 4.14.11
0197      */
0198     void setMergeMode(MergeMode mergeMode);
0199 
0200 Q_SIGNALS:
0201     /**
0202      * Signals the resource that new items can be delivered.
0203      * @param remainingBatchSize the number of items required to complete the batch (typically the same as batchSize())
0204      *
0205      * @since 4.14
0206      */
0207     void readyForNextBatch(int remainingBatchSize);
0208 
0209     /**
0210      * @internal
0211      * Emitted whenever a transaction is committed. This is for testing only.
0212      *
0213      * @since 4.14
0214      */
0215     void transactionCommitted();
0216 
0217 protected:
0218     void doStart() override;
0219     void slotResult(KJob *job) override;
0220 
0221 private:
0222     /// @cond PRIVATE
0223     Q_DECLARE_PRIVATE(ItemSync)
0224 
0225     Q_PRIVATE_SLOT(d_func(), void slotLocalListDone(KJob *))
0226     Q_PRIVATE_SLOT(d_func(), void slotTransactionResult(KJob *))
0227     Q_PRIVATE_SLOT(d_func(), void slotItemsReceived(const Akonadi::Item::List &))
0228     /// @endcond
0229 };
0230 
0231 }