d_cfg_mgr.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. // Copyright (C) 2013-2016 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #ifndef D_CFG_MGR_H
  7. #define D_CFG_MGR_H
  8. #include <cc/data.h>
  9. #include <exceptions/exceptions.h>
  10. #include <dhcpsrv/parsers/dhcp_parsers.h>
  11. #include <stdint.h>
  12. #include <string>
  13. // Undefine the macro OPTIONAL which is defined in some operating
  14. // systems but conflicts with class constant is the context base class.
  15. #ifdef OPTIONAL
  16. #undef OPTIONAL
  17. #endif
  18. namespace isc {
  19. namespace process {
  20. /// @brief Defines a map of ConstElementPtrs keyed by name
  21. typedef std::map<std::string, isc::data::ConstElementPtr> ElementMap;
  22. /// @brief Exception thrown if the configuration manager encounters an error.
  23. class DCfgMgrBaseError : public isc::Exception {
  24. public:
  25. DCfgMgrBaseError(const char* file, size_t line, const char* what) :
  26. isc::Exception(file, line, what) { };
  27. };
  28. class DCfgContextBase;
  29. /// @brief Pointer to a configuration context.
  30. typedef boost::shared_ptr<DCfgContextBase> DCfgContextBasePtr;
  31. /// @brief Abstract class that implements a container for configuration context.
  32. /// It provides a single enclosure for the storage of configuration parameters
  33. /// and any other context specific information that needs to be accessible
  34. /// during configuration parsing as well as to the application as a whole.
  35. /// The base class supports storage for a small set of simple data types.
  36. /// Derivations simply add additional storage as needed. Note that this class
  37. /// declares the pure virtual clone() method, its copy constructor is protected,
  38. /// and its copy operator is inaccessible. Derivations must supply an
  39. /// implementation of clone that calls the base class copy constructor.
  40. /// This allows the management class to perform context backup and restoration
  41. /// without derivation specific knowledge using logic like
  42. /// the following:
  43. ///
  44. /// // Make a backup copy
  45. /// DCfgContextBasePtr backup_copy(context_->clone());
  46. /// :
  47. /// // Restore from backup
  48. /// context_ = backup_copy;
  49. ///
  50. class DCfgContextBase {
  51. public:
  52. /// @brief Indicator that a configuration parameter is optional.
  53. static const bool OPTIONAL = true;
  54. static const bool REQUIRED = false;
  55. /// @brief Constructor
  56. DCfgContextBase();
  57. /// @brief Destructor
  58. virtual ~DCfgContextBase();
  59. /// @brief Fetches the value for a given boolean configuration parameter
  60. /// from the context.
  61. ///
  62. /// @param name is the name of the parameter to retrieve.
  63. /// @param value is an output parameter in which to return the retrieved
  64. /// value.
  65. /// @param optional if true, the parameter is optional and the method
  66. /// will not throw if the parameter is not found in the context. The
  67. /// contents of the output parameter, value, will not be altered.
  68. /// It defaults to false if not specified.
  69. ///
  70. /// @return The parameter's element's position information if found,
  71. /// otherwise it returns isc::data::Element::ZERO_POSITION().
  72. ///
  73. /// @throw throws DhcpConfigError if the context does not contain the
  74. /// parameter and optional is false.
  75. const data::Element::Position&
  76. getParam(const std::string& name, bool& value, bool optional=false);
  77. /// @brief Fetches the value for a given uint32_t configuration parameter
  78. /// from the context.
  79. ///
  80. /// @param name is the name of the parameter to retrieve.
  81. /// @param value is an output parameter in which to return the retrieved
  82. /// value.
  83. /// @param optional if true, the parameter is optional and the method
  84. /// will not throw if the parameter is not found in the context. The
  85. /// contents of the output parameter, value, will not be altered.
  86. ///
  87. /// @return The parameter's element's position information if found,
  88. /// otherwise it returns isc::data::Element::ZERO_POSITION().
  89. ///
  90. /// @throw throws DhcpConfigError if the context does not contain the
  91. /// parameter and optional is false.
  92. const data::Element::Position&
  93. getParam(const std::string& name, uint32_t& value,
  94. bool optional=false);
  95. /// @brief Fetches the value for a given string configuration parameter
  96. /// from the context.
  97. ///
  98. /// @param name is the name of the parameter to retrieve.
  99. /// @param value is an output parameter in which to return the retrieved
  100. /// value.
  101. /// @param optional if true, the parameter is optional and the method
  102. /// will not throw if the parameter is not found in the context. The
  103. /// contents of the output parameter, value, will not be altered.
  104. ///
  105. /// @return The parameter's element's position information if found,
  106. /// otherwise it returns isc::data::Element::ZERO_POSITION().
  107. ///
  108. /// @throw throws DhcpConfigError if the context does not contain the
  109. /// parameter and optional is false.
  110. const data::Element::Position&
  111. getParam(const std::string& name, std::string& value,
  112. bool optional=false);
  113. /// @brief Fetches the Boolean Storage. Typically used for passing
  114. /// into parsers.
  115. ///
  116. /// @return returns a pointer to the Boolean Storage.
  117. isc::dhcp::BooleanStoragePtr getBooleanStorage() {
  118. return (boolean_values_);
  119. }
  120. /// @brief Fetches the uint32 Storage. Typically used for passing
  121. /// into parsers.
  122. ///
  123. /// @return returns a pointer to the uint32 Storage.
  124. isc::dhcp::Uint32StoragePtr getUint32Storage() {
  125. return (uint32_values_);
  126. }
  127. /// @brief Fetches the string Storage. Typically used for passing
  128. /// into parsers.
  129. ///
  130. /// @return returns a pointer to the string Storage.
  131. isc::dhcp::StringStoragePtr getStringStorage() {
  132. return (string_values_);
  133. }
  134. /// @brief Creates a clone of this context object.
  135. ///
  136. /// As mentioned in the the class brief, derivation must supply an
  137. /// implementation that initializes the base class storage as well as its
  138. /// own. Typically the derivation's clone method would return the result
  139. /// of passing "*this" into its own copy constructor:
  140. ///
  141. /// @code
  142. /// class DStubContext : public DCfgContextBase {
  143. /// public:
  144. /// :
  145. /// // Clone calls its own copy constructor
  146. /// virtual DCfgContextBasePtr clone() {
  147. /// return (DCfgContextBasePtr(new DStubContext(*this)));
  148. /// }
  149. ///
  150. /// // Note that the copy constructor calls the base class copy ctor
  151. /// // then initializes its additional storage.
  152. /// DStubContext(const DStubContext& rhs) : DCfgContextBase(rhs),
  153. /// extra_values_(new Uint32Storage(*(rhs.extra_values_))) {
  154. /// }
  155. /// :
  156. /// // Here's the derivation's additional storage.
  157. /// isc::dhcp::Uint32StoragePtr extra_values_;
  158. /// :
  159. /// @endcode
  160. ///
  161. /// @return returns a pointer to the new clone.
  162. virtual DCfgContextBasePtr clone() = 0;
  163. protected:
  164. /// @brief Copy constructor for use by derivations in clone().
  165. DCfgContextBase(const DCfgContextBase& rhs);
  166. private:
  167. /// @brief Private assignment operator to avoid potential for slicing.
  168. DCfgContextBase& operator=(const DCfgContextBase& rhs);
  169. /// @brief Storage for boolean parameters.
  170. isc::dhcp::BooleanStoragePtr boolean_values_;
  171. /// @brief Storage for uint32 parameters.
  172. isc::dhcp::Uint32StoragePtr uint32_values_;
  173. /// @brief Storage for string parameters.
  174. isc::dhcp::StringStoragePtr string_values_;
  175. };
  176. /// @brief Defines a sequence of Element IDs used to specify a parsing order.
  177. typedef std::vector<std::string> ElementIdList;
  178. /// @brief Configuration Manager
  179. ///
  180. /// DCfgMgrBase is an abstract class that provides the mechanisms for managing
  181. /// an application's configuration. This includes services for parsing sets of
  182. /// configuration values, storing the parsed information in its converted form,
  183. /// and retrieving the information on demand. It is intended to be the worker
  184. /// class which is handed a set of configuration values to process by upper
  185. /// application management layers.
  186. ///
  187. /// The class presents a public method for receiving new configurations,
  188. /// parseConfig. This method coordinates the parsing effort as follows:
  189. ///
  190. /// @code
  191. /// make backup copy of configuration context
  192. /// Split top-level configuration elements into to sets:
  193. /// 1. Set of scalar elements (strings, booleans, ints, etc..)
  194. /// 2. Set of object elements (maps, lists, etc...)
  195. /// For each entry in the scalar set:
  196. /// get derivation-specific parser for element
  197. /// run parser
  198. /// update context with parsed results
  199. /// break on error
  200. ///
  201. /// For each entry in the object set;
  202. /// get derivation-specific parser for element
  203. /// run parser
  204. /// update context with parsed results
  205. /// break on error
  206. ///
  207. /// if an error occurred
  208. /// restore configuration context from backup
  209. /// @endcode
  210. ///
  211. /// The above structuring ensures that global parameters are parsed first
  212. /// making them available during subsequent object element parsing. The order
  213. /// in which the object elements are processed is either:
  214. ///
  215. /// 1. Natural order presented by the configuration set
  216. /// 2. Specific order determined by a list of element ids
  217. ///
  218. /// This allows a derivation to specify the order in which its elements are
  219. /// parsed if there are dependencies between elements.
  220. ///
  221. /// To parse a given element, its id is passed into createConfigParser,
  222. /// which returns an instance of the appropriate parser. This method is
  223. /// abstract so the derivation's implementation determines the type of parser
  224. /// created. This isolates the knowledge of specific element ids and which
  225. /// application specific parsers to derivation.
  226. ///
  227. /// Once the parser has been created, it is used to parse the data value
  228. /// associated with the element id and update the context with the parsed
  229. /// results.
  230. ///
  231. /// In the event that an error occurs, parsing is halted and the
  232. /// configuration context is restored from backup.
  233. class DCfgMgrBase {
  234. public:
  235. /// @brief Constructor
  236. ///
  237. /// @param context is a pointer to the configuration context the manager
  238. /// will use for storing parsed results.
  239. ///
  240. /// @throw throws DCfgMgrBaseError if context is null
  241. DCfgMgrBase(DCfgContextBasePtr context);
  242. /// @brief Destructor
  243. virtual ~DCfgMgrBase();
  244. /// @brief Acts as the receiver of new configurations and coordinates
  245. /// the parsing as described in the class brief.
  246. ///
  247. /// @param config_set is a set of configuration elements to parsed.
  248. ///
  249. /// @return an Element that contains the results of configuration composed
  250. /// of an integer status value (0 means successful, non-zero means failure),
  251. /// and a string explanation of the outcome.
  252. isc::data::ConstElementPtr parseConfig(isc::data::ConstElementPtr
  253. config_set);
  254. /// @brief Adds a given element id to the end of the parse order list.
  255. ///
  256. /// The order in which object elements are retrieved from this is the
  257. /// order in which they are added to the list. Derivations should use this
  258. /// method to populate the parse order as part of their constructor.
  259. /// Scalar parameters should NOT be included in this list.
  260. ///
  261. /// @param element_id is the string name of the element as it will appear
  262. /// in the configuration set.
  263. void addToParseOrder(const std::string& element_id){
  264. parse_order_.push_back(element_id);
  265. }
  266. /// @brief Fetches the parse order list.
  267. ///
  268. /// @return returns a const reference to the list.
  269. const ElementIdList& getParseOrder() const {
  270. return (parse_order_);
  271. }
  272. /// @brief Fetches the configuration context.
  273. ///
  274. /// @return returns a pointer reference to the configuration context.
  275. DCfgContextBasePtr& getContext() {
  276. return (context_);
  277. }
  278. /// @brief Returns configuration summary in the textual format.
  279. ///
  280. /// This method returns the brief text describing the current configuration.
  281. /// It may be used for logging purposes, e.g. whn the new configuration is
  282. /// committed to notify a user about the changes in configuration.
  283. ///
  284. /// @param selection Bitfield which describes the parts of the configuration
  285. /// to be returned.
  286. ///
  287. /// @return Summary of the configuration in the textual format.
  288. virtual std::string getConfigSummary(const uint32_t selection) = 0;
  289. protected:
  290. /// @brief Parses a set of scalar configuration elements into global
  291. /// parameters
  292. ///
  293. /// For each scalar element in the set:
  294. /// - create a parser for the element
  295. /// - invoke the parser's build method
  296. /// - invoke the parser's commit method
  297. ///
  298. /// This will commit the values to context storage making them accessible
  299. /// during object parsing.
  300. ///
  301. /// @param params_config set of scalar configuration elements to parse
  302. virtual void buildParams(isc::data::ConstElementPtr params_config);
  303. /// @brief Create a parser instance based on an element id.
  304. ///
  305. /// Given an element_id returns an instance of the appropriate parser.
  306. /// This method is abstract, isolating any direct knowledge of element_ids
  307. /// and parsers to within the application-specific derivation.
  308. ///
  309. /// @param element_id is the string name of the element as it will appear
  310. /// in the configuration set.
  311. /// @param pos position within the configuration text (or file) of element
  312. /// to be parsed. This is passed for error messaging.
  313. ///
  314. /// @return returns a ParserPtr to the parser instance.
  315. /// @throw throws DCfgMgrBaseError if an error occurs.
  316. virtual isc::dhcp::ParserPtr
  317. createConfigParser(const std::string& element_id,
  318. const isc::data::Element::Position& pos
  319. = isc::data::Element::Position()) = 0;
  320. /// @brief Abstract factory which creates a context instance.
  321. ///
  322. /// This method is used at the beginning of configuration process to
  323. /// create a fresh, empty copy of the derivation-specific context. This
  324. /// new context will be populated during the configuration process
  325. /// and will replace the existing context provided the configuration
  326. /// process completes without error.
  327. ///
  328. /// @return Returns a DCfgContextBasePtr to the new context instance.
  329. virtual DCfgContextBasePtr createNewContext() = 0;
  330. /// @brief Replaces existing context with a new, emtpy context.
  331. void resetContext();
  332. /// @brief Update the current context.
  333. ///
  334. /// Replaces the existing context with the given context.
  335. /// @param context Pointer to the new context.
  336. /// @throw DCfgMgrBaseError if context is NULL.
  337. void setContext(DCfgContextBasePtr& context);
  338. private:
  339. /// @brief Parse a configuration element.
  340. ///
  341. /// Given an element_id and data value, instantiate the appropriate
  342. /// parser, parse the data value, and commit the results.
  343. ///
  344. /// @param element_id is the string name of the element as it will appear
  345. /// in the configuration set.
  346. /// @param value is the data value to be parsed and associated with
  347. /// element_id.
  348. ///
  349. /// @throw throws DCfgMgrBaseError if an error occurs.
  350. void buildAndCommit(std::string& element_id,
  351. isc::data::ConstElementPtr value);
  352. /// @brief A list of element ids which specifies the element parsing order.
  353. ///
  354. /// If the list is empty, the natural order in the configuration set
  355. /// it used.
  356. ElementIdList parse_order_;
  357. /// @brief Pointer to the configuration context instance.
  358. DCfgContextBasePtr context_;
  359. };
  360. /// @brief Defines a shared pointer to DCfgMgrBase.
  361. typedef boost::shared_ptr<DCfgMgrBase> DCfgMgrBasePtr;
  362. }; // end of isc::process namespace
  363. }; // end of isc namespace
  364. #endif // D_CFG_MGR_H