From 8112bd0febcfa1e3a76e0d03363facbefc3822f7 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 15 Oct 2012 13:17:30 +0200 Subject: Implement early connection release --- odb/sqlite/connection-factory.cxx | 4 ++ odb/sqlite/connection.cxx | 14 ++----- odb/sqlite/connection.hxx | 7 +++- odb/sqlite/container-statements.hxx | 6 --- odb/sqlite/no-id-object-result.hxx | 3 ++ odb/sqlite/no-id-object-result.txx | 24 ++++++++--- odb/sqlite/no-id-object-statements.hxx | 2 - odb/sqlite/polymorphic-object-result.hxx | 3 ++ odb/sqlite/polymorphic-object-result.txx | 28 +++++++++---- odb/sqlite/polymorphic-object-statements.hxx | 10 ----- odb/sqlite/prepared-query.hxx | 2 + odb/sqlite/simple-object-result.hxx | 3 ++ odb/sqlite/simple-object-result.txx | 23 ++++++++--- odb/sqlite/simple-object-statements.hxx | 10 ----- odb/sqlite/statement-cache.cxx | 5 --- odb/sqlite/statement.cxx | 41 +++++-------------- odb/sqlite/statement.hxx | 61 ++++++++-------------------- odb/sqlite/transaction-impl.cxx | 25 ++++++++---- odb/sqlite/view-result.hxx | 3 ++ odb/sqlite/view-result.txx | 24 ++++++++--- 20 files changed, 148 insertions(+), 150 deletions(-) (limited to 'odb/sqlite') diff --git a/odb/sqlite/connection-factory.cxx b/odb/sqlite/connection-factory.cxx index 62e43f2..8eb9885 100644 --- a/odb/sqlite/connection-factory.cxx +++ b/odb/sqlite/connection-factory.cxx @@ -68,6 +68,7 @@ namespace odb { c->factory_ = 0; connection_.reset (inc_ref (c)); + connection_->recycle (); mutex_.unlock (); return false; } @@ -224,7 +225,10 @@ namespace odb in_use_--; if (keep) + { connections_.push_back (pooled_connection_ptr (inc_ref (c))); + connections_.back ()->recycle (); + } if (waiters_ != 0) cond_.signal (); diff --git a/odb/sqlite/connection.cxx b/odb/sqlite/connection.cxx index bcf28a2..b62ac8c 100644 --- a/odb/sqlite/connection.cxx +++ b/odb/sqlite/connection.cxx @@ -104,7 +104,8 @@ namespace odb { // Destroy prepared query statements before freeing the connections. // - prepared_map_.clear (); + recycle (); + clear_prepared_map (); } transaction_impl* connection:: @@ -176,15 +177,8 @@ namespace odb // The current first statement will remove itself from the list // and make the second statement (if any) the new first. // - while (statement* s = statements_) - { - if (!s->cached ()) - s->finilize (); - else if (s->active ()) - s->reset (); - else - assert (false); // Statement is neither active nor unached. - } + while (statements_ != 0) + statements_->reset (); } } } diff --git a/odb/sqlite/connection.hxx b/odb/sqlite/connection.hxx index 3524a48..2754102 100644 --- a/odb/sqlite/connection.hxx +++ b/odb/sqlite/connection.hxx @@ -123,7 +123,7 @@ namespace odb wait (); public: - // Reset active and finalize uncached statements. + // Reset active statements. // void clear (); @@ -159,7 +159,10 @@ namespace odb friend void connection_unlock_callback (void**, int); - // Linked list of active and uncached statements currently associated + private: + friend class transaction_impl; // invalidate_results() + + // Linked list of active statements currently associated // with this connection. // private: diff --git a/odb/sqlite/container-statements.hxx b/odb/sqlite/container-statements.hxx index 80011d9..a7b39bf 100644 --- a/odb/sqlite/container-statements.hxx +++ b/odb/sqlite/container-statements.hxx @@ -173,8 +173,6 @@ namespace odb insert_one_.reset ( new (details::shared) insert_statement_type ( conn_, insert_one_text_, data_image_binding_)); - - insert_one_->cached (true); } return *insert_one_; @@ -191,8 +189,6 @@ namespace odb select_all_text_, cond_image_binding_, select_image_binding_)); - - select_all_->cached (true); } return *select_all_; @@ -206,8 +202,6 @@ namespace odb delete_all_.reset ( new (details::shared) delete_statement_type ( conn_, delete_all_text_, cond_image_binding_)); - - delete_all_->cached (true); } return *delete_all_; diff --git a/odb/sqlite/no-id-object-result.hxx b/odb/sqlite/no-id-object-result.hxx index 60e69e3..3b653bb 100644 --- a/odb/sqlite/no-id-object-result.hxx +++ b/odb/sqlite/no-id-object-result.hxx @@ -56,6 +56,9 @@ namespace odb virtual std::size_t size (); + virtual void + invalidate (); + using base_type::current; private: diff --git a/odb/sqlite/no-id-object-result.txx b/odb/sqlite/no-id-object-result.txx index 3fe9fc2..9ffb836 100644 --- a/odb/sqlite/no-id-object-result.txx +++ b/odb/sqlite/no-id-object-result.txx @@ -20,11 +20,25 @@ namespace odb } template + void no_id_object_result_impl:: + invalidate () + { + if (!this->end_) + { + statement_->free_result (); + this->end_ = true; + } + + params_.reset (); + statement_.reset (); + } + + template no_id_object_result_impl:: no_id_object_result_impl (const query_base& q, const details::shared_ptr& s, statements_type& sts) - : base_type (sts.connection ().database ()), + : base_type (sts.connection ()), result_impl_base (q, s), statements_ (sts) { @@ -64,11 +78,9 @@ namespace odb } } - odb::database& db (this->database ()); - - object_traits::callback (db, obj, callback_event::pre_load); - object_traits::init (obj, im, &db); - object_traits::callback (db, obj, callback_event::post_load); + object_traits::callback (this->db_, obj, callback_event::pre_load); + object_traits::init (obj, im, &this->db_); + object_traits::callback (this->db_, obj, callback_event::post_load); } template diff --git a/odb/sqlite/no-id-object-statements.hxx b/odb/sqlite/no-id-object-statements.hxx index 93aedb0..f942cf4 100644 --- a/odb/sqlite/no-id-object-statements.hxx +++ b/odb/sqlite/no-id-object-statements.hxx @@ -88,8 +88,6 @@ namespace odb conn_, object_traits::persist_statement, insert_image_binding_)); - - persist_->cached (true); } return *persist_; diff --git a/odb/sqlite/polymorphic-object-result.hxx b/odb/sqlite/polymorphic-object-result.hxx index 9cf9c6c..0b03456 100644 --- a/odb/sqlite/polymorphic-object-result.hxx +++ b/odb/sqlite/polymorphic-object-result.hxx @@ -70,6 +70,9 @@ namespace odb virtual std::size_t size (); + virtual void + invalidate (); + using base_type::current; private: diff --git a/odb/sqlite/polymorphic-object-result.txx b/odb/sqlite/polymorphic-object-result.txx index 0dd68cf..8e09bf1 100644 --- a/odb/sqlite/polymorphic-object-result.txx +++ b/odb/sqlite/polymorphic-object-result.txx @@ -22,12 +22,26 @@ namespace odb } template + void polymorphic_object_result_impl:: + invalidate () + { + if (!this->end_) + { + statement_->free_result (); + this->end_ = true; + } + + params_.reset (); + statement_.reset (); + } + + template polymorphic_object_result_impl:: polymorphic_object_result_impl ( const query_base& q, const details::shared_ptr& st, statements_type& sts) - : base_type (sts.connection ().database ()), + : base_type (sts.connection ()), result_impl_base (q, st), statements_ (sts) { @@ -48,7 +62,6 @@ namespace odb assert (!rsts.locked ()); typename statements_type::auto_lock l (rsts); - odb::database& db (this->database ()); typename object_traits::image_type& i (statements_.image ()); typename root_traits::image_type& ri (rsts.image ()); @@ -85,7 +98,8 @@ namespace odb // Insert it as a root pointer (for non-unique pointers, rp should // still be valid and for unique pointers this is a no-op). // - ig.reset (object_traits::pointer_cache_traits::insert (db, id, rp)); + ig.reset ( + object_traits::pointer_cache_traits::insert (this->db_, id, rp)); pobj = &pointer_traits::get_ref (p); current (p); @@ -106,9 +120,9 @@ namespace odb } callback_event ce (callback_event::pre_load); - pi.dispatch (info_type::call_callback, db, pobj, &ce); + pi.dispatch (info_type::call_callback, this->db_, pobj, &ce); - object_traits::init (*pobj, i, &db); + object_traits::init (*pobj, i, &this->db_); // Initialize the id image and binding and load the rest of the object // (containers, dynamic part, etc). @@ -132,14 +146,14 @@ namespace odb if (&pi != &object_traits::info) { std::size_t d (object_traits::depth); - pi.dispatch (info_type::call_load, db, pobj, &d); + pi.dispatch (info_type::call_load, this->db_, pobj, &d); }; rsts.load_delayed (); l.unlock (); ce = callback_event::post_load; - pi.dispatch (info_type::call_callback, db, pobj, &ce); + pi.dispatch (info_type::call_callback, this->db_, pobj, &ce); ig.release (); } diff --git a/odb/sqlite/polymorphic-object-statements.hxx b/odb/sqlite/polymorphic-object-statements.hxx index 286b9e3..50d66a3 100644 --- a/odb/sqlite/polymorphic-object-statements.hxx +++ b/odb/sqlite/polymorphic-object-statements.hxx @@ -107,8 +107,6 @@ namespace odb object_traits::find_discriminator_statement, discriminator_id_image_binding_, discriminator_image_binding_)); - - find_discriminator_->cached (true); } return *find_discriminator_; @@ -296,8 +294,6 @@ namespace odb conn_, object_traits::persist_statement, insert_image_binding_)); - - persist_->cached (true); } return *persist_; @@ -317,8 +313,6 @@ namespace odb object_traits::find_statements[i], root_statements_.id_image_binding (), select_image_bindings_[i])); - - p->cached (true); } return *p; @@ -334,8 +328,6 @@ namespace odb conn_, object_traits::update_statement, update_image_binding_)); - - update_->cached (true); } return *update_; @@ -351,8 +343,6 @@ namespace odb conn_, object_traits::erase_statement, root_statements_.id_image_binding ())); - - erase_->cached (true); } return *erase_; diff --git a/odb/sqlite/prepared-query.hxx b/odb/sqlite/prepared-query.hxx index ddc2c9c..2615179 100644 --- a/odb/sqlite/prepared-query.hxx +++ b/odb/sqlite/prepared-query.hxx @@ -23,6 +23,8 @@ namespace odb virtual ~prepared_query_impl (); + prepared_query_impl (odb::connection& c): odb::prepared_query_impl (c) {} + sqlite::query_base query; }; } diff --git a/odb/sqlite/simple-object-result.hxx b/odb/sqlite/simple-object-result.hxx index 3e2a17b..02b671e 100644 --- a/odb/sqlite/simple-object-result.hxx +++ b/odb/sqlite/simple-object-result.hxx @@ -60,6 +60,9 @@ namespace odb virtual std::size_t size (); + virtual void + invalidate (); + using base_type::current; private: diff --git a/odb/sqlite/simple-object-result.txx b/odb/sqlite/simple-object-result.txx index 6763850..1de4b91 100644 --- a/odb/sqlite/simple-object-result.txx +++ b/odb/sqlite/simple-object-result.txx @@ -22,11 +22,25 @@ namespace odb } template + void object_result_impl:: + invalidate () + { + if (!this->end_) + { + statement_->free_result (); + this->end_ = true; + } + + params_.reset (); + statement_.reset (); + } + + template object_result_impl:: object_result_impl (const query_base& q, const details::shared_ptr& statement, statements_type& statements) - : base_type (statements.connection ().database ()), + : base_type (statements.connection ()), result_impl_base (q, statement), statements_ (statements) { @@ -44,11 +58,10 @@ namespace odb assert (!statements_.locked ()); typename statements_type::auto_lock l (statements_); - odb::database& db (this->database ()); - object_traits::callback (db, obj, callback_event::pre_load); + object_traits::callback (this->db_, obj, callback_event::pre_load); typename object_traits::image_type& i (statements_.image ()); - object_traits::init (obj, i, &db); + object_traits::init (obj, i, &this->db_); // Initialize the id image and binding and load the rest of the object // (containers, etc). @@ -67,7 +80,7 @@ namespace odb object_traits::load_ (statements_, obj); statements_.load_delayed (); l.unlock (); - object_traits::callback (db, obj, callback_event::post_load); + object_traits::callback (this->db_, obj, callback_event::post_load); } template diff --git a/odb/sqlite/simple-object-statements.hxx b/odb/sqlite/simple-object-statements.hxx index 66dc0f9..9ff3faf 100644 --- a/odb/sqlite/simple-object-statements.hxx +++ b/odb/sqlite/simple-object-statements.hxx @@ -345,8 +345,6 @@ namespace odb conn_, object_traits::persist_statement, insert_image_binding_)); - - persist_->cached (true); } return *persist_; @@ -363,8 +361,6 @@ namespace odb object_traits::find_statement, id_image_binding_, select_image_binding_)); - - find_->cached (true); } return *find_; @@ -380,8 +376,6 @@ namespace odb conn_, object_traits::update_statement, update_image_binding_)); - - update_->cached (true); } return *update_; @@ -397,8 +391,6 @@ namespace odb conn_, object_traits::erase_statement, id_image_binding_)); - - erase_->cached (true); } return *erase_; @@ -414,8 +406,6 @@ namespace odb conn_, object_traits::optimistic_erase_statement, od_.id_image_binding_)); - - od_.erase_->cached (true); } return *od_.erase_; diff --git a/odb/sqlite/statement-cache.cxx b/odb/sqlite/statement-cache.cxx index 6262b25..c350e02 100644 --- a/odb/sqlite/statement-cache.cxx +++ b/odb/sqlite/statement-cache.cxx @@ -20,9 +20,6 @@ namespace odb commit_ (new (shared) generic_statement (conn_, "COMMIT", 7)), rollback_ (new (shared) generic_statement (conn_, "ROLLBACK", 9)) { - rollback_->cached (true); - commit_->cached (true); - begin_->cached (true); } void statement_cache:: @@ -30,7 +27,6 @@ namespace odb { begin_immediate_.reset ( new (shared) generic_statement (conn_, "BEGIN IMMEDIATE", 16)); - begin_immediate_->cached (true); } void statement_cache:: @@ -38,7 +34,6 @@ namespace odb { begin_exclusive_.reset ( new (shared) generic_statement (conn_, "BEGIN EXCLUSIVE", 16)); - begin_exclusive_->cached (true); } } } diff --git a/odb/sqlite/statement.cxx b/odb/sqlite/statement.cxx index ce194ed..09cf994 100644 --- a/odb/sqlite/statement.cxx +++ b/odb/sqlite/statement.cxx @@ -24,22 +24,18 @@ namespace odb statement:: ~statement () { - if (stmt_ != 0) - finilize (); - } - - void statement:: - cached (bool cached) - { - assert (cached); - - if (!cached_) { - if (!active_) - list_remove (); - - cached_ = true; + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->deallocate (conn_, *this); } + + if (next_ != this) + list_remove (); + + stmt_.reset (); } void statement:: @@ -65,8 +61,6 @@ namespace odb prev_ = 0; next_ = this; - list_add (); // Add to the list because we are uncached. - { odb::tracer* t; if ((t = conn_.transaction_tracer ()) || @@ -76,21 +70,6 @@ namespace odb } } - void statement:: - finilize () - { - { - odb::tracer* t; - if ((t = conn_.transaction_tracer ()) || - (t = conn_.tracer ()) || - (t = conn_.database ().tracer ())) - t->deallocate (conn_, *this); - } - - list_remove (); - stmt_.reset (); - } - const char* statement:: text () const { diff --git a/odb/sqlite/statement.hxx b/odb/sqlite/statement.hxx index 92b9c7c..aabb57d 100644 --- a/odb/sqlite/statement.hxx +++ b/odb/sqlite/statement.hxx @@ -53,12 +53,6 @@ namespace odb return conn_; } - public: - using odb::statement::cached; - - virtual void - cached (bool); - protected: statement (connection_type& conn, const std::string& text) : conn_ (conn) @@ -118,22 +112,12 @@ namespace odb { if (active_) { - if (stmt_ != 0) - sqlite3_reset (stmt_); - - if (cached_) - list_remove (); - + sqlite3_reset (stmt_); + list_remove (); active_ = false; } } - // Cached state (protected part). - // - protected: - void - finilize (); - protected: friend class sqlite::connection; @@ -146,38 +130,29 @@ namespace odb void init (const char* text, std::size_t text_size); - // Doubly-linked list of active/uncached statements. + // Doubly-linked list of active statements. // private: - void list_add () + void + list_add () { - if (next_ == this) - { - next_ = conn_.statements_; - conn_.statements_ = this; + next_ = conn_.statements_; + conn_.statements_ = this; - if (next_ != 0) - next_->prev_ = this; - } + if (next_ != 0) + next_->prev_ = this; } - void list_remove () + void + list_remove () { - if (next_ != this) - { - if (prev_ == 0) - conn_.statements_ = next_; - else - { - prev_->next_ = next_; - } - - if (next_ != 0) - next_->prev_ = prev_; - - prev_ = 0; - next_ = this; - } + (prev_ == 0 ? conn_.statements_ : prev_->next_) = next_; + + if (next_ != 0) + next_->prev_ = prev_; + + prev_ = 0; + next_ = this; } // prev_ == 0 means we are the first element. diff --git a/odb/sqlite/transaction-impl.cxx b/odb/sqlite/transaction-impl.cxx index 9497c0a..1975308 100644 --- a/odb/sqlite/transaction-impl.cxx +++ b/odb/sqlite/transaction-impl.cxx @@ -67,10 +67,15 @@ namespace odb void transaction_impl:: commit () { - // Reset active and finilize uncached statements. Active statements - // will prevent COMMIT from completing (write statements) or releasing - // the locks (read statements). Finilization of uncached statements is - // needed to release the connection. + // Invalidate query results. + // + connection_->invalidate_results (); + + // Reset active statements. Active statements will prevent COMMIT + // from completing (write statements) or releasing the locks (read + // statements). Normally, a statement is automatically reset on + // completion, however, if an exception is thrown, that may not + // happen. // connection_->clear (); @@ -84,9 +89,15 @@ namespace odb void transaction_impl:: rollback () { - // Reset active and finilize uncached statements. Active statements - // will prevent ROLLBACK from completing. Finilization of uncached - // statements is needed to release the connection. + // Invalidate query results. + // + connection_->invalidate_results (); + + // Reset active statements. Active statements will prevent ROLLBACK + // from completing (write statements) or releasing the locks (read + // statements). Normally, a statement is automatically reset on + // completion, however, if an exception is thrown, that may not + // happen. // connection_->clear (); diff --git a/odb/sqlite/view-result.hxx b/odb/sqlite/view-result.hxx index 7d552b7..a6d07e7 100644 --- a/odb/sqlite/view-result.hxx +++ b/odb/sqlite/view-result.hxx @@ -55,6 +55,9 @@ namespace odb virtual std::size_t size (); + virtual void + invalidate (); + using base_type::current; private: diff --git a/odb/sqlite/view-result.txx b/odb/sqlite/view-result.txx index 5256467..ed7fdc8 100644 --- a/odb/sqlite/view-result.txx +++ b/odb/sqlite/view-result.txx @@ -20,11 +20,25 @@ namespace odb } template + void view_result_impl:: + invalidate () + { + if (!this->end_) + { + statement_->free_result (); + this->end_ = true; + } + + params_.reset (); + statement_.reset (); + } + + template view_result_impl:: view_result_impl (const query_base& q, const details::shared_ptr& statement, statements_type& statements) - : base_type (statements.connection ().database ()), + : base_type (statements.connection ()), result_impl_base (q, statement), statements_ (statements) { @@ -64,11 +78,9 @@ namespace odb } } - odb::database& db (this->database ()); - - view_traits::callback (db, view, callback_event::pre_load); - view_traits::init (view, im, &db); - view_traits::callback (db, view, callback_event::post_load); + view_traits::callback (this->db_, view, callback_event::pre_load); + view_traits::init (view, im, &this->db_); + view_traits::callback (this->db_, view, callback_event::post_load); } template -- cgit v1.1