File indexing completed on 2024-05-26 05:14:37

0001 /*
0002     SPDX-FileCopyrightText: 2011 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "akthread.h"
0010 #include "storage/dbconfig.h"
0011 
0012 #include <QDBusConnection>
0013 
0014 namespace Akonadi
0015 {
0016 namespace Server
0017 {
0018 class Collection;
0019 class AkonadiServer;
0020 class DataStore;
0021 
0022 /**
0023  * Various database checking/maintenance features.
0024  */
0025 class StorageJanitor : public AkThread
0026 {
0027     Q_OBJECT
0028     Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Akonadi.Janitor")
0029 
0030 protected:
0031     /**
0032      * Use AkThread::create() to create and start a new StorageJanitor thread.
0033      */
0034     explicit StorageJanitor(AkonadiServer *mAkonadi, DbConfig *config = DbConfig::configuredDatabase());
0035 
0036 public:
0037     /**
0038      * Use AkThread::create() to run StorageJanitor in a separate thread. Only use this constructor
0039      * if you want to run StorageJanitor in the current thread.
0040      */
0041     explicit StorageJanitor(DbConfig *config);
0042     ~StorageJanitor() override;
0043 
0044 public Q_SLOTS:
0045     /** Triggers a consistency check of the internal storage. */
0046     Q_SCRIPTABLE Q_NOREPLY void check();
0047     /** Triggers a vacuuming of the database, that is compacting of unused space. */
0048     Q_SCRIPTABLE Q_NOREPLY void vacuum();
0049 
0050 Q_SIGNALS:
0051     /** Sends informational messages to a possible UI for this. */
0052     Q_SCRIPTABLE void information(const QString &msg);
0053     Q_SCRIPTABLE void done();
0054 
0055 protected:
0056     void init() override;
0057     void quit() override;
0058 
0059 private:
0060     void registerTasks();
0061 
0062     void inform(const char *msg);
0063     void inform(const QString &msg);
0064     /** Create a lost+found collection if necessary. */
0065     qint64 lostAndFoundCollection();
0066 
0067     /**
0068      * Look for resources in the DB not existing in reality.
0069      */
0070     void findOrphanedResources();
0071 
0072     /**
0073      * Look for collections belonging to non-existent resources.
0074      */
0075     void findOrphanedCollections();
0076 
0077     /**
0078      * Verifies that each collection in the collection tree has a path to the root
0079      * and that all collections along that path belong to the same resource.
0080      */
0081     void checkCollectionTreeConsistency();
0082     void checkPathToRoot(const Collection &col);
0083 
0084     /**
0085      * Look for items belonging to non-existing collections.
0086      */
0087     void findOrphanedItems();
0088 
0089     /**
0090      * Look for parts belonging to non-existing items.
0091      */
0092     void findOrphanedParts();
0093 
0094     /**
0095      * Look for item flags belonging to non-existing items.
0096      */
0097     void findOrphanedPimItemFlags();
0098 
0099     /**
0100      * Look for duplicate item flags and fix them.
0101      */
0102     void findDuplicateFlags();
0103 
0104     /**
0105      * Look for duplicate mime type names and fix them.
0106      */
0107     void findDuplicateMimeTypes();
0108 
0109     /**
0110      * Look for duplicate part type names and fix them.
0111      */
0112     void findDuplicatePartTypes();
0113 
0114     /**
0115      * Look for duplicate tag names and fix them.
0116      */
0117     void findDuplicateTagTypes();
0118 
0119     /**
0120      * Look for duplicate relation type names and fix them.
0121      */
0122     void findDuplicateRelationTypes();
0123 
0124     /**
0125      * Look for parts referring to the same external file.
0126      */
0127     void findOverlappingParts();
0128 
0129     /**
0130      * Verify fs and db part state.
0131      */
0132     void verifyExternalParts();
0133 
0134     /**
0135      * Look for dirty objects.
0136      */
0137     void findDirtyObjects();
0138 
0139     /**
0140      * Look for duplicates by RID.
0141      *
0142      * ..and remove the one that doesn't match the parent collections content mimetype.
0143      */
0144     void findRIDDuplicates();
0145 
0146     /**
0147      * Check whether part sizes match what's in database.
0148      *
0149      * If SizeTreshold has change, it will move parts from or to database
0150      * where necessary.
0151      */
0152     void checkSizeTreshold();
0153 
0154     /**
0155      * Check if all external payload files are migrated to the levelled folder
0156      * hierarchy and migrates them if necessary
0157      */
0158     void migrateToLevelledCacheHierarchy();
0159 
0160     /**
0161      * Check if the search index contains any entries that refer to Akonadi
0162      * Items that no longer exist in the DB.
0163      */
0164     void findOrphanSearchIndexEntries();
0165 
0166     /**
0167      * Make sure that the "Search" collection in the virtual search resource
0168      * exists. It is only created during database initialization, so if user
0169      * somehow manages to delete it, their search would be completely borked.
0170      */
0171     void ensureSearchCollection();
0172 
0173     /**
0174      * Clear cache that holds pre-computed collection statistics.
0175      * They will be re-computed on demand.
0176      */
0177     void expireCollectionStatisticsCache();
0178 
0179 private:
0180     qint64 m_lostFoundCollectionId;
0181     AkonadiServer *m_akonadi = nullptr;
0182     DbConfig *m_dbConfig = nullptr;
0183     std::unique_ptr<DataStore> m_dataStore;
0184 
0185     struct Task {
0186         QString name;
0187         void (StorageJanitor::*func)();
0188     };
0189     QList<Task> m_tasks;
0190 };
0191 
0192 } // namespace Server
0193 } // namespace Akonadi