## Table of Contents |
|
- [Role](#role) |
- [Objects stored in cache](#obj) |
- [General](#gen) |
- [Trigger-less Cache](#tlc) |
|
- [Web Pages](#tlc1) |
- [C++ Objects and HTML Frames](#tlc2) |
|
- [Cache with triggers](#trig) |
|
- [Concept](#concept) |
- [Manual Triggers Management](#man) |
- [Semi-automatic Triggers Management](#auto) |
- [Triggers for objects](#tobj) |
- [Notes](#not) |
|
- [General Functions](#func) |
|
## <span id="role"></span>Role |
|
This class provides access to cache API of cppcms. It is usually accessed by `cache` member of `application` or `worker_thread`. |
|
In order to use cache, you should [enable it](/wikipp/en/page/ref_config#cache) in CppCMS configurations, otherwise, dummy cache would be used. |
|
## <span id="obj"></span>Objects that are stored in cache: |
|
Various objects can be stored in cache using unique key. |
|
1. Output pages -- including two versions compressed and not for user agents that support gzip compression or not. |
2. HTML Frames -- or simple strings stored in cache. |
3. [Serializable]((/wikipp/en/page/ref_cppcms_serializable) objects. |
|
Each one of them has little bit different semantics and API. |
|
_Note:_ Keys starting with underscore "_" are reserved for internal CppCMS use. |
|
## <span id="gen"></span>General |
|
CppCMS provides sophisticated cache system that allows keep its consistency using special triggers that allow cleanup dependent groups of entries using single call. |
|
However, in many cases, timeout only based approach is good enough. So, we would divide the API into two sections: |
|
1. Trigger-less cache access |
2. Full trigger based cache access |
|
|
## <span id="tlc"></span>Trigger-less cache access |
|
### <span id="tlc1"></span>Web Page |
|
- **`bool fetch_page(string const &key)`** -- fetch page from cache. If it is fetched, `true` is returned and output is prepared, otherwise false is returned. |
|
_Note:_ The output is prepared according to request of user agent --- compressed or not compressed format. Thus, output stream may include already compressed data, so you should not try to append any output after you use this function. |
|
- **`void store_page(string const &key,int timeout=-1);`** -- store prepared output in cache using `timeout` in seconds. |
|
_Note_: default timeout = -1 -- infinite. |
|
For example: |
|
if(cache.fetch_page("main")) |
return; |
... |
render(...) |
cache.store_page("main",3600); |
|
The page can be removed from cache calling: |
|
- **`void rise(string const &key)`** -- that removes data associated with this key. |
|
|
### <span id="tlc2"></span>HTML frames and C++ Objects. |
|
You can fetch such objects using: |
|
bool fetch_frame(string const &key, |
string &result, |
bool notriggers=false); |
bool fetch_data(string const &key, |
serializable &data, |
bool notriggers=false); |
|
_Note:_ Because we work without triggers you should specify `notriggers` as true. |
|
For example: |
|
roles user_roles; // some serializable object |
if(cache.fetch_data("user_"+user_id,user_roles,true)) |
.... |
|
|
You can store these objects using: |
|
void store_frame(string const &key, |
string const &frame, |
int timeout, |
bool notriggers=false); |
void store_data(string const &key, |
serializable const &data, |
int timeout, |
bool notriggers=false); |
|
_Notes:_ |
|
- When working without triggers, specify `notriggers` to `true`, |
- You specify timeout in seconds, when -1 is infinity. |
- `notriggers` option for `store_data` and `store_frame` are available from cppcms v0.0.3. |
|
For example: |
|
roles user_roles; // some serializable object |
string key="user_"+user_id; |
if(!cache.fetch_data(key,user_roles,true)) { |
load_user_roles_from_db(user_id,user_roles); |
cache.store_data(key,user_roles,-1,true); |
} |
|
As in case of web pages you can clean data from cache using `void rise(string const &key)` member function. |
|
|
## <span id="trig"></span>Triggers based cache |
|
### <span id="concept"></span>Concept |
|
First of all basic concept --- every stored key has triggers --- other keys that can be risen and the cache would be clean. |
Each key has at least one trigger --- itself. |
|
For example you have article #1234 in blog that may be displayed in several places: |
|
- Summary of all topics (summary) |
- Rss feed (rss) |
- Summary for specific category #5 it belongs to. |
- Article itself |
|
So the structure of triggers may look like this |
|
- `summary` depends on `article_1234`, `article_1233` and `article_1232`, `summary` |
- `rss` would depend on `article_1234` up to `article_1224` and `rss` |
- `cat_5` would depend on `article_1234` and `article_1100` and `cat_5` |
- `post_1234` would depend on `article_1234` and `post_1234`. |
|
|
So, if we "rise" trigger `article_1234` by calling `rise("article_1234")`, all these cached entries would be automatically dropped. |
|
So every cached object has a set of triggers associated with it that would cause its cleanup. This is the general idea of CppCMS cache system. |
|
### <span id="man"></span>Manual Triggers Management |
|
You can add triggers to current HTML page calling: |
|
void add_trigger(string const &trigger); |
|
Thus, when the page is stored calling `store_page(key,timeout)`, this trigger would be automatically added. For example |
|
for(i=0;i<articles.size();i++) { |
content.articles_summary.push_back(articles[i]); |
cache.add_trigger("article_" + articles[i].id); |
} |
render("summary",content); |
cache.store_page("summary",3600); |
|
Then when we update some content we simply call `rise()` to cleanup all dependent pages: |
|
void on_update_article(article a) |
{ |
save_article_to_db(a); |
cache.rise("article_"+a.id); |
} |
|
Such triggers allows keep cache consistent in relatively simple way. |
|
### <span id="auto"></span>Semi-automatic dependencies management |
|
CppCMS cache system provides some automation of dependencies management. |
|
For example, if you have general cached C++ objects or some prepared HTML parts like headers, footers, than you may want to make sure that their updates would cause cleanup of dependent pages and keeping them consistent. |
|
When you call `store_frame`, `store_data`, `fetch_frame`, `fetch_data` with parameter `notriggers` set to **false** (this is default) it's triggers are automatically added to dependencies of current page. |
|
For example: |
|
if(cache.fetch_page("main")) |
return; |
if(!cache.fetch_data("options",opts)) { |
load_opts(opts); |
cache.store_data("options",opts); |
} |
/// Generate some HTML here |
cache.store_page("main"); |
|
Because we call `fetch_data` and `store_data` with default parameter `notriggers=false` --- trigger "options" is automatically added to key "main" |
|
So next time, you update "options" and rise it's trigger, all pages that actually used options would be automatically cleaned up. |
|
### <span id="tobj"></span>Setting Triggers for Stored Objects |
|
You can also manage triggers for stored objects: |
|
void store_frame(string const &key, |
string const &frame, |
set<string> const &trig=set<string>(), |
int timeout=-1, |
bool notriggers=false); |
void store_data(string const &key, |
serializable const &data, |
set<string> const &trig=set<string>(), |
int timeout=-1, |
bool notriggers=false); |
|
You can specify the set of trigger for specific object and define whether you want them to be added to current page triggers set. |
|
_Note:_ You should specify these dependencies manually. |
|
For example: |
|
if(cache.fetch_page("main")) |
return; |
if(!cache.fetch_data("options",opts)) { |
load_opts(opts); |
cache.store_data("options",opts); |
} |
if(!cache.fetch_frame("sidebar",sidebar)) { |
/// Generate sidebar |
set<string> tags; |
tags.insert("options"); |
cache.store_frame("sidebar",sidebar,tags); |
} |
/// Generate some HTML here using sidebar; |
cache.store_page("main"); |
|
Now, in this case, `main` depends on `sidebar` and `options` and `sidebar` depends on `options` only. |
|
### <span id="not"></span>Some Important Notes |
|
- Storing data is cache never rises its trigger. You should rise trigger manually |
- If you manage cache consistency correctly you may never use timeouts at all |
- In some cases, full cache consistency may hurt performance (think of sidebar that includes hits statistics) and cleanup pages too frequently. |
|
In such cases, it is better to work without full triggers, but in this case you must specify reasonable timeouts. |
|
- Function **`void reset();`** allows to clear all triggers that where added to current page. |
|
## <span id="func"></span>General Operations |
|
- **`void clear()`** -- clear all cache in the system. |
- **`bool stats(unsigned &keys,unsigned &triggers)`** -- fetch statistics from cache system. |
|
_Note:_ function returns false if cache system is disabled. |