LogCabin
Server/Globals.h
Go to the documentation of this file.
00001 /* Copyright (c) 2012 Stanford University
00002  * Copyright (c) 2015 Diego Ongaro
00003  *
00004  * Permission to use, copy, modify, and distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
00009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
00011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 #include <memory>
00018 
00019 #include "Client/SessionManager.h"
00020 #include "Core/Config.h"
00021 #include "Core/Mutex.h"
00022 #include "Event/Loop.h"
00023 #include "Event/Signal.h"
00024 #include "Server/ServerStats.h"
00025 
00026 #ifndef LOGCABIN_SERVER_GLOBALS_H
00027 #define LOGCABIN_SERVER_GLOBALS_H
00028 
00029 namespace LogCabin {
00030 
00031 // forward declarations
00032 namespace RPC {
00033 class Server;
00034 }
00035 
00036 namespace Server {
00037 
00038 // forward declarations
00039 class ClientService;
00040 class ControlService;
00041 class RaftConsensus;
00042 class RaftService;
00043 class StateMachine;
00044 
00045 /**
00046  * Holds the LogCabin daemon's top-level objects.
00047  * The purpose of main() is to create and run a Globals object.
00048  * Other classes may refer to this object if they need access to other
00049  * top-level objects.
00050  */
00051 class Globals {
00052   private:
00053     /**
00054      * Exits from the event loop upon receiving a UNIX signal.
00055      */
00056     class ExitHandler : public Event::Signal {
00057       public:
00058         ExitHandler(Event::Loop& eventLoop, int signalNumber);
00059         void handleSignalEvent();
00060         Event::Loop& eventLoop;
00061     };
00062 
00063     /**
00064      * Re-opens the log file upon receiving a UNIX signal.
00065      */
00066     class LogRotateHandler : public Event::Signal {
00067       public:
00068         LogRotateHandler(Event::Loop& eventLoop, int signalNumber);
00069         void handleSignalEvent();
00070         Event::Loop& eventLoop;
00071     };
00072 
00073   public:
00074 
00075     /// Constructor.
00076     Globals();
00077 
00078     /// Destructor.
00079     ~Globals();
00080 
00081     /**
00082      * Finish initializing this object.
00083      * This should be called after #config has been filled in.
00084      */
00085     void init();
00086 
00087     /**
00088      * Leave the signals blocked when this object is destroyed.
00089      * This is used in Server/Main.cc for the long-running daemon; it's not
00090      * used in unit tests.
00091      *
00092      * This was added to work around a specific problem: when running the
00093      * servers under valgrind through cluster.py, the servers would receive
00094      * SIGTERM, start to shut down, then the instant the SIGTERM signal was
00095      * unmasked, the server would appear to exit with a 0 status, yet it
00096      * wouldn't finish the shutdown process. I couldn't reproduce this outside
00097      * of cluster.py. As there's no reason to unblock the signals before
00098      * exiting the daemon, this seems like the safer bet for now.
00099      * -Diego 2015-04-29
00100      */
00101     void leaveSignalsBlocked();
00102 
00103     /**
00104      * Run the event loop until SIGINT, SIGTERM, or someone calls
00105      * Event::Loop::exit().
00106      */
00107     void run();
00108 
00109     /**
00110      * Enable asynchronous signal delivery for all signals that this class is
00111      * in charge of. This should be called in a child process after invoking
00112      * fork(), as the StateMachine does.
00113      */
00114     void unblockAllSignals();
00115 
00116     /**
00117      * Global configuration options.
00118      */
00119     Core::Config config;
00120 
00121     /**
00122      * Statistics and information about the server's current state. Useful for
00123      * diagnostics.
00124      */
00125     Server::ServerStats serverStats;
00126 
00127     /**
00128      * The event loop that runs the RPC system.
00129      */
00130     Event::Loop eventLoop;
00131 
00132   private:
00133     /**
00134      * Block SIGINT, which is handled by sigIntHandler.
00135      * Signals are blocked early on in the startup process so that newly
00136      * spawned threads also have them blocked.
00137      */
00138     Event::Signal::Blocker sigIntBlocker;
00139 
00140     /**
00141      * Block SIGTERM, which is handled by sigTermHandler.
00142      */
00143     Event::Signal::Blocker sigTermBlocker;
00144 
00145     /**
00146      * Block SIGUSR1, which is handled by serverStats.
00147      */
00148     Event::Signal::Blocker sigUsr1Blocker;
00149 
00150     /**
00151      * Block SIGUSR2, which is handled by sigUsr2Handler.
00152      */
00153     Event::Signal::Blocker sigUsr2Blocker;
00154 
00155     /**
00156      * Exits the event loop upon receiving SIGINT (keyboard interrupt).
00157      */
00158     ExitHandler sigIntHandler;
00159 
00160     /**
00161      * Registers sigIntHandler with the event loop.
00162      */
00163     Event::Signal::Monitor sigIntMonitor;
00164 
00165     /**
00166      * Exits the event loop upon receiving SIGTERM (kill).
00167      */
00168     ExitHandler sigTermHandler;
00169 
00170     /**
00171      * Registers sigTermHandler with the event loop.
00172      */
00173     Event::Signal::Monitor sigTermMonitor;
00174 
00175     /**
00176      * Re-opens log files upon receiving SIGUSR2 (user-defined signal). This
00177      * should normally be invoked by tools like logrotate.
00178      */
00179     LogRotateHandler sigUsr2Handler;
00180 
00181     /**
00182      * Registers sigUsr2Handler with the event loop.
00183      */
00184     Event::Signal::Monitor sigUsr2Monitor;
00185 
00186   public:
00187     /**
00188      * A unique ID for the cluster that this server may connect to. This is
00189      * initialized to a value from the config file. If it's not set then, it
00190      * may be set later as a result of learning a UUID from some other server.
00191      */
00192     Client::SessionManager::ClusterUUID clusterUUID;
00193 
00194     /**
00195      * Unique ID for this server. Set from config file.
00196      */
00197     uint64_t serverId;
00198 
00199     /**
00200      * Consensus module.
00201      */
00202     std::shared_ptr<Server::RaftConsensus> raft;
00203 
00204     /**
00205      * State machine used to process client requests.
00206      */
00207     std::shared_ptr<Server::StateMachine> stateMachine;
00208 
00209   private:
00210 
00211     /**
00212      * Service used by logcabinctl to query and change a server's internal
00213      * state.
00214      */
00215     std::shared_ptr<Server::ControlService> controlService;
00216 
00217     /**
00218      * Service used to communicate between servers.
00219      */
00220     std::shared_ptr<Server::RaftService> raftService;
00221 
00222     /**
00223      * The application-facing facing RPC service.
00224      */
00225     std::shared_ptr<Server::ClientService> clientService;
00226 
00227     /**
00228      * Listens for inbound RPCs and passes them off to the services.
00229      */
00230     std::unique_ptr<RPC::Server> rpcServer;
00231 
00232     // Globals is non-copyable.
00233     Globals(const Globals&) = delete;
00234     Globals& operator=(const Globals&) = delete;
00235 
00236 }; // class Globals
00237 
00238 } // namespace LogCabin::Server
00239 } // namespace LogCabin
00240 
00241 #endif /* LOGCABIN_SERVER_GLOBALS_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines