File indexing completed on 2024-04-28 15:29:54

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