LCOV - code coverage report
Current view: top level - snaplogger - private_logger.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 214 258 82.9 %
Date: 2021-06-01 17:16:42 Functions: 36 43 83.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2013-2021  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/snaplogger
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software; you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation; either version 2 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19             : 
      20             : /** \file
      21             :  * \brief Appenders are used to append data to somewhere.
      22             :  *
      23             :  * This file declares the base appender class.
      24             :  */
      25             : 
      26             : // self
      27             : //
      28             : #include    "snaplogger/private_logger.h"
      29             : 
      30             : #include    "snaplogger/console_appender.h"
      31             : #include    "snaplogger/exception.h"
      32             : #include    "snaplogger/file_appender.h"
      33             : #include    "snaplogger/guard.h"
      34             : #include    "snaplogger/logger.h"
      35             : #include    "snaplogger/syslog_appender.h"
      36             : 
      37             : 
      38             : // cppthread lib
      39             : //
      40             : #include    <cppthread/log.h>
      41             : #include    <cppthread/runner.h>
      42             : 
      43             : 
      44             : // last include
      45             : //
      46             : #include    <snapdev/poison.h>
      47             : 
      48             : 
      49             : 
      50             : namespace snaplogger
      51             : {
      52             : 
      53             : 
      54             : namespace
      55             : {
      56             : 
      57             : 
      58             : 
      59           2 : void getopt_logs(cppthread::log_level_t l, std::string const & m)
      60             : {
      61           2 :     severity_t sev(severity_t::SEVERITY_ERROR);
      62           2 :     switch(l)
      63             :     {
      64           0 :     case cppthread::log_level_t::debug:
      65           0 :         sev = severity_t::SEVERITY_DEBUG;
      66           0 :         break;
      67             : 
      68           2 :     case cppthread::log_level_t::info:
      69           2 :         sev = severity_t::SEVERITY_INFORMATION;
      70           2 :         break;
      71             : 
      72           0 :     case cppthread::log_level_t::warning:
      73           0 :         sev = severity_t::SEVERITY_WARNING;
      74           0 :         break;
      75             : 
      76           0 :     case cppthread::log_level_t::fatal:
      77           0 :         sev = severity_t::SEVERITY_FATAL;
      78           0 :         break;
      79             : 
      80             :     //case cppthread::log_level_t::error:
      81           0 :     default:
      82             :         // anything else, keep SEVERITY_ERROR
      83           0 :         break;
      84             : 
      85             :     }
      86             : 
      87           4 :     message msg(sev, __FILE__, __func__, __LINE__);
      88             : 
      89             :     // we do not use the g_... names in case they were not yet allocated
      90             :     //
      91           2 :     msg.add_component(get_component(COMPONENT_NORMAL));
      92           2 :     msg.add_component(get_component(COMPONENT_CPPTHREAD));
      93             : 
      94           2 :     msg << m;
      95             : 
      96             :     // this call cannot create a loop, if the creation of the logger
      97             :     // generates an cppthread log, then the second call will generate
      98             :     // an exception (see get_instance() in snaplogger/logger.cpp)
      99             :     //
     100           4 :     logger::pointer_t lg(logger::get_instance());
     101             : 
     102           2 :     lg->log_message(msg);
     103           2 : }
     104             : 
     105             : 
     106             : 
     107             : }
     108             : // no name namespace
     109             : 
     110             : 
     111             : namespace detail
     112             : {
     113             : 
     114             : 
     115             : 
     116             : 
     117           1 : class asynchronous_logger
     118             :     : public cppthread::runner
     119             : {
     120             : public:
     121           1 :     asynchronous_logger(message_fifo_t::pointer_t fifo)
     122           1 :         : runner("logger asynchronous thread")
     123           2 :         , f_logger(logger::get_instance())
     124           3 :         , f_fifo(fifo)
     125             :     {
     126           1 :     }
     127             : 
     128           2 :     virtual void run()
     129             :     {
     130             :         // loop until the FIFO is marked as being done
     131             :         //
     132             :         for(;;)
     133             :         {
     134           3 :             message::pointer_t msg;
     135           2 :             if(!f_fifo->pop_front(msg, -1))
     136             :             {
     137           1 :                 break;
     138             :             }
     139           2 :             logger::pointer_t l(f_logger.lock());
     140           1 :             if(l != nullptr)
     141             :             {
     142           1 :                 l->process_message(*msg);
     143             :             }
     144           1 :         }
     145           1 :     }
     146             : 
     147             : private:
     148             :     logger::weak_pointer_t      f_logger = logger::pointer_t();
     149             :     message_fifo_t::pointer_t   f_fifo = message_fifo_t::pointer_t();
     150             : };
     151             : 
     152             : 
     153             : 
     154             : }
     155             : // detail namespace
     156             : 
     157             : 
     158             : 
     159           2 : private_logger::private_logger()
     160             : {
     161             :     // if a call arrives really early, this is defined in the logger
     162             :     //
     163           2 :     f_normal_component = get_component(COMPONENT_NORMAL);
     164             : 
     165           2 :     cppthread::set_log_callback(getopt_logs);
     166           2 : }
     167             : 
     168             : 
     169           6 : private_logger::~private_logger()
     170             : {
     171           2 :     delete_thread();
     172           4 : }
     173             : 
     174             : 
     175           2 : void private_logger::shutdown()
     176             : {
     177           2 :     delete_thread();
     178           2 : }
     179             : 
     180             : 
     181           8 : void private_logger::register_appender_factory(appender_factory::pointer_t factory)
     182             : {
     183           8 :     if(factory == nullptr)
     184             :     {
     185             :         throw logger_logic_error(                                       // LCOV_EXCL_LINE
     186             :                 "register_appender_factory() called with a nullptr.");  // LCOV_EXCL_LINE
     187             :     }
     188             : 
     189          16 :     guard g;
     190             : 
     191           8 :     if(f_appender_factories.find(factory->get_type()) != f_appender_factories.end())
     192             :     {
     193             :         throw duplicate_error(                                  // LCOV_EXCL_LINE
     194             :                   "trying to register appender type \""         // LCOV_EXCL_LINE
     195             :                 + factory->get_type()                           // LCOV_EXCL_LINE
     196             :                 + "\" twice won't work.");                      // LCOV_EXCL_LINE
     197             :     }
     198             : 
     199           8 :     f_appender_factories[factory->get_type()] = factory;
     200           8 : }
     201             : 
     202             : 
     203           2 : appender::pointer_t private_logger::create_appender(std::string const & type, std::string const & name)
     204             : {
     205           4 :     guard g;
     206             : 
     207           2 :     auto it(f_appender_factories.find(type));
     208           2 :     if(it != f_appender_factories.end())
     209             :     {
     210           1 :         return it->second->create(name);
     211             :     }
     212             : 
     213           1 :     return appender::pointer_t();
     214             : }
     215             : 
     216             : 
     217             : /** \brief Get a component by name.
     218             :  *
     219             :  * All components are stored in the f_components set managed by the
     220             :  * private_logger object instance. This way each component is unique.
     221             :  *
     222             :  * This function searches the list of existing components. If one with
     223             :  * the same name already exists, then that one is picked and returned.
     224             :  * If it doesn't exist yet, then a new component is created and that
     225             :  * new component's pointer is saved in the f_components list and
     226             :  * returned.
     227             :  *
     228             :  * The name of the components must be composed of letters (a-z),
     229             :  * underscores (_), and digits (0-9). Any other character is considered
     230             :  * invalid. The function will force uppercase characters (A-Z) to lowercase
     231             :  * and dashes (-) to underscores (_). Finally, a component name can't start
     232             :  * with a digit (0-9).
     233             :  *
     234             :  * \exception invalid_parameter
     235             :  * This function raises an invalid_parameter exception when it find an
     236             :  * invalid character in the input name.
     237             :  *
     238             :  * \param[in] name  The name of the component to retrieve.
     239             :  *
     240             :  * \return The pointer to the component named \p name.
     241             :  */
     242          54 : component::pointer_t private_logger::get_component(std::string const & name)
     243             : {
     244         108 :     guard g;
     245             : 
     246         108 :     std::string n;
     247          54 :     n.reserve(name.length());
     248         466 :     for(char const * s(name.c_str()); *s != '\0'; ++s)
     249             :     {
     250         412 :         if(*s >= 'a' && *s <= 'z')
     251             :         {
     252         390 :             n += *s;
     253             :         }
     254          22 :         else if(*s >= 'A' && *s <= 'Z')
     255             :         {
     256             :             // force to lowercase
     257             :             //
     258           0 :             n += *s | 0x20;
     259             :         }
     260          22 :         else if(*s == '-' || *s == '_')
     261             :         {
     262           0 :             n += '_';
     263             :         }
     264          22 :         else if(*s >= '0' && *s <= '9')
     265             :         {
     266          22 :             if(n.empty())
     267             :             {
     268             :                 throw invalid_parameter(
     269             :                           "a component name cannot start with a digits ("
     270           0 :                         + name
     271           0 :                         + ")");
     272             :             }
     273          22 :             n += *s;
     274             :         }
     275             :         else
     276             :         {
     277             :             throw invalid_parameter(
     278             :                       "a component name cannot include a '"
     279           0 :                     + *s
     280           0 :                     + ("' character ("
     281           0 :                     + name
     282           0 :                     + ")"));
     283             :         }
     284             :     }
     285             : 
     286          54 :     auto it(f_components.find(n));
     287          54 :     if(it != f_components.end())
     288             :     {
     289          34 :         return it->second;
     290             :     }
     291             : 
     292             :     // the component constructor is only accessible to the private_logger
     293             :     // so we can't do a make_shared<>()
     294             :     //
     295             :     //auto comp(std::make_shared<component>(n));
     296             : 
     297          20 :     f_components[n].reset(new component(n));
     298             : 
     299          20 :     return f_components[n];
     300             : }
     301             : 
     302             : 
     303          18 : format::pointer_t private_logger::get_default_format()
     304             : {
     305          36 :     guard g;
     306             : 
     307          18 :     if(f_default_format == nullptr)
     308             :     {
     309           2 :         f_default_format = std::make_shared<format>(
     310             :             //"${env:name=HOME:padding='-':align=center:exact_width=6} "
     311             :             "${date} ${time} ${hostname}"
     312             :             " ${progname}[${pid}]: ${severity}:"
     313             :             " ${message:escape:max_width=1000}"
     314             :             " (in function \"${function}()\")"
     315             :             " (${basename}:${line})"
     316           1 :         );
     317             :     }
     318             : 
     319          36 :     return f_default_format;
     320             : }
     321             : 
     322             : 
     323       93563 : environment::pointer_t private_logger::create_environment()
     324             : {
     325       93563 :     pid_t const tid(cppthread::gettid());
     326             : 
     327      187126 :     guard g;
     328             : 
     329       93563 :     auto it(f_environment.find(tid));
     330       93563 :     if(it == f_environment.end())
     331             :     {
     332           4 :         auto result(std::make_shared<environment>(tid));
     333           2 :         f_environment[tid] = result;
     334           2 :         return result;
     335             :     }
     336             : 
     337       93561 :     return it->second;
     338             : }
     339             : 
     340             : 
     341             : /** \brief Add a severity.
     342             :  *
     343             :  * This function adds a severity to the private logger object.
     344             :  *
     345             :  * Remember that a severity can be given aliases so this function may
     346             :  * add quite a few entries, not just one.
     347             :  *
     348             :  * To add an alias after creation, make sure to use the add_alias() instead.
     349             :  * This makes sure you link the same severity to several names.
     350             :  *
     351             :  * \warning
     352             :  * You should not be calling this function directly. Please see the
     353             :  * direct snaplogger::add_severity() function instead.
     354             :  *
     355             :  * \exception duplicate_error
     356             :  * The function verifies that the new severity is not a duplicate of
     357             :  * an existing system severity. The verification process checks the
     358             :  * severity by severity level and by name. You can, however, have
     359             :  * _duplicates_ of user defined severity levels. However, the last
     360             :  * user defined severity of a given name & level sticks, the others
     361             :  * get deleted.
     362             :  *
     363             :  * \param[in] sev  The severity object to be added.
     364             :  */
     365          25 : void private_logger::add_severity(severity::pointer_t sev)
     366             : {
     367          50 :     guard g;
     368             : 
     369          25 :     auto it(f_severity_by_severity.find(sev->get_severity()));
     370          25 :     if(it != f_severity_by_severity.end())
     371             :     {
     372           2 :         if(it->second->is_system())
     373             :         {
     374             :             throw duplicate_error("a system severity ("
     375           4 :                                 + std::to_string(static_cast<long>(it->first))
     376           4 :                                 + ") cannot be replaced (same severity level: "
     377           8 :                                 + std::to_string(static_cast<long>(sev->get_severity()))
     378           6 :                                 + ").");
     379             :         }
     380             :     }
     381             : 
     382          60 :     for(auto n : sev->get_all_names())
     383             :     {
     384          37 :         auto s(f_severity_by_name.find(n));
     385          37 :         if(s != f_severity_by_name.end())
     386             :         {
     387           2 :             if(s->second->is_system())
     388             :             {
     389             :                 // note that any severity can be partially edited, just not
     390             :                 // added more than once
     391             :                 //
     392             :                 throw duplicate_error("a system severity ("
     393           4 :                                     + n
     394           6 :                                     + ") cannot be replaced (same name).");
     395             :             }
     396             :         }
     397             :     }
     398             : 
     399          21 :     sev->mark_as_registered();
     400             : 
     401          21 :     f_severity_by_severity[sev->get_severity()] = sev;
     402             : 
     403          56 :     for(auto const n : sev->get_all_names())
     404             :     {
     405          35 :         f_severity_by_name[n] = sev;
     406             :     }
     407          21 : }
     408             : 
     409             : 
     410             : /** \brief Add yet another alias.
     411             :  *
     412             :  * This function is used when the system aliases get assigned additional
     413             :  * aliases. The add_severity() was already called with system definitions,
     414             :  * so this is the only way to add additional aliases to them trhough the .ini
     415             :  * files.
     416             :  *
     417             :  * \param[in] sev  A pointer to the severity to be added.
     418             :  * \param[in] name  The name of the alias.
     419             :  */
     420           2 : void private_logger::add_alias(severity::pointer_t sev, std::string const & name)
     421             : {
     422           4 :     guard g;
     423             : 
     424           2 :     auto it(f_severity_by_severity.find(sev->get_severity()));
     425           2 :     if(it == f_severity_by_severity.end())
     426             :     {
     427             :         throw duplicate_error("to register an alias the corresponding main severity must already be registered. We could not find a severity with level "
     428           0 :                             + std::to_string(static_cast<long>(sev->get_severity()))
     429           0 :                             + ".");
     430             :     }
     431             : 
     432           2 :     auto s(f_severity_by_name.find(name));
     433           2 :     if(s != f_severity_by_name.end())
     434             :     {
     435           0 :         if(s->second->is_system())
     436             :         {
     437             :             // note that any severity can be partially edited, just not
     438             :             // added more than once
     439             :             //
     440             :             throw duplicate_error("a system severity ("
     441           0 :                                 + name
     442           0 :                                 + ") cannot be replaced (same name).");
     443             :         }
     444             :     }
     445             : 
     446           2 :     f_severity_by_name[name] = sev;
     447           2 : }
     448             : 
     449             : 
     450          30 : severity::pointer_t private_logger::get_severity(std::string const & name) const
     451             : {
     452          60 :     guard g;
     453             : 
     454          60 :     std::string n(name);
     455          30 :     std::transform(n.begin(), n.end(), n.begin(), std::towlower);
     456          30 :     auto it(f_severity_by_name.find(n));
     457          30 :     if(it == f_severity_by_name.end())
     458             :     {
     459           5 :         return severity::pointer_t();
     460             :     }
     461             : 
     462          25 :     return it->second;
     463             : }
     464             : 
     465             : 
     466          18 : severity::pointer_t private_logger::get_severity(severity_t sev) const
     467             : {
     468          36 :     guard g;
     469             : 
     470          18 :     auto it(f_severity_by_severity.find(sev));
     471          18 :     if(it == f_severity_by_severity.end())
     472             :     {
     473           2 :         return severity::pointer_t();
     474             :     }
     475             : 
     476          16 :     return it->second;
     477             : }
     478             : 
     479             : 
     480           0 : severity::pointer_t private_logger::get_default_severity() const
     481             : {
     482           0 :     return f_default_severity;
     483             : }
     484             : 
     485             : 
     486           1 : void private_logger::set_default_severity(severity::pointer_t sev)
     487             : {
     488           1 :     f_default_severity = sev;
     489           1 : }
     490             : 
     491             : 
     492          26 : void private_logger::set_diagnostic(std::string const & key, std::string const & diagnostic)
     493             : {
     494          52 :     guard g;
     495             : 
     496          26 :     f_map_diagnostics[key] = diagnostic;
     497          26 : }
     498             : 
     499             : 
     500           1 : void private_logger::unset_diagnostic(std::string const & key)
     501             : {
     502           2 :     guard g;
     503             : 
     504           1 :     auto it(f_map_diagnostics.find(key));
     505           1 :     if(it != f_map_diagnostics.end())
     506             :     {
     507           1 :         f_map_diagnostics.erase(it);
     508             :     }
     509           1 : }
     510             : 
     511             : 
     512          46 : map_diagnostics_t private_logger::get_map_diagnostics()
     513             : {
     514          92 :     guard g;
     515             : 
     516          92 :     return f_map_diagnostics;
     517             : }
     518             : 
     519             : 
     520           0 : void private_logger::set_maximum_trace_diagnostics(size_t max)
     521             : {
     522           0 :     f_maximum_trace_diagnostics = max;
     523           0 : }
     524             : 
     525             : 
     526           0 : size_t private_logger::get_maximum_trace_diagnostics() const
     527             : {
     528           0 :     return f_maximum_trace_diagnostics;
     529             : }
     530             : 
     531             : 
     532           0 : void private_logger::add_trace_diagnostic(std::string const & diagnostic)
     533             : {
     534           0 :     guard g;
     535             : 
     536           0 :     f_trace_diagnostics.push_back(diagnostic);
     537           0 :     if(f_trace_diagnostics.size() > f_maximum_trace_diagnostics)
     538             :     {
     539           0 :         f_trace_diagnostics.pop_front();
     540             :     }
     541           0 : }
     542             : 
     543             : 
     544           0 : void private_logger::clear_trace_diagnostics()
     545             : {
     546           0 :     guard g;
     547             : 
     548           0 :     f_trace_diagnostics.clear();
     549           0 : }
     550             : 
     551             : 
     552           0 : trace_diagnostics_t private_logger::get_trace_diagnostics()
     553             : {
     554           0 :     guard g;
     555             : 
     556           0 :     return f_trace_diagnostics;
     557             : }
     558             : 
     559             : 
     560           3 : void private_logger::push_nested_diagnostic(std::string const & diagnostic)
     561             : {
     562           6 :     guard g;
     563             : 
     564           3 :     f_nested_diagnostics.push_back(diagnostic);
     565           3 : }
     566             : 
     567             : 
     568           3 : void private_logger::pop_nested_diagnostic()
     569             : {
     570           6 :     guard g;
     571             : 
     572           3 :     f_nested_diagnostics.pop_back();
     573           3 : }
     574             : 
     575             : 
     576           8 : string_vector_t private_logger::get_nested_diagnostics() const
     577             : {
     578          16 :     guard g;
     579             : 
     580          16 :     return f_nested_diagnostics;
     581             : }
     582             : 
     583             : 
     584          61 : void private_logger::register_variable_factory(variable_factory::pointer_t factory)
     585             : {
     586         122 :     guard g;
     587             : 
     588          61 :     auto it(f_variable_factories.find(factory->get_type()));
     589          61 :     if(it != f_variable_factories.end())
     590             :     {
     591             :         throw duplicate_error(
     592             :                   "trying to add two variable factories of type \""
     593           2 :                 + factory->get_type()
     594           3 :                 + "\".");
     595             :     }
     596             : 
     597          60 :     f_variable_factories[factory->get_type()] = factory;
     598          60 : }
     599             : 
     600             : 
     601         218 : variable::pointer_t private_logger::get_variable(std::string const & type)
     602             : {
     603         436 :     guard g;
     604             : 
     605         218 :     if(f_variable_factories.empty())
     606             :     {
     607             :         throw invalid_variable("No variable factories were registered yet; you can't create a variable with type \""    // LCOV_EXCL_LINE
     608             :                              + type                                     // LCOV_EXCL_LINE
     609             :                              + "\" at this point.");                    // LCOV_EXCL_LINE
     610             :     }
     611             : 
     612         218 :     auto it(f_variable_factories.find(type));
     613         218 :     if(it == f_variable_factories.end())
     614             :     {
     615             :         // TBD: should we instead return a null var.?
     616             :         throw invalid_variable("You can't create variable with type \""
     617           2 :                              + type
     618           3 :                              + "\", no such variable type was registered.");
     619             :     }
     620             : 
     621         434 :     return it->second->create_variable();
     622             : }
     623             : 
     624             : 
     625       47267 : bool private_logger::has_functions() const
     626             : {
     627       94534 :     guard g;
     628             : 
     629       94534 :     return !f_functions.empty();
     630             : }
     631             : 
     632             : 
     633          23 : void private_logger::register_function(function::pointer_t func)
     634             : {
     635          46 :     guard g;
     636             : 
     637          23 :     auto it(f_functions.find(func->get_name()));
     638          23 :     if(it != f_functions.end())
     639             :     {
     640             :         throw duplicate_error(
     641             :                   "trying to add two functions named \""
     642           2 :                 + func->get_name()
     643           3 :                 + "\".");
     644             :     }
     645          22 :     f_functions[func->get_name()] = func;
     646          22 : }
     647             : 
     648             : 
     649          96 : function::pointer_t private_logger::get_function(std::string const & name) const
     650             : {
     651         192 :     guard g;
     652             : 
     653          96 :     auto it(f_functions.find(name));
     654          96 :     if(it != f_functions.end())
     655             :     {
     656          73 :         return it->second;
     657             :     }
     658             : 
     659          23 :     return function::pointer_t();
     660             : }
     661             : 
     662             : 
     663           1 : void private_logger::create_thread()
     664             : {
     665           2 :     guard g;
     666             : 
     667             :     try
     668             :     {
     669           1 :         f_fifo = std::make_shared<message_fifo_t>();
     670           1 :         f_asynchronous_logger = std::make_shared<detail::asynchronous_logger>(f_fifo);
     671           1 :         f_thread = std::make_shared<cppthread::thread>("asynchronous logger thread", f_asynchronous_logger.get());
     672           1 :         f_thread->start();
     673             :     }
     674             :     catch(...)                              // LCOV_EXCL_LINE
     675             :     {
     676             :         if(f_fifo != nullptr)               // LCOV_EXCL_LINE
     677             :         {
     678             :             f_fifo->done(false);            // LCOV_EXCL_LINE
     679             :         }
     680             : 
     681             :         f_thread.reset();                   // LCOV_EXCL_LINE
     682             :         f_asynchronous_logger.reset();      // LCOV_EXCL_LINE
     683             :         f_fifo.reset();                     // LCOV_EXCL_LINE
     684             :         throw;                              // LCOV_EXCL_LINE
     685             :     }
     686           1 : }
     687             : 
     688             : 
     689           5 : void private_logger::delete_thread()
     690             : {
     691             :     // WARNING: we can't call fifo::done() while our guard is locked
     692             :     //          we also have to make sure it's not a null pointer
     693             :     //
     694          10 :     message_fifo_t::pointer_t       fifo                = message_fifo_t::pointer_t();
     695          10 :     asynchronous_logger_pointer_t   asynchronous_logger = asynchronous_logger_pointer_t();
     696          10 :     cppthread::thread::pointer_t    thread              = cppthread::thread::pointer_t();
     697             : 
     698             :     {
     699          10 :         guard g;
     700             : 
     701           5 :         swap(thread,              f_thread);
     702           5 :         swap(asynchronous_logger, f_asynchronous_logger);
     703           5 :         swap(fifo,                f_fifo);
     704             :     }
     705             : 
     706           5 :     if(fifo != nullptr)
     707             :     {
     708           1 :         fifo->done(false);
     709             :     }
     710             : 
     711             :     try
     712             :     {
     713           5 :         thread.reset();
     714             :     }
     715             :     catch(std::exception const & e)
     716             :     {
     717             :         // in most cases this one happens when quitting when one of your
     718             :         // functions attempts to get an instance of the logger, which is
     719             :         // forbidden once you return from your main() function
     720             :         //
     721             :         std::cerr << "got exception \""
     722             :                   << e.what()
     723             :                   << "\" while deleting the asynchronous thread."
     724             :                   << std::endl;
     725             :     }
     726           5 : }
     727             : 
     728             : 
     729           1 : void private_logger::send_message_to_thread(message::pointer_t msg)
     730             : {
     731             :     {
     732           2 :         guard g;
     733             : 
     734           1 :         if(f_fifo == nullptr)
     735             :         {
     736           1 :             create_thread();
     737             :         }
     738             :     }
     739             : 
     740           1 :     f_fifo->push_back(msg);
     741           1 : }
     742             : 
     743             : 
     744             : 
     745             : 
     746       94040 : private_logger::pointer_t get_private_logger()
     747             : {
     748       94040 :     return std::dynamic_pointer_cast<private_logger>(logger::get_instance());
     749             : }
     750             : 
     751             : 
     752       47333 : private_logger::pointer_t get_private_logger(message const & msg)
     753             : {
     754       47333 :     return std::dynamic_pointer_cast<private_logger>(msg.get_logger());
     755             : }
     756             : 
     757             : 
     758             : 
     759           6 : } // snaplogger namespace
     760             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13