Menu

[r2375]: / framework / trunk / cppcms / cache_interface.h  Maximize  Restore  History

Download this file

352 lines (309 with data), 12.0 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
//
// See accompanying file COPYING.TXT file for licensing details.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef CPPCMS_CACHE_INTERFACE_H
#define CPPCMS_CACHE_INTERFACE_H
#include <string>
#include <set>
#include <cppcms/defs.h>
#include <cppcms/serialization_classes.h>
#include <booster/noncopyable.h>
#include <booster/intrusive_ptr.h>
#include <booster/hold_ptr.h>
#include <cppcms/cstdint.h>
namespace cppcms {
class service;
namespace impl {
class base_cache;
}
namespace http {
class context;
};
class cache_interface;
///
/// \brief triggers_recorder is a class that allows you to record all triggers added in certain scope.
///
/// It is useful to have have "sub-dependencies" for smaller parts.
///
/// For example:
///
/// \code
///
/// if(cache().fetch_page("news"))
/// return;
/// // something there
/// if(cache().fetch_frame("politics",text))
/// response().out() << text;
/// else {
/// copy_filter politics(respone().out());
/// triggers_recorder politics_triggers(cache());
/// // some thing else there
/// for(int i=0;i<articles.size();i++) {
/// if(cache().fetch_frame(article_tag,text);
/// response().out() << text;
/// else {
/// copy_filter article(respone().out());
/// // generate article
/// cache().store_frame(article_tag,article.detach());
/// }
/// }
/// cache().store_frame("polotics",
/// politics.detach(), // the recorded content of politics
/// politics_triggers.detach());
/// }
/// ...
/// \endcode
///
/// So tag "politics" records all added triggers like "article_234" and
/// now rise of "article_234" would invalidate "politics" section as well
/// as we automatically record all triggers inserted in triggers_recorder scope.
///
///
class CPPCMS_API triggers_recorder : public booster::noncopyable {
public:
///
/// Start recording all triggers
///
triggers_recorder(cache_interface &);
///
/// Stop recording triggers
///
~triggers_recorder();
///
/// Stop recording triggers and get the set of all triggers
/// being added in its scope
///
std::set<std::string> detach();
private:
friend class cache_interface;
void add(std::string const &t);
struct data;
booster::hold_ptr<data> d;
std::set<std::string> triggers_;
cache_interface *cache_;
};
///
/// \brief This class is the major gateway of the application to CppCMS caching abilities. Any access too cache
/// would be done via this class.
///
/// CppCMS cache model supports following concepts:
///
/// - \a key the unique identification of the object in cache
/// - \a timeout -- the maximal time the cached object remains valid
/// - \a trigger -- special key that allows fast invalidation of multiple cache objects.
///
/// The first two concepts are quite popular and available in most of Web framework, but the last one is very
/// unique to CppCMS that gives fine grained cache invalidation tools.
///
/// Each time the page is created it automatically receives some triggers during the process of creation.
/// When some object is fetched from the cache or stored into it, it adds triggers to the major page. This provides
/// semi-automatic triggers management.
///
/// For example:
///
/// \code
/// if(cache().fetch_page("main_page"))
/// return;
/// if(!cache().fetch_frame("article_"+id,article)) {
/// article=generate_article_from_data_base(id);
/// cache.store_frame("article_"+id,article);
/// }
/// // Generate some HTML here using article
/// cache.store_page("main");
/// \endcode
///
/// Let's assume that "main_page" wasn't found in cache, then we try to fetch a frame that holds only a single
/// article "article_123", if it is fetched, the result is stored in a string article and the trigger "article_123"
/// is automatically added to set of triggers that "main_page" depends on them.
///
/// When the article updated, and "article_123" key is risen, it would automatically invalidate "main_page" as well.
///
/// CppCMS cache_interface allows storing arbitrary object in cache, For this purpose they should be "serializable".
/// This can be done by specializing a class cppcms::setialization_traits
///
class CPPCMS_API cache_interface : public booster::noncopyable {
public:
///
/// Create interface object without a context, everything but
/// fetch_page and store_page would work, it is not possible to
/// handle pages without full i/o context
///
/// \ver{v1_2}
cache_interface(cppcms::service &srv);
///
/// \cond INTERNAL
///
/// Internal API, don't use it
///
cache_interface(http::context &context);
~cache_interface();
/// \endcond
///
/// Rise a trigger \a trigger. All cached objects that depend on this trigger would be invalidated
///
void rise(std::string const &trigger);
///
/// Add a trigger \a trigger to the list of dependencies of current page.
///
void add_trigger(std::string const &trigger);
///
/// Clear all CppCMS cache - use carefully
///
void clear();
///
/// Remove all triggers added to current page so far
///
void reset();
///
/// Get statistics about items stored in cache. May require O(n) complexity, use with care.
///
/// \param keys -- the number of items stored in cache
/// \param triggers -- the number of various triggers existing in the cache.
///
/// Returns false if caching system is disabled.
///
bool stats(unsigned &keys,unsigned &triggers);
///
/// Returns true if caching system is enabled
///
bool has_cache();
///
/// Opposite of \a has_cache
///
bool nocache();
///
/// Fetch a page from the cache with a key \a key. If the page exists, it is written to output
/// and true is returned. Otherwise false is returned.
///
bool fetch_page(std::string const &key);
///
/// Store page with key \a akey in cache, with timeout \a timeout.
///
/// This function stores a page with dependencies on all triggers that were added so far.
///
/// \param key -- the key that defines the cache.
/// \param timeout -- maximal valid time of the page. \a timeout=-1 means infinite. Use with care.
///
/// Note: store_page does not rise the trigger \a key, only replaces the value.
///
void store_page(std::string const &key,int timeout=-1);
///
/// Fetch a string (usually some HTML part) from the cache.
///
/// \param key -- the key that uniquely defines the frame.
/// \param result -- string to store fetched value
/// \param notriggers -- if true, no triggers that a frame is dependent on would be added to dependencies of
/// the current page, otherwise (false, default), the all triggers that page is dependent on, including
/// the \a key itself would be added as dependent triggers to current rendered page.
/// \return returns true if the entry was found.
///
bool fetch_frame(std::string const &key,std::string &result,bool notriggers=false);
///
/// Store a string (usually some HTML part) to the cache.
///
/// \param key -- the key that uniquely defines the frame.
/// \param frame -- the actual value
/// \param triggers -- the set of triggers that the key should depend on (\a key is added automatically)
/// \param timeout -- maximal object lifetime, -1 is infinity
/// \param notriggers -- if \a notriggers is true no frame dependent triggers would be added to the current
/// page trigger set. Otherwise (default) current page would depend on the \a key and \a triggers as its
/// dependent triggers.
///
void store_frame(std::string const &key,
std::string const &frame,
std::set<std::string> const &triggers=std::set<std::string>(),
int timeout=-1,
bool notriggers=false);
///
/// Store a string (usually some HTML part) to the cache.
///
/// \param key -- the key that uniquely defines the frame.
/// \param frame -- the actual value
/// \param timeout -- maximal object lifetime, -1 is infinity
/// \param notriggers -- if \a notriggers is true \a key added to the current
/// page trigger set. Otherwise (default) current page would depend on the \a key
///
void store_frame(std::string const &key,
std::string const &frame,
int timeout,
bool notriggers=false);
///
/// Fetch a serializeable object from the cache.
///
/// \param key -- the key that uniquely defines the frame.
/// \param data -- an object store fetched data
/// \param notriggers -- if true, no triggers that an object is dependent on would be added to dependencies of
/// the current page, otherwise (false, default), the all triggers that the object is dependent on, including
/// the \a key itself would be added as dependent triggers to current rendered page.
/// \return returns true if the entry was found.
///
template<typename Serializable>
bool fetch_data(std::string const &key,Serializable &data,bool notriggers=false)
{
std::string buffer;
if(!fetch(key,buffer,notriggers))
return false;
serialization_traits<Serializable>::load(buffer,data);
return true;
}
///
/// Store a serializeable object to the cache.
///
/// \param key -- the key that uniquely defines the object.
/// \param data -- the actual object
/// \param triggers -- the set of triggers that the key should depend on (\a key is added automatically)
/// \param timeout -- maximal object lifetime, -1 is infinity
/// \param notriggers -- if \a notriggers is true no frame dependent triggers would be added to the current
/// page trigger set. Otherwise (default) current page would depend on the \a key and \a triggers as its
/// dependent triggers.
///
template<typename Serializable>
void store_data(std::string const &key,Serializable const &data,
std::set<std::string> const &triggers=std::set<std::string>(),
int timeout=-1,bool notriggers=false)
{
std::string buffer;
serialization_traits<Serializable>::save(data,buffer);
store(key,buffer,triggers,timeout,notriggers);
}
///
/// Store a serializeable object to the cache.
///
/// \param key -- the key that uniquely defines the object.
/// \param data -- the actual object
/// \param timeout -- maximal object lifetime, -1 is infinity
/// \param notriggers -- if \a notriggers is true \a key added to the current
/// page trigger set. Otherwise (default) current page would depend on the \a key
///
template<typename Serializable>
void store_data(std::string const &key,Serializable const &data,int timeout,bool notriggers=false)
{
store_data<Serializable>(key,data,std::set<std::string>(),timeout,notriggers);
}
private:
friend class triggers_recorder;
void add_triggers_recorder(triggers_recorder *rec);
void remove_triggers_recorder(triggers_recorder *rec);
void store( std::string const &key,
std::string const &data,
std::set<std::string> const &triggers,
int timeout,
bool notriggers);
bool fetch( std::string const &key,
std::string &buffer,
bool notriggers);
struct _data;
booster::hold_ptr<_data> d;
http::context *context_;
std::set<std::string> triggers_;
std::set<triggers_recorder *> recorders_;
booster::intrusive_ptr<impl::base_cache> cache_module_;
uint32_t page_compression_used_ : 1;
uint32_t reserved : 31;
};
}
#endif
MongoDB Logo MongoDB