From 0cbbce437ec709e5dde8056c0462d7bd501f65c9 Mon Sep 17 00:00:00 2001 From: Marcin Siodelski Date: Thu, 14 Feb 2013 11:08:05 +0100 Subject: [PATCH] [2701] Added composite index to the container holding leases. This change applies to the Memfile backend and is intended to significantly improve its performance. --- src/lib/dhcp/duid.h | 2 +- src/lib/dhcpsrv/memfile_lease_mgr.cc | 67 ++++++++++---------- src/lib/dhcpsrv/memfile_lease_mgr.h | 93 ++++++++++++++++++++++------ 3 files changed, 108 insertions(+), 54 deletions(-) diff --git a/src/lib/dhcp/duid.h b/src/lib/dhcp/duid.h index c28b98a1b2..21c6b8f60f 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 getDuid() const; + std::vector getDuid() const; /// @brief Returns the DUID type DUIDType getType() const; diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc index 191c3e2afb..713d6257f9 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.cc +++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc @@ -79,26 +79,22 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr, DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id) .arg(hwaddr.toText()); + // 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>(); - SearchIndex::const_iterator lease = idx.find(boost::make_tuple(hwaddr.hwaddr_, - subnet_id)); + // 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(); } + // Lease was found. Return it to the caller. return (*lease); - - Lease4Storage::iterator l; - for (l = storage4_.begin(); l != storage4_.end(); ++l) { - if ( ((*l)->hwaddr_ == hwaddr.hwaddr_) && - ((*l)->subnet_id_ == subnet_id)) { - return (*l); - } - } - - // not found - return (Lease4Ptr()); } Lease4Collection Memfile_LeaseMgr::getLease4(const ClientId& clientid) const { @@ -113,26 +109,21 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const ClientId& client_id, DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id) .arg(client_id.toText()); + // 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>(); - SearchIndex::const_iterator lease = idx.find(boost::make_tuple(client_id.getClientId(), - subnet_id)); + // 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); - - 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()); } Lease6Ptr Memfile_LeaseMgr::getLease6( @@ -162,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 202aa34f7f..917e06415b 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 @@ -244,49 +244,106 @@ protected: KeyExtractor2 key2_; ///< key 2. }; - - 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 + >, + + // 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 KeyFromKey + // class to extract the DUID value from this cascaded structure. + KeyFromKey< + // The value of the DUID is accessed by the getDuid() method + // from the DUID object. + boost::multi_index::const_mem_fun, + &DUID::getDuid>, + // The DUID object is stored in the duid_ member of the + // Lease6 object. + boost::multi_index::member + >, + // The two other ingredients of this index are IAID and + // subnet id. + boost::multi_index::member, + boost::multi_index::member + > > > - > 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_ - boost::multi_index::hashed_unique< + > 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 >, + + // 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::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 > >, + + // 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 KeyFromKey class to specify the key + // that gets the client id value through this cascade. KeyFromKey< + // Specify that the vector holding client id value can be obtained + // from the ClientId object. boost::multi_index::const_mem_fun, &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 >, + // The subnet id is accessed through the subnet_id_ member. boost::multi_index::member > > > - > Lease4Storage; // Let the whole contraption be called Lease6Storage. + > Lease4Storage; // Specify the type name for this container. /// @brief stores IPv4 leases Lease4Storage storage4_; -- GitLab