File indexing completed on 2024-05-19 05:16:11

0001 /*
0002  * SPDX-FileCopyrightText: 2013 Christian Mollekopf <mollekopf@kolabsys.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  *
0006  */
0007 
0008 #pragma once
0009 
0010 #include <KConfig>
0011 #include <KConfigGroup>
0012 #include <QFile>
0013 #include <QObject>
0014 
0015 class NullableConfigGroup
0016 {
0017 public:
0018     NullableConfigGroup() = default;
0019 
0020     explicit NullableConfigGroup(const KConfigGroup &grp)
0021         : mConfigGroup(grp)
0022     {
0023     }
0024 
0025     KConfigGroup &configGroup()
0026     {
0027         return mConfigGroup;
0028     }
0029 
0030     template<typename T>
0031     inline T readEntry(const QString &key, const T &aDefault) const
0032     {
0033         if (mConfigGroup.isValid()) {
0034             return mConfigGroup.readEntry<T>(key, aDefault);
0035         }
0036         return aDefault;
0037     }
0038 
0039     template<typename T>
0040     inline void writeEntry(const QString &key, const T &value)
0041     {
0042         if (mConfigGroup.isValid()) {
0043             mConfigGroup.writeEntry<T>(key, value);
0044         }
0045     }
0046 
0047 private:
0048     KConfigGroup mConfigGroup;
0049 };
0050 
0051 /**
0052  * Base class for generic migration jobs in akonadi.
0053  *
0054  * MigrationJobs can be run standalone from commandline using a small wrapper application or using the
0055  * Akonadi Migration Agent.
0056  *
0057  * Each migrator should assign a unique identifier for it's state (this identifier must never change).
0058  *
0059  * The work done by the migrator may be paused, and the migrator may persist it's state to resume migrations after a reboot.
0060  *
0061  * TODO: The migrator base ensures that no migrator can be run multiple times by locking it over dbus.
0062  *
0063  * The status is stored in the akonadi instance config directory, meaning the status is stored per akonadi instance.
0064  * This is the only reason why this MigratorBase is currently specific to akonadi migration jobs.
0065  */
0066 class MigratorBase : public QObject
0067 {
0068     Q_OBJECT
0069 public:
0070     /**
0071      * Default constructor with default config and logfile
0072      */
0073     explicit MigratorBase(const QString &identifier, QObject *parent = nullptr);
0074 
0075     /**
0076      * Constructor that allows to inject a configfile and logfile.
0077      *
0078      * Pass and empty string to disable config and log.
0079      */
0080     explicit MigratorBase(const QString &identifier, const QString &configFile, const QString &logFile, QObject *parent = nullptr);
0081 
0082     ~MigratorBase() override;
0083 
0084     QString identifier() const;
0085 
0086     /**
0087      * Translated, human readable display name of migrator.
0088      */
0089     virtual QString displayName() const;
0090 
0091     /**
0092      * Translated, human readable description of migrator.
0093      */
0094     virtual QString description() const;
0095 
0096     /**
0097      * Returns the filename of the logfile used by this migrator.
0098      *
0099      * Returns QString() if there is no logfile set.
0100      */
0101     QString logfile() const;
0102 
0103     enum MigrationState {
0104         None,
0105         InProgress,
0106         Paused,
0107         Complete,
0108         NeedsUpdate,
0109         Aborted,
0110         Failed,
0111     };
0112 
0113     enum MessageType {
0114         Success,
0115         Skip,
0116         Info,
0117         Warning,
0118         Error,
0119     };
0120 
0121     /**
0122      * Read migration state.
0123      *
0124      * @return MigrationState.
0125      */
0126     MigrationState migrationState() const;
0127 
0128     /**
0129      * Return false if this job cannot start (i.e. due to missing dependencies).
0130      */
0131     virtual bool canStart();
0132 
0133     /**
0134      * Mandatory updates that the Migration Agent should autostart should return true
0135      */
0136     virtual bool shouldAutostart() const;
0137 
0138     /**
0139      * Start migration.
0140      *
0141      * Implement startWork instead.
0142      *
0143      * Note that this will directly (blocking) call startWork().
0144      */
0145     void start();
0146 
0147     /**
0148      * Pause migration.
0149      */
0150     virtual void pause();
0151 
0152     /**
0153      * Resume migration.
0154      */
0155     virtual void resume();
0156 
0157     /**
0158      * Abort migration.
0159      */
0160     virtual void abort();
0161 
0162     /**
0163      * progress in percent
0164      */
0165     int progress() const;
0166 
0167     /**
0168      * Status
0169      */
0170     QString status() const;
0171 
0172 Q_SIGNALS:
0173     // Signal for state changes
0174     void stateChanged(MigratorBase::MigrationState);
0175 
0176     // Signal for log window
0177     void message(MigratorBase::MessageType type, const QString &msg);
0178 
0179     // Signal for progress bar
0180     void progress(int progress);
0181 
0182     // Signal for scheduling. The migrator has finished for some reason (success, failure, ...) and we can forget about it and move on.
0183     void stoppedProcessing();
0184 
0185 protected:
0186     /**
0187      * Reimplement to start work.
0188      */
0189     virtual void startWork() = 0;
0190 
0191     void setMigrationState(MigratorBase::MigrationState state);
0192 
0193     void setProgress(int);
0194 
0195 private Q_SLOTS:
0196     /**
0197      * Logs a message, that appears in the logfile and potentially in a log window.
0198      * Do not call this directly. Emit the message signal instead, which is connected to this slot.
0199      */
0200     void logMessage(MigratorBase::MessageType type, const QString &msg);
0201 
0202 private:
0203     NullableConfigGroup config();
0204     void saveState();
0205     void loadState();
0206 
0207     void setLogfile(const QString &);
0208 
0209     const QString mIdentifier;
0210     MigrationState mMigrationState = None;
0211     QScopedPointer<QFile> mLogFile;
0212     QScopedPointer<KConfig> mConfig;
0213     int mProgress;
0214 };
0215 
0216 Q_DECLARE_METATYPE(MigratorBase::MigrationState)