summaryrefslogtreecommitdiffstats
path: root/src/bin/d2/d2_process.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/d2/d2_process.h')
-rw-r--r--src/bin/d2/d2_process.h324
1 files changed, 324 insertions, 0 deletions
diff --git a/src/bin/d2/d2_process.h b/src/bin/d2/d2_process.h
new file mode 100644
index 0000000..5ca3422
--- /dev/null
+++ b/src/bin/d2/d2_process.h
@@ -0,0 +1,324 @@
+// Copyright (C) 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef D2_PROCESS_H
+#define D2_PROCESS_H
+
+#include <d2/d2_queue_mgr.h>
+#include <d2/d2_update_mgr.h>
+#include <process/d_process.h>
+
+namespace isc {
+namespace d2 {
+
+/// @brief DHCP-DDNS Application Process
+///
+/// D2Process provides the top level application logic for DHCP-driven DDNS
+/// update processing. It provides the asynchronous event processing required
+/// to receive DNS mapping change requests and carry them out.
+/// It implements the DProcessBase interface, which structures it such that it
+/// is a managed "application", controlled by a management layer.
+class D2Process : public process::DProcessBase {
+public:
+
+ /// @brief Defines the shutdown types supported by D2Process
+ ///
+ /// * SD_NORMAL - Stops the queue manager and finishes all current
+ /// transactions before exiting. This is the default.
+ ///
+ /// * SD_DRAIN_FIRST - Stops the queue manager but continues processing
+ /// requests from the queue until it is empty.
+ ///
+ /// * SD_NOW - Exits immediately.
+ enum ShutdownType {
+ SD_NORMAL,
+ SD_DRAIN_FIRST,
+ SD_NOW
+ };
+
+ /// @brief Defines the point at which to resume receiving requests.
+ /// If the receive queue has become full, D2Process will "pause" the
+ /// reception of requests by putting the queue manager in the stopped
+ /// state. Once the number of entries has decreased to this percentage
+ /// of the maximum allowed, D2Process will "resume" receiving requests
+ /// by restarting the queue manager.
+ static const unsigned int QUEUE_RESTART_PERCENT;
+
+ /// @brief Constructor
+ ///
+ /// Construction creates the configuration manager, the queue
+ /// manager, and the update manager.
+ ///
+ /// @param name name is a text label for the process. Generally used
+ /// in log statements, but otherwise arbitrary.
+ /// @param io_service is the io_service used by the caller for
+ /// asynchronous event handling.
+ ///
+ /// @throw DProcessBaseError if io_service is NULL.
+ D2Process(const char* name, const asiolink::IOServicePtr& io_service);
+
+ /// @brief Called after instantiation to perform initialization unique to
+ /// D2.
+ ///
+ /// This is invoked by the controller after command line arguments but
+ /// PRIOR to configuration reception. The base class provides this method
+ /// as a place to perform any derivation-specific initialization steps
+ /// that are inappropriate for the constructor but necessary prior to
+ /// configure.
+ /// For D2 it is used to initialize the command manager.
+ virtual void init();
+
+ /// @brief Implements the process's event loop.
+ ///
+ /// Once entered, the main control thread remains inside this method
+ /// until shutdown. The event loop logic is as follows:
+ /// @code
+ /// while should not shutdown {
+ /// process queue manager state change
+ /// process completed jobs
+ /// dequeue new jobs
+ /// wait for IO event(s)
+ ///
+ /// ON an exception, exit with fatal error
+ /// }
+ /// @endcode
+ ///
+ /// To summarize, each pass through the event loop first checks the state
+ /// of the received queue and takes any steps required to ensure it is
+ /// operating in the manner necessary. Next the update manager is given
+ /// a chance to clean up any completed transactions and start new
+ /// transactions by dequeuing jobs from the request queue. Lastly, it
+ /// allows IOService to process until one or more event handlers are
+ /// called. Note that this last step will block until at least one
+ /// ready handler is invoked. In other words, if no IO events have occurred
+ /// since it was last called, the event loop will block at this step until
+ /// an IO event occurs. At that time we return to the top of the loop.
+ ///
+ /// @throw DProcessBaseError if an error is encountered. Note that
+ /// exceptions thrown at this point are assumed to be FATAL exceptions.
+ /// This includes exceptions generated but not caught by IO callbacks.
+ /// Services which rely on callbacks are expected to be well behaved and
+ /// any errors they encounter handled internally.
+ virtual void run();
+
+ /// @brief Initiates the D2Process shutdown process.
+ ///
+ /// This is last step in the shutdown event callback chain. It is invoked
+ /// to notify D2Process that it needs to begin its shutdown procedure.
+ /// Note that shutting down may be neither instantaneous nor synchronous,
+ /// This method records the request for and the type of shutdown desired.
+ /// Generally it will require one or more subsequent events to complete,
+ /// dependent on the type of shutdown requested. The type of shutdown is
+ /// specified as an optional argument of the shutdown command. The types
+ /// of shutdown supported are:
+ ///
+ /// * "normal" - Stops the queue manager and finishes all current
+ /// transactions before exiting. This is the default.
+ ///
+ /// * "drain_first" - Stops the queue manager but continues processing
+ /// requests from the queue until it is empty.
+ ///
+ /// * "now" - Exits immediately.
+ ///
+ /// @param args Specifies the shutdown "type" as "normal", "drain_first",
+ /// or "now"
+ ///
+ /// @return an Element that contains the results of argument processing,
+ /// consisting of an integer status value (0 means successful,
+ /// non-zero means failure), and a string explanation of the outcome.
+ virtual isc::data::ConstElementPtr
+ shutdown(isc::data::ConstElementPtr args);
+
+ /// @brief Processes the given configuration.
+ ///
+ /// This method may be called multiple times during the process lifetime.
+ /// Certainly once during process startup, and possibly later if the user
+ /// alters the configuration. This method must not throw, it should catch any
+ /// processing errors and return a success or failure answer as described
+ /// below.
+ ///
+ /// This method passes the newly received configuration to the configuration
+ /// manager instance for parsing. The configuration manager parses the
+ /// configuration and updates the necessary values within the context,
+ /// assuming it parses correctly. If that's the case this method sets the
+ /// flag to reconfigure the queue manager and returns a successful response
+ /// as described below.
+ ///
+ /// If the new configuration fails to parse, then the current configuration
+ /// is retained and a failure response is returned as described below.
+ ///
+ /// @param config_set a new configuration (JSON) for the process
+ /// @param check_only true if configuration is to be verified only, not applied
+ /// @return an Element that contains the results of configuration composed
+ /// of an integer status value (0 means successful, non-zero means failure),
+ /// and a string explanation of the outcome.
+ virtual isc::data::ConstElementPtr
+ configure(isc::data::ConstElementPtr config_set,
+ bool check_only = false);
+
+ /// @brief Destructor
+ virtual ~D2Process();
+
+protected:
+ /// @brief Monitors current queue manager state, takes action accordingly
+ ///
+ /// This method ensures that the queue manager transitions to the state
+ /// most appropriate to the operational state of the D2Process and any
+ /// events that may have occurred since it was last called. It is called
+ /// once for each iteration of the event loop. It is essentially a
+ /// switch statement based on the D2QueueMgr's current state. The logic
+ /// is as follows:
+ ///
+ /// If the state is D2QueueMgr::RUNNING, and the queue manager needs to be
+ /// reconfigured or we have been told to shutdown, then instruct the queue
+ /// manager to stop listening. Exit the method.
+ ///
+ /// If the state is D2QueueMgr::STOPPED_QUEUE_FULL, then check if the
+ /// number of entries in the queue has fallen below the "resume threshold".
+ /// If it has, then instruct the queue manager to start listening. Exit
+ /// the method.
+ ///
+ /// If the state is D2QueueMgr::STOPPED_RECV_ERROR, then attempt to recover
+ /// by calling reconfigureQueueMgr(). Exit the method.
+ ///
+ /// If the state is D2QueueMgr::STOPPING, simply exit the method. This is
+ /// a NOP condition as we are waiting for the IO cancel event
+ ///
+ /// For any other state, (NOT_INITTED,INITTED,STOPPED), if the reconfigure
+ /// queue flag is set, call reconfigureQueueMgr(). Exit the method.
+ ///
+ /// This method is exception safe.
+ virtual void checkQueueStatus();
+
+ /// @brief Initializes then starts the queue manager.
+ ///
+ /// This method initializes the queue manager with the current
+ /// configuration parameters and instructs it to start listening.
+ /// Note the existing listener instance (if it exists) is destroyed,
+ /// and that a new listener is created during initialization.
+ ///
+ /// This method is exception safe.
+ virtual void reconfigureQueueMgr();
+
+ /// @brief Allows IO processing to run until at least callback is invoked.
+ ///
+ /// This method is called from within the D2Process main event loop and is
+ /// the point at which the D2Process blocks, waiting for IO events to
+ /// cause IO event callbacks to be invoked.
+ ///
+ /// If callbacks are ready to be executed upon entry, the method will
+ /// return as soon as these callbacks have completed. If no callbacks
+ /// are ready, then it will wait (indefinitely) until at least one callback
+ /// is executed.
+ ///
+ /// @note: Should become desirable to periodically force an
+ /// event, an interval timer could be used to do so.
+ ///
+ /// @return The number of callback handlers executed, or 0 if the IO
+ /// service has been stopped.
+ ///
+ /// @throw This method does not throw directly, but the execution of
+ /// callbacks invoked in response to IO events might. If so, these
+ /// will propagate upward out of this method.
+ virtual size_t runIO();
+
+ /// @brief Indicates whether or not the process can perform a shutdown.
+ ///
+ /// Determines if the process has been instructed to shutdown and if
+ /// the criteria for performing the type of shutdown requested has been
+ /// met.
+ ///
+ /// @return Returns true if the criteria has been met, false otherwise.
+ virtual bool canShutdown() const;
+
+ /// @brief Sets queue reconfigure indicator to the given value.
+ ///
+ /// @param value is the new value to assign to the indicator
+ ///
+ /// @note this method is really only intended for testing purposes.
+ void setReconfQueueFlag(const bool value) {
+ reconf_queue_flag_ = value;
+ }
+
+ /// @brief Sets the shutdown type to the given value.
+ ///
+ /// @param value is the new value to assign to shutdown type.
+ ///
+ /// @note this method is really only intended for testing purposes.
+ void setShutdownType(const ShutdownType& value) {
+ shutdown_type_ = value;
+ }
+
+ /// @brief (Re-)Configure the command channel.
+ ///
+ /// Only close the current channel, if the new channel configuration is
+ /// different. This avoids disconnecting a client and hence not sending
+ /// them a command result, unless they specifically alter the channel
+ /// configuration. In that case the user simply has to accept they'll
+ /// be disconnected.
+ void reconfigureCommandChannel();
+
+public:
+ /// @brief Returns a pointer to the configuration manager.
+ /// Note, this method cannot return a reference as it uses dynamic
+ /// pointer casting of the base class configuration manager.
+ D2CfgMgrPtr getD2CfgMgr();
+
+ /// @brief Returns a reference to the queue manager.
+ const D2QueueMgrPtr& getD2QueueMgr() const {
+ return (queue_mgr_);
+ }
+
+ /// @brief Returns a reference to the update manager.
+ const D2UpdateMgrPtr& getD2UpdateMgr() const {
+ return (update_mgr_);
+ }
+
+ /// @brief Returns true if the queue manager should be reconfigured.
+ bool getReconfQueueFlag() const {
+ return (reconf_queue_flag_);
+ }
+
+ /// @brief Returns the type of shutdown requested.
+ ///
+ /// Note, this value is meaningless unless shouldShutdown() returns true.
+ ShutdownType getShutdownType() const {
+ return (shutdown_type_);
+ }
+
+ /// @brief Returns a text label for the given shutdown type.
+ ///
+ /// @param type the numerical shutdown type for which the label is desired.
+ ///
+ /// @return A text label corresponding the value or "invalid" if the
+ /// value is not a valid value.
+ static const char* getShutdownTypeStr(const ShutdownType& type);
+
+private:
+ /// @brief Pointer to our queue manager instance.
+ D2QueueMgrPtr queue_mgr_;
+
+ /// @brief Pointer to our update manager instance.
+ D2UpdateMgrPtr update_mgr_;
+
+ /// @brief Indicates if the queue manager should be reconfigured.
+ bool reconf_queue_flag_;
+
+ /// @brief Indicates the type of shutdown requested.
+ ShutdownType shutdown_type_;
+
+ /// @brief Current socket control configuration.
+ isc::data::ConstElementPtr current_control_socket_;
+
+};
+
+/// @brief Defines a shared pointer to D2Process.
+typedef boost::shared_ptr<D2Process> D2ProcessPtr;
+
+}; // namespace isc::d2
+}; // namespace isc
+
+#endif