Parcourir la source

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

This change applies to the Memfile backend and is intended to significantly
improve its performance.
Marcin Siodelski il y a 12 ans
Parent
commit
0cbbce437e
3 fichiers modifiés avec 108 ajouts et 54 suppressions
  1. 1 1
      src/lib/dhcp/duid.h
  2. 32 35
      src/lib/dhcpsrv/memfile_lease_mgr.cc
  3. 75 18
      src/lib/dhcpsrv/memfile_lease_mgr.h

+ 1 - 1
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;

+ 32 - 35
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) {

+ 75 - 18
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<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_;