BIND 10 master, updated. b96a30b26a045cfaa8ad579b0a8bf84f5ed4e73f [master] Merge branch 'trac2701'
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Mar 7 09:42:27 UTC 2013
The branch, master has been updated
via b96a30b26a045cfaa8ad579b0a8bf84f5ed4e73f (commit)
via fc64e5bbe8b9f06f5073e461590e0013c184889c (commit)
via b58a4e5e12ee86e6ece24e90bc2f1e854cd92527 (commit)
via 86ac11a23c5c1c50b3d8daf1932103476674c72c (commit)
via b377f3a03ff6d2ba7b1fc562ae75707ddff310c7 (commit)
via 6085d54e697681307b4a5f60d169c9e4110c8286 (commit)
via 0cbbce437ec709e5dde8056c0462d7bd501f65c9 (commit)
via e0c71421f186a8cf77f1bf7aba7aff072a9caff7 (commit)
via 532c36304e8b5caf9faf9e98a66967c1073f5353 (commit)
via 27b34684dc5476292dc1f35c430c4509847fd31e (commit)
from bf86e0c9ea67c5ddd6e70ddec63a1f46d8c62630 (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 b96a30b26a045cfaa8ad579b0a8bf84f5ed4e73f
Merge: bf86e0c fc64e5b
Author: Marcin Siodelski <marcin at isc.org>
Date: Thu Mar 7 10:22:45 2013 +0100
[master] Merge branch 'trac2701'
-----------------------------------------------------------------------
Summary of changes:
src/lib/dhcp/duid.cc | 4 +-
src/lib/dhcp/duid.h | 4 +-
src/lib/dhcp/option_definition.cc | 4 --
src/lib/dhcp/option_definition.h | 22 ++++++-
src/lib/dhcpsrv/Makefile.am | 1 +
src/lib/dhcpsrv/alloc_engine.cc | 4 +-
src/lib/dhcpsrv/key_from_key.h | 82 ++++++++++++++++++++++++
src/lib/dhcpsrv/memfile_lease_mgr.cc | 72 ++++++++++++++--------
src/lib/dhcpsrv/memfile_lease_mgr.h | 113 +++++++++++++++++++++++++++++-----
src/lib/dhcpsrv/subnet.h | 56 ++---------------
10 files changed, 256 insertions(+), 106 deletions(-)
create mode 100644 src/lib/dhcpsrv/key_from_key.h
-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/duid.cc b/src/lib/dhcp/duid.cc
index f1c8866..e0df45d 100644
--- a/src/lib/dhcp/duid.cc
+++ b/src/lib/dhcp/duid.cc
@@ -41,7 +41,7 @@ DUID::DUID(const uint8_t* data, size_t len) {
duid_ = std::vector<uint8_t>(data, data + len);
}
-const std::vector<uint8_t> DUID::getDuid() const {
+std::vector<uint8_t> DUID::getDuid() const {
return (duid_);
}
@@ -91,7 +91,7 @@ ClientId::ClientId(const uint8_t *clientid, size_t len)
}
// Returns a copy of client-id data
-const std::vector<uint8_t> ClientId::getClientId() const {
+std::vector<uint8_t> ClientId::getClientId() const {
return (duid_);
}
diff --git a/src/lib/dhcp/duid.h b/src/lib/dhcp/duid.h
index 688885b..21c6b8f 100644
--- a/src/lib/dhcp/duid.h
+++ b/src/lib/dhcp/duid.h
@@ -58,7 +58,7 @@ class DUID {
/// returned it. In any case, this method should be used only sporadically.
/// If there are frequent uses, we must implement some other method
/// (e.g. storeSelf()) that will avoid data copying.
- const std::vector<uint8_t> getDuid() const;
+ std::vector<uint8_t> getDuid() const;
/// @brief Returns the DUID type
DUIDType getType() const;
@@ -105,7 +105,7 @@ public:
ClientId(const uint8_t* clientid, size_t len);
/// @brief Returns reference to the client-id data
- const std::vector<uint8_t> getClientId() const;
+ std::vector<uint8_t> getClientId() const;
/// @brief Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
std::string toText() const;
diff --git a/src/lib/dhcp/option_definition.cc b/src/lib/dhcp/option_definition.cc
index 59ff022..7f0d578 100644
--- a/src/lib/dhcp/option_definition.cc
+++ b/src/lib/dhcp/option_definition.cc
@@ -109,8 +109,6 @@ OptionPtr
OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
OptionBufferConstIter begin,
OptionBufferConstIter end) const {
- validate();
-
try {
switch(type_) {
case OPT_EMPTY_TYPE:
@@ -200,8 +198,6 @@ OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
OptionPtr
OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
const std::vector<std::string>& values) const {
- validate();
-
OptionBuffer buf;
if (!array_type_ && type_ != OPT_RECORD_TYPE) {
if (values.empty()) {
diff --git a/src/lib/dhcp/option_definition.h b/src/lib/dhcp/option_definition.h
index efb48b9..233f778 100644
--- a/src/lib/dhcp/option_definition.h
+++ b/src/lib/dhcp/option_definition.h
@@ -255,6 +255,13 @@ public:
/// @brief Check if the option definition is valid.
///
+ /// Note that it is a responsibility of the code that created
+ /// the OptionDefinition object to validate that it is valid.
+ /// This function will not be called internally anywhere in this
+ /// class to verify that the option definition is valid. Using
+ /// invalid option definition to create an instance of the
+ /// DHCP option leads to undefined behavior.
+ ///
/// @throw MalformedOptionDefinition option definition is invalid.
void validate() const;
@@ -274,13 +281,16 @@ public:
/// provided chunk of buffer. This function may be used to
/// create option which is to be sent in the outgoing packet.
///
+ /// @warning calling this function on invalid option definition
+ /// yields undefined behavior. Use \ref validate to test that
+ /// the option definition is valid.
+ ///
/// @param u option universe (V4 or V6).
/// @param type option type.
/// @param begin beginning of the option buffer.
/// @param end end of the option buffer.
///
/// @return instance of the DHCP option.
- /// @throw MalformedOptionDefinition if option definition is invalid.
/// @throw InvalidOptionValue if data for the option is invalid.
OptionPtr optionFactory(Option::Universe u, uint16_t type,
OptionBufferConstIter begin,
@@ -292,12 +302,15 @@ public:
/// whole provided buffer. This function may be used to
/// create option which is to be sent in the outgoing packet.
///
+ /// @warning calling this function on invalid option definition
+ /// yields undefined behavior. Use \ref validate to test that
+ /// the option definition is valid.
+ ///
/// @param u option universe (V4 or V6).
/// @param type option type.
/// @param buf option buffer.
///
/// @return instance of the DHCP option.
- /// @throw MalformedOptionDefinition if option definition is invalid.
/// @throw InvalidOptionValue if data for the option is invalid.
OptionPtr optionFactory(Option::Universe u, uint16_t type,
const OptionBuffer& buf = OptionBuffer()) const;
@@ -316,12 +329,15 @@ public:
/// must be tokenized into the vector of string values and this vector
/// can be supplied to this function.
///
+ /// @warning calling this function on invalid option definition
+ /// yields undefined behavior. Use \ref validate to test that
+ /// the option definition is valid.
+ ///
/// @param u option universe (V4 or V6).
/// @param type option type.
/// @param values a vector of values to be used to set data for an option.
///
/// @return instance of the DHCP option.
- /// @throw MalformedOptionDefinition if option definition is invalid.
/// @throw InvalidOptionValue if data for the option is invalid.
OptionPtr optionFactory(Option::Universe u, uint16_t type,
const std::vector<std::string>& values) const;
diff --git a/src/lib/dhcpsrv/Makefile.am b/src/lib/dhcpsrv/Makefile.am
index e721267..db82513 100644
--- a/src/lib/dhcpsrv/Makefile.am
+++ b/src/lib/dhcpsrv/Makefile.am
@@ -37,6 +37,7 @@ libb10_dhcpsrv_la_SOURCES += dbaccess_parser.cc dbaccess_parser.h
libb10_dhcpsrv_la_SOURCES += dhcpsrv_log.cc dhcpsrv_log.h
libb10_dhcpsrv_la_SOURCES += cfgmgr.cc cfgmgr.h
libb10_dhcpsrv_la_SOURCES += dhcp_config_parser.h
+libb10_dhcpsrv_la_SOURCES += key_from_key.h
libb10_dhcpsrv_la_SOURCES += lease_mgr.cc lease_mgr.h
libb10_dhcpsrv_la_SOURCES += lease_mgr_factory.cc lease_mgr_factory.h
libb10_dhcpsrv_la_SOURCES += memfile_lease_mgr.cc memfile_lease_mgr.h
diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc
index bcb7851..a3df8e1 100644
--- a/src/lib/dhcpsrv/alloc_engine.cc
+++ b/src/lib/dhcpsrv/alloc_engine.cc
@@ -285,8 +285,9 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
}
// Check if there's existing lease for that subnet/clientid/hwaddr combination.
- Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(hwaddr->hwaddr_, subnet->getID());
+ Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(*hwaddr, subnet->getID());
if (existing) {
+ std::cout << "Got lease using HWADdr" << std::endl;
// We have a lease already. This is a returning client, probably after
// its reboot.
existing = renewLease4(subnet, clientid, hwaddr, existing, fake_allocation);
@@ -301,6 +302,7 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
if (clientid) {
existing = LeaseMgrFactory::instance().getLease4(*clientid, subnet->getID());
if (existing) {
+ std::cout << "Got lease using Clientid" << std::endl;
// we have a lease already. This is a returning client, probably after
// its reboot.
existing = renewLease4(subnet, clientid, hwaddr, existing, fake_allocation);
diff --git a/src/lib/dhcpsrv/key_from_key.h b/src/lib/dhcpsrv/key_from_key.h
new file mode 100644
index 0000000..4fb9ddb
--- /dev/null
+++ b/src/lib/dhcpsrv/key_from_key.h
@@ -0,0 +1,82 @@
+// 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 KEY_FROM_KEY_H
+#define KEY_FROM_KEY_H
+
+#include <functional>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Utility class which cascades two key extractors.
+///
+/// The key extractor (a.k.a. key extraction class) is used by the
+/// key-based indices to obtain the indexing keys from the elements of
+/// a multi_index_container. The standard key extractors can be used
+/// to retrieve indexing key values by accessing members or methods
+/// exposed by the elements (objects or structures) stored in a
+/// multi_index_container. For example, if a container holds objects
+/// of type A, then the public members of object A or its accessors can
+/// be used by the standard extractor classes such as "member" or
+/// "const_mem_fun" respectively. Assume more complex scenario, where
+/// multi_index_container holds objects of a type A, object A exposes
+/// its public member B, which in turn exposes the accessor function
+/// returning object C. One may want to use the value C (e.g. integer)
+/// to index objects A in the container. This can't be solved by using
+/// standard key extractors because object C is nested in B and thus
+/// it is not directly accessible from A. However, it is possible
+/// to specify two distinct key extractors, one used to extract value
+/// C from B, another one to extract value B from A. These two extractors
+/// can be then wrapped by another key extractor which can be used
+/// to obtain index key C from object A. This key extractor is implemented
+/// as a functor class. The functor calls functors specified as
+/// template parameters to retrieve the index value from the cascaded
+/// structure.
+///
+/// @tparam KeyExtractor1 extractor used to extract the key value from
+/// the object containing it.
+/// @tparam KeyExtractor2 extractor used to extract the nested object
+/// containing a key.
+template<typename KeyExtractor1, typename KeyExtractor2>
+class KeyFromKeyExtractor {
+public:
+ typedef typename KeyExtractor1::result_type result_type;
+
+ /// @brief Constructor.
+ KeyFromKeyExtractor()
+ : key1_(KeyExtractor1()), key2_(KeyExtractor2()) { };
+
+ /// @brief Extract key value from the object hierarchy.
+ ///
+ /// @param arg the key value.
+ ///
+ /// @tparam key value type.
+ template<typename T>
+ result_type operator() (T& arg) const {
+ return (key1_(key2_(arg)));
+ }
+private:
+ /// Key Extractor used to extract the key value from the
+ /// object containing it.
+ KeyExtractor1 key1_;
+ /// Key Extractor used to extract the nested object
+ /// containing a key.
+ KeyExtractor2 key2_;
+};
+
+} // end of isc::dhcp namespace
+} // end of isc namespace
+
+#endif // KEY_FROM_KEY_H
diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc
index e5846eb..713d625 100644
--- a/src/lib/dhcpsrv/memfile_lease_mgr.cc
+++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc
@@ -56,7 +56,9 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const isc::asiolink::IOAddress& addr) cons
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
- Lease4Storage::iterator l = storage4_.find(addr);
+ typedef Lease4Storage::nth_index<0>::type SearchIndex;
+ const SearchIndex& idx = storage4_.get<0>();
+ Lease4Storage::iterator l = idx.find(addr);
if (l == storage4_.end()) {
return (Lease4Ptr());
} else {
@@ -77,16 +79,22 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr,
DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
.arg(hwaddr.toText());
- Lease4Storage::iterator l;
- for (l = storage4_.begin(); l != storage4_.end(); ++l) {
- if ( ((*l)->hwaddr_ == hwaddr.hwaddr_) &&
- ((*l)->subnet_id_ == subnet_id)) {
- return (*l);
- }
+ // We are going to use index #1 of the multi index container.
+ // We define SearchIndex locally in this function because
+ // currently only this function uses this index.
+ typedef Lease4Storage::nth_index<1>::type SearchIndex;
+ // Get the index.
+ const SearchIndex& idx = storage4_.get<1>();
+ // Try to find the lease using HWAddr and subnet id.
+ SearchIndex::const_iterator lease =
+ idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
+ // Lease was not found. Return empty pointer to the caller.
+ if (lease == idx.end()) {
+ return Lease4Ptr();
}
- // not found
- return (Lease4Ptr());
+ // Lease was found. Return it to the caller.
+ return (*lease);
}
Lease4Collection Memfile_LeaseMgr::getLease4(const ClientId& clientid) const {
@@ -100,16 +108,22 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const ClientId& client_id,
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id)
.arg(client_id.toText());
- Lease4Storage::iterator l;
- for (l = storage4_.begin(); l != storage4_.end(); ++l) {
- if ( (*(*l)->client_id_ == client_id) &&
- ((*l)->subnet_id_ == subnet_id)) {
- return (*l);
- }
- }
- // not found
- return (Lease4Ptr());
+ // We are going to use index #2 of the multi index container.
+ // We define SearchIndex locally in this function because
+ // currently only this function uses this index.
+ typedef Lease4Storage::nth_index<2>::type SearchIndex;
+ // Get the index.
+ const SearchIndex& idx = storage4_.get<2>();
+ // Try to get the lease using client id and subnet id.
+ SearchIndex::const_iterator lease =
+ idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
+ // Lease was not found. Return empty pointer to the caller.
+ if (lease == idx.end()) {
+ return Lease4Ptr();
+ }
+ // Lease was found. Return it to the caller.
+ return (*lease);
}
Lease6Ptr Memfile_LeaseMgr::getLease6(
@@ -139,15 +153,21 @@ Lease6Ptr Memfile_LeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID)
.arg(iaid).arg(subnet_id).arg(duid.toText());
- /// @todo: Slow, naive implementation. Write it using additional indexes
- for (Lease6Storage::iterator l = storage6_.begin(); l != storage6_.end(); ++l) {
- if ( (*((*l)->duid_) == duid) &&
- ( (*l)->iaid_ == iaid) &&
- ( (*l)->subnet_id_ == subnet_id)) {
- return (*l);
- }
+ // We are going to use index #1 of the multi index container.
+ // We define SearchIndex locally in this function because
+ // currently only this function uses this index.
+ typedef Lease6Storage::nth_index<1>::type SearchIndex;
+ // Get the index.
+ const SearchIndex& idx = storage6_.get<1>();
+ // Try to get the lease using the DUID, IAID and Subnet ID.
+ SearchIndex::const_iterator lease =
+ idx.find(boost::make_tuple(duid.getDuid(), iaid, subnet_id));
+ // Lease was not found. Return empty pointer.
+ if (lease == idx.end()) {
+ return (Lease6Ptr());
}
- return (Lease6Ptr());
+ // Lease was found, return it to the caller.
+ return (*lease);
}
void Memfile_LeaseMgr::updateLease4(const Lease4Ptr& lease) {
diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.h b/src/lib/dhcpsrv/memfile_lease_mgr.h
index 81e5fe3..4ac7536 100644
--- a/src/lib/dhcpsrv/memfile_lease_mgr.h
+++ b/src/lib/dhcpsrv/memfile_lease_mgr.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-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
@@ -16,12 +16,14 @@
#define MEMFILE_LEASE_MGR_H
#include <dhcp/hwaddr.h>
+#include <dhcpsrv/key_from_key.h>
#include <dhcpsrv/lease_mgr.h>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/composite_key.hpp>
namespace isc {
namespace dhcp {
@@ -220,29 +222,108 @@ public:
protected:
- typedef boost::multi_index_container< // this is a multi-index container...
- Lease6Ptr, // it will hold shared_ptr to leases6
- boost::multi_index::indexed_by< // and will be sorted by
- // IPv6 address that are unique. That particular key is a member
- // of the Lease6 structure, is of type IOAddress and can be accessed
- // by doing &Lease6::addr_
+ // This is a multi-index container, which holds elements that can
+ // be accessed using different search indexes.
+ typedef boost::multi_index_container<
+ // It holds pointers to Lease6 objects.
+ Lease6Ptr,
+ boost::multi_index::indexed_by<
+ // Specification of the first index starts here.
+ // This index sorts leases by IPv6 addresses represented as
+ // IOAddress objects.
boost::multi_index::ordered_unique<
boost::multi_index::member<Lease, isc::asiolink::IOAddress, &Lease::addr_>
+ >,
+
+ // Specification of the second index starts here.
+ boost::multi_index::ordered_unique<
+ // This is a composite index that will be used to search for
+ // the lease using three attributes: DUID, IAID, Subnet Id.
+ boost::multi_index::composite_key<
+ Lease6,
+ // The DUID value can't be directly accessed from the Lease6
+ // object because it is wrapped with the DUID object (actually
+ // pointer to this object). Therefore we need to use
+ // KeyFromKeyExtractor class to extract the DUID value from
+ // this cascaded structure.
+ KeyFromKeyExtractor<
+ // The value of the DUID is accessed by the getDuid() method
+ // from the DUID object.
+ boost::multi_index::const_mem_fun<DUID, std::vector<uint8_t>,
+ &DUID::getDuid>,
+ // The DUID object is stored in the duid_ member of the
+ // Lease6 object.
+ boost::multi_index::member<Lease6, DuidPtr, &Lease6::duid_>
+ >,
+ // The two other ingredients of this index are IAID and
+ // subnet id.
+ boost::multi_index::member<Lease6, uint32_t, &Lease6::iaid_>,
+ boost::multi_index::member<Lease, SubnetID, &Lease::subnet_id_>
+ >
>
>
- > Lease6Storage; // Let the whole contraption be called Lease6Storage.
-
- typedef boost::multi_index_container< // this is a multi-index container...
- Lease4Ptr, // it will hold shared_ptr to leases6
- boost::multi_index::indexed_by< // and will be sorted by
- // IPv6 address that are unique. That particular key is a member
- // of the Lease6 structure, is of type IOAddress and can be accessed
- // by doing &Lease6::addr_
+ > Lease6Storage; // Specify the type name of this container.
+
+ // This is a multi-index container, which holds elements that can
+ // be accessed using different search indexes.
+ typedef boost::multi_index_container<
+ // It holds pointers to Lease4 objects.
+ Lease4Ptr,
+ // Specification of search indexes starts here.
+ boost::multi_index::indexed_by<
+ // Specification of the first index starts here.
+ // This index sorts leases by IPv4 addresses represented as
+ // IOAddress objects.
boost::multi_index::ordered_unique<
+ // The IPv4 address are held in addr_ members that belong to
+ // Lease class.
boost::multi_index::member<Lease, isc::asiolink::IOAddress, &Lease::addr_>
+ >,
+
+ // Specification of the second index starts here.
+ boost::multi_index::ordered_unique<
+ // This is a composite index that combines two attributes of the
+ // Lease4 object: hardware address and subnet id.
+ boost::multi_index::composite_key<
+ Lease4,
+ // The hardware address is held in the hwaddr_ member of the
+ // Lease4 object.
+ boost::multi_index::member<Lease4, std::vector<uint8_t>,
+ &Lease4::hwaddr_>,
+ // The subnet id is held in the subnet_id_ member of Lease4
+ // class. Note that the subnet_id_ is defined in the base
+ // class (Lease) so we have to point to this class rather
+ // than derived class: Lease4.
+ boost::multi_index::member<Lease, SubnetID, &Lease::subnet_id_>
+ >
+ >,
+
+ // Specification of the third index starts here.
+ boost::multi_index::ordered_unique<
+ // This is a composite index that uses two values to search for a
+ // lease: client id and subnet id.
+ boost::multi_index::composite_key<
+ Lease4,
+ // The client id value is not directly accessible through the
+ // Lease4 object as it is wrapped with the ClientIdPtr object.
+ // Therefore we use the KeyFromKeyExtractor class to access
+ // client id through this cascaded structure. The client id
+ // is used as an index value.
+ KeyFromKeyExtractor<
+ // Specify that the vector holding client id value can be obtained
+ // from the ClientId object.
+ boost::multi_index::const_mem_fun<ClientId, std::vector<uint8_t>,
+ &ClientId::getClientId>,
+ // Specify that the ClientId object (actually pointer to it) can
+ // be accessed by the client_id_ member of Lease4 class.
+ boost::multi_index::member<Lease4, ClientIdPtr, &Lease4::client_id_>
+ >,
+ // The subnet id is accessed through the subnet_id_ member.
+ boost::multi_index::member<Lease, uint32_t, &Lease::subnet_id_>
+ >
>
>
- > Lease4Storage; // Let the whole contraption be called Lease6Storage.
+ > Lease4Storage; // Specify the type name for this container.
/// @brief stores IPv4 leases
Lease4Storage storage4_;
diff --git a/src/lib/dhcpsrv/subnet.h b/src/lib/dhcpsrv/subnet.h
index e797bdf..5a16647 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/key_from_key.h>
#include <dhcpsrv/option_space_container.h>
#include <dhcpsrv/pool.h>
#include <dhcpsrv/triplet.h>
@@ -82,55 +83,6 @@ public:
/// A pointer to option descriptor.
typedef boost::shared_ptr<OptionDescriptor> OptionDescriptorPtr;
- /// @brief Extractor class to extract key with another key.
- ///
- /// This class solves the problem of accessing index key values
- /// that are stored in objects nested in other objects.
- /// Each OptionDescriptor structure contains the OptionPtr object.
- /// The value retured by one of its accessors (getType) is used
- /// as an indexing value in the multi_index_container defined below.
- /// There is no easy way to mark that value returned by Option::getType
- /// should be an index of this multi_index_container. There are standard
- /// key extractors such as 'member' or 'mem_fun' but they are not
- /// sufficient here. The former can be used to mark that member of
- /// the structure that is held in the container should be used as an
- /// indexing value. The latter can be used if the indexing value is
- /// a product of the class being held in the container. In this complex
- /// scenario when the indexing value is a product of the function that
- /// is wrapped by the structure, this new extractor template has to be
- /// defined. The template class provides a 'chain' of two extractors
- /// to access the value returned by nested object and to use it as
- /// indexing value.
- /// For some more examples of complex keys see:
- /// http://www.cs.brown.edu/~jwicks/boost/libs/multi_index/doc/index.html
- ///
- /// @tparam KeyExtractor1 extractor used to access data in
- /// OptionDescriptor::option
- /// @tparam KeyExtractor2 extractor used to access
- /// OptionDescriptor::option member.
- template<typename KeyExtractor1, typename KeyExtractor2>
- class KeyFromKey {
- public:
- typedef typename KeyExtractor1::result_type result_type;
-
- /// @brief Constructor.
- KeyFromKey()
- : key1_(KeyExtractor1()), key2_(KeyExtractor2()) { };
-
- /// @brief Extract key with another key.
- ///
- /// @param arg the key value.
- ///
- /// @tparam key value type.
- template<typename T>
- result_type operator() (T& arg) const {
- return (key1_(key2_(arg)));
- }
- private:
- KeyExtractor1 key1_; ///< key 1.
- KeyExtractor2 key2_; ///< key 2.
- };
-
/// @brief Multi index container for DHCP option descriptors.
///
/// This container comprises three indexes to access option
@@ -169,10 +121,10 @@ public:
boost::multi_index::sequenced<>,
// Start definition of index #1.
boost::multi_index::hashed_non_unique<
- // KeyFromKey is the index key extractor that allows accessing
- // option type being held by the OptionPtr through
+ // KeyFromKeyExtractor is the index key extractor that allows
+ // accessing option type being held by the OptionPtr through
// OptionDescriptor structure.
- KeyFromKey<
+ KeyFromKeyExtractor<
// Use option type as the index key. The type is held
// in OptionPtr object so we have to call Option::getType
// to retrieve this key for each element.
More information about the bind10-changes
mailing list