Commit c519aa88 authored by Thomas Markwalder's avatar Thomas Markwalder

[2355] Minor changes in response to review comments.

parent f18722f2
......@@ -41,10 +41,6 @@ using namespace isc::asiolink;
namespace {
/// @brief Create the global parser context which stores global
/// parameters, options, and option definitions.
ParserContextPtr global_context_ptr(new ParserContext(Option::V4));
/// @brief Parser for DHCP4 option data value.
///
/// This parser parses configuration entries that specify value of
......@@ -66,7 +62,7 @@ public:
/// @brief static factory method for instantiating Dhcp4OptionDataParsers
///
/// @param param_name name fo the parameter to be parsed.
/// @param param_name name of the parameter to be parsed.
/// @param options storage where the parameter value is to be stored.
/// @param global_context is a pointer to the global context which
/// stores global scope parameters, options, option defintions.
......@@ -130,10 +126,10 @@ protected:
///
/// @param addr is the IPv4 prefix of the pool.
/// @param len is the prefix length.
/// @param ignored dummy parameter to provide symmetry between
/// @param ignored dummy parameter to provide symmetry between the
/// PoolParser derivations. The V6 derivation requires a third value.
/// @return returns a PoolPtr to the new Pool4 object.
PoolPtr poolMaker (IOAddress &addr, uint32_t len, int32_t)
{
PoolPtr poolMaker (IOAddress &addr, uint32_t len, int32_t) {
return (PoolPtr(new Pool4(addr, len)));
}
......@@ -144,8 +140,7 @@ protected:
/// @param ignored dummy parameter to provide symmetry between the
/// PoolParser derivations. The V6 derivation requires a third value.
/// @return returns a PoolPtr to the new Pool4 object.
PoolPtr poolMaker (IOAddress &min, IOAddress &max, int32_t)
{
PoolPtr poolMaker (IOAddress &min, IOAddress &max, int32_t) {
return (PoolPtr(new Pool4(min, max)));
}
};
......@@ -162,15 +157,22 @@ public:
/// @param ignored first parameter
/// @param global_context is a pointer to the global context which
/// stores global scope parameters, options, option defintions.
Subnet4ConfigParser(const std::string&, ParserContextPtr global_context)
:SubnetConfigParser("", global_context) {
Subnet4ConfigParser(const std::string&)
:SubnetConfigParser("", globalContext()) {
}
/// @brief Adds the created subnet to a server's configuration.
/// @throw throws Unexpected if dynamic cast fails.
void commit() {
if (subnet_) {
Subnet4Ptr bs = boost::dynamic_pointer_cast<Subnet4>(subnet_);
isc::dhcp::CfgMgr::instance().addSubnet4(bs);
Subnet4Ptr sub4ptr = boost::dynamic_pointer_cast<Subnet4>(subnet_);
if (!sub4ptr) {
// If we hit this, it is a programming error.
isc_throw(Unexpected,
"Invalid cast in Subnet4ConfigParser::commit");
}
isc::dhcp::CfgMgr::instance().addSubnet4(sub4ptr);
}
}
......@@ -191,14 +193,14 @@ protected:
(config_id.compare("rebind-timer") == 0)) {
parser = new Uint32Parser(config_id, uint32_values_);
} else if ((config_id.compare("subnet") == 0) ||
(config_id.compare("interface") == 0)) {
(config_id.compare("interface") == 0)) {
parser = new StringParser(config_id, string_values_);
} else if (config_id.compare("pool") == 0) {
parser = new Pool4Parser(config_id, pools_);
} else if (config_id.compare("option-data") == 0) {
parser = new OptionDataListParser(config_id, options_,
global_context_,
Dhcp4OptionDataParser::factory);
global_context_,
Dhcp4OptionDataParser::factory);
} else {
isc_throw(NotImplemented,
"parser error: Subnet4 parameter not supported: " << config_id);
......@@ -277,7 +279,7 @@ public:
/// @brief constructor
///
/// @param dummy first argument, always ingored. All parsers accept a
/// @param dummy first argument, always ignored. All parsers accept a
/// string parameter "name" as their first argument.
Subnets4ListConfigParser(const std::string&) {
}
......@@ -290,8 +292,7 @@ public:
/// @param subnets_list pointer to a list of IPv4 subnets
void build(ConstElementPtr subnets_list) {
BOOST_FOREACH(ConstElementPtr subnet, subnets_list->listValue()) {
ParserPtr parser(new Subnet4ConfigParser("subnet",
global_context_ptr));
ParserPtr parser(new Subnet4ConfigParser("subnet"));
parser->build(subnet);
subnets_.push_back(parser);
}
......@@ -346,22 +347,22 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id) {
(config_id.compare("renew-timer") == 0) ||
(config_id.compare("rebind-timer") == 0)) {
parser = new Uint32Parser(config_id,
global_context_ptr->uint32_values_);
globalContext()->uint32_values_);
} else if (config_id.compare("interface") == 0) {
parser = new InterfaceListConfigParser(config_id);
} else if (config_id.compare("subnet4") == 0) {
parser = new Subnets4ListConfigParser(config_id);
} else if (config_id.compare("option-data") == 0) {
parser = new OptionDataListParser(config_id,
global_context_ptr->options_,
global_context_ptr,
globalContext()->options_,
globalContext(),
Dhcp4OptionDataParser::factory);
} else if (config_id.compare("option-def") == 0) {
parser = new OptionDefListParser(config_id,
global_context_ptr->option_defs_);
globalContext()->option_defs_);
} else if (config_id.compare("version") == 0) {
parser = new StringParser(config_id,
global_context_ptr->string_values_);
globalContext()->string_values_);
} else if (config_id.compare("lease-database") == 0) {
parser = new DbAccessParser(config_id);
} else {
......@@ -405,7 +406,7 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
// parsing operation fails after the global storage has been
// modified. We need to preserve the original global data here
// so as we can rollback changes when an error occurs.
ParserContext original_context(*global_context_ptr);
ParserContext original_context(*globalContext());
// Answer will hold the result.
ConstElementPtr answer;
......@@ -500,7 +501,7 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
// Rollback changes as the configuration parsing failed.
if (rollback) {
global_context_ptr.reset(new ParserContext(original_context));
globalContext().reset(new ParserContext(original_context));
return (answer);
}
......@@ -511,11 +512,13 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
return (answer);
}
// Makes global context accessible for unit tests.
const ParserContext& getGlobalParserContext() {
return (*global_context_ptr);
ParserContextPtr globalContext() {
static ParserContextPtr global_context_ptr(new ParserContext(Option::V4));
return (global_context_ptr);
}
}; // end of isc::dhcp namespace
}; // end of isc namespace
......@@ -63,11 +63,8 @@ configureDhcp4Server(Dhcpv4Srv&,
/// @brief Returns the global context
///
/// This function must be only used by unit tests that need
/// to access global context.
///
/// @returns a const reference to the global context
const ParserContext& getGlobalParserContext();
/// @return a const reference to the global context
ParserContextPtr globalContext();
}; // end of isc::dhcp namespace
}; // end of isc namespace
......
......@@ -53,7 +53,11 @@ public:
// Checks if global parameter of name have expected_value
void checkGlobalUint32(string name, uint32_t expected_value) {
const Uint32StoragePtr uint32_defaults =
#if 0
getGlobalParserContext().uint32_values_;
#else
globalContext()->uint32_values_;
#endif
try {
uint32_t actual_value = uint32_defaults->getParam(name);
EXPECT_EQ(expected_value, actual_value);
......
......@@ -55,9 +55,6 @@ typedef boost::shared_ptr<BooleanParser> BooleanParserPtr;
typedef boost::shared_ptr<StringParser> StringParserPtr;
typedef boost::shared_ptr<Uint32Parser> Uint32ParserPtr;
// TKM - declare a global parser context
ParserContextPtr global_context_ptr(new ParserContext(Option::V6));
/// @brief Parser for DHCP6 option data value.
///
/// This parser parses configuration entries that specify value of
......@@ -182,15 +179,21 @@ public:
/// @param ignored first parameter
/// @param global_context is a pointer to the global context which
/// stores global scope parameters, options, option defintions.
Subnet6ConfigParser(const std::string&, ParserContextPtr global_context)
:SubnetConfigParser("", global_context) {
Subnet6ConfigParser(const std::string&)
:SubnetConfigParser("", globalContext()) {
}
/// @brief Adds the created subnet to a server's configuration.
/// @throw throws Unexpected if dynamic cast fails.
void commit() {
if (subnet_) {
Subnet6Ptr bs = boost::dynamic_pointer_cast<Subnet6>(subnet_);
isc::dhcp::CfgMgr::instance().addSubnet6(bs);
Subnet6Ptr sub6ptr = boost::dynamic_pointer_cast<Subnet6>(subnet_);
if (!sub6ptr) {
// If we hit this, it is a programming error.
isc_throw(Unexpected,
"Invalid cast in Subnet4ConfigParser::commit");
}
isc::dhcp::CfgMgr::instance().addSubnet6(sub6ptr);
}
}
......@@ -212,7 +215,7 @@ protected:
(config_id.compare("rebind-timer") == 0)) {
parser = new Uint32Parser(config_id, uint32_values_);
} else if ((config_id.compare("subnet") == 0) ||
(config_id.compare("interface") == 0)) {
(config_id.compare("interface") == 0)) {
parser = new StringParser(config_id, string_values_);
} else if (config_id.compare("pool") == 0) {
parser = new Pool6Parser(config_id, pools_);
......@@ -303,7 +306,7 @@ public:
/// @brief constructor
///
/// @param dummy first argument, always ingored. All parsers accept a
/// @param dummy first argument, always ignored. All parsers accept a
/// string parameter "name" as their first argument.
Subnets6ListConfigParser(const std::string&) {
}
......@@ -316,8 +319,7 @@ public:
/// @param subnets_list pointer to a list of IPv6 subnets
void build(ConstElementPtr subnets_list) {
BOOST_FOREACH(ConstElementPtr subnet, subnets_list->listValue()) {
ParserPtr parser(new Subnet6ConfigParser("subnet",
global_context_ptr));
ParserPtr parser(new Subnet6ConfigParser("subnet" ));
parser->build(subnet);
subnets_.push_back(parser);
}
......@@ -373,22 +375,22 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id) {
(config_id.compare("renew-timer") == 0) ||
(config_id.compare("rebind-timer") == 0)) {
parser = new Uint32Parser(config_id,
global_context_ptr->uint32_values_);
globalContext()->uint32_values_);
} else if (config_id.compare("interface") == 0) {
parser = new InterfaceListConfigParser(config_id);
} else if (config_id.compare("subnet6") == 0) {
parser = new Subnets6ListConfigParser(config_id);
} else if (config_id.compare("option-data") == 0) {
parser = new OptionDataListParser(config_id,
global_context_ptr->options_,
global_context_ptr,
globalContext()->options_,
globalContext(),
Dhcp6OptionDataParser::factory);
} else if (config_id.compare("option-def") == 0) {
parser = new OptionDefListParser(config_id,
global_context_ptr->option_defs_);
globalContext()->option_defs_);
} else if (config_id.compare("version") == 0) {
parser = new StringParser(config_id,
global_context_ptr->string_values_);
globalContext()->string_values_);
} else if (config_id.compare("lease-database") == 0) {
parser = new DbAccessParser(config_id);
} else {
......@@ -432,7 +434,7 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
// parsing operation fails after the global storage has been
// modified. We need to preserve the original global data here
// so as we can rollback changes when an error occurs.
ParserContext original_context(*global_context_ptr);
ParserContext original_context(*globalContext());
// answer will hold the result.
ConstElementPtr answer;
......@@ -528,7 +530,7 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
// Rollback changes as the configuration parsing failed.
if (rollback) {
global_context_ptr.reset(new ParserContext(original_context));
globalContext().reset(new ParserContext(original_context));
return (answer);
}
......@@ -539,9 +541,9 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
return (answer);
}
// Makes global context accessible for unit tests.
const ParserContext& getGlobalParserContext() {
return (*global_context_ptr);
ParserContextPtr globalContext() {
static ParserContextPtr global_context_ptr(new ParserContext(Option::V6));
return (global_context_ptr);
}
}; // end of isc::dhcp namespace
......
......@@ -51,11 +51,8 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set);
/// @brief Returns the global context
///
/// This function must be only used by unit tests that need
/// to access global context.
///
/// @returns a const reference to the global context
const ParserContext& getGlobalParserContext();
ParserContextPtr globalContext();
}; // end of isc::dhcp namespace
}; // end of isc namespace
......
......@@ -130,82 +130,6 @@ public:
virtual void commit() = 0;
};
/// @brief A template class that stores named elements of a given data type.
///
/// This template class is provides data value storage for configuration parameters
/// of a given data type. The values are stored by parameter name and as instances
/// of type "ValueType".
///
/// @param ValueType is the data type of the elements to store.
template<typename ValueType>
class ValueStorage {
public:
/// @brief Stores the the parameter and its value in the store.
///
/// If the parameter does not exist in the store, then it will be added,
/// otherwise its data value will be updated with the given value.
///
/// @param name is the name of the paramater to store.
/// @param value is the data value to store.
void setParam(const std::string& name, const ValueType& value) {
values_[name] = value;
}
/// @brief Returns the data value for the given parameter.
///
/// Finds and returns the data value for the given parameter.
/// @param name is the name of the parameter for which the data
/// value is desired.
///
/// @return The paramater's data value of type <ValueType>.
/// @throw DhcpConfigError if the parameter is not found.
ValueType getParam(const std::string& name) const {
typename std::map<std::string, ValueType>::const_iterator param
= values_.find(name);
if (param == values_.end()) {
isc_throw(DhcpConfigError, "Missing parameter '"
<< name << "'");
}
return (param->second);
}
/// @brief Remove the parameter from the store.
///
/// Deletes the entry for the given parameter from the store if it
/// exists.
///
/// @param name is the name of the paramater to delete.
void delParam(const std::string& name) {
values_.erase(name);
}
/// @brief Deletes all of the entries from the store.
///
void clear() {
values_.clear();
}
private:
/// @brief An std::map of the data values, keyed by parameter names.
std::map<std::string, ValueType> values_;
};
/// @brief a collection of elements that store uint32 values (e.g. renew-timer = 900)
typedef ValueStorage<uint32_t> Uint32Storage;
typedef boost::shared_ptr<Uint32Storage> Uint32StoragePtr;
/// @brief a collection of elements that store string values
typedef ValueStorage<std::string> StringStorage;
typedef boost::shared_ptr<StringStorage> StringStoragePtr;
/// @brief Storage for parsed boolean values.
typedef ValueStorage<bool> BooleanStorage;
typedef boost::shared_ptr<BooleanStorage> BooleanStoragePtr;
}; // end of isc::dhcp namespace
}; // end of isc namespace
......
......@@ -44,7 +44,7 @@ ParserContext::ParserContext(Option::Universe universe):
universe_(universe) {
}
ParserContext::ParserContext(ParserContext& rhs):
ParserContext::ParserContext(const ParserContext& rhs):
boolean_values_(new BooleanStorage(*(rhs.boolean_values_))),
uint32_values_(new Uint32Storage(*(rhs.uint32_values_))),
string_values_(new StringStorage(*(rhs.string_values_))),
......@@ -53,19 +53,38 @@ ParserContext::ParserContext(ParserContext& rhs):
universe_(rhs.universe_) {
}
ParserContext&
ParserContext::operator=(const ParserContext& rhs) {
ParserContext tmp(rhs);
boolean_values_ =
BooleanStoragePtr(new BooleanStorage(*(rhs.boolean_values_)));
uint32_values_ =
Uint32StoragePtr(new Uint32Storage(*(tmp.uint32_values_)));
string_values_ =
StringStoragePtr(new StringStorage(*(tmp.string_values_)));
options_ = OptionStoragePtr(new OptionStorage(*(tmp.options_)));
option_defs_ =
OptionDefStoragePtr(new OptionDefStorage(*(tmp.option_defs_)));
universe_ = rhs.universe_;
return (*this);
}
// **************************** DebugParser *************************
DebugParser::DebugParser(const std::string& param_name)
:param_name_(param_name) {
}
void DebugParser::build(ConstElementPtr new_config) {
void
DebugParser::build(ConstElementPtr new_config) {
std::cout << "Build for token: [" << param_name_ << "] = ["
<< value_->str() << "]" << std::endl;
value_ = new_config;
}
void DebugParser::commit() {
void
DebugParser::commit() {
// Debug message. The whole DebugParser class is used only for parser
// debugging, and is not used in production code. It is very convenient
// to keep it around. Please do not turn this cout into logger calls.
......@@ -128,13 +147,15 @@ InterfaceListConfigParser::InterfaceListConfigParser(const std::string&
}
}
void InterfaceListConfigParser::build(ConstElementPtr value) {
void
InterfaceListConfigParser::build(ConstElementPtr value) {
BOOST_FOREACH(ConstElementPtr iface, value->listValue()) {
interfaces_.push_back(iface->str());
}
}
void InterfaceListConfigParser::commit() {
void
InterfaceListConfigParser::commit() {
/// @todo: Implement per interface listening. Currently always listening
/// on all interfaces.
}
......@@ -157,7 +178,8 @@ OptionDataParser::OptionDataParser(const std::string&, OptionStoragePtr options,
}
}
void OptionDataParser::build(ConstElementPtr option_data_entries) {
void
OptionDataParser::build(ConstElementPtr option_data_entries) {
BOOST_FOREACH(ConfigPair param, option_data_entries->mapValue()) {
ParserPtr parser;
if (param.first == "name" || param.first == "data" ||
......@@ -193,7 +215,8 @@ void OptionDataParser::build(ConstElementPtr option_data_entries) {
createOption();
}
void OptionDataParser::commit() {
void
OptionDataParser::commit() {
if (!option_descriptor_.option) {
// Before we can commit the new option should be configured. If it is
// not than somebody must have called commit() before build().
......@@ -221,7 +244,8 @@ void OptionDataParser::commit() {
options_->addItem(option_descriptor_, option_space_);
}
void OptionDataParser::createOption() {
void
OptionDataParser::createOption() {
// Option code is held in the uint32_t storage but is supposed to
// be uint16_t value. We need to check that value in the configuration
// does not exceed range of uint8_t and is not zero.
......@@ -389,7 +413,8 @@ OptionDataListParser::OptionDataListParser(const std::string&,
}
}
void OptionDataListParser::build(ConstElementPtr option_data_list) {
void
OptionDataListParser::build(ConstElementPtr option_data_list) {
BOOST_FOREACH(ConstElementPtr option_value, option_data_list->listValue()) {
boost::shared_ptr<OptionDataParser>
parser((*optionDataParserFactory_)("option-data",
......@@ -404,7 +429,8 @@ void OptionDataListParser::build(ConstElementPtr option_data_list) {
}
}
void OptionDataListParser::commit() {
void
OptionDataListParser::commit() {
BOOST_FOREACH(ParserPtr parser, parsers_) {
parser->commit();
}
......@@ -426,7 +452,8 @@ OptionDefParser::OptionDefParser(const std::string&,
}
}
void OptionDefParser::build(ConstElementPtr option_def) {
void
OptionDefParser::build(ConstElementPtr option_def) {
// Parse the elements that make up the option definition.
BOOST_FOREACH(ConfigPair param, option_def->mapValue()) {
std::string entry(param.first);
......@@ -473,14 +500,16 @@ void OptionDefParser::build(ConstElementPtr option_def) {
}
}
void OptionDefParser::commit() {
void
OptionDefParser::commit() {
if (storage_ && option_definition_ &&
OptionSpace::validateName(option_space_name_)) {
storage_->addItem(option_definition_, option_space_name_);
}
}
void OptionDefParser::createOptionDef() {
void
OptionDefParser::createOptionDef() {
// Get the option space name and validate it.
std::string space = string_values_->getParam("space");
if (!OptionSpace::validateName(space)) {
......@@ -567,7 +596,8 @@ OptionDefListParser::OptionDefListParser(const std::string&,
}
}
void OptionDefListParser::build(ConstElementPtr option_def_list) {
void
OptionDefListParser::build(ConstElementPtr option_def_list) {
// Clear existing items in the storage.
// We are going to replace all of them.
storage_->clearItems();
......@@ -585,7 +615,8 @@ void OptionDefListParser::build(ConstElementPtr option_def_list) {
}
}
void OptionDefListParser::commit() {
void
OptionDefListParser::commit() {
CfgMgr& cfg_mgr = CfgMgr::instance();
cfg_mgr.deleteOptionDefs();
......@@ -616,7 +647,8 @@ PoolParser::PoolParser(const std::string&, PoolStoragePtr pools)
}
}
void PoolParser::build(ConstElementPtr pools_list) {
void
PoolParser::build(ConstElementPtr pools_list) {
BOOST_FOREACH(ConstElementPtr text_pool, pools_list->listValue()) {
// That should be a single pool representation. It should contain
// text is form prefix/len or first - last. Note that spaces
......@@ -673,9 +705,10 @@ void PoolParser::build(ConstElementPtr pools_list) {
<< text_pool->stringValue() <<
". Does not contain - (for min-max) nor / (prefix/len)");
}
}
}
void PoolParser::commit() {
void
PoolParser::commit() {
if (pools_) {
// local_pools_ holds the values produced by the build function.
// At this point parsing should have completed successfuly so
......@@ -699,7 +732,8 @@ SubnetConfigParser::SubnetConfigParser(const std::string&,
}
}
void SubnetConfigParser::build(ConstElementPtr subnet) {
void
SubnetConfigParser::build(ConstElementPtr subnet) {
BOOST_FOREACH(ConfigPair param, subnet->mapValue()) {
ParserPtr parser(createSubnetConfigParser(param.first));
parser->build(param.second);
......@@ -722,8 +756,9 @@ void SubnetConfigParser::build(ConstElementPtr subnet) {
createSubnet();
}
void SubnetConfigParser::appendSubOptions(const std::string& option_space,
OptionPtr& option) {
void
SubnetConfigParser::appendSubOptions(const std::string& option_space,
OptionPtr& option) {
// Only non-NULL options are stored in option container.
// If this option pointer is NULL this is a serious error.
assert(option);
......@@ -776,7 +811,8 @@ void SubnetConfigParser::appendSubOptions(const std::string& option_space,
}
}
void SubnetConfigParser::createSubnet() {
void
SubnetConfigParser::createSubnet() {
std::string subnet_txt;