From b72424fca7a6af6ff7921101c450850fef875152 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Sun, 6 Mar 2016 13:52:48 +0300 Subject: Support multiple instances of brep in a single Apache instance --- brep/database.cxx | 58 +++++++++++++++++++++--------------- brep/mod-package-details | 8 +++++ brep/mod-package-details.cxx | 23 +++++++++----- brep/mod-package-search | 8 +++++ brep/mod-package-search.cxx | 23 +++++++++----- brep/mod-package-version-details | 8 +++++ brep/mod-package-version-details.cxx | 21 ++++++++----- brep/mod-repository-details | 8 +++++ brep/mod-repository-details.cxx | 21 ++++++++----- brep/mod-repository-root | 6 ++++ brep/mod-repository-root.cxx | 33 +++++++++++++++++++- brep/module | 2 +- brep/module.cxx | 12 +++++--- 13 files changed, 171 insertions(+), 60 deletions(-) (limited to 'brep') diff --git a/brep/database.cxx b/brep/database.cxx index 9177b55..17605c5 100644 --- a/brep/database.cxx +++ b/brep/database.cxx @@ -4,40 +4,50 @@ #include +#include + #include namespace brep { + namespace options + { + bool + operator< (const db& x, const db& y) + { + int r; + if ((r = x.db_user ().compare (y.db_user ())) != 0 || + (r = x.db_password ().compare (y.db_password ())) != 0 || + (r = x.db_name ().compare (y.db_name ())) != 0 || + (r = x.db_host ().compare (y.db_host ()))) + return r < 0; + + return x.db_port () < y.db_port (); + } + } + shared_ptr shared_database (const options::db& o) { using odb::pgsql::database; - static weak_ptr db; - // In C++11, function-static variable initialization is guaranteed to be - // thread-safe, thought this doesn't seem to be enough in our case - // (because we are re-initializing the weak pointer). - // - if (shared_ptr d = db.lock ()) - { - if (o.db_user () != d->user () || - o.db_password () != d->password () || - o.db_name () != d->db () || - o.db_host () != d->host () || - o.db_port () != d->port ()) - throw runtime_error ("shared database options mismatch"); - - return d; - } - else + static std::map> databases; + + auto i (databases.find (o)); + if (i != databases.end ()) { - d = make_shared (o.db_user (), - o.db_password (), - o.db_name (), - o.db_host (), - o.db_port ()); - db = d; - return d; + if (shared_ptr d = i->second.lock ()) + return d; } + + shared_ptr d ( + make_shared (o.db_user (), + o.db_password (), + o.db_name (), + o.db_host (), + o.db_port ())); + + databases[o] = d; + return d; } } diff --git a/brep/mod-package-details b/brep/mod-package-details index a99d271..0a86fc2 100644 --- a/brep/mod-package-details +++ b/brep/mod-package-details @@ -18,6 +18,14 @@ namespace brep class package_details: public module { public: + package_details () = default; + + // Create a shallow copy (handling instance) if initialized and a deep + // copy (context exemplar) otherwise. + // + explicit + package_details (const package_details&); + virtual bool handle (request&, response&); diff --git a/brep/mod-package-details.cxx b/brep/mod-package-details.cxx index fa07dd1..a5c2e3e 100644 --- a/brep/mod-package-details.cxx +++ b/brep/mod-package-details.cxx @@ -24,6 +24,18 @@ using namespace odb::core; using namespace brep::cli; +// While currently the user-defined copy constructor is not required (we don't +// need to deep copy nullptr's), it is a good idea to keep the placeholder +// ready for less trivial cases. +// +brep::package_details:: +package_details (const package_details& r) + : module (r), + options_ (r.initialized_ ? r.options_ : nullptr), + db_ (r.initialized_ ? r.db_ : nullptr) +{ +} + void brep::package_details:: init (scanner& s) { @@ -61,13 +73,8 @@ handle (request& rq, response& rs) MODULE_DIAG; - // The module options object is not changed after being created once per - // server process. - // - static const size_t res_page (options_->search_results ()); - static const dir_path& root (options_->root ()); - static const fragment& logo (options_->logo ()); - static const vector& menu (options_->menu ()); + const size_t res_page (options_->search_results ()); + const dir_path& root (options_->root ()); const string& name (*rq.path ().rbegin ()); const string ename (mime_url_encode (name)); @@ -130,7 +137,7 @@ handle (request& rq, response& rs) << SCRIPT << " " << ~SCRIPT << ~HEAD << BODY - << DIV_HEADER (root, logo, menu) + << DIV_HEADER (root, options_->logo (), options_->menu ()) << DIV(ID="content"); if (full) diff --git a/brep/mod-package-search b/brep/mod-package-search index 7db976b..1730be4 100644 --- a/brep/mod-package-search +++ b/brep/mod-package-search @@ -18,6 +18,14 @@ namespace brep class package_search: public module { public: + package_search () = default; + + // Create a shallow copy (handling instance) if initialized and a deep + // copy (context exemplar) otherwise. + // + explicit + package_search (const package_search&); + virtual bool handle (request&, response&); diff --git a/brep/mod-package-search.cxx b/brep/mod-package-search.cxx index 7505e02..77a06b6 100644 --- a/brep/mod-package-search.cxx +++ b/brep/mod-package-search.cxx @@ -27,6 +27,18 @@ using namespace odb::core; using namespace brep::cli; +// While currently the user-defined copy constructor is not required (we don't +// need to deep copy nullptr's), it is a good idea to keep the placeholder +// ready for less trivial cases. +// +brep::package_search:: +package_search (const package_search& r) + : module (r), + options_ (r.initialized_ ? r.options_ : nullptr), + db_ (r.initialized_ ? r.db_ : nullptr) +{ +} + void brep::package_search:: init (scanner& s) { @@ -74,13 +86,8 @@ handle (request& rq, response& rs) MODULE_DIAG; - // The module options object is not changed after being created once per - // server process. - // - static const size_t res_page (options_->search_results ()); - static const dir_path& root (options_->root ()); - static const fragment& logo (options_->logo ()); - static const vector& menu (options_->menu ()); + const size_t res_page (options_->search_results ()); + const dir_path& root (options_->root ()); params::package_search params; @@ -124,7 +131,7 @@ handle (request& rq, response& rs) << SCRIPT << " " << ~SCRIPT << ~HEAD << BODY - << DIV_HEADER (root, logo, menu) + << DIV_HEADER (root, options_->logo (), options_->menu ()) << DIV(ID="content"); session sn; diff --git a/brep/mod-package-version-details b/brep/mod-package-version-details index d102fdf..cfbcf94 100644 --- a/brep/mod-package-version-details +++ b/brep/mod-package-version-details @@ -18,6 +18,14 @@ namespace brep class package_version_details: public module { public: + package_version_details () = default; + + // Create a shallow copy (handling instance) if initialized and a deep + // copy (context exemplar) otherwise. + // + explicit + package_version_details (const package_version_details&); + virtual bool handle (request&, response&); diff --git a/brep/mod-package-version-details.cxx b/brep/mod-package-version-details.cxx index c9055a5..cbf9c86 100644 --- a/brep/mod-package-version-details.cxx +++ b/brep/mod-package-version-details.cxx @@ -25,6 +25,18 @@ using namespace std; using namespace odb::core; using namespace brep::cli; +// While currently the user-defined copy constructor is not required (we don't +// need to deep copy nullptr's), it is a good idea to keep the placeholder +// ready for less trivial cases. +// +brep::package_version_details:: +package_version_details (const package_version_details& r) + : module (r), + options_ (r.initialized_ ? r.options_ : nullptr), + db_ (r.initialized_ ? r.db_ : nullptr) +{ +} + void brep::package_version_details:: init (scanner& s) { @@ -48,12 +60,7 @@ handle (request& rq, response& rs) MODULE_DIAG; - // The module options object is not changed after being created once per - // server process. - // - static const dir_path& root (options_->root ()); - static const fragment& logo (options_->logo ()); - static const vector& menu (options_->menu ()); + const dir_path& root (options_->root ()); auto i (rq.path ().rbegin ()); version ver; @@ -107,7 +114,7 @@ handle (request& rq, response& rs) << CSS_LINKS (path ("package-version-details.css"), root) << ~HEAD << BODY - << DIV_HEADER (root, logo, menu) + << DIV_HEADER (root, options_->logo (), options_->menu ()) << DIV(ID="content"); if (full) diff --git a/brep/mod-repository-details b/brep/mod-repository-details index 5f1e93f..411d9e6 100644 --- a/brep/mod-repository-details +++ b/brep/mod-repository-details @@ -18,6 +18,14 @@ namespace brep class repository_details: public module { public: + repository_details () = default; + + // Create a shallow copy (handling instance) if initialized and a deep + // copy (context exemplar) otherwise. + // + explicit + repository_details (const repository_details&); + virtual bool handle (request&, response&); diff --git a/brep/mod-repository-details.cxx b/brep/mod-repository-details.cxx index 0a88a16..f040be6 100644 --- a/brep/mod-repository-details.cxx +++ b/brep/mod-repository-details.cxx @@ -31,6 +31,18 @@ using namespace std; using namespace odb::core; using namespace brep::cli; +// While currently the user-defined copy constructor is not required (we don't +// need to deep copy nullptr's), it is a good idea to keep the placeholder +// ready for less trivial cases. +// +brep::repository_details:: +repository_details (const repository_details& r) + : module (r), + options_ (r.initialized_ ? r.options_ : nullptr), + db_ (r.initialized_ ? r.db_ : nullptr) +{ +} + void brep::repository_details:: init (scanner& s) { @@ -54,12 +66,7 @@ handle (request& rq, response& rs) MODULE_DIAG; - // The module options object is not changed after being created once per - // server process. - // - static const dir_path& root (options_->root ()); - static const fragment& logo (options_->logo ()); - static const vector& menu (options_->menu ()); + const dir_path& root (options_->root ()); // Make sure no parameters passed. // @@ -82,7 +89,7 @@ handle (request& rq, response& rs) << CSS_LINKS (path ("repository-details.css"), root) << ~HEAD << BODY - << DIV_HEADER (root, logo, menu) + << DIV_HEADER (root, options_->logo (), options_->menu ()) << DIV(ID="content"); transaction t (db_->begin ()); diff --git a/brep/mod-repository-root b/brep/mod-repository-root index 254dfa3..f2c2ba0 100644 --- a/brep/mod-repository-root +++ b/brep/mod-repository-root @@ -23,6 +23,12 @@ namespace brep public: repository_root (); + // Create a shallow copy (handling instance) if initialized and a deep + // copy (context exemplar) otherwise. + // + explicit + repository_root (const repository_root&); + private: virtual bool handle (request&, response&); diff --git a/brep/mod-repository-root.cxx b/brep/mod-repository-root.cxx index 61aa71b..7c27a60 100644 --- a/brep/mod-repository-root.cxx +++ b/brep/mod-repository-root.cxx @@ -58,6 +58,37 @@ namespace brep { } + repository_root:: + repository_root (const repository_root& r) + : module (r), + // + // Deep/shallow-copy sub-modules depending on whether this is an + // exemplar/handler. + // + package_search_ ( + r.initialized_ + ? r.package_search_ + : make_shared (*r.package_search_)), + package_details_ ( + r.initialized_ + ? r.package_details_ + : make_shared (*r.package_details_)), + package_version_details_ ( + r.initialized_ + ? r.package_version_details_ + : make_shared ( + *r.package_version_details_)), + repository_details_ ( + r.initialized_ + ? r.repository_details_ + : make_shared (*r.repository_details_)), + options_ ( + r.initialized_ + ? r.options_ + : nullptr) + { + } + // Return amalgamation of repository_root and all its sub-modules option // descriptions. // @@ -112,7 +143,7 @@ namespace brep { MODULE_DIAG; - static const dir_path& root (options_->root ()); + const dir_path& root (options_->root ()); const path& rpath (rq.path ()); if (!rpath.sub (root)) diff --git a/brep/module b/brep/module index 4ea5164..52106cd 100644 --- a/brep/module +++ b/brep/module @@ -88,7 +88,7 @@ namespace brep // Set to true when the module is successfully initialized. // - bool loaded_ {false}; + bool initialized_ {false}; // Implementation details. // diff --git a/brep/module.cxx b/brep/module.cxx index e8a824d..1257d82 100644 --- a/brep/module.cxx +++ b/brep/module.cxx @@ -30,7 +30,7 @@ namespace brep try { - if (!loaded_) + if (!initialized_) { MODULE_DIAG; fail << "not initialized, presumably due to misconfiguration"; @@ -187,7 +187,7 @@ namespace brep void module:: init (const name_values& options, log& log) { - assert (!loaded_); + assert (!initialized_); log_ = &log; @@ -207,7 +207,7 @@ namespace brep options::module o (s, cli::unknown_mode::fail, cli::unknown_mode::fail); verb_ = o.verbosity (); - loaded_ = true; + initialized_ = true; } catch (const server_error& e) { @@ -236,7 +236,11 @@ namespace brep // Custom copy constructor is required to initialize log_writer_ properly. // module:: - module (const module& m): module () {verb_ = m.verb_; loaded_ = m.loaded_;} + module (const module& m): module () + { + verb_ = m.verb_; + initialized_ = m.initialized_; + } // For function func declared like this: // using B = std::string (*)(int); -- cgit v1.1