1 | /* |
2 | This file is part of the KDE project. |
3 | |
4 | SPDX-FileCopyrightText: 2010 Michael Pyne <mpyne@kde.org> |
5 | |
6 | SPDX-License-Identifier: LGPL-2.0-only |
7 | */ |
8 | |
9 | #ifndef KSHAREDDATACACHE_H |
10 | #define KSHAREDDATACACHE_H |
11 | |
12 | #include <kcoreaddons_export.h> |
13 | |
14 | class QString; |
15 | class QByteArray; |
16 | |
17 | /*! |
18 | * \class KSharedDataCache |
19 | * \inmodule KCoreAddons |
20 | * |
21 | * \brief A simple data cache which uses shared memory to quickly access data |
22 | * stored on disk. |
23 | * |
24 | * This class is meant to be used with KImageCache and similar classes but can |
25 | * be used directly if used with care. |
26 | * |
27 | * Example usage: |
28 | * |
29 | * \code |
30 | * QString loadTranslatedDocument(KSharedDataCache *cache) { |
31 | * |
32 | * // Find the data |
33 | * QByteArray document; |
34 | * |
35 | * if (!cache->find("translated-doc-template", &document)) { |
36 | * // Entry is not cached, manually generate and then add to cache. |
37 | * document = translateDocument(globalTemplate()); |
38 | * cache->insert(document); |
39 | * } |
40 | * |
41 | * // Don't forget to encode/decode properly |
42 | * return QString::fromUtf8(document); |
43 | * } |
44 | * \endcode |
45 | * |
46 | * \sa KImageCache |
47 | * \since 4.5 |
48 | */ |
49 | class KCOREADDONS_EXPORT KSharedDataCache |
50 | { |
51 | public: |
52 | /*! |
53 | * Attaches to a shared cache, creating it if necessary. If supported, this |
54 | * data cache will be shared across all processes using this cache (with |
55 | * subsequent memory savings). If shared memory is unsupported or a |
56 | * failure occurs, caching will still be supported, but only in the same |
57 | * process, and only using the same KSharedDataCache object. |
58 | * |
59 | * \a cacheName Name of the cache to use/share. |
60 | * |
61 | * \a defaultCacheSize Amount of data to be able to store, in bytes. The |
62 | * actual size will be slightly larger on disk due to accounting |
63 | * overhead. If the cache already existed then it will not be |
64 | * resized. For this reason you should specify some reasonable size. |
65 | * |
66 | * \a expectedItemSize The average size of an item that would be stored |
67 | * in the cache, in bytes. Choosing an average size of zero bytes causes |
68 | * KSharedDataCache to use whatever it feels is the best default for the |
69 | * system. |
70 | */ |
71 | KSharedDataCache(const QString &cacheName, unsigned defaultCacheSize, unsigned expectedItemSize = 0); |
72 | ~KSharedDataCache(); |
73 | |
74 | KSharedDataCache(const KSharedDataCache &) = delete; |
75 | KSharedDataCache &operator=(const KSharedDataCache &) = delete; |
76 | |
77 | /*! |
78 | * \value NoEvictionPreference No preference |
79 | * \value EvictLeastRecentlyUsed Evict the least recently used entry |
80 | * \value EvictLeastOftenUsed Evict the lest often used item |
81 | * \value EvictOldest Evict the oldest item |
82 | */ |
83 | enum EvictionPolicy { |
84 | // The default value for data in our shared memory will be 0, so it is |
85 | // important that whatever we want for the default value is also 0. |
86 | NoEvictionPreference = 0, |
87 | EvictLeastRecentlyUsed, |
88 | EvictLeastOftenUsed, |
89 | EvictOldest, |
90 | }; |
91 | |
92 | /*! |
93 | * Returns the removal policy in use by the shared cache. |
94 | */ |
95 | EvictionPolicy evictionPolicy() const; |
96 | |
97 | /*! |
98 | * Sets the entry removal policy for the shared cache to |
99 | * |
100 | * \a newPolicy. The default is EvictionPolicy::NoEvictionPreference. |
101 | */ |
102 | void setEvictionPolicy(EvictionPolicy newPolicy); |
103 | |
104 | /*! |
105 | * Attempts to insert the entry \a data into the shared cache, named by |
106 | * \a key, and returns true only if successful. |
107 | * |
108 | * Note that even if the insert was successful, that the newly added entry |
109 | * may be evicted by other processes contending for the cache. |
110 | */ |
111 | bool insert(const QString &key, const QByteArray &data); |
112 | |
113 | /*! |
114 | * Attempts to remove an entry with the specified \a key. Returns \c true if an entry has |
115 | * been removed; otherwise returns \c false. |
116 | * |
117 | * \since 6.18 |
118 | */ |
119 | bool remove(const QString &key); |
120 | |
121 | /*! |
122 | * Returns the data in the cache named by \a key (even if it's some other |
123 | * process's data named with the same key!), stored in \a destination. If there is |
124 | * no entry named by \a key then \a destination is left unchanged. The return value |
125 | * is used to tell what happened. |
126 | * |
127 | * If you simply want to verify whether an entry is present in the cache then |
128 | * see contains(). |
129 | * |
130 | * \a key The key to find in the cache. |
131 | * |
132 | * \a destination Is set to the value of \a key in the cache if \a key is |
133 | * present, left unchanged otherwise. |
134 | * |
135 | * Returns true if \a key was present in the cache (\a destination will also be |
136 | * updated), false if \a key was not present (\a destination will be |
137 | * unchanged). |
138 | */ |
139 | bool find(const QString &key, QByteArray *destination) const; |
140 | |
141 | /*! |
142 | * Removes all entries from the cache. |
143 | */ |
144 | void clear(); |
145 | |
146 | /*! |
147 | * Removes the underlying file from the cache. Note that this is *all* that this |
148 | * function does. The shared memory segment is still attached and will still contain |
149 | * all the data until all processes currently attached remove the mapping. |
150 | * |
151 | * In order to remove the data see clear(). |
152 | */ |
153 | static void deleteCache(const QString &cacheName); |
154 | |
155 | /*! |
156 | * Returns true if the cache currently contains the image for the given |
157 | * filename. |
158 | * |
159 | * \note Calling this function is threadsafe, but it is in general not |
160 | * possible to guarantee the image stays cached immediately afterwards, |
161 | * so if you need the result use find(). |
162 | */ |
163 | bool contains(const QString &key) const; |
164 | |
165 | /*! |
166 | * Returns the usable cache size in bytes. The actual amount of memory |
167 | * used will be slightly larger than this to account for required |
168 | * accounting overhead. |
169 | */ |
170 | unsigned totalSize() const; |
171 | |
172 | /*! |
173 | * Returns the amount of free space in the cache, in bytes. Due to |
174 | * implementation details it is possible to still not be able to fit an |
175 | * entry in the cache at any given time even if it is smaller than the |
176 | * amount of space remaining. |
177 | */ |
178 | unsigned freeSize() const; |
179 | |
180 | /*! |
181 | * Returns the shared timestamp of the cache. The interpretation of the |
182 | * timestamp returned is up to the application. KSharedDataCache |
183 | * will initialize the timestamp to the time returned by \c time(2) |
184 | * on cache creation, but KSharedDataCache will not touch the |
185 | * timestamp again. |
186 | * \sa setTimestamp() |
187 | * \since 4.6 |
188 | */ |
189 | unsigned timestamp() const; |
190 | |
191 | /*! |
192 | * Sets the shared timestamp of the cache. Timestamping is supported to |
193 | * allow applications to more effectively "version" the data stored in the |
194 | * cache. However, the timestamp is shared with all applications |
195 | * using the cache so you should always be prepared for invalid |
196 | * timestamps. |
197 | * |
198 | * When the cache is first created (note that this is different from |
199 | * attaching to an existing shared cache on disk), the cache timestamp is |
200 | * initialized to the time returned by \c time(2). KSharedDataCache will |
201 | * not update the timestamp again, it is only updated through this method. |
202 | * |
203 | * Example: |
204 | * \code |
205 | * QImage loadCachedImage(const QString &key) |
206 | * { |
207 | * // Check timestamp |
208 | * if (m_sharedCache->timestamp() < m_currentThemeTimestamp) { |
209 | * // Cache is stale, clean it out. |
210 | * m_sharedCache->clear(); |
211 | * m_sharedCache->setTimestamp(m_currentThemeTimestamp); |
212 | * } |
213 | * |
214 | * // Check cache and load image as usual... |
215 | * } |
216 | * \endcode |
217 | * |
218 | * \a newTimestamp The new timestamp to mark the shared cache with. |
219 | * \sa timestamp() |
220 | * \since 4.6 |
221 | */ |
222 | void setTimestamp(unsigned newTimestamp); |
223 | |
224 | private: |
225 | class Private; |
226 | Private *d; |
227 | }; |
228 | |
229 | #endif |
230 | |