BIND 10 trac2317, updated. 6b78fee487016e4920ab469448c559752523d474 [2317] Store configured option definitions in the CfgMgr object.
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Jan 9 15:18:42 UTC 2013
The branch, trac2317 has been updated
via 6b78fee487016e4920ab469448c559752523d474 (commit)
via db45e761f5f8c140d80d242033642e2d929a2a2d (commit)
from 36d56446c3758b1d8e6c005fabfe8432b9751131 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 6b78fee487016e4920ab469448c559752523d474
Author: Marcin Siodelski <marcin at isc.org>
Date: Wed Jan 9 16:18:28 2013 +0100
[2317] Store configured option definitions in the CfgMgr object.
commit db45e761f5f8c140d80d242033642e2d929a2a2d
Author: Marcin Siodelski <marcin at isc.org>
Date: Wed Jan 9 13:18:15 2013 +0100
[2317] Added generic container holding option spaces.
-----------------------------------------------------------------------
Summary of changes:
src/bin/dhcp4/config_parser.cc | 87 ++++++++++++++++------
src/bin/dhcp4/tests/config_parser_unittest.cc | 8 ++-
src/lib/dhcpsrv/Makefile.am | 1 +
src/lib/dhcpsrv/cfgmgr.cc | 23 ++----
src/lib/dhcpsrv/cfgmgr.h | 14 ++--
src/lib/dhcpsrv/option_space_container.h | 95 +++++++++++++++++++++++++
src/lib/dhcpsrv/subnet.cc | 26 ++-----
src/lib/dhcpsrv/subnet.h | 10 +--
8 files changed, 188 insertions(+), 76 deletions(-)
create mode 100644 src/lib/dhcpsrv/option_space_container.h
-----------------------------------------------------------------------
diff --git a/src/bin/dhcp4/config_parser.cc b/src/bin/dhcp4/config_parser.cc
index 584552c..6fe9030 100644
--- a/src/bin/dhcp4/config_parser.cc
+++ b/src/bin/dhcp4/config_parser.cc
@@ -19,6 +19,7 @@
#include <dhcp/option_definition.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/dhcp_config_parser.h>
+#include <dhcpsrv/option_space_container.h>
#include <util/encode/hex.h>
#include <util/strutil.h>
#include <boost/foreach.hpp>
@@ -66,6 +67,10 @@ typedef std::map<std::string, std::string> StringStorage;
/// @brief Storage for parsed boolean values.
typedef std::map<string, bool> BooleanStorage;
+/// @brief Storage for option definitions.
+typedef OptionSpaceContainer<OptionDefContainer,
+ OptionDefinitionPtr> OptionDefStorage;
+
/// @brief a collection of pools
///
/// That type is used as intermediate storage, when pools are parsed, but there is
@@ -986,11 +991,31 @@ public:
parser->commit();
}
+ // Create an instance of option definition.
createOptionDef();
+
+ // Get all items we collected so far for the particular option space.
+ OptionDefContainerPtr defs = storage_->getItems(option_space_name_);
+ // Check if there are any items with option code the same as the
+ // one specified for the definition we are now creating.
+ const OptionDefContainerTypeIndex& idx = defs->get<1>();
+ const OptionDefContainerTypeRange& range =
+ idx.equal_range(option_definition_->getCode());
+ // If there are any items with this option code already we need
+ // to issue an error because we don't allow duplicates for
+ // option definitions within an option space.
+ if (std::distance(range.first, range.second) > 0) {
+ isc_throw(DhcpConfigError, "duplicated option definition for"
+ << " code '" << option_definition_->getCode() << "'");
+ }
}
/// @brief Stores the parsed option definition in a storage.
void commit() {
+ // @todo validate option space name once 2313 is merged.
+ if (storage_ && option_definition_) {
+ storage_->addItem(option_definition_, option_space_name_);
+ }
}
/// @brief Sets a pointer to a storage.
@@ -1000,7 +1025,7 @@ public:
///
/// @param storage pointer to a storage where the option definition
/// will be added to.
- void setStorage(OptionDefContainer* storage) {
+ void setStorage(OptionDefStorage* storage) {
storage_ = storage;
}
@@ -1033,15 +1058,18 @@ private:
<< " parameters" << ex.what());
}
// Option definition has been created successfully.
+ option_space_name_ = space;
option_definition_ = def;
}
/// Instance of option definition being created by this parser.
OptionDefinitionPtr option_definition_;
+ std::string option_space_name_;
+
/// Pointer to a storage where the option definition will be
/// added when \ref commit is called.
- OptionDefContainer* storage_;
+ OptionDefStorage* storage_;
/// Storage for boolean values.
BooleanStorage boolean_values_;
@@ -1065,8 +1093,7 @@ public:
/// This constructor initializes the pointer to option definitions
/// storage to NULL value. This pointer has to be set to point to
/// the actual storage before the \ref build function is called.
- OptionDefListParser(const std::string&)
- : option_defs_(NULL) {
+ OptionDefListParser(const std::string&) {
}
/// @brief Parse configuration entries.
@@ -1081,10 +1108,6 @@ public:
if (!option_def_list) {
isc_throw(DhcpConfigError, "parser error: a pointer to a list of"
<< " option definitions is NULL");
- } else if (option_defs_ == NULL) {
- isc_throw(DhcpConfigError, "parser error: the storage for option"
- << " definitions must be set before parsing option"
- << " definitions");
}
BOOST_FOREACH(ConstElementPtr option_def, option_def_list->listValue()) {
@@ -1092,11 +1115,44 @@ public:
parser(new OptionDefParser("single-option-def"));
parser->setStorage(&option_defs_local_);
parser->build(option_def);
+ parser->commit();
}
}
/// @brief Stores option definitions in the provided storage.
void commit() {
+
+ CfgMgr& cfg_mgr = CfgMgr::instance();
+
+ // We need to move option definitions from the temporary
+ // storage to the global storage. However for new definition
+ // we need to check whether such a definition already exists
+ // or we are adding it for the fitsy time.
+ BOOST_FOREACH(std::string space_name,
+ option_defs_local_.getOptionSpaceNames()) {
+ // For the particular option space we have to get all
+ // items in the temporary storage and store it in the
+ // global storage.
+ BOOST_FOREACH(OptionDefinitionPtr def,
+ *option_defs_local_.getItems(space_name)) {
+ assert(def);
+ // For the particular option space get all definitions
+ // existing in the global storage.
+ OptionDefContainerPtr global_defs = cfg_mgr.getOptionDefs(space_name);
+ assert(global_defs);
+ // Find the option definition for the particular
+ // option code.
+ OptionDefContainerTypeIndex& idx = global_defs->get<1>();
+ const OptionDefContainerTypeRange& range =
+ idx.equal_range(def->getCode());
+ // If there is one in the global storage, erase it.
+ if (std::distance(range.first, range.second) > 0) {
+ idx.erase(range.first, range.second);
+ }
+ // Add the newly created option definition.
+ cfg_mgr.addOptionDef(def, space_name);
+ }
+ }
}
/// @brief Create an OptionDefListParser object.
@@ -1108,23 +1164,11 @@ public:
return (new OptionDefListParser(param_name));
}
- /// @brief Set storage for option definition instances.
- ///
- /// @param storage pointer to the option definition storage
- /// where created option instances should be stored.
- void setStorage(OptionDefContainer* storage) {
- option_defs_ = storage;
- }
-
private:
- /// Pointer to the container where option definitions should
- /// be stored when \ref commit is called.
- OptionDefContainer* option_defs_;
-
/// Temporary storage for option definitions. It holds option
/// definitions before \ref commit is called.
- OptionDefContainer option_defs_local_;
+ OptionDefStorage option_defs_local_;
};
/// @brief this class parses a single subnet
@@ -1490,6 +1534,7 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id) {
factories["interface"] = InterfaceListConfigParser::factory;
factories["subnet4"] = Subnets4ListConfigParser::factory;
factories["option-data"] = OptionDataListParser::factory;
+ factories["option-def"] = OptionDefListParser::factory;
factories["version"] = StringParser::factory;
FactoryMap::iterator f = factories.find(config_id);
diff --git a/src/bin/dhcp4/tests/config_parser_unittest.cc b/src/bin/dhcp4/tests/config_parser_unittest.cc
index 7ccd923..2cd8c93 100644
--- a/src/bin/dhcp4/tests/config_parser_unittest.cc
+++ b/src/bin/dhcp4/tests/config_parser_unittest.cc
@@ -447,7 +447,7 @@ TEST_F(Dhcp4ParserTest, optionDefAdd) {
" \"code\": 100,"
" \"type\": \"ipv4-address\","
" \"array\": False,"
- " \"record_types\": [ ],"
+ // " \"record_types\": [ ],"
" \"space\": \"isc\""
" } ]"
"}";
@@ -465,6 +465,12 @@ TEST_F(Dhcp4ParserTest, optionDefAdd) {
// The option definition should now be available in the CfgMgr.
def = CfgMgr::instance().getOptionDef("isc", 100);
ASSERT_TRUE(def);
+
+ // Verify that the option definition data is valid.
+ EXPECT_EQ("foo", def->getName());
+ EXPECT_EQ(100, def->getCode());
+ EXPECT_FALSE(def->getArrayType());
+ EXPECT_EQ(OPT_IPV4_ADDRESS_TYPE, def->getType());
}
// Goal of this test is to verify that global option
diff --git a/src/lib/dhcpsrv/Makefile.am b/src/lib/dhcpsrv/Makefile.am
index db7ea6a..76c67a2 100644
--- a/src/lib/dhcpsrv/Makefile.am
+++ b/src/lib/dhcpsrv/Makefile.am
@@ -43,6 +43,7 @@ libb10_dhcpsrv_la_SOURCES += memfile_lease_mgr.cc memfile_lease_mgr.h
if HAVE_MYSQL
libb10_dhcpsrv_la_SOURCES += mysql_lease_mgr.cc mysql_lease_mgr.h
endif
+libb10_dhcpsrv_la_SOURCES += option_space_container.h
libb10_dhcpsrv_la_SOURCES += pool.cc pool.h
libb10_dhcpsrv_la_SOURCES += subnet.cc subnet.h
libb10_dhcpsrv_la_SOURCES += triplet.h
diff --git a/src/lib/dhcpsrv/cfgmgr.cc b/src/lib/dhcpsrv/cfgmgr.cc
index ce28575..72b3254 100644
--- a/src/lib/dhcpsrv/cfgmgr.cc
+++ b/src/lib/dhcpsrv/cfgmgr.cc
@@ -56,30 +56,15 @@ CfgMgr::addOptionDef(const OptionDefinitionPtr& def,
<< option_space << "'.");
}
- // Get existing option definitions for the option space.
- OptionDefContainerPtr defs = getOptionDefs(option_space);
- // getOptionDefs always returns a valid pointer to
- // the container. Let's make an assert to make sure.
- assert(defs);
- // Actually add the new definition.
- defs->push_back(def);
- option_def_spaces_[option_space] = defs;
+ // Actually add a new item.
+ option_def_spaces_.addItem(def, option_space);
}
OptionDefContainerPtr
CfgMgr::getOptionDefs(const std::string& option_space) const {
// @todo Validate the option space once the #2313 is implemented.
- // Get all option definitions for the particular option space.
- const OptionDefsMap::const_iterator& defs =
- option_def_spaces_.find(option_space);
- // If there are no option definitions for the particular option space
- // then return empty container.
- if (defs == option_def_spaces_.end()) {
- return (OptionDefContainerPtr(new OptionDefContainer()));
- }
- // If option definitions found, return them.
- return (defs->second);
+ return (option_def_spaces_.getItems(option_space));
}
OptionDefinitionPtr
@@ -199,7 +184,7 @@ void CfgMgr::addSubnet4(const Subnet4Ptr& subnet) {
}
void CfgMgr::deleteOptionDefs() {
- option_def_spaces_.clear();
+ option_def_spaces_.clearItems();
}
void CfgMgr::deleteSubnets4() {
diff --git a/src/lib/dhcpsrv/cfgmgr.h b/src/lib/dhcpsrv/cfgmgr.h
index 9628f24..368536c 100644
--- a/src/lib/dhcpsrv/cfgmgr.h
+++ b/src/lib/dhcpsrv/cfgmgr.h
@@ -18,6 +18,7 @@
#include <asiolink/io_address.h>
#include <dhcp/option.h>
#include <dhcp/option_definition.h>
+#include <dhcpsrv/option_space_container.h>
#include <dhcpsrv/pool.h>
#include <dhcpsrv/subnet.h>
#include <util/buffer.h>
@@ -220,15 +221,12 @@ protected:
private:
- /// A map containing option definitions for various option spaces.
- /// They key of this map is the name of the option space. The
- /// value is the the option container holding option definitions
- /// for the particular option space.
- typedef std::map<std::string, OptionDefContainerPtr> OptionDefsMap;
+ /// A collection of option definitions accessible with option
+ /// space name.
+ typedef OptionSpaceContainer<OptionDefContainer,
+ OptionDefinitionPtr> OptionSpaceCollection;
- /// A map containing option definitions for different option spaces.
- /// The map key holds an option space name.
- OptionDefsMap option_def_spaces_;
+ OptionSpaceCollection option_def_spaces_;
};
diff --git a/src/lib/dhcpsrv/option_space_container.h b/src/lib/dhcpsrv/option_space_container.h
new file mode 100644
index 0000000..e063f7b
--- /dev/null
+++ b/src/lib/dhcpsrv/option_space_container.h
@@ -0,0 +1,95 @@
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef OPTION_SPACE_CONTAINER_H
+#define OPTION_SPACE_CONTAINER_H
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Simple container for option spaces holding various items.
+///
+/// This helper class is used to store items of various types in
+/// that are grouped by option space names. Each option space is
+/// mapped to a container that holds items which specifically can
+/// be OptionDefinition objects or Subnet::OptionDescriptor structures.
+///
+/// @tparam ContainerType of the container holding items within
+/// option space.
+/// @tparam ItemType type of the item being held by the container.
+template<typename ContainerType, typename ItemType>
+class OptionSpaceContainer {
+public:
+
+ /// Pointer to the container.
+ typedef boost::shared_ptr<ContainerType> ItemsContainerPtr;
+
+ /// @brief Adds a new item to the option_space.
+ ///
+ /// @param item reference to the item being added.
+ /// @param name of the option space.
+ void addItem(const ItemType& item, const std::string& option_space) {
+ ItemsContainerPtr items = getItems(option_space);
+ items->push_back(item);
+ option_space_map_[option_space] = items;
+ }
+
+ /// @brief Get all items for the particular option space.
+ ///
+ /// @param option_space name of the option space.
+ ///
+ /// @return pointer to the container holding items.
+ ItemsContainerPtr getItems(const std::string& option_space) const {
+ const typename OptionSpaceMap::const_iterator& items =
+ option_space_map_.find(option_space);
+ if (items == option_space_map_.end()) {
+ return (ItemsContainerPtr(new ContainerType()));
+ }
+ return (items->second);
+ }
+
+ /// @brief Get a list of existing option spaces.
+ ///
+ /// @return a list of option spaces.
+ ///
+ /// @todo This function is likely to be removed once
+ /// we create a structore of OptionSpaces defined
+ /// through the configuration manager.
+ std::list<std::string> getOptionSpaceNames() {
+ std::list<std::string> names;
+ for (typename OptionSpaceMap::const_iterator space =
+ option_space_map_.begin();
+ space != option_space_map_.end(); ++space) {
+ names.push_back(space->first);
+ }
+ return (names);
+ }
+
+ /// @brief Remove all items from the container.
+ void clearItems() {
+ option_space_map_.clear();
+ }
+
+private:
+
+ /// A map holding container (option space name is the key).
+ typedef std::map<std::string, ItemsContainerPtr> OptionSpaceMap;
+ OptionSpaceMap option_space_map_;
+};
+
+
+} // end of isc::dhcp namespace
+} // end of isc namespace
+
+#endif // OPTION_SPACE_CONTAINER_H
diff --git a/src/lib/dhcpsrv/subnet.cc b/src/lib/dhcpsrv/subnet.cc
index 3f31130..98ef8c8 100644
--- a/src/lib/dhcpsrv/subnet.cc
+++ b/src/lib/dhcpsrv/subnet.cc
@@ -55,36 +55,18 @@ Subnet::addOption(OptionPtr& option, bool persistent,
}
validateOption(option);
- OptionContainerPtr container = getOptionDescriptors(option_space);
- // getOptionDescriptors is expected to return the pointer to the
- // valid container. Let's make sure it does by performing an assert.
- assert(container);
- // Actually add the new descriptor.
- container->push_back(OptionDescriptor(option, persistent));
- option_spaces_[option_space] = container;
+ // Actually add new option descriptor.
+ option_spaces_.addItem(OptionDescriptor(option, persistent), option_space);
}
void
Subnet::delOptions() {
- option_spaces_.clear();
+ option_spaces_.clearItems();
}
Subnet::OptionContainerPtr
Subnet::getOptionDescriptors(const std::string& option_space) const {
- // Search the map to get the options container for the particular
- // option space.
- const OptionSpacesPtr::const_iterator& options =
- option_spaces_.find(option_space);
- // If the option space has not been found it means that no option
- // has been configured for this option space yet. Thus we have to
- // return an empty container to the caller.
- if (options == option_spaces_.end()) {
- // The default constructor creates an empty container.
- return (OptionContainerPtr(new OptionContainer()));
- }
- // We found some option container for the option space specified.
- // Let's return a const reference to it.
- return (options->second);
+ return (option_spaces_.getItems(option_space));
}
Subnet::OptionDescriptor
diff --git a/src/lib/dhcpsrv/subnet.h b/src/lib/dhcpsrv/subnet.h
index 442369f..806d86e 100644
--- a/src/lib/dhcpsrv/subnet.h
+++ b/src/lib/dhcpsrv/subnet.h
@@ -24,6 +24,7 @@
#include <asiolink/io_address.h>
#include <dhcp/option.h>
+#include <dhcpsrv/option_space_container.h>
#include <dhcpsrv/pool.h>
#include <dhcpsrv/triplet.h>
@@ -383,12 +384,11 @@ protected:
private:
- /// Container holding options grouped by option space names.
- typedef std::map<std::string, OptionContainerPtr> OptionSpacesPtr;
+ /// A collection of option spaces grouping option descriptors.
+ typedef OptionSpaceContainer<OptionContainer,
+ OptionDescriptor> OptionSpaceCollection;
+ OptionSpaceCollection option_spaces_;
- /// @brief a collection of DHCP option spaces holding options
- /// configured for a subnet.
- OptionSpacesPtr option_spaces_;
};
/// @brief A configuration holder for IPv4 subnet.
More information about the bind10-changes
mailing list