// file : common/session/custom/session.txx // copyright : Copyright (c) 2009-2017 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file #include template typename session::cache_position session:: _cache_insert (odb::database&, const typename odb::object_traits::id_type& id, const typename odb::object_traits::pointer_type& obj) { if (current == 0) return cache_position (); // No session, return empty position. std::shared_ptr& pm (current->map_[&typeid (T)]); if (!pm) pm.reset (new object_map); object_map& m (static_cast&> (*pm)); typename object_map::value_type vt (id, object_data (obj)); std::pair::iterator, bool> r (m.insert (vt)); // We shall never try to re-insert the same object into the cache. // assert (r.second); return cache_position (m, r.first); } template typename odb::object_traits::pointer_type session:: _cache_find (odb::database&, const typename odb::object_traits::id_type& id) { typedef typename odb::object_traits::pointer_type pointer_type; if (current == 0) return pointer_type (); // No session, return NULL pointer. type_map::const_iterator ti (current->map_.find (&typeid (T))); if (ti == current->map_.end ()) return pointer_type (); const object_map& m (static_cast&> (*ti->second)); typename object_map::const_iterator oi (m.find (id)); if (oi == m.end ()) return pointer_type (); return oi->second.obj; } template void session:: _cache_load (const cache_position& p) { typedef typename odb::object_traits::pointer_type pointer_type; if (p.map_ == 0) return; // Empty position. // Make a copy for change tracking. If our object model had a // polymorphic hierarchy, then we would have had to use a // virtual function-based mechanism (e.g., clone()) instead of // the copy constructor since for a polymorphic hierarchy all // the derived objects are stored as pointers to the root object. // p.pos_->second.orig = pointer_type (new T (*p.pos_->second.obj)); } template void session:: _cache_update (odb::database&, const T& obj) { typedef odb::object_traits object_traits; typedef typename object_traits::pointer_type pointer_type; if (current == 0) return; // No session. // User explicitly updated the object by calling database::update(). // Change the state to flushed and reset the original copy (we are // still tracking changes after the update). // type_map::iterator ti (current->map_.find (&typeid (T))); if (ti == current->map_.end ()) return; // This object is not in the session. object_map& m (static_cast&> (*ti->second)); typename object_map::iterator oi (m.find (object_traits::id (obj))); if (oi == m.end ()) return; // This object is not in the session. object_data& d (oi->second); d.orig = pointer_type (new T (*d.obj)); d.state = flushed; } template void session:: _cache_erase (odb::database&, const typename odb::object_traits::id_type& id) { if (current == 0) return; // No session. type_map::iterator ti (current->map_.find (&typeid (T))); if (ti == current->map_.end ()) return; object_map& m (static_cast&> (*ti->second)); typename object_map::iterator oi (m.find (id)); if (oi == m.end ()) return; m.erase (oi); if (m.empty ()) current->map_.erase (ti); } template bool session::object_map:: flush (odb::database& db) { bool r (false); for (typename object_map::iterator i (this->begin ()), e (this->end ()); i != e; ++i) { object_data& d (i->second); if (d.state == changed || d.obj->changed (*d.orig)) db.update (d.obj); // State changed by the update() notification. r = r || d.state == flushed; } return r; } template void session::object_map:: mark (unsigned short event) { for (typename object_map::iterator i (this->begin ()), e (this->end ()); i != e; ++i) { object_data& d (i->second); if (d.state == flushed) d.state = event == odb::transaction::event_commit ? tracking : changed; } }