File indexing completed on 2024-04-14 03:54:37

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 1999-2000 Waldo Bastian <bastian@kde.org>
0004     SPDX-FileCopyrightText: 2005-2009 David Faure <faure@kde.org>
0005     SPDX-FileCopyrightText: 2008 Hamish Rodda <rodda@kde.org>
0006     SPDX-FileCopyrightText: 2020 Harald Sitter <sitter@kde.org>
0007 
0008     SPDX-License-Identifier: LGPL-2.0-only
0009 */
0010 
0011 #ifndef KSYCOCA_P_H
0012 #define KSYCOCA_P_H
0013 
0014 #include "ksycocafactory_p.h"
0015 #include <KDirWatch>
0016 #include <QDateTime>
0017 #include <QElapsedTimer>
0018 #include <QStringList>
0019 
0020 #include <memory>
0021 
0022 class QFile;
0023 class QDataStream;
0024 class KSycocaAbstractDevice;
0025 class KMimeTypeFactory;
0026 class KServiceFactory;
0027 class KServiceGroupFactory;
0028 
0029 // This is for the part of the global header that we don't need to store,
0030 // i.e. it's just a struct for returning temp data from readSycocaHeader().
0031 struct KSycocaHeader {
0032     KSycocaHeader()
0033         : timeStamp(0)
0034         , updateSignature(0)
0035     {
0036     }
0037     QString prefixes;
0038     QString language;
0039     qint64 timeStamp; // in ms
0040     quint32 updateSignature;
0041 };
0042 
0043 QDataStream &operator>>(QDataStream &in, KSycocaHeader &h);
0044 
0045 /**
0046  * \internal
0047  * Exported for unittests
0048  */
0049 class KSERVICE_EXPORT KSycocaPrivate
0050 {
0051 public:
0052     explicit KSycocaPrivate(KSycoca *qq);
0053 
0054     // per-thread "singleton"
0055     static KSycocaPrivate *self()
0056     {
0057         return KSycoca::self()->d;
0058     }
0059 
0060     bool checkVersion();
0061     bool openDatabase();
0062     enum BehaviorIfNotFound {
0063         IfNotFoundDoNothing = 0,
0064         IfNotFoundRecreate = 1,
0065     };
0066     Q_DECLARE_FLAGS(BehaviorsIfNotFound, BehaviorIfNotFound)
0067     bool checkDatabase(BehaviorsIfNotFound ifNotFound);
0068     void closeDatabase();
0069     void setStrategyFromString(const QString &strategy);
0070     bool tryMmap();
0071 
0072     /**
0073      * Check if the on-disk cache needs to be rebuilt, and do it then.
0074      */
0075     void checkDirectories();
0076 
0077     /**
0078      * Check if the on-disk cache needs to be rebuilt, and return true
0079      */
0080     bool needsRebuild();
0081 
0082     /**
0083      * Recreate the cache and reopen the database
0084      */
0085     bool buildSycoca();
0086 
0087     KSycocaHeader readSycocaHeader();
0088 
0089     KSycocaAbstractDevice *device();
0090     QDataStream *&stream();
0091 
0092     QString findDatabase();
0093     void slotDatabaseChanged();
0094 
0095     KMimeTypeFactory *mimeTypeFactory();
0096     KServiceFactory *serviceFactory();
0097     KServiceGroupFactory *serviceGroupFactory();
0098 
0099     enum {
0100         DatabaseNotOpen, // openDatabase must be called
0101         BadVersion, // it's opened, but it's not usable
0102         DatabaseOK,
0103     } databaseStatus;
0104     bool readError;
0105 
0106     qint64 timeStamp; // in ms since epoch
0107     enum { StrategyMmap, StrategyMemFile, StrategyFile } m_sycocaStrategy;
0108     QString m_databasePath;
0109     QString language;
0110     quint32 updateSig;
0111     QMap<QString, qint64> allResourceDirs; // path, modification time in "ms since epoch"
0112     QMap<QString, qint64> extraFiles; // path, modification time in "ms since epoch"
0113 
0114     void addFactory(KSycocaFactory *factory)
0115     {
0116         m_factories.append(factory);
0117     }
0118     KSycocaFactoryList *factories()
0119     {
0120         return &m_factories;
0121     }
0122 
0123     QElapsedTimer m_lastCheck;
0124     QDateTime m_dbLastModified;
0125 
0126     // Using KDirWatch because it will reliably tell us every time ksycoca is recreated.
0127     // QFileSystemWatcher's inotify implementation easily gets confused between "removed" and "changed",
0128     // and fails to re-add an inotify watch after the file was replaced at some point (KServiceTest::testThreads),
0129     // thinking it only got changed and not removed+recreated.
0130     // NOTE: this may be nullptr when file watching is disabled on the current thread
0131     std::unique_ptr<KDirWatch> m_fileWatcher;
0132     bool m_haveListeners;
0133 
0134     KSycoca *q;
0135 
0136 private:
0137     KSycocaFactoryList m_factories;
0138     size_t sycoca_size;
0139     const char *sycoca_mmap;
0140     QFile *m_mmapFile;
0141     KSycocaAbstractDevice *m_device;
0142 
0143 public:
0144     KMimeTypeFactory *m_mimeTypeFactory;
0145     KServiceFactory *m_serviceFactory;
0146     KServiceGroupFactory *m_serviceGroupFactory;
0147 };
0148 
0149 #endif /* KSYCOCA_P_H */