// file : common/session/custom/session.hxx // copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file #ifndef SESSION_HXX #define SESSION_HXX #include <map> #include <memory> #include <typeinfo> #include <odb/database.hxx> #include <odb/transaction.hxx> #include <odb/traits.hxx> // odb::object_traits #include <odb/details/type-info.hxx> // odb::details::type_info_comparator // This custom session implementation assumes we are working with // one database at a time. // class session { public: session (); ~session (); private: session (const session&); session& operator= (const session&); // Session for the current thread. This can be implemented in pretty // much any way that makes sense to the application. It can be a global // session as we have here. In multi-threaded applications we could use // TLS instead. // public: static session* current; // Change tracking interface. // public: // Call flush() within a transaction to apply the changes to the // database. // void flush (odb::database&); private: struct object_map_base { virtual ~object_map_base () {} // Return true if we flushed anything. // virtual bool flush (odb::database&) = 0; virtual void mark (unsigned short event) = 0; }; enum object_state { tracking, // Tracking any modifications by storing the original copy. changed, // Known to be changed. flushed // Flushed but not yet committed/rolled back. }; template <typename T> struct object_data { typedef typename odb::object_traits<T>::pointer_type pointer_type; explicit object_data (pointer_type o): obj (o), state (tracking) {} pointer_type obj; pointer_type orig; object_state state; }; template <typename T> struct object_map: object_map_base, std::map<typename odb::object_traits<T>::id_type, object_data<T> > { virtual bool flush (odb::database&); virtual void mark (unsigned short event); }; // Object cache interface. // public: template <typename T> struct cache_position { typedef object_map<T> map; typedef typename map::iterator iterator; cache_position (): map_ (0) {} cache_position (map& m, const iterator& p): map_ (&m), pos_ (p) {} cache_position& operator= (const cache_position& p) { // It might not be ok to use an uninitialized iterator on the rhs. // if (p.map_ != 0) pos_ = p.pos_; map_ = p.map_; return *this; } map* map_; iterator pos_; }; // Cache management. // template <typename T> static cache_position<T> _cache_insert (odb::database&, const typename odb::object_traits<T>::id_type&, const typename odb::object_traits<T>::pointer_type&); template <typename T> static typename odb::object_traits<T>::pointer_type _cache_find (odb::database&, const typename odb::object_traits<T>::id_type&); template <typename T> static void _cache_erase (const cache_position<T>& p) { if (p.map_ != 0) p.map_->erase (p.pos_); } // Notifications. // template <typename T> static void _cache_persist (const cache_position<T>& p) { _cache_load (p); } template <typename T> static void _cache_load (const cache_position<T>&); template <typename T> static void _cache_update (odb::database&, const T&); template <typename T> static void _cache_erase (odb::database&, const typename odb::object_traits<T>::id_type&); private: // Post-commit/rollback callback. // static void mark (unsigned short event, void* key, unsigned long long); private: typedef std::map<const std::type_info*, std::shared_ptr<object_map_base>, odb::details::type_info_comparator> type_map; type_map map_; odb::transaction* tran_; }; #include "session.txx" #endif // SESSION_HXX