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 {
/// 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;
......
......@@ -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) {
......
// 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<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.
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<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 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, 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_;
......
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