From 7feb2014005750c6fe4ef7b76740663c2259d3a9 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 20 Jan 2013 08:51:29 +0200 Subject: Document custom session support --- doc/manual.xhtml | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 155 insertions(+), 10 deletions(-) (limited to 'doc') diff --git a/doc/manual.xhtml b/doc/manual.xhtml index 22b68bf..13b467a 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -438,6 +438,7 @@ for consistency. 10Session +
10.1Object Cache
10.2Custom Session
@@ -9270,8 +9271,12 @@ struct employee_name

A session is an application's unit of work that may encompass several database transactions. In this version of ODB a session is just an - object cache. In future versions it will provide additional - functionality, such as automatic object state change tracking.

+ object cache. In future versions it may provide additional + functionality, such as delayed database operations and automatic + object state change tracking. As discussed later in + Section 10.2, "Custom Session", it is also + possible to provide a custom session implementation that provides + these or other features.

Session support is optional and can be enabled or disabled on the per object basis using the db session pragma, for @@ -9386,24 +9391,35 @@ namespace odb static void reset_current (); + static session* + current_pointer (); + + static void + current_pointer (session*); + // Object cache interface. // public: - typedef odb::database database_type; + template <typename T> + struct cache_position {...}; template <typename T> - void - insert (database_type&, - const object_traits<T>::id_type&, - const object_traits<T>::pointer_type&); + cache_position<T> + cache_insert (database&, + const object_traits<T>::id_type&, + const object_traits<T>::pointer_type&); template <typename T> object_traits<T>::pointer_type - find (database_type&, const object_traits<T>::id_type&) const; + cache_find (database&, const object_traits<T>::id_type&) const; template <typename T> void - erase (database_type&, const object_traits<T>::id_type&); + cache_erase (const cache_position<T>&); + + template <typename T> + void + cache_erase (database&, const object_traits<T>::id_type&); }; } @@ -9428,9 +9444,22 @@ namespace odb allow for more advanced use cases, such as multiplexing two or more sessions on the same thread.

+

The static current_pointer() overloaded functions + provided the same functionality but using pointers. Specifically, + the current_pointer() accessor can be used to + test whether there is a current session and get a pointer to it + all with a single call.

+

We normally don't use the object cache interface directly. However, it could be useful in some cases, for example, to find out whether - an object has already been loaded.

+ an object has already been loaded. Note that when calling + cache_insert(), cache_find(), or + the second version of cache_erase(), you need to + specify the template argument (object type) explicitly. It is + also possible to access the underlying cache data structures + directly. This can be useful if, for example, you want to + iterate over the objects store in the cache. Refer to the ODB + runtime header files for more details on this direct access.

10.1 Object Cache

@@ -9514,6 +9543,122 @@ unsigned long id2 (save (db, p2)); // p2 is cached in s as non-const. } +

10.2 Custom Session

+ +

ODB can use a custom session implementation instead of the + default odb::session. There could be multiple + reasons for an application to provide its own session. For + example, the application may already include a notion of an + object cache or registry which ODB can re-use. A custom + session can also provide additional functionality, such as + automatic change tracking, delayed database operations, or + object eviction. Finally, the session-per-thread approach used + by odb::session may not be suitable for all + applications. For instance, some may need a thread-safe + session that can be shared among multiple threads. For + an example of a custom session that implements automatic + change tracking by keeping original copies of the objects, + refer to the common/session/custom test + in the odb-tests package.

+ +

To use a custom session we need to specify its type with + the --session-type ODB compiler command line + option. We also need to include its definition into the + generated header file. This can be achieved with the + --hxx-prologue option. For example, if our + custom session is called app::session and + is defined in the app/session.hxx header + file, then the corresponding ODB compiler options would + look like this:

+ +
+odb --hxx-prologue "#include \"app/session.hxx\"" \
+--session-type ::app::session ...
+  
+ +

A custom session should provide the following interface:

+ +
+class custom_session
+{
+public:
+  template <typename T>
+  struct cache_position
+  {
+    ...
+  };
+
+  // Cache management functions.
+  //
+  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>&);
+
+  // Notification functions.
+  //
+  template <typename T>
+  static void
+  _cache_persist (const cache_position<T>&);
+
+  template <typename T>
+  static void
+  _cache_load (const cache_position<T>&);
+
+  template <typename T>
+  static void
+  _cache_update (odb::database&, const T& obj);
+
+  template <typename T>
+  static void
+  _cache_erase (odb::database&,
+                const typename odb::object_traits<T>::id_type&);
+};
+  
+ +

The cache_position class template represent a position + in the cache of the inserted object. It should be default and + copy-constructible as well as copy-assignable. The default + constructor shall create a special empty/NULL + position. A call of any of the cache management or notification + functions with such an empty/NULL position shall be + ignored.

+ +

The _cache_insert() function shall add the object into + the object cache and return its position. The _cache_find() + function looks an object up in the object cache given its id. + It returns a NULL pointer if the object is not + found. The _cache_erase() cache management function + shall remove the object from the cache. It is called + if the database operation that caused the object to be inserted + (for example, load) failed. Note also that after insertion the object + state is undefined. You can only access the object state + (for example, make a copy or clear a flag) from one of the + notification functions discussed below.

+ +

The notification functions are called after an object has + been persisted, loaded, updated, or erased, respectively. If + your session implementation does not need some of the + notifications, you still have to provide their functions, + however, you can leave their implementations empty.

+ +

Notice also that all the cache management and notification + functions are static. This is done in order to allow for a + custom notion of a current session. Normally, the first + step a non-empty implementation will perform is lookup the + current session.

+ + -- cgit v1.1