From 0d49ea1fe08cf1eab41a00149393a291c65a59d7 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 25 Jan 2024 20:32:06 +0300 Subject: Turn odb-tests repository into package for muti-package repository --- odb-tests/common/session/custom/session.txx | 159 ++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 odb-tests/common/session/custom/session.txx (limited to 'odb-tests/common/session/custom/session.txx') diff --git a/odb-tests/common/session/custom/session.txx b/odb-tests/common/session/custom/session.txx new file mode 100644 index 0000000..65ab933 --- /dev/null +++ b/odb-tests/common/session/custom/session.txx @@ -0,0 +1,159 @@ +// file : common/session/custom/session.txx +// 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; + } +} -- cgit v1.1