File indexing completed on 2024-06-09 05:18:09

0001 /*
0002  * SPDX-FileCopyrightText: 2004 David Faure <faure@kde.org>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #pragma once
0008 
0009 #include "mailcommon_export.h"
0010 
0011 #include <QObject>
0012 
0013 #include <QList>
0014 #include <QTimer>
0015 
0016 #include "folderjob.h"
0017 #include <Akonadi/Collection>
0018 // If this define is set, JobScheduler will show debug output, and related kmkernel
0019 // timers will be shortened.
0020 // This is for debugging purposes only, don't commit with it.
0021 //#define DEBUG_SCHEDULER
0022 
0023 namespace MailCommon
0024 {
0025 class FolderJob;
0026 class ScheduledJob;
0027 
0028 /**
0029  * A scheduled task is some information about a folder job that should be run later.
0030  * As long as it's not running, it's called a "task", i.e. something that needs to be done.
0031  * Tasks are managed by the JobScheduler.
0032  */
0033 class MAILCOMMON_EXPORT ScheduledTask
0034 {
0035 public:
0036     /**
0037      * Creates a scheduled task for a given folder.
0038      * If @p immediate is true, the scheduler will run this task as soon
0039      * as possible (but won't interrupt a currently running job for it).
0040      */
0041     ScheduledTask(const Akonadi::Collection &folder, bool immediate);
0042     virtual ~ScheduledTask();
0043 
0044     /**
0045      * Run this task, i.e. create a job for it.
0046      * Important: the job's execute() method must either call open() on the folder
0047      * or storage immediately, or abort (deleting itself).
0048      * Usually, that job should also be cancellable.
0049      * Otherwise (if the open() is delayed) an unrelated open() could happen first
0050      * and mess things up.
0051      * If for some reason (e.g. a folder is deleted) nothing should be done, return 0.
0052      */
0053     virtual ScheduledJob *run() = 0;
0054 
0055     /**
0056      * An identifier for the type of task (a bit like QListViewItem::rtti).
0057      * This allows to automatically prevent two identical tasks from being scheduled
0058      * for the same folder. To circumvent this feature and make every task unique,
0059      * return 0 here.
0060      */
0061     virtual int taskTypeId() const = 0;
0062 
0063     /**
0064      * The folder which this task is supposed to handle, 0 if it was deleted meanwhile.
0065      */
0066     [[nodiscard]] Akonadi::Collection folder() const;
0067 
0068     [[nodiscard]] bool isImmediate() const;
0069 
0070 private:
0071     const Akonadi::Collection mCurrentFolder;
0072     const bool mImmediate;
0073 };
0074 
0075 /**
0076  * The unique JobScheduler instance (owned by kmkernel) implements "background processing"
0077  * of folder operations (like expiration and compaction). Tasks (things to be done)
0078  * are registered with the JobScheduler, and it will execute them one at a time,
0079  * separated by a 1-minute timer. The jobs themselves should use timers to avoid
0080  * using too much CPU for too long. Tasks for opened folders are not executed until
0081  * the folder is closed.
0082  */
0083 class MAILCOMMON_EXPORT JobScheduler : public QObject
0084 {
0085     Q_OBJECT
0086 public:
0087     explicit JobScheduler(QObject *parent);
0088     ~JobScheduler() override;
0089 
0090     /**
0091      * Register a task to be done for a given folder. The ownership of the task is transferred
0092      * to the JobScheduler.
0093      */
0094     void registerTask(ScheduledTask *task);
0095 
0096     // D-Bus calls, called from KMKernel
0097     void pause();
0098     void resume();
0099 
0100 private:
0101     // Called by a timer to run the next job
0102     MAILCOMMON_NO_EXPORT void slotRunNextJob();
0103 
0104     // Called when the current job terminates
0105     MAILCOMMON_NO_EXPORT void slotJobFinished();
0106     MAILCOMMON_NO_EXPORT void restartTimer();
0107     MAILCOMMON_NO_EXPORT void interruptCurrentTask();
0108     MAILCOMMON_NO_EXPORT void runTaskNow(ScheduledTask *task);
0109     using TaskList = QList<ScheduledTask *>;
0110     MAILCOMMON_NO_EXPORT void removeTask(TaskList::Iterator &it);
0111 
0112 private:
0113     TaskList mTaskList; // FIFO of tasks to be run
0114 
0115     QTimer mTimer;
0116     int mPendingImmediateTasks = 0;
0117 
0118     /// Information about the currently running job, if any
0119     ScheduledTask *mCurrentTask = nullptr;
0120     ScheduledJob *mCurrentJob = nullptr;
0121 };
0122 
0123 /**
0124  * Base class for scheduled jobs.
0125  */
0126 class MAILCOMMON_EXPORT ScheduledJob : public FolderJob
0127 {
0128 public:
0129     ScheduledJob(const Akonadi::Collection &folder, bool immediate);
0130     ~ScheduledJob() override;
0131 
0132 protected:
0133     bool mImmediate;
0134 };
0135 }