PageRenderTime 223ms CodeModel.GetById 81ms app.highlight 50ms RepoModel.GetById 61ms app.codeStats 0ms

/libs/cgi/example/cgi/DebugServer2/TracebackServer.cpp

http://github.com/darrengarvey/cgi
C++ | 143 lines | 123 code | 18 blank | 2 comment | 9 complexity | 703466f520d8ef34b2a9c5222fac5dd2 MD5 | raw file
  1#include "TracebackServer.hpp"
  2#include <boost/chrono/chrono.hpp>
  3
  4#define TBS_TEMPLATE__DEBUG_VIEW "../stencils/debug_view.html"
  5
  6namespace detail {
  7
  8boost::uint64_t
  9get_microseconds(boost::chrono::process_clock::duration const& tp)
 10{
 11  return boost::chrono::duration_cast<boost::chrono::microseconds>(tp).count();
 12}
 13
 14} // namespace detail
 15
 16
 17TracebackServer::TracebackServer(void)
 18    : timer_()
 19{
 20}
 21
 22TracebackServer::~TracebackServer(void)
 23{
 24}
 25
 26template<typename MapT>
 27void TracebackServer::expand_map(dictionary_type& dict, MapT& data, std::string const& title)
 28{
 29    dictionary_type* sub_dict = dict.AddSectionDictionary("REQUEST_DATA_MAP");
 30    sub_dict->SetValue("REQUEST_DATA_MAP_TITLE", title);
 31    if (data.empty())
 32        sub_dict->ShowSection("REQUEST_DATA_MAP_EMPTY");
 33    else {
 34        for(typename MapT::const_iterator iter(data.begin()), end(data.end()); iter != end; ++iter)
 35        {
 36            dictionary_type* nvpair_dict = sub_dict->AddSectionDictionary("REQUEST_DATA_PAIR");
 37            nvpair_dict->SetValue("REQUEST_DATA_NAME", iter->first.c_str());
 38            nvpair_dict->SetValue("REQUEST_DATA_VALUE", iter->second.c_str());
 39        }
 40    }
 41}
 42
 43void TracebackServer::stop_timer()
 44{
 45    timer_.elapsed(stop_times_);
 46}
 47
 48void TracebackServer::dump_times(dictionary_type& dict)
 49{
 50    dict.SetValue("RUNNING_TIME_RESOLUTION", "microseconds");
 51    dict.SetFormattedValue("REAL_TIME", "%d us", detail::get_microseconds(stop_times_.real));
 52    dict.SetFormattedValue("CPU_TIME", "%d us", detail::get_microseconds(stop_times_.user + stop_times_.system));
 53    dict.SetFormattedValue("USER_TIME", "%d us", detail::get_microseconds(stop_times_.user));
 54    dict.SetFormattedValue("SYSTEM_TIME", "%d us", detail::get_microseconds(stop_times_.system));
 55    dict.ShowSection("RUNNING_TIME");
 56}
 57
 58void TracebackServer::bomb_out(std::string const& error, response_type& response, request_type& request)
 59{
 60    stop_timer();
 61    response_type resp2;
 62    template_ = ctemplate::Template::GetTemplate(TBS_TEMPLATE__DEBUG_VIEW, ctemplate::STRIP_WHITESPACE);
 63    dictionary_type dict("debug_view");
 64    dict.SetValue("ERROR", error);
 65    expand_map(dict, request.env, "Environment Data");
 66    expand_map(dict, request.form, "Form (" + request.method() + ") data");
 67    expand_map(dict, request.cookies, "Cookies");
 68    BOOST_FOREACH(std::string& hstring, response.headers())
 69    {
 70        dict.SetValueAndShowSection("HEADER", hstring, "RESPONSE_HEADER");
 71    }
 72    dump_times(dict);
 73
 74    //dict.SetValue("ORIGINAL_RESPONSE", response.rdbuf()->data());
 75    std::string debug_output;
 76    template_->Expand(&debug_output, &dict);
 77    resp2<< boost::cgi::content_type("text/html")
 78         << debug_output
 79         << response;
 80    resp2.send(request.client());
 81    request.close();
 82}
 83
 84
 85void TracebackServer::bomb_out(boost::system::system_error* err, response_type& response, request_type& request) {
 86    //dictionary_type* sub_dict = dict.AddSectionDictionary("REQUEST_DATA_MAP");
 87    typedef request_type::string_type string;
 88    string err_msg("boost::system::system_error*<ul class=nvpair><li class=name>Code:</li>");
 89    err_msg += string("<li class=value>") + boost::lexical_cast<std::string>(err->code()) + "</li>" 
 90            + "<li class=name>What:</li>"
 91            + "<li class=value>" + err->what() + "</li>"
 92            + "<li class=name>Type:</li>"
 93            + "<li class=value>" + typeid(*err).name() + "</li><br class=clear /></ul>";
 94    bomb_out(err_msg, response, request);
 95}
 96
 97void TracebackServer::bomb_out(std::exception* e, response_type& response, request_type& request) {
 98    typedef request_type::string_type string;
 99    string err_msg("std::exception*<ul class=nvpair><li class=name>What:</li>");
100    err_msg += string("<li class=value>") + e->what() + "</li>" 
101            + "<li class=name>Type:</li>"
102            + "<li class=value>" + typeid(*e).name() + "</li><br class=clear /></ul>";
103    bomb_out(err_msg, response, request);
104}
105
106void TracebackServer::bomb_out(std::exception& e, response_type& response, request_type& request) {
107    typedef request_type::string_type string;
108    string err_msg("std::exception<ul class=nvpair><li class=name>What:</li>");
109    err_msg += string("<li class=value>") + e.what() + "</li>" 
110            + "<li class=name>Type:</li>"
111            + "<li class=value>" + typeid(e).name() + "</li><br class=clear /></ul>";
112    bomb_out(err_msg, response, request);
113}
114
115bool TracebackServer::run(callback_type const& callback)
116{
117    timer_.start();
118    request_type request;
119    response_type response;
120    try {
121        request.load(boost::cgi::parse_all);  
122        int ret(callback(request, response));
123        if (request.form["debug"] == "1") {
124            bomb_out("** Debug mode ** - client callback returned code #" + boost::lexical_cast<std::string>(ret)
125                    , response, request);
126        }else
127        if (!ret) {
128            return 0 == boost::cgi::commit(request, response);
129        } else {
130            bomb_out("Callback returned code #" + boost::lexical_cast<std::string>(ret) + "; unknown error", response, request);
131        }
132    }catch(boost::system::system_error* err) {
133        bomb_out(err, response, request); return false;
134    }catch(std::exception* e) {
135        bomb_out(e, response, request); return false;
136    }catch(std::exception& e) {
137        bomb_out(e, response, request); return false;
138    }catch(...){
139        bomb_out("Unknown exception (captor: CGI hello example TracebackServer::run())", response, request); return false;
140    }
141    return false;
142}
143