|
- ///////////////////////////////////////////////////////////////////////////////
- //
- // 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;
- CPPCMS_UNUSED_MEMBER uint32_t reserved : 31;
- };
-
-
- }
-
- #endif
|