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