File indexing completed on 2024-05-19 03:56:19

0001 /*
0002     This file is part of the KDE project.
0003 
0004     SPDX-FileCopyrightText: 2010 Michael Pyne <mpyne@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-only
0007 */
0008 
0009 #ifndef KSHAREDDATACACHE_H
0010 #define KSHAREDDATACACHE_H
0011 
0012 #include <kcoreaddons_export.h>
0013 
0014 class QString;
0015 class QByteArray;
0016 
0017 /**
0018  * @class KSharedDataCache kshareddatacache.h KSharedDataCache
0019  *
0020  * @brief A simple data cache which uses shared memory to quickly access data
0021  * stored on disk.
0022  *
0023  * This class is meant to be used with KImageCache and similar classes but can
0024  * be used directly if used with care.
0025  *
0026  * Example usage:
0027  *
0028  * @code
0029  * QString loadTranslatedDocument(KSharedDataCache *cache) {
0030  *
0031  *   // Find the data
0032  *   QByteArray document;
0033  *
0034  *   if (!cache->find("translated-doc-template", &document)) {
0035  *     // Entry is not cached, manually generate and then add to cache.
0036  *     document = translateDocument(globalTemplate());
0037  *     cache->insert(document);
0038  *   }
0039  *
0040  *   // Don't forget to encode/decode properly
0041  *   return QString::fromUtf8(document);
0042  * }
0043  * @endcode
0044  *
0045  * @author Michael Pyne <mpyne@kde.org>
0046  * @see KImageCache
0047  * @since 4.5
0048  */
0049 class KCOREADDONS_EXPORT KSharedDataCache
0050 {
0051 public:
0052     /**
0053      * Attaches to a shared cache, creating it if necessary. If supported, this
0054      * data cache will be shared across all processes using this cache (with
0055      * subsequent memory savings).  If shared memory is unsupported or a
0056      * failure occurs, caching will still be supported, but only in the same
0057      * process, and only using the same KSharedDataCache object.
0058      *
0059      * @param cacheName Name of the cache to use/share.
0060      * @param defaultCacheSize Amount of data to be able to store, in bytes. The
0061      *   actual size will be slightly larger on disk due to accounting
0062      *   overhead.  If the cache already existed then it <em>will not</em> be
0063      *   resized. For this reason you should specify some reasonable size.
0064      * @param expectedItemSize The average size of an item that would be stored
0065      *   in the cache, in bytes. Choosing an average size of zero bytes causes
0066      *   KSharedDataCache to use whatever it feels is the best default for the
0067      *   system.
0068      */
0069     KSharedDataCache(const QString &cacheName, unsigned defaultCacheSize, unsigned expectedItemSize = 0);
0070     ~KSharedDataCache();
0071 
0072     KSharedDataCache(const KSharedDataCache &) = delete;
0073     KSharedDataCache &operator=(const KSharedDataCache &) = delete;
0074 
0075     enum EvictionPolicy {
0076         // The default value for data in our shared memory will be 0, so it is
0077         // important that whatever we want for the default value is also 0.
0078         NoEvictionPreference = 0,
0079         EvictLeastRecentlyUsed,
0080         EvictLeastOftenUsed,
0081         EvictOldest,
0082     };
0083 
0084     /**
0085      * @return The removal policy in use by the shared cache.
0086      * @see EvictionPolicy
0087      */
0088     EvictionPolicy evictionPolicy() const;
0089 
0090     /**
0091      * Sets the entry removal policy for the shared cache to
0092      * @p newPolicy. The default is EvictionPolicy::NoEvictionPreference.
0093      *
0094      * @see EvictionPolicy
0095      */
0096     void setEvictionPolicy(EvictionPolicy newPolicy);
0097 
0098     /**
0099      * Attempts to insert the entry @p data into the shared cache, named by
0100      * @p key, and returns true only if successful.
0101      *
0102      * Note that even if the insert was successful, that the newly added entry
0103      * may be evicted by other processes contending for the cache.
0104      */
0105     bool insert(const QString &key, const QByteArray &data);
0106 
0107     /**
0108      * Returns the data in the cache named by @p key (even if it's some other
0109      * process's data named with the same key!), stored in @p destination. If there is
0110      * no entry named by @p key then @p destination is left unchanged. The return value
0111      * is used to tell what happened.
0112      *
0113      * If you simply want to verify whether an entry is present in the cache then
0114      * see contains().
0115      *
0116      * @param key The key to find in the cache.
0117      * @param destination Is set to the value of @p key in the cache if @p key is
0118      *                    present, left unchanged otherwise.
0119      * @return true if @p key was present in the cache (@p destination will also be
0120      *         updated), false if @p key was not present (@p destination will be
0121      *         unchanged).
0122      */
0123     bool find(const QString &key, QByteArray *destination) const;
0124 
0125     /**
0126      * Removes all entries from the cache.
0127      */
0128     void clear();
0129 
0130     /**
0131      * Removes the underlying file from the cache. Note that this is *all* that this
0132      * function does. The shared memory segment is still attached and will still contain
0133      * all the data until all processes currently attached remove the mapping.
0134      *
0135      * In order to remove the data see clear().
0136      */
0137     static void deleteCache(const QString &cacheName);
0138 
0139     /**
0140      * Returns true if the cache currently contains the image for the given
0141      * filename.
0142      *
0143      * NOTE: Calling this function is threadsafe, but it is in general not
0144      * possible to guarantee the image stays cached immediately afterwards,
0145      * so if you need the result use find().
0146      */
0147     bool contains(const QString &key) const;
0148 
0149     /**
0150      * Returns the usable cache size in bytes. The actual amount of memory
0151      * used will be slightly larger than this to account for required
0152      * accounting overhead.
0153      */
0154     unsigned totalSize() const;
0155 
0156     /**
0157      * Returns the amount of free space in the cache, in bytes. Due to
0158      * implementation details it is possible to still not be able to fit an
0159      * entry in the cache at any given time even if it is smaller than the
0160      * amount of space remaining.
0161      */
0162     unsigned freeSize() const;
0163 
0164     /**
0165      * @return The shared timestamp of the cache. The interpretation of the
0166      *         timestamp returned is up to the application. KSharedDataCache
0167      *         will initialize the timestamp to the time returned by @c time(2)
0168      *         on cache creation, but KSharedDataCache will not touch the
0169      *         timestamp again.
0170      * @see setTimestamp()
0171      * @since 4.6
0172      */
0173     unsigned timestamp() const;
0174 
0175     /**
0176      * Sets the shared timestamp of the cache. Timestamping is supported to
0177      * allow applications to more effectively "version" the data stored in the
0178      * cache. However, the timestamp is shared with <em>all</em> applications
0179      * using the cache so you should always be prepared for invalid
0180      * timestamps.
0181      *
0182      * When the cache is first created (note that this is different from
0183      * attaching to an existing shared cache on disk), the cache timestamp is
0184      * initialized to the time returned by @c time(2). KSharedDataCache will
0185      * not update the timestamp again, it is only updated through this method.
0186      *
0187      * Example:
0188      * @code
0189      * QImage loadCachedImage(const QString &key)
0190      * {
0191      *     // Check timestamp
0192      *     if (m_sharedCache->timestamp() < m_currentThemeTimestamp) {
0193      *         // Cache is stale, clean it out.
0194      *         m_sharedCache->clear();
0195      *         m_sharedCache->setTimestamp(m_currentThemeTimestamp);
0196      *     }
0197      *
0198      *     // Check cache and load image as usual...
0199      * }
0200      * @endcode
0201      *
0202      * @param newTimestamp The new timestamp to mark the shared cache with.
0203      * @see timestamp()
0204      * @since 4.6
0205      */
0206     void setTimestamp(unsigned newTimestamp);
0207 
0208 private:
0209     class Private;
0210     Private *d;
0211 };
0212 
0213 #endif