LCOV - code coverage report
Current view: top level - snaplogger - private_logger.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 215 259 83.0 %
Date: 2021-05-29 11:58:38 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          40 :     auto comp(std::make_shared<component>(n));
     293          20 :     f_components[n] = comp;
     294             : 
     295          20 :     return comp;
     296             : }
     297             : 
     298             : 
     299          18 : format::pointer_t private_logger::get_default_format()
     300             : {
     301          36 :     guard g;
     302             : 
     303          18 :     if(f_default_format == nullptr)
     304             :     {
     305           2 :         f_default_format = std::make_shared<format>(
     306             :             //"${env:name=HOME:padding='-':align=center:exact_width=6} "
     307             :             "${date} ${time} ${hostname}"
     308             :             " ${progname}[${pid}]: ${severity}:"
     309             :             " ${message:escape:max_width=1000}"
     310             :             " (in function \"${function}()\")"
     311             :             " (${basename}:${line})"
     312           1 :         );
     313             :     }
     314             : 
     315          36 :     return f_default_format;
     316             : }
     317             : 
     318             : 
     319       91736 : environment::pointer_t private_logger::create_environment()
     320             : {
     321       91736 :     pid_t const tid(cppthread::gettid());
     322             : 
     323      183472 :     guard g;
     324             : 
     325       91736 :     auto it(f_environment.find(tid));
     326       91736 :     if(it == f_environment.end())
     327             :     {
     328           4 :         auto result(std::make_shared<environment>(tid));
     329           2 :         f_environment[tid] = result;
     330           2 :         return result;
     331             :     }
     332             : 
     333       91734 :     return it->second;
     334             : }
     335             : 
     336             : 
     337             : /** \brief Add a severity.
     338             :  *
     339             :  * This function adds a severity to the private logger object.
     340             :  *
     341             :  * Remember that a severity can be given aliases so this function may
     342             :  * add quite a few entries, not just one.
     343             :  *
     344             :  * To add an alias after creation, make sure to use the add_alias() instead.
     345             :  * This makes sure you link the same severity to several names.
     346             :  *
     347             :  * \warning
     348             :  * You should not be calling this function directly. Please see the
     349             :  * direct snaplogger::add_severity() function instead.
     350             :  *
     351             :  * \exception duplicate_error
     352             :  * The function verifies that the new severity is not a duplicate of
     353             :  * an existing system severity. The verification process checks the
     354             :  * severity by severity level and by name. You can, however, have
     355             :  * _duplicates_ of user defined severity levels. However, the last
     356             :  * user defined severity of a given name & level sticks, the others
     357             :  * get deleted.
     358             :  *
     359             :  * \param[in] sev  The severity object to be added.
     360             :  */
     361          25 : void private_logger::add_severity(severity::pointer_t sev)
     362             : {
     363          50 :     guard g;
     364             : 
     365          25 :     auto it(f_severity_by_severity.find(sev->get_severity()));
     366          25 :     if(it != f_severity_by_severity.end())
     367             :     {
     368           2 :         if(it->second->is_system())
     369             :         {
     370             :             throw duplicate_error("a system severity ("
     371           4 :                                 + std::to_string(static_cast<long>(it->first))
     372           4 :                                 + ") cannot be replaced (same severity level: "
     373           8 :                                 + std::to_string(static_cast<long>(sev->get_severity()))
     374           6 :                                 + ").");
     375             :         }
     376             :     }
     377             : 
     378          60 :     for(auto n : sev->get_all_names())
     379             :     {
     380          37 :         auto s(f_severity_by_name.find(n));
     381          37 :         if(s != f_severity_by_name.end())
     382             :         {
     383           2 :             if(s->second->is_system())
     384             :             {
     385             :                 // note that any severity can be partially edited, just not
     386             :                 // added more than once
     387             :                 //
     388             :                 throw duplicate_error("a system severity ("
     389           4 :                                     + n
     390           6 :                                     + ") cannot be replaced (same name).");
     391             :             }
     392             :         }
     393             :     }
     394             : 
     395          21 :     sev->mark_as_registered();
     396             : 
     397          21 :     f_severity_by_severity[sev->get_severity()] = sev;
     398             : 
     399          56 :     for(auto const n : sev->get_all_names())
     400             :     {
     401          35 :         f_severity_by_name[n] = sev;
     402             :     }
     403          21 : }
     404             : 
     405             : 
     406             : /** \brief Add yet another alias.
     407             :  *
     408             :  * This function is used when the system aliases get assigned additional
     409             :  * aliases. The add_severity() was already called with system definitions,
     410             :  * so this is the only way to add additional aliases to them trhough the .ini
     411             :  * files.
     412             :  *
     413             :  * \param[in] sev  A pointer to the severity to be added.
     414             :  * \param[in] name  The name of the alias.
     415             :  */
     416           2 : void private_logger::add_alias(severity::pointer_t sev, std::string const & name)
     417             : {
     418           4 :     guard g;
     419             : 
     420           2 :     auto it(f_severity_by_severity.find(sev->get_severity()));
     421           2 :     if(it == f_severity_by_severity.end())
     422             :     {
     423             :         throw duplicate_error("to register an alias the corresponding main severity must already be registered. We could not find a severity with level "
     424           0 :                             + std::to_string(static_cast<long>(sev->get_severity()))
     425           0 :                             + ".");
     426             :     }
     427             : 
     428           2 :     auto s(f_severity_by_name.find(name));
     429           2 :     if(s != f_severity_by_name.end())
     430             :     {
     431           0 :         if(s->second->is_system())
     432             :         {
     433             :             // note that any severity can be partially edited, just not
     434             :             // added more than once
     435             :             //
     436             :             throw duplicate_error("a system severity ("
     437           0 :                                 + name
     438           0 :                                 + ") cannot be replaced (same name).");
     439             :         }
     440             :     }
     441             : 
     442           2 :     f_severity_by_name[name] = sev;
     443           2 : }
     444             : 
     445             : 
     446          30 : severity::pointer_t private_logger::get_severity(std::string const & name) const
     447             : {
     448          60 :     guard g;
     449             : 
     450          60 :     std::string n(name);
     451          30 :     std::transform(n.begin(), n.end(), n.begin(), std::towlower);
     452          30 :     auto it(f_severity_by_name.find(n));
     453          30 :     if(it == f_severity_by_name.end())
     454             :     {
     455           5 :         return severity::pointer_t();
     456             :     }
     457             : 
     458          25 :     return it->second;
     459             : }
     460             : 
     461             : 
     462          18 : severity::pointer_t private_logger::get_severity(severity_t sev) const
     463             : {
     464          36 :     guard g;
     465             : 
     466          18 :     auto it(f_severity_by_severity.find(sev));
     467          18 :     if(it == f_severity_by_severity.end())
     468             :     {
     469           2 :         return severity::pointer_t();
     470             :     }
     471             : 
     472          16 :     return it->second;
     473             : }
     474             : 
     475             : 
     476           0 : severity::pointer_t private_logger::get_default_severity() const
     477             : {
     478           0 :     return f_default_severity;
     479             : }
     480             : 
     481             : 
     482           1 : void private_logger::set_default_severity(severity::pointer_t sev)
     483             : {
     484           1 :     f_default_severity = sev;
     485           1 : }
     486             : 
     487             : 
     488          26 : void private_logger::set_diagnostic(std::string const & key, std::string const & diagnostic)
     489             : {
     490          52 :     guard g;
     491             : 
     492          26 :     f_map_diagnostics[key] = diagnostic;
     493          26 : }
     494             : 
     495             : 
     496           1 : void private_logger::unset_diagnostic(std::string const & key)
     497             : {
     498           2 :     guard g;
     499             : 
     500           1 :     auto it(f_map_diagnostics.find(key));
     501           1 :     if(it != f_map_diagnostics.end())
     502             :     {
     503           1 :         f_map_diagnostics.erase(it);
     504             :     }
     505           1 : }
     506             : 
     507             : 
     508          46 : map_diagnostics_t private_logger::get_map_diagnostics()
     509             : {
     510          92 :     guard g;
     511             : 
     512          92 :     return f_map_diagnostics;
     513             : }
     514             : 
     515             : 
     516           0 : void private_logger::set_maximum_trace_diagnostics(size_t max)
     517             : {
     518           0 :     f_maximum_trace_diagnostics = max;
     519           0 : }
     520             : 
     521             : 
     522           0 : size_t private_logger::get_maximum_trace_diagnostics() const
     523             : {
     524           0 :     return f_maximum_trace_diagnostics;
     525             : }
     526             : 
     527             : 
     528           0 : void private_logger::add_trace_diagnostic(std::string const & diagnostic)
     529             : {
     530           0 :     guard g;
     531             : 
     532           0 :     f_trace_diagnostics.push_back(diagnostic);
     533           0 :     if(f_trace_diagnostics.size() > f_maximum_trace_diagnostics)
     534             :     {
     535           0 :         f_trace_diagnostics.pop_front();
     536             :     }
     537           0 : }
     538             : 
     539             : 
     540           0 : void private_logger::clear_trace_diagnostics()
     541             : {
     542           0 :     guard g;
     543             : 
     544           0 :     f_trace_diagnostics.clear();
     545           0 : }
     546             : 
     547             : 
     548           0 : trace_diagnostics_t private_logger::get_trace_diagnostics()
     549             : {
     550           0 :     guard g;
     551             : 
     552           0 :     return f_trace_diagnostics;
     553             : }
     554             : 
     555             : 
     556           3 : void private_logger::push_nested_diagnostic(std::string const & diagnostic)
     557             : {
     558           6 :     guard g;
     559             : 
     560           3 :     f_nested_diagnostics.push_back(diagnostic);
     561           3 : }
     562             : 
     563             : 
     564           3 : void private_logger::pop_nested_diagnostic()
     565             : {
     566           6 :     guard g;
     567             : 
     568           3 :     f_nested_diagnostics.pop_back();
     569           3 : }
     570             : 
     571             : 
     572           8 : string_vector_t private_logger::get_nested_diagnostics() const
     573             : {
     574          16 :     guard g;
     575             : 
     576          16 :     return f_nested_diagnostics;
     577             : }
     578             : 
     579             : 
     580          61 : void private_logger::register_variable_factory(variable_factory::pointer_t factory)
     581             : {
     582         122 :     guard g;
     583             : 
     584          61 :     auto it(f_variable_factories.find(factory->get_type()));
     585          61 :     if(it != f_variable_factories.end())
     586             :     {
     587             :         throw duplicate_error(
     588             :                   "trying to add two variable factories of type \""
     589           2 :                 + factory->get_type()
     590           3 :                 + "\".");
     591             :     }
     592             : 
     593          60 :     f_variable_factories[factory->get_type()] = factory;
     594          60 : }
     595             : 
     596             : 
     597         218 : variable::pointer_t private_logger::get_variable(std::string const & type)
     598             : {
     599         436 :     guard g;
     600             : 
     601         218 :     if(f_variable_factories.empty())
     602             :     {
     603             :         throw invalid_variable("No variable factories were registered yet; you can't create a variable with type \""    // LCOV_EXCL_LINE
     604             :                              + type                                     // LCOV_EXCL_LINE
     605             :                              + "\" at this point.");                    // LCOV_EXCL_LINE
     606             :     }
     607             : 
     608         218 :     auto it(f_variable_factories.find(type));
     609         218 :     if(it == f_variable_factories.end())
     610             :     {
     611             :         // TBD: should we instead return a null var.?
     612             :         throw invalid_variable("You can't create variable with type \""
     613           2 :                              + type
     614           3 :                              + "\", no such variable type was registered.");
     615             :     }
     616             : 
     617         434 :     return it->second->create_variable();
     618             : }
     619             : 
     620             : 
     621       45816 : bool private_logger::has_functions() const
     622             : {
     623       91632 :     guard g;
     624             : 
     625       91632 :     return !f_functions.empty();
     626             : }
     627             : 
     628             : 
     629          23 : void private_logger::register_function(function::pointer_t func)
     630             : {
     631          46 :     guard g;
     632             : 
     633          23 :     auto it(f_functions.find(func->get_name()));
     634          23 :     if(it != f_functions.end())
     635             :     {
     636             :         throw duplicate_error(
     637             :                   "trying to add two functions named \""
     638           2 :                 + func->get_name()
     639           3 :                 + "\".");
     640             :     }
     641          22 :     f_functions[func->get_name()] = func;
     642          22 : }
     643             : 
     644             : 
     645          96 : function::pointer_t private_logger::get_function(std::string const & name) const
     646             : {
     647         192 :     guard g;
     648             : 
     649          96 :     auto it(f_functions.find(name));
     650          96 :     if(it != f_functions.end())
     651             :     {
     652          73 :         return it->second;
     653             :     }
     654             : 
     655          23 :     return function::pointer_t();
     656             : }
     657             : 
     658             : 
     659           1 : void private_logger::create_thread()
     660             : {
     661           2 :     guard g;
     662             : 
     663             :     try
     664             :     {
     665           1 :         f_fifo = std::make_shared<message_fifo_t>();
     666           1 :         f_asynchronous_logger = std::make_shared<detail::asynchronous_logger>(f_fifo);
     667           1 :         f_thread = std::make_shared<cppthread::thread>("asynchronous logger thread", f_asynchronous_logger.get());
     668           1 :         f_thread->start();
     669             :     }
     670             :     catch(...)                              // LCOV_EXCL_LINE
     671             :     {
     672             :         if(f_fifo != nullptr)               // LCOV_EXCL_LINE
     673             :         {
     674             :             f_fifo->done(false);            // LCOV_EXCL_LINE
     675             :         }
     676             : 
     677             :         f_thread.reset();                   // LCOV_EXCL_LINE
     678             :         f_asynchronous_logger.reset();      // LCOV_EXCL_LINE
     679             :         f_fifo.reset();                     // LCOV_EXCL_LINE
     680             :         throw;                              // LCOV_EXCL_LINE
     681             :     }
     682           1 : }
     683             : 
     684             : 
     685           5 : void private_logger::delete_thread()
     686             : {
     687             :     // WARNING: we can't call fifo::done() while our guard is locked
     688             :     //          we also have to make sure it's not a null pointer
     689             :     //
     690          10 :     message_fifo_t::pointer_t       fifo                = message_fifo_t::pointer_t();
     691          10 :     asynchronous_logger_pointer_t   asynchronous_logger = asynchronous_logger_pointer_t();
     692          10 :     cppthread::thread::pointer_t    thread              = cppthread::thread::pointer_t();
     693             : 
     694             :     {
     695          10 :         guard g;
     696             : 
     697           5 :         swap(thread,              f_thread);
     698           5 :         swap(asynchronous_logger, f_asynchronous_logger);
     699           5 :         swap(fifo,                f_fifo);
     700             :     }
     701             : 
     702           5 :     if(fifo != nullptr)
     703             :     {
     704           1 :         fifo->done(false);
     705             :     }
     706             : 
     707             :     try
     708             :     {
     709           5 :         thread.reset();
     710             :     }
     711             :     catch(std::exception const & e)
     712             :     {
     713             :         // in most cases this one happens when quitting when one of your
     714             :         // functions attempts to get an instance of the logger, which is
     715             :         // forbidden once you return from your main() function
     716             :         //
     717             :         std::cerr << "got exception \""
     718             :                   << e.what()
     719             :                   << "\" while deleting the asynchronous thread."
     720             :                   << std::endl;
     721             :     }
     722           5 : }
     723             : 
     724             : 
     725           1 : void private_logger::send_message_to_thread(message::pointer_t msg)
     726             : {
     727             :     {
     728           2 :         guard g;
     729             : 
     730           1 :         if(f_fifo == nullptr)
     731             :         {
     732           1 :             create_thread();
     733             :         }
     734             :     }
     735             : 
     736           1 :     f_fifo->push_back(msg);
     737           1 : }
     738             : 
     739             : 
     740             : 
     741             : 
     742       92213 : private_logger::pointer_t get_private_logger()
     743             : {
     744       92213 :     return std::dynamic_pointer_cast<private_logger>(logger::get_instance());
     745             : }
     746             : 
     747             : 
     748       45882 : private_logger::pointer_t get_private_logger(message const & msg)
     749             : {
     750       45882 :     return std::dynamic_pointer_cast<private_logger>(msg.get_logger());
     751             : }
     752             : 
     753             : 
     754             : 
     755           6 : } // snaplogger namespace
     756             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13