From b4825d95472f8d9e2b9892a56c585a035b6230ac Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 28 Sep 2013 10:51:12 +0200 Subject: Make schema version access (but not modification) thread-safe Also cache the version in statements so that we don't have to lock the mutex (slow) every time we need to check the version. --- odb/database.cxx | 25 ++++++++++++------------- odb/database.hxx | 28 ++++++++++++++++------------ odb/database.ixx | 15 +-------------- 3 files changed, 29 insertions(+), 39 deletions(-) diff --git a/odb/database.cxx b/odb/database.cxx index c9692ba..5578abd 100644 --- a/odb/database.cxx +++ b/odb/database.cxx @@ -4,10 +4,14 @@ #include +#include + using namespace std; namespace odb { + using details::lock; + database:: ~database () { @@ -20,25 +24,23 @@ namespace odb return c.execute (st, n); } - const database::schema_version_info& database:: - schema_version_migration_ (const string& name) const + const database::schema_version_migration_type& database:: + schema_version_migration (const string& name) const { + lock l (mutex_); // Prevents concurrent loading. + schema_version_map::const_iterator i (schema_version_map_.find (name)); - const schema_version_info& svi ( - i != schema_version_map_.end () && i->second.version != 0 + return i != schema_version_map_.end () && i->second.version != 0 ? i->second - : load_schema_version (name)); - - if (default_schema_version_ == 0 && name.empty ()) - default_schema_version_ = &svi; - - return svi; + : load_schema_version (name); } void database:: schema_version_migration (const schema_version_migration_type& svm, const string& name) { + // Note: no lock, not thread-safe. + schema_version_info& svi (schema_version_map_[name]); if (svi.version != svm.version || svi.migration != svm.migration) { @@ -46,8 +48,5 @@ namespace odb svi.migration = svm.migration; schema_version_seq_++; } - - if (default_schema_version_ == 0 && name.empty ()) - default_schema_version_ = &svi; } } diff --git a/odb/database.hxx b/odb/database.hxx index 7ddbecb..91d8e94 100644 --- a/odb/database.hxx +++ b/odb/database.hxx @@ -28,6 +28,7 @@ #include #include +#include #include namespace odb @@ -339,31 +340,34 @@ namespace odb typedef odb::schema_version_migration schema_version_migration_type; schema_version_type - schema_version (const std::string& schema_name = std::string ()) const; + schema_version (const std::string& schema_name = "") const; bool - schema_migration (const std::string& schema_name = std::string ()) const; + schema_migration (const std::string& schema_name = "") const; // Note that there is code that relies on the returned reference // being valid until the version is changed or the database instance // is destroyed. // const schema_version_migration_type& - schema_version_migration ( - const std::string& schema_name = std::string ()) const; + schema_version_migration (const std::string& schema_name = "") const; // Set schema version and migration state manually. // + // Note that the modifier API is not thread-safe. That is, you should + // not modify the schema version while other threads may be accessing + // or modifying the same information. + // void schema_version_migration (schema_version_type, bool migration, - const std::string& schema_name = std::string ()); + const std::string& schema_name = ""); void schema_version_migration (const schema_version_migration_type&, - const std::string& schema_name = std::string ()); + const std::string& schema_name = ""); - // Set default schema version table for all schema names. The table + // Set default schema version table for all the schema names. The table // name should already be quoted if necessary. // void @@ -375,9 +379,9 @@ namespace odb schema_version_table (const std::string& table_name, const std::string& schema_name); - // Schema version sequence number. It is incremented every time - // the schema version or migration flag is changed and can be - // used to detect version changes. The starting value is 1. + // Schema version sequence number. It is incremented every time the + // schema version or migration flag is changed and can be used to + // detect overall version changes. The starting value is 1. // unsigned int schema_version_sequence () const; @@ -485,9 +489,9 @@ namespace odb tracer_type* tracer_; query_factory_map query_factory_map_; - std::string schema_version_table_; + mutable details::mutex mutex_; mutable schema_version_map schema_version_map_; - mutable const schema_version_info* default_schema_version_; // Cached. + std::string schema_version_table_; unsigned int schema_version_seq_; }; } diff --git a/odb/database.ixx b/odb/database.ixx index 378a376..a15bb7d 100644 --- a/odb/database.ixx +++ b/odb/database.ixx @@ -11,10 +11,7 @@ namespace odb { inline database:: database (database_id id) - : id_ (id), - tracer_ (0), - default_schema_version_ (0), - schema_version_seq_ (1) + : id_ (id), tracer_ (0), schema_version_seq_ (1) { } @@ -36,16 +33,6 @@ namespace odb return schema_version_migration (name).migration; } - inline const database::schema_version_migration_type& database:: - schema_version_migration (const std::string& name) const - { - return name.empty () && - default_schema_version_ != 0 && - default_schema_version_->version != 0 - ? *default_schema_version_ - : schema_version_migration_ (name); - } - inline void database:: schema_version_migration (schema_version_type v, bool m, -- cgit v1.1