cc.dox 4.55 KB
Newer Older
// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
2 3 4 5 6 7
// 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

 @page libcc libkea-cc - Kea Configuration Utilities Library
9 10 11 12 13 14 15 16 17 18

@section ccSimpleParser Simple JSON Parser

Since the early beginnings, our configuration parsing code was a mess. It
started back in 2011 when Tomek joined ISC recently and was told to implement
Kea configuration handling in similar way as DNS Auth module. The code grew
over time (DHCP configuration is significantly more complex than DNS, with
more interdependent values) and as of Kea 1.1 release it became very difficult
to manage. The decision has been made to significantly refactor or even
partially rewrite the parser code. The design for this effort is documented
here: It discusses the original issues
20 21
and the proposed architecture.

Francis Dupont's avatar
Francis Dupont committed
22 23 24 25 26 27
There are several aspects of this new approach. The base class for all
parsers is @ref isc::data::SimpleParser. It simplifies the parsers
based on DhcpConfigParser by rejecting the concept of build/commit
phases.  Instead, there should be a single method called parse that
takes ConstElementPtr as a single parameter (that's the JSON
structures to be parsed) and returns the config structure to be used
28 29 30 31 32 33 34 35 36 37 38
in CfgMgr. An example of such a method can be the following:

std::pair<OptionDescriptor, std::string>
OptionDataParser::parse(isc::data::ConstElementPtr single_option)

Since each derived class will have the same parameter, but a different return
type, it's not possible to use virtual methods mechanism. That's perfectly
ok, though, as there is only a single instance of the class needed to parse
arbitrary number of parameters of the same type. There is no need to
keep pointers to the parser object. As such there are fewer incentives to have
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
one generic way to handle all parsers.

@subsection ccSimpleParserDefaults Default values in Simple Parser

Another simplification comes from the fact that almost all parameters
are mandatory in SimpleParser. One source of complexities in the old
parser was the necessity to deal with optional parameters. Simple
parser deals with that by explicitly requiring the input structure to
have all parameters filled. Obviously, it's not feasible to expect
everyone to always specify all parameters, therefore there's an easy
way to fill missing parameters with their default values. There are
several methods to do this, but the most generic one is:

static size_t
isc::data::SimpleParser::setDefaults(isc::data::ElementPtr scope,
                                     const SimpleDefaults& default_values);

It takes a pointer to element to be filled with default values and
vector of default values. Having those values specified in a single
place in a way that can easily be read even by non-programmers is a
big advantage of this approach. Here's an example from file:

/// This table defines default values for option definitions in DHCPv6
const SimpleDefaults OPTION6_DEF_DEFAULTS = {
    { "record-types", Element::string,  ""},
    { "space",        Element::string,  "dhcp6"},
    { "array",        Element::boolean, "false"},
    { "encapsulate",  Element::string,  "" }

This array (which technically is implemented as a vector and
initialized the C++11 way) can be passed to the aforementioned
setDefaults. That code will iterate over all default values and see if
there are explicit values provided. If not, the gaps will be filled
with default values. There are also convenience methods specified for
filling in option data defaults, option definition defaults and
setAllDefaults that sets all defaults (starts with global, but then
walks down the Element tree and fills defaults in subsequent scopes).

@subsection ccSimpleParserInherits Inheriting parameters between scopes

SimpleParser provides a mechanism to inherit parameters between scopes,
e.g. to inherit global parameters in the subnet scope if more specific
values are not defined in the subnet scope. This is achieved by calling
static size_t SimpleParser::deriveParams(isc::data::ConstElementPtr parent,
                                         isc::data::ElementPtr child,
                                         const ParamsList& params);


ParamsList is a simple vector<string>. There will be more specific
methods implemented in the future, but for the time being only
@ref isc::data::SimpleParser::deriveParams is implemented.