LCOV - code coverage report
Current view: top level - eventdispatcher - dispatcher_support.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 22 4.5 %
Date: 2019-08-10 01:48:51 Functions: 2 8 25.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2012-2019  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/eventdispatcher
       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
      17             : // along with this program; if not, write to the Free Software
      18             : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      19             : 
      20             : /** \file
      21             :  * \brief Implementation of the dispatcher_support class.
      22             :  *
      23             :  * The various connection classes that know how to handle a message derive
      24             :  * from this class. This means the message can then automatically get
      25             :  * dispatched.
      26             :  */
      27             : 
      28             : 
      29             : // self
      30             : //
      31             : #include    "eventdispatcher/dispatcher_support.h"
      32             : 
      33             : #include    "eventdispatcher/exception.h"
      34             : 
      35             : 
      36             : // snaplogger lib
      37             : //
      38             : #include    <snaplogger/message.h>
      39             : 
      40             : 
      41             : // last include
      42             : //
      43             : #include    <snapdev/poison.h>
      44             : 
      45             : 
      46             : 
      47             : namespace ed
      48             : {
      49             : 
      50             : 
      51             : 
      52             : /** \brief The destuctor.
      53             :  *
      54             :  * The destructor cleans up the dispatcher support object.
      55             :  */
      56           0 : dispatcher_support::~dispatcher_support()
      57             : {
      58           0 : }
      59             : 
      60             : 
      61             : /** \brief Define a dispatcher to execute your functions.
      62             :  *
      63             :  * The dispatcher to use to dispatch messages when received. The dispatch
      64             :  * happens by matching the command name with the dispatcher_match and
      65             :  * calling the corresponding function.
      66             :  *
      67             :  * If no match is found, then nothing gets executed by the dispatcher and
      68             :  * your default process_message() function gets called instead. If you
      69             :  * use a "match all" type of entry in your dispatcher, then your
      70             :  * process_message() function never gets called.
      71             :  *
      72             :  * \param[in] d  The pointer to your dispatcher object.
      73             :  */
      74           0 : void dispatcher_support::set_dispatcher(dispatcher_base::pointer_t d)
      75             : {
      76           0 :     f_dispatcher = d;
      77           0 : }
      78             : 
      79             : 
      80             : /** \brief Get the dispatcher used to execute your message functions.
      81             :  *
      82             :  * This function returns the dispatcher one set with the set_dispatcher()
      83             :  * function. It may be a nullptr.
      84             :  *
      85             :  * \warning
      86             :  * Note that it may return nullptr because the weak pointer was just
      87             :  * set to nullptr as the owner of the dispatcher was deleted.
      88             :  *
      89             :  * \return The pointer to the dispatcher used to execite messages or nullptr.
      90             :  */
      91           0 : dispatcher_base::pointer_t dispatcher_support::get_dispatcher() const
      92             : {
      93           0 :     return f_dispatcher.lock();
      94             : }
      95             : 
      96             : 
      97             : /** \brief Dispatcher the specified message.
      98             :  *
      99             :  * This dispatcher function searches for a function that matches the
     100             :  * command of the specified \p message.
     101             :  *
     102             :  * The dispatcher handles a vector of dispatcher_match structures each
     103             :  * of which defines a message that this daemon understands. The dispatch
     104             :  * is done on a match as determined the the f_match() static function.
     105             :  *
     106             :  * The function executes the f_execute() function on a match. If none of
     107             :  * the dispatcher_match entries match the input message, then the default
     108             :  * process resumes, which is to call the process_message() function. This
     109             :  * is done as a fallback and it should only be used if you want to be
     110             :  * able to handle very complex cases as in the snapcommunicator. In most
     111             :  * cases, having a function that handles your command(s) will be more
     112             :  * than enough.
     113             :  *
     114             :  * If you called the add_snap_communicator_commands() function on your
     115             :  * dispatcher, it won't be necessary to implement the process_message()
     116             :  * since it adds a last entry which is a "catch all" entry. This entry
     117             :  * uses the function that replies to the user with the UNKNOWN message.
     118             :  * Assuming you do not do anything extraordinary, you just need to
     119             :  * implement the ready() and stop() functions. If you have dynamic
     120             :  * commands that the default msg_help() wont' understand, then you
     121             :  * need to also implement the help() function.
     122             :  *
     123             :  * \param[in,out] message  The message being dispatched.
     124             :  *
     125             :  * \return true if the dispatcher handled the message, false if the
     126             :  *         process_message() function was called instead.
     127             :  */
     128           0 : bool dispatcher_support::dispatch_message(message & msg)
     129             : {
     130           0 :     auto d(f_dispatcher.lock());
     131           0 :     if(d != nullptr)
     132             :     {
     133             :         // we have a dispatcher installed, try to dispatch that message
     134             :         //
     135           0 :         if(d->dispatch(msg))
     136             :         {
     137           0 :             return true;
     138             :         }
     139             :     }
     140             : 
     141             :     // either there was no dispatcher installed or the message is
     142             :     // not in the list of messages handled by this dispatcher
     143             :     //
     144           0 :     process_message(msg);
     145             : 
     146           0 :     return false;
     147             : }
     148             : 
     149             : 
     150             : /** \brief A default implementation of the process_message() function.
     151             :  *
     152             :  * This function is adefault fallback for the process_message()
     153             :  * functionality. If you define a dispatcher, then you probably
     154             :  * won't need to define a process_message() which in most cases
     155             :  * would do the exact same thing but it would be called.
     156             :  *
     157             :  * This is especially true if you finish your list of matches
     158             :  * with the always_match() function and msg_reply_with_unknown()
     159             :  * as the function to run when that entry is hit.
     160             :  *
     161             :  * \code
     162             :  *      {
     163             :  *          nullptr
     164             :  *        , &dispatcher<my_connection>::dispatcher_match::msg_reply_with_unknown
     165             :  *        , &dispatcher<my_connection>::dispatcher_match::always_match
     166             :  *      },
     167             :  * \endcode
     168             :  *
     169             :  * \todo
     170             :  * Look into fixing this function so it can send the UNKNOWN message itself.
     171             :  * That way we'd avoid the last entry in the match array, which would allow
     172             :  * us to have binary search (much faster).
     173             :  *
     174             :  * \param[in] message  The message to be processed.
     175             :  */
     176           0 : void dispatcher_support::process_message(message const & msg)
     177             : {
     178             :     // We don't currently have access to the send_message() function from
     179             :     // here--the snap_inter_thread_message_connection class causes a problem
     180             :     // because it has two process_message() functions: process_message_a()
     181             :     // and process_message_b().
     182             :     //
     183             :     //snap::snap_communicator_message unknown;
     184             :     //unknown.reply_to(message);
     185             :     //unknown.set_command("UNKNOWN");
     186             :     //unknown.add_parameter("command", message.get_command());
     187             :     //if(!send_message(unknown, false))
     188             :     //{
     189             :     //    SNAP_LOG_WARNING("could not reply with UNKNOWN message to \"")(message.get_command())("\"");
     190             :     //}
     191             : 
     192             :     SNAP_LOG_FATAL
     193           0 :         << "process_message() with message \""
     194           0 :         << msg.to_message()
     195           0 :         << "\" was not reimplemented in your class and"
     196           0 :         << " the always_match() was not used in your dispatcher matches.";
     197             : 
     198             :     throw event_dispatcher_implementation_error(
     199             :               "your class is not reimplementing the process_message()"
     200             :               " virtual function and your dispatcher did not catch mnessage \""
     201           0 :             + msg.to_message()
     202           0 :             + "\".");
     203             : }
     204             : 
     205             : 
     206             : 
     207           6 : } // namespace ed
     208             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.12