1// Copyright (C) 2016-2020 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 7/** 8 @page libcc libkea-cc - Kea Configuration Utilities Library 9 10@section ccSimpleParser Simple JSON Parser 11 12Since the early beginnings, our configuration parsing code was a mess. It 13started back in 2011 when Tomek joined ISC recently and was told to implement 14Kea configuration handling in similar way as DNS Auth module. The code grew 15over time (DHCP configuration is significantly more complex than DNS, with 16more interdependent values) and as of Kea 1.1 release it became very difficult 17to manage. The decision has been made to significantly refactor or even 18partially rewrite the parser code. The design for this effort is documented 19here: https://gitlab.isc.org/isc-projects/kea/wikis/designs/simple-parser-design. It discusses the original issues 20and the proposed architecture. 21 22There are several aspects of this new approach. The base class for all 23parsers is @ref isc::data::SimpleParser. It simplifies the parsers 24based on DhcpConfigParser by rejecting the concept of build/commit 25phases. Instead, there should be a single method called parse that 26takes ConstElementPtr as a single parameter (that's the JSON 27structures to be parsed) and returns the config structure to be used 28in CfgMgr. An example of such a method can be the following: 29 30@code 31std::pair<OptionDescriptor, std::string> 32OptionDataParser::parse(isc::data::ConstElementPtr single_option) 33@endcode 34 35Since each derived class will have the same parameter, but a different return 36type, it's not possible to use virtual methods mechanism. That's perfectly 37ok, though, as there is only a single instance of the class needed to parse 38arbitrary number of parameters of the same type. There is no need to 39keep pointers to the parser object. As such there are fewer incentives to have 40one generic way to handle all parsers. 41 42@subsection ccSimpleParserDefaults Default values in Simple Parser 43 44Another simplification comes from the fact that almost all parameters 45are mandatory in SimpleParser. One source of complexities in the old 46parser was the necessity to deal with optional parameters. Simple 47parser deals with that by explicitly requiring the input structure to 48have all parameters filled. Obviously, it's not feasible to expect 49everyone to always specify all parameters, therefore there's an easy 50way to fill missing parameters with their default values. There are 51several methods to do this, but the most generic one is: 52 53@code 54static size_t 55isc::data::SimpleParser::setDefaults(isc::data::ElementPtr scope, 56 const SimpleDefaults& default_values); 57@endcode 58 59It takes a pointer to element to be filled with default values and 60vector of default values. Having those values specified in a single 61place in a way that can easily be read even by non-programmers is a 62big advantage of this approach. Here's an example from simple_parser.cc file: 63 64@code 65/// This table defines default values for option definitions in DHCPv6 66const SimpleDefaults OPTION6_DEF_DEFAULTS = { 67 { "record-types", Element::string, ""}, 68 { "space", Element::string, "dhcp6"}, 69 { "array", Element::boolean, "false"}, 70 { "encapsulate", Element::string, "" } 71}; 72@endcode 73 74This array (which technically is implemented as a vector and 75initialized the C++11 way) can be passed to the aforementioned 76setDefaults. That code will iterate over all default values and see if 77there are explicit values provided. If not, the gaps will be filled 78with default values. There are also convenience methods specified for 79filling in option data defaults, option definition defaults and 80setAllDefaults that sets all defaults (starts with global, but then 81walks down the Element tree and fills defaults in subsequent scopes). 82 83@subsection ccSimpleParserInherits Inheriting parameters between scopes 84 85SimpleParser provides a mechanism to inherit parameters between scopes, 86e.g. to inherit global parameters in the subnet scope if more specific 87values are not defined in the subnet scope. This is achieved by calling 88@code 89static size_t SimpleParser::deriveParams(isc::data::ConstElementPtr parent, 90 isc::data::ElementPtr child, 91 const ParamsList& params); 92 93@endcode 94 95ParamsList is a simple vector<string>. There will be more specific 96methods implemented in the future, but for the time being only 97@ref isc::data::SimpleParser::deriveParams is implemented. 98 99@subsection ccMTConsiderations Multi-Threading Consideration for Configuration Utilities 100 101No configuration utility is thread safe. For instance stamped values are 102not thread safe so any read access must be done in a context where write 103access at the same time is not possible. Note that configuration is 104performed by the main thread with service threads stopped so this constraint 105is fulfilled. 106 107*/ 108