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