aboutsummaryrefslogtreecommitdiff
path: root/optimistic/driver.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-11-02 14:29:23 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-11-02 14:29:23 +0200
commit1dab2da7c969e328281765d59d2fe90d618fadc6 (patch)
tree5271af031172c7751ab09e1adc5fb731c6c846d7 /optimistic/driver.cxx
parent9b10c11da5fdc5e64187d390b33ab62f6d2c49c0 (diff)
Add example for optimistic concurrency support
Diffstat (limited to 'optimistic/driver.cxx')
-rw-r--r--optimistic/driver.cxx159
1 files changed, 159 insertions, 0 deletions
diff --git a/optimistic/driver.cxx b/optimistic/driver.cxx
new file mode 100644
index 0000000..78cb14d
--- /dev/null
+++ b/optimistic/driver.cxx
@@ -0,0 +1,159 @@
+// file : optimistic/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <memory> // std::auto_ptr
+#include <iostream>
+
+#include <odb/database.hxx>
+#include <odb/transaction.hxx>
+
+#include "database.hxx" // create_database
+
+#include "person.hxx"
+#include "person-odb.hxx"
+
+using namespace std;
+using namespace odb::core;
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ auto_ptr<database> db (create_database (argc, argv));
+
+ // Persist the object.
+ //
+ // At this point the initial version (1) is assigned.
+ //
+ unsigned long id;
+ {
+ person p ("John", "Doe", 21);
+
+ transaction t (db->begin ());
+ id = db->persist (p);
+ t.commit ();
+
+ cout << "version after persist: " << p.version () << endl;
+ }
+
+ // Process 1: load the object.
+ //
+ person p1;
+ {
+ transaction t (db->begin ());
+ db->load (id, p1);
+ t.commit ();
+
+ cout << "process 1 version after load: " << p1.version () << endl;
+ }
+
+ // Process 2: load the object.
+ //
+ person p2;
+ {
+ transaction t (db->begin ());
+ db->load (id, p2);
+ t.commit ();
+
+ cout << "process 2 version after load: " << p2.version () << endl;
+ }
+
+ // Process 1: update the object.
+ //
+ // At this point the version is incremented and becomes 2.
+ //
+ {
+ p1.age (20); // Correct the wrong age.
+
+ transaction t (db->begin ());
+ db->update (p1);
+ t.commit ();
+
+ cout << "process 1 version after update: " << p1.version () << endl;
+ }
+
+ // Process 2: update the object.
+ //
+ // Since the object version in this process is 1 while in the database
+ // it is 2, this operation will fail.
+ //
+ {
+ p2.age (p2.age () + 1); // Increment the age.
+
+ transaction t (db->begin ());
+
+ try
+ {
+ db->update (p2);
+ }
+ catch (const object_changed&)
+ {
+ cout << "process 2 version is out of date: " << p2.version () << endl;
+
+ // Reload the object and retry the operation. Note that the second
+ // update call cannot throw object_changed since we reloaded the
+ // object and are trying to update it in a single transaction.
+ //
+ db->reload (p2);
+
+ cout << "process 2 version after reload: " << p2.version () << endl;
+
+ p2.age (p2.age () + 1);
+ db->update (p2);
+ }
+
+ t.commit ();
+
+ cout << "process 2 version after update: " << p2.version () << endl;
+ cout << "final age value: " << p2.age () << endl;
+ }
+
+ // Process 1: delete the object if the person is younger than 21.
+ //
+ // Since the object version in this process is 2 while in the database
+ // it is 3, this operation will fail. Note that this will only hold
+ // true if we are deleting the object by passing an object instance
+ // to the erase() function. If instead we pass object id, then the
+ // object will be deleted regardless of the version.
+ //
+ if (p1.age () < 21)
+ {
+ transaction t (db->begin ());
+
+ try
+ {
+ db->erase (p1);
+ // db->erase (id); // Never throws object_changed.
+ }
+ catch (const object_changed&)
+ {
+ cout << "process 1 version is out of date: " << p1.version () << endl;
+
+ // Reload the object and retry the operation. Similar to update, the
+ // second erase call cannot throw object_changed since we reloaded
+ // the object and are trying to erase it in a single transaction.
+ //
+ db->reload (p1);
+
+ cout << "process 1 version after reload: " << p2.version () << endl;
+
+ if (p1.age () < 21)
+ {
+ db->erase (p1);
+ cout << "object deleted" << endl;
+ }
+ else
+ cout << "object not deleted" << endl;
+ }
+
+ t.commit ();
+ }
+ }
+ catch (const odb::exception& e)
+ {
+ cerr << e.what () << endl;
+ return 1;
+ }
+}