Commit 0cbbce43 authored by Marcin Siodelski's avatar Marcin Siodelski

[2701] Added composite index to the container holding leases.

This change applies to the Memfile backend and is intended to significantly
improve its performance.
parent e0c71421
...@@ -58,7 +58,7 @@ class DUID { ...@@ -58,7 +58,7 @@ class DUID {
/// returned it. In any case, this method should be used only sporadically. /// returned it. In any case, this method should be used only sporadically.
/// If there are frequent uses, we must implement some other method /// If there are frequent uses, we must implement some other method
/// (e.g. storeSelf()) that will avoid data copying. /// (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 /// @brief Returns the DUID type
DUIDType getType() const; DUIDType getType() const;
......
...@@ -79,26 +79,22 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr, ...@@ -79,26 +79,22 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr,
DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id) DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
.arg(hwaddr.toText()); .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; typedef Lease4Storage::nth_index<1>::type SearchIndex;
// Get the index.
const SearchIndex& idx = storage4_.get<1>(); const SearchIndex& idx = storage4_.get<1>();
SearchIndex::const_iterator lease = idx.find(boost::make_tuple(hwaddr.hwaddr_, // Try to find the lease using HWAddr and subnet id.
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()) { if (lease == idx.end()) {
return Lease4Ptr(); return Lease4Ptr();
} }
// Lease was found. Return it to the caller.
return (*lease); 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 { Lease4Collection Memfile_LeaseMgr::getLease4(const ClientId& clientid) const {
...@@ -113,26 +109,21 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const ClientId& client_id, ...@@ -113,26 +109,21 @@ Lease4Ptr Memfile_LeaseMgr::getLease4(const ClientId& client_id,
DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id) DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id)
.arg(client_id.toText()); .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; typedef Lease4Storage::nth_index<2>::type SearchIndex;
// Get the index.
const SearchIndex& idx = storage4_.get<2>(); const SearchIndex& idx = storage4_.get<2>();
SearchIndex::const_iterator lease = idx.find(boost::make_tuple(client_id.getClientId(), // Try to get the lease using client id and subnet id.
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()) { if (lease == idx.end()) {
return Lease4Ptr(); return Lease4Ptr();
} }
// Lease was found. Return it to the caller.
return (*lease); 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( Lease6Ptr Memfile_LeaseMgr::getLease6(
...@@ -162,15 +153,21 @@ Lease6Ptr Memfile_LeaseMgr::getLease6(const DUID& duid, uint32_t iaid, ...@@ -162,15 +153,21 @@ Lease6Ptr Memfile_LeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID) DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID)
.arg(iaid).arg(subnet_id).arg(duid.toText()); .arg(iaid).arg(subnet_id).arg(duid.toText());
/// @todo: Slow, naive implementation. Write it using additional indexes // We are going to use index #1 of the multi index container.
for (Lease6Storage::iterator l = storage6_.begin(); l != storage6_.end(); ++l) { // We define SearchIndex locally in this function because
if ( (*((*l)->duid_) == duid) && // currently only this function uses this index.
( (*l)->iaid_ == iaid) && typedef Lease6Storage::nth_index<1>::type SearchIndex;
( (*l)->subnet_id_ == subnet_id)) { // Get the index.
return (*l); 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) { void Memfile_LeaseMgr::updateLease4(const Lease4Ptr& lease) {
......
// 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 // Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above // purpose with or without fee is hereby granted, provided that the above
...@@ -244,49 +244,106 @@ protected: ...@@ -244,49 +244,106 @@ protected:
KeyExtractor2 key2_; ///< key 2. KeyExtractor2 key2_; ///< key 2.
}; };
// This is a multi-index container, which holds elements that can
typedef boost::multi_index_container< // this is a multi-index container... // be accessed using different search indexes.
Lease6Ptr, // it will hold shared_ptr to leases6 typedef boost::multi_index_container<
boost::multi_index::indexed_by< // and will be sorted by // It holds pointers to Lease6 objects.
// IPv6 address that are unique. That particular key is a member Lease6Ptr,
// of the Lease6 structure, is of type IOAddress and can be accessed boost::multi_index::indexed_by<
// by doing &Lease6::addr_ // 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::ordered_unique<
boost::multi_index::member<Lease, isc::asiolink::IOAddress, &Lease::addr_> 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 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, 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. > Lease6Storage; // Specify the type name of this container.
typedef boost::multi_index_container< // this is a multi-index container... // This is a multi-index container, which holds elements that can
Lease4Ptr, // it will hold shared_ptr to leases6 // be accessed using different search indexes.
boost::multi_index::indexed_by< // and will be sorted by typedef boost::multi_index_container<
// IPv6 address that are unique. That particular key is a member // It holds pointers to Lease4 objects.
// of the Lease6 structure, is of type IOAddress and can be accessed Lease4Ptr,
// by doing &Lease6::addr_ // Specification of search indexes starts here.
boost::multi_index::hashed_unique< 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_> boost::multi_index::member<Lease, isc::asiolink::IOAddress, &Lease::addr_>
>, >,
// Specification of the second index starts here.
boost::multi_index::ordered_unique< 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< boost::multi_index::composite_key<
Lease4, Lease4,
// The hardware address is held in the hwaddr_ member of the
// Lease4 object.
boost::multi_index::member<Lease4, std::vector<uint8_t>, boost::multi_index::member<Lease4, std::vector<uint8_t>,
&Lease4::hwaddr_>, &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_> boost::multi_index::member<Lease, SubnetID, &Lease::subnet_id_>
> >
>, >,
// Specification of the third index starts here.
boost::multi_index::ordered_unique< 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< boost::multi_index::composite_key<
Lease4, 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< KeyFromKey<
// 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>, boost::multi_index::const_mem_fun<ClientId, std::vector<uint8_t>,
&ClientId::getClientId>, &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_> 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_> 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 /// @brief stores IPv4 leases
Lease4Storage storage4_; Lease4Storage storage4_;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment