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

Generated by: LCOV version 1.12