| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 | // \file service.hpp
//
// Copyright (C) 2014 MicroNeil Research Corporation.
//
// This program is part of the MicroNeil Research Open Library Project. For
// more information go to http://www.microneil.com/OpenLibrary/index.html
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the Free Software Foundation, Inc., 59 Temple
// Place, Suite 330, Boston, MA 02111-1307 USA
//==============================================================================
/*
  \brief The service module provides a framework for implementing *nix
  daemons and Windows services.
*/
#ifndef SERVICE_HPP
#define SERVICE_HPP
#include <string>
#include <vector>
#include <mutex>
namespace CodeDweller {
  /** Singleton class that implements a daemon (*nix) or service
      (Windows).
      This class implements a *nix daemon or a Windows service.
      To implement a daemon or service, implement the required methods
      of this class, and link with service.cpp.  When compiled under
      *nix, the file service.cpp contains the definition of main for
      the *nix daemon.  When compiled under Windows, the file
      service.cpp contains the entry points for the Windows service.
      Nomenclature:
      <ol>
        <li>Service is a *nix daemon or Windows service.</li>
	<li>Message is a posix signal or Windows message.  This class
	supports the following messages:
	  <ol>
	    <li>Pause.  This is the posix TSTP signal or Windows Pause
	    message.  This instructs the service to temporarily stop
	    running.</li>
	    <li>Resume.  This is the posix CONT signal or Windows
	    Resume message.  This instructs the service to resume
	    running after receiving a Pause message.  If the service
	    isn't temporarily stopped after receiving a Pause message,
	    the Resume message has no effect.</li>
	    <li>Restart.  This is the posix HUP signal or Windows
	    Restart message.  This instructs the service to shut down
	    and restart.</li>
	    <li>Stop.  This is the posix TERM signal or Windows Stop
	    message.  This instructs the service to shut down and
	    exit.</li>
	  </ol>
	</li>
	<li>Callback.  This is a function that is executed when a
	message is received.</li>
      </ol>
  */
  class Service
  {
  public:
    /// Get the instance of the singleton.
    //
    // \returns a reference to the singleton.
    //
    static Service& getInstance();
    /// Callback functor interface.
    class Callback {
    public:
      /// Callback method.
      virtual void operator()() = 0;
    };
    /// Main entry point.
    //
    // \param[in] argc is the number of arguments.
    //
    // \param[in] argv is an array of strings containing the
    // command-line arguments.  The end of the array is indicated by a
    // null pointer.
    //
    // \returns exit code of the service.
    //
    int main(int argc, char *argv[]);
    /// Register a callback for receipt of Pause.
    //
    // \param[in] pauseFunctor is the function object to invoke when
    // Pause is received.
    //
    void onPauseCall(Callback &pauseFunctor);
    /// Register a callback for receipt of Resume.
    //
    // \param[in] resumeFunctor is the function object to invoke when
    // Resume is received.
    //
    void onResumeCall(Callback &resumeFunctor);
    /// Register a callback for receipt of Restart.
    //
    // \param[in] restartFunctor is the function object to invoke when
    // Restart is received.
    //
    void onRestartCall(Callback &restartFunctor);
    /// Register a callback for receipt of Stop.
    //
    // \param[in] stopFunctor is the function object to invoke when
    // Stop is received.
    //
    void onStopCall(Callback &stopFunctor);
    /// Check whether Pause was received.
    //
    // \returns if the Pause message was received, false otherwise.
    //
    bool receivedPause();
    /// Check whether Resume was received.
    //
    // \returns if the Resume message was received, false otherwise.
    //
    bool receivedResume();
    /// Check whether Restart was received.
    //
    // \returns if the Restart message was received, false otherwise.
    //
    bool receivedRestart();
    /// Check whether the last message received was Stop.
    //
    // \returns true if Stop was the most recent message received,
    // false otherwise.
    //
    bool receivedStop();
    /// Clear receiving the Pause message.
    void clearReceivedPause();
    /// Clear receiving the Resume message.
    void clearReceivedResume();
    /// Clear receiving the Restart message.
    void clearReceivedRestart();
    /// Clear receiving the Stop message.
    void clearReceivedStop();
    /// Get a reference to the command-line arguments.
    //
    // \returns a reference to the vector of command-line arguments of
    // the application.  Index i corresponds to command-line argument
    // i.
    //
    const std::vector<std::string> &arguments();
  private:
    /// Private constructor prevents instantiation.
    Service();
    /// Prevent copying.
    Service(Service const&) {}
    /// Prevent assignment.
    void operator=(Service const&) {}
    /// Load the command-line arguments.
    //
    // This method loads the object with the command-line parameters.
    //
    // \param[in] argc is the number of arguments.
    //
    // \param[in] argv is an array of strings containing the
    // command-line arguments.  The end of the array is indicated by a
    // null pointer.
    //
    void loadArguments(int argc, char *argv[]);
    /// Initialize and run the application.
    //
    // \returns the exit status of the service.
    //
    int run();
    /// Mutex to serialize access to the object.
    static std::mutex objectMutex;
    /// Thread start function to receive messages.
    void processMessages();
    /// Command-line arguments.
    std::vector<std::string> cmdLineArgs;
    /// Enumeration specifying the most recent message received.
    enum class Message {
      Pause,
	Resume,
	Restart,
	Stop,
	None
	};
    /// True if Pause message was received.
    bool pauseReceived;
    /// True if Resume message was received.
    bool resumeReceived;
    /// True if Restart message was received.
    bool restartReceived;
    /// True if Stop message was received.
    bool stopReceived;
    /// Functions to invoke when the Pause is received.
    std::vector<Callback *> pauseCallbacks;
    /// Functions to invoke when the Resume is received.
    std::vector<Callback *> resumeCallbacks;
    /// Functions to invoke when the Restart is received.
    std::vector<Callback *> restartCallbacks;
    /// Functions to invoke when the Stop is received.
    std::vector<Callback *> stopCallbacks;
    /// Set of signals to wait for.
    sigset_t signalSet;
  };
}
#endif // SERVICE_HPP
 |