diff options
Diffstat (limited to 'brep/module.cxx')
-rw-r--r-- | brep/module.cxx | 410 |
1 files changed, 0 insertions, 410 deletions
diff --git a/brep/module.cxx b/brep/module.cxx deleted file mode 100644 index 68969eb..0000000 --- a/brep/module.cxx +++ /dev/null @@ -1,410 +0,0 @@ -// file : brep/module.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include <brep/module> - -#include <httpd.h> -#include <http_log.h> - -#include <sstream> -#include <cstring> // strchr() -#include <functional> // bind() - -#include <web/module> -#include <web/apache/log> - -#include <brep/options> - -using namespace std; -using namespace placeholders; // For std::bind's _1, etc. - -namespace brep -{ - // module - // - bool module:: - handle (request& rq, response& rs, log& l) - { - log_ = &l; - - try - { - // Web server should terminate if initialization failed. - // - assert (initialized_); - - return handle (rq, rs); - } - catch (const server_error& e) - { - log_write (e.data); - - try - { - static const char* sev_str[] = {"error", "warning", "info", "trace"}; - ostream& o (rs.content (500, "text/plain;charset=utf-8")); - - for (const auto& d: e.data) - { - string name; - - try - { - name = func_name (d.name); - } - catch (const invalid_argument&) - { - // Log "pretty" function description, see in log file & fix. - name = d.name; - } - - o << name << ": " << sev_str[static_cast<size_t> (d.sev)] << ": " - << d.msg << endl; - } - } - catch (const sequence_error&) - { - // We tried to return the error status/description but some - // content has already been written. Nothing we can do about - // it. - } - } - - return true; - } - - option_descriptions module:: - convert (const cli::options& o) - { - option_descriptions r; - append (r, o); - return r; - } - - void module:: - append (option_descriptions& dst, const cli::options& src) - { - for (const auto& o: src) - { - bool v (!o.flag ()); - auto i (dst.emplace (o.name (), v)); - assert (i.first->second == v); // Consistent option/flag. - - for (const auto& a: o.aliases ()) - { - i = dst.emplace (a, v); - assert (i.first->second == v); - } - } - } - - void module:: - append (option_descriptions& dst, const option_descriptions& src) - { - for (const auto& o: src) - { - auto i (dst.emplace (o)); - assert (i.first->second == o.second); // Consistent option/flag. - } - } - - name_values module:: - filter (const name_values& v, const option_descriptions& d) - { - name_values r; - for (const auto& nv: v) - { - if (d.find (nv.name) != d.end ()) - r.push_back (nv); - } - - return r; - } - - // Convert CLI option descriptions to the general interface of option - // descriptions, extend with brep::module own option descriptions. - // - option_descriptions module:: - options () - { - option_descriptions r ({{"conf", true}}); - append (r, options::module::description ()); - append (r, cli_options ()); - return r; - } - - // Expand option list parsing configuration files. - // - name_values module:: - expand_options (const name_values& v) - { - using namespace cli; - - vector<const char*> argv; - for (const auto& nv: v) - { - argv.push_back (nv.name.c_str ()); - - if (nv.value) - argv.push_back (nv.value->c_str ()); - } - - int argc (argv.size ()); - argv_file_scanner s (0, argc, const_cast<char**> (argv.data ()), "conf"); - - name_values r; - const option_descriptions& o (options ()); - - while (s.more ()) - { - string n (s.next ()); - auto i (o.find (n)); - - if (i == o.end ()) - throw unknown_argument (n); - - optional<string> v; - if (i->second) - v = s.next (); - - r.emplace_back (move (n), move (v)); - } - - return r; - } - - // Parse options with a cli-generated scanner. Options verb and conf are - // recognized by brep::module::init while others to be interpreted by the - // derived init(). If there is an option which can not be interpreted - // neither by brep::module nor by the derived class, then the web server - // is terminated with a corresponding error message being logged. Though - // this should not happen if the options() function returned the correct - // set of options. - // - void module:: - init (const name_values& options, log& log) - { - assert (!initialized_); - - log_ = &log; - - try - { - name_values opts (expand_options (options)); - - // Read module implementation configuration. - // - init (opts); - - // Read brep::module configuration. - // - static option_descriptions od ( - convert (options::module::description ())); - - name_values mo (filter (opts, od)); - name_value_scanner s (mo); - options::module o (s, cli::unknown_mode::fail, cli::unknown_mode::fail); - - verb_ = o.verbosity (); - initialized_ = true; - } - catch (const server_error& e) - { - log_write (e.data); - throw runtime_error ("initialization failed"); - } - catch (const cli::exception& e) - { - ostringstream o; - e.print (o); - throw runtime_error (o.str ()); - } - } - - void module:: - init (const name_values& options) - { - name_value_scanner s (options); - init (s); - assert (!s.more ()); // Module didn't handle its options. - } - - module:: - module (): log_writer_ (bind (&module::log_write, this, _1)) {} - - // Custom copy constructor is required to initialize log_writer_ properly. - // - module:: - module (const module& m): module () - { - verb_ = m.verb_; - initialized_ = m.initialized_; - } - -// For function func declared like this: -// using B = std::string (*)(int); -// using A = B (*)(int,int); -// A func(B (*)(char),B (*)(wchar_t)); -// __PRETTY_FUNCTION__ looks like this: -// virtual std::string (* (* brep::search::func(std::string (* (*)(char))(int) -// ,std::string (* (*)(wchar_t))(int)) const)(int, int))(int) -// - string module:: - func_name (const char* pretty_name) - { - const char* e (strchr (pretty_name, ')')); - - if (e && e > pretty_name) - { - // Position e at last matching '(' which is the beginning of the - // argument list.. - // - size_t d (1); - - do - { - switch (*--e) - { - case ')': ++d; break; - case '(': --d; break; - } - } - while (d && e > pretty_name); - - if (!d && e > pretty_name) - { - // Position e at the character following the function name. - // - while (e > pretty_name && - (*e != '(' || *(e - 1) == ' ' || *(e - 1) == ')')) - --e; - - if (e > pretty_name) - { - // Position b at the beginning of the qualified function name. - // - const char* b (e); - while (--b > pretty_name && *b != ' '); - if (*b == ' ') ++b; - - return string (b, e - b); - } - } - } - - throw invalid_argument ("::brep::module::func_name"); - } - - void module:: - log_write (const diag_data& d) const - { - if (log_ == nullptr) - return; // No backend yet. - - //@@ Cast log_ to apache::log and write the records. - // - auto al (dynamic_cast<web::apache::log*> (log_)); - - if (al) - { - // Considered using lambda for mapping but looks too verbose while can - // be a bit safer in runtime. - // - // Use APLOG_INFO (as opposed to APLOG_TRACE1) as a mapping for - // severity::trace. "LogLevel trace1" configuration directive switches - // on the avalanche of log messages from various modules. Would be good - // to avoid wading through them. - // - static int s[] = {APLOG_ERR, APLOG_WARNING, APLOG_INFO, APLOG_INFO}; - - for (const auto& e: d) - { - string name; - - try - { - name = func_name (e.name); - } - catch (const invalid_argument&) - { - // Log "pretty" function description, see in log file & fix. - name = e.name; - } - - al->write (e.loc.file.c_str (), - e.loc.line, - name.c_str (), - s[static_cast<size_t> (e.sev)], - e.msg.c_str ()); - } - } - } - - void module:: - version (log& l) - { - log_ = &l; - version (); - } - - // module::name_value_scanner - // - module::name_value_scanner:: - name_value_scanner (const name_values& nv) noexcept - : name_values_ (nv), - i_ (nv.begin ()), - name_ (true) - { - } - - bool module::name_value_scanner:: - more () - { - return i_ != name_values_.end (); - } - - const char* module::name_value_scanner:: - peek () - { - if (i_ != name_values_.end ()) - return name_ ? i_->name.c_str () : i_->value->c_str (); - else - throw cli::eos_reached (); - } - - const char* module::name_value_scanner:: - next () - { - if (i_ != name_values_.end ()) - { - const char* r (name_ ? i_->name.c_str () : i_->value->c_str ()); - skip (); - return r; - } - else - throw cli::eos_reached (); - } - - void module::name_value_scanner:: - skip () - { - if (i_ != name_values_.end ()) - { - if (name_) - { - if (i_->value) - name_ = false; - else - ++i_; - } - else - { - ++i_; - name_ = true; - } - } - else - throw cli::eos_reached (); - } -} |