From: Francis Dupont Date: Sun, 13 Jan 2019 16:11:57 +0000 (+0100) Subject: [313-return-a-list-of-all-reservations-by-subnet-id] Added getPage[46] X-Git-Tag: 429-Updated-StampedValue-to-support-reals_base~85 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d94a41a771a599055b091bb9c651732c189aa9f;p=thirdparty%2Fkea.git [313-return-a-list-of-all-reservations-by-subnet-id] Added getPage[46] --- diff --git a/src/lib/dhcpsrv/base_host_data_source.h b/src/lib/dhcpsrv/base_host_data_source.h index 815a0d9d07..9c56abd258 100644 --- a/src/lib/dhcpsrv/base_host_data_source.h +++ b/src/lib/dhcpsrv/base_host_data_source.h @@ -40,6 +40,28 @@ public: isc::BadValue(file, line, what) { }; }; +/// @brief Wraps value holding size of the page with host reservations. +class HostPageSize { +public: + + /// @brief Constructor. + /// + /// @param page_size page size value. + /// @throw OutOfRange if page size is 0 or greater than uint32_t numeric + /// limit. + explicit HostPageSize(const size_t page_size) : page_size_(page_size) { + if (page_size_ == 0) { + isc_throw(OutOfRange, "page size of retrieved hosts must not be 0"); + } + if (page_size_ > std::numeric_limits::max()) { + isc_throw(OutOfRange, "page size of retrieved hosts must not be greate than " + << std::numeric_limits::max()); + } + } + + const size_t page_size_; ///< Holds page size. +}; + /// @brief Base interface for the classes implementing simple data source /// for host reservations. /// @@ -114,6 +136,50 @@ public: virtual ConstHostCollection getAll6(const SubnetID& subnet_id) const = 0; + /// @brief Returns range of hosts in a DHCPv4 subnet. + /// + /// This method implements paged browsing of host databases. The + /// parameters specify a page size, an index in sources and the + /// starting host id of the range. If not zero this host id is + /// excluded from the returned range. When a source is exhausted + /// the index is updated. There is no guarantee about the order + /// of returned host reservations, only the sources are ordered. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source. + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Host collection (may be empty). + virtual ConstHostCollection + getPage4(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const = 0; + + /// @brief Returns range of hosts in a DHCPv6 subnet. + /// + /// This method implements paged browsing of host databases. The + /// parameters specify a page size, an index in sources and the + /// starting host id of the range. If not zero this host id is + /// excluded from the returned range. When a source is exhausted + /// the index is updated. There is no guarantee about the order + /// of returned host reservations, only the sources are ordered. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source. + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Host collection (may be empty). + virtual ConstHostCollection + getPage6(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const = 0; + /// @brief Returns a collection of hosts using the specified IPv4 address. /// /// This method may return multiple @c Host objects if they are connected diff --git a/src/lib/dhcpsrv/cfg_hosts.cc b/src/lib/dhcpsrv/cfg_hosts.cc index 386bc2888e..81051cb4e6 100644 --- a/src/lib/dhcpsrv/cfg_hosts.cc +++ b/src/lib/dhcpsrv/cfg_hosts.cc @@ -49,7 +49,7 @@ CfgHosts::getAll(const Host::IdentifierType& identifier_type, ConstHostCollection CfgHosts::getAll4(const SubnetID& subnet_id) const { // Do not issue logging message here because it will be logged by - // the getAllInternal method. + // the getAllInternal4 method. ConstHostCollection collection; getAllInternal4(subnet_id, collection); return (collection); @@ -58,7 +58,7 @@ CfgHosts::getAll4(const SubnetID& subnet_id) const { HostCollection CfgHosts::getAll4(const SubnetID& subnet_id) { // Do not issue logging message here because it will be logged by - // the getAllInternal method. + // the getAllInternal4 method. HostCollection collection; getAllInternal4(subnet_id, collection); return (collection); @@ -67,7 +67,7 @@ CfgHosts::getAll4(const SubnetID& subnet_id) { ConstHostCollection CfgHosts::getAll6(const SubnetID& subnet_id) const { // Do not issue logging message here because it will be logged by - // the getAllInternal method. + // the getAllInternal6 method. ConstHostCollection collection; getAllInternal6(subnet_id, collection); return (collection); @@ -76,12 +76,72 @@ CfgHosts::getAll6(const SubnetID& subnet_id) const { HostCollection CfgHosts::getAll6(const SubnetID& subnet_id) { // Do not issue logging message here because it will be logged by - // the getAllInternal method. + // the getAllInternal6 method. HostCollection collection; getAllInternal6(subnet_id, collection); return (collection); } +ConstHostCollection +CfgHosts::getPage4(const SubnetID& subnet_id, + size_t& /*source_index*/, + uint64_t lower_host_id, + const HostPageSize& page_size) const { + // Do not issue logging message here because it will be logged by + // the getPageInternal4 method. + ConstHostCollection collection; + getPageInternal4(subnet_id, + lower_host_id, + page_size, + collection); + return (collection); +} + +HostCollection +CfgHosts::getPage4(const SubnetID& subnet_id, + size_t& /*source_index*/, + uint64_t lower_host_id, + const HostPageSize& page_size) { + // Do not issue logging message here because it will be logged by + // the getPageInternal4 method. + HostCollection collection; + getPageInternal4(subnet_id, + lower_host_id, + page_size, + collection); + return (collection); +} + +ConstHostCollection +CfgHosts::getPage6(const SubnetID& subnet_id, + size_t& /*source_index*/, + uint64_t lower_host_id, + const HostPageSize& page_size) const { + // Do not issue logging message here because it will be logged by + // the getPageInternal6 method. + ConstHostCollection collection; + getPageInternal6(subnet_id, + lower_host_id, + page_size, + collection); + return (collection); +} + +HostCollection +CfgHosts::getPage6(const SubnetID& subnet_id, + size_t& /*source_index*/, + uint64_t lower_host_id, + const HostPageSize& page_size) { + // Do not issue logging message here because it will be logged by + // the getPageInternal6 method. + HostCollection collection; + getPageInternal6(subnet_id, + lower_host_id, + page_size, + collection); + return (collection); +} + ConstHostCollection CfgHosts::getAll4(const IOAddress& address) const { // Do not issue logging message here because it will be logged by @@ -213,6 +273,88 @@ CfgHosts::getAllInternal6(const SubnetID& subnet_id, .arg(storage.size()); } +template +void +CfgHosts::getPageInternal4(const SubnetID& subnet_id, + uint64_t lower_host_id, + const HostPageSize& page_size, + Storage& storage) const { + + LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_SUBNET_ID4) + .arg(subnet_id); + + // Use the host id last index. + const HostContainerIndex4& idx = hosts_.get<4>(); + HostContainerIndex4::const_iterator host = idx.lower_bound(lower_host_id); + + // Exclude the lower bound id when it is not zero. + if (lower_host_id && + (host != idx.end()) && ((*host)->getHostId() == lower_host_id)) { + ++host; + } + + // Return hosts in the subnet within the page size. + for (; host != idx.end(); ++host) { + if ((*host)->getIPv4SubnetID() != subnet_id) { + continue; + } + LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA, + HOSTS_CFG_GET_ALL_SUBNET_ID4_HOST) + .arg(subnet_id) + .arg((*host)->toText()); + storage.push_back(*host); + if (storage.size() >= page_size.page_size_) { + break; + } + } + + // Log how many hosts have been found. + LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ALL_SUBNET_ID4_COUNT) + .arg(subnet_id) + .arg(storage.size()); +} + +template +void +CfgHosts::getPageInternal6(const SubnetID& subnet_id, + uint64_t lower_host_id, + const HostPageSize& page_size, + Storage& storage) const { + + LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_SUBNET_ID6) + .arg(subnet_id); + + // Use the host id last index. + const HostContainerIndex4& idx = hosts_.get<4>(); + HostContainerIndex4::const_iterator host = idx.lower_bound(lower_host_id); + + // Exclude the lower bound id when it is not zero. + if (lower_host_id && + (host != idx.end()) && ((*host)->getHostId() == lower_host_id)) { + ++host; + } + + // Return hosts in the subnet within the page size. + for (; host != idx.end(); ++host) { + if ((*host)->getIPv6SubnetID() != subnet_id) { + continue; + } + LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA, + HOSTS_CFG_GET_ALL_SUBNET_ID6_HOST) + .arg(subnet_id) + .arg((*host)->toText()); + storage.push_back(*host); + if (storage.size() >= page_size.page_size_) { + break; + } + } + + // Log how many hosts have been found. + LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ALL_SUBNET_ID6_COUNT) + .arg(subnet_id) + .arg(storage.size()); +} + template void @@ -644,6 +786,7 @@ CfgHosts::add4(const HostPtr& host) { } // This is a new instance - add it. + host->setHostId(++next_host_id_); hosts_.insert(host); } diff --git a/src/lib/dhcpsrv/cfg_hosts.h b/src/lib/dhcpsrv/cfg_hosts.h index eada8a2a0c..b2d400aaa8 100644 --- a/src/lib/dhcpsrv/cfg_hosts.h +++ b/src/lib/dhcpsrv/cfg_hosts.h @@ -119,6 +119,78 @@ public: virtual HostCollection getAll6(const SubnetID& subnet_id); + /// @brief Returns range of hosts in a DHCPv4 subnet. + /// + /// This method returns a page of @c Host objects which represent + /// reservations in a specified subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source (unused). + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Collection of const @c Host objects (may be empty). + virtual ConstHostCollection + getPage4(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const; + + /// @brief Returns range of hosts in a DHCPv4 subnet. + /// + /// This method returns a page of @c Host objects which represent + /// reservations in a specified subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source (unused). + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Collection of non-const @c Host objects (may be empty). + virtual HostCollection + getPage4(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size); + + /// @brief Returns range of hosts in a DHCPv6 subnet. + /// + /// This method returns a page of @c Host objects which represent + /// reservations in a specified subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source (unused). + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Collection of const @c Host objects (may be empty). + virtual ConstHostCollection + getPage6(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const; + + /// @brief Returns range of hosts in a DHCPv6 subnet. + /// + /// This method returns a page of @c Host objects which represent + /// reservations in a specified subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source (unused). + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Collection of non-const @c Host objects (may be empty). + virtual HostCollection + getPage6(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size); + /// @brief Returns a collection of hosts using the specified IPv4 address. /// /// This method may return multiple @c Host objects if they are connected @@ -360,7 +432,7 @@ private: /// @brief Returns @c Host objects for the specific identifier and type. /// - /// This private method is called by the @c CfgHosts::getAllInternal + /// This private method is called by the @c CfgHosts::getAll /// method which finds the @c Host objects using specified identifier. /// The retrieved objects are appended to the @c storage container. /// @@ -378,7 +450,7 @@ private: /// @brief Returns @c Host objects in a DHCPv4 subnet. /// - /// This private method is called by the @c CfgHosts::getAllInternal + /// This private method is called by the @c CfgHosts::getAll4 /// method which finds the @c Host objects in a specified subnet. /// The retrieved objects are appended to the @c storage container. /// @@ -392,7 +464,7 @@ private: /// @brief Returns @c Host objects in a DHCPv6 subnet. /// - /// This private method is called by the @c CfgHosts::getAllInternal + /// This private method is called by the @c CfgHosts::getAll6 /// method which finds the @c Host objects in a specified subnet. /// The retrieved objects are appended to the @c storage container. /// @@ -404,6 +476,44 @@ private: void getAllInternal6(const SubnetID& subnet_id, Storage& storage) const; + /// @brief Returns a page of @c Host objects in a DHCPv4 subnet. + /// + /// This private method is called by the @c CfgHosts::getPage4 + /// method which finds the @c Host objects in a specified subnet. + /// The retrieved objects are appended to the @c storage container. + /// + /// @param subnet_id Subnet identifier. + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// @param [out] storage Container to which the retrieved objects are + /// appended. + /// @tparam One of the @c ConstHostCollection of @c HostCollection. + template + void getPageInternal4(const SubnetID& subnet_id, + uint64_t lower_host_id, + const HostPageSize& page_size, + Storage& storage) const; + + /// @brief Returns a page of @c Host objects in a DHCPv6 subnet. + /// + /// This private method is called by the @c CfgHosts::getPage6 + /// method which finds the @c Host objects in a specified subnet. + /// The retrieved objects are appended to the @c storage container. + /// + /// @param subnet_id Subnet identifier. + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// @param [out] storage Container to which the retrieved objects are + /// appended. + /// @tparam One of the @c ConstHostCollection of @c HostCollection. + template + void getPageInternal6(const SubnetID& subnet_id, + uint64_t lower_host_id, + const HostPageSize& page_size, + Storage& storage) const; + /// @brief Returns @c Host objects for the specified IPv4 address. /// /// This private method is called by the @c CfgHosts::getAll4 methods @@ -522,12 +632,17 @@ private: /// the IPv6 subnet. virtual void add6(const HostPtr& host); + /// @brief Next host id. + uint64_t next_host_id_; + /// @brief Multi-index container holding @c Host objects. /// /// It can be used for finding hosts by the following criteria: /// - IPv4 address /// - DUID /// - HW/MAC address + /// - subnet ID + /// - host ID HostContainer hosts_; /// @brief Multi-index container holding @c Host objects with v6 reservations. diff --git a/src/lib/dhcpsrv/cql_host_data_source.cc b/src/lib/dhcpsrv/cql_host_data_source.cc index ad9dd5d71b..0b513c63f1 100644 --- a/src/lib/dhcpsrv/cql_host_data_source.cc +++ b/src/lib/dhcpsrv/cql_host_data_source.cc @@ -321,6 +321,26 @@ public: // associated with a host using subnet identifier. static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID = "GET_HOST_BY_IPV6_SUBNET_ID"; + + // Retrieves host information along with the IPv4 options associated + // with it using a subnet identifier. First page. + static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_LIMIT = + "GET_HOST_BY_IPV4_SUBNET_ID_LIMIT"; + + // Retrieves host information along with the IPv4 options associated + // with it using a subnet identifier. Next page. + static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_PAGE = + "GET_HOST_BY_IPV4_SUBNET_ID_PAGE"; + + // Retrieves host information along with the IPv6 options associated + // with it using a subnet identifier. First page. + static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID_LIMIT = + "GET_HOST_BY_IPV6_SUBNET_ID_LIMIT"; + + // Retrieves host information along with the IPv6 options associated + // with it using a subnet identifier. Next page. + static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID_PAGE = + "GET_HOST_BY_IPV6_SUBNET_ID_PAGE"; /// @} /// @brief Cassandra statements @@ -432,6 +452,10 @@ constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS; constexpr StatementTag CqlHostExchange::DELETE_HOST; constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID; constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID; +constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_LIMIT; +constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_PAGE; +constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_LIMIT; +constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_PAGE; StatementMap CqlHostExchange::tagged_statements_ = { {INSERT_HOST, @@ -846,6 +870,154 @@ StatementMap CqlHostExchange::tagged_statements_ = { "FROM host_reservations " "WHERE host_ipv6_subnet_id = ? " "ALLOW FILTERING " + }}, + + {GET_HOST_BY_IPV4_SUBNET_ID_LIMIT, + {GET_HOST_BY_IPV4_SUBNET_ID_LIMIT, + "SELECT " + "id, " + "host_identifier, " + "host_identifier_type, " + "host_ipv4_subnet_id, " + "host_ipv6_subnet_id, " + "host_ipv4_address, " + "host_ipv4_next_server, " + "host_ipv4_server_hostname, " + "host_ipv4_boot_file_name, " + "auth_key, " + "hostname, " + "user_context, " + "host_ipv4_client_classes, " + "host_ipv6_client_classes, " + "reserved_ipv6_prefix_address, " + "reserved_ipv6_prefix_length, " + "reserved_ipv6_prefix_address_type, " + "iaid, " + "option_universe, " + "option_code, " + "option_value, " + "option_formatted_value, " + "option_space, " + "option_is_persistent, " + "option_client_class, " + "option_subnet_id, " + "option_user_context, " + "option_scope_id " + "FROM host_reservations " + "WHERE host_ipv4_subnet_id = ? " + "LIMIT ? " + "ALLOW FILTERING " + }}, + + {GET_HOST_BY_IPV4_SUBNET_ID_PAGE, + {GET_HOST_BY_IPV4_SUBNET_ID_PAGE, + "SELECT " + "id, " + "host_identifier, " + "host_identifier_type, " + "host_ipv4_subnet_id, " + "host_ipv6_subnet_id, " + "host_ipv4_address, " + "host_ipv4_next_server, " + "host_ipv4_server_hostname, " + "host_ipv4_boot_file_name, " + "auth_key, " + "hostname, " + "user_context, " + "host_ipv4_client_classes, " + "host_ipv6_client_classes, " + "reserved_ipv6_prefix_address, " + "reserved_ipv6_prefix_length, " + "reserved_ipv6_prefix_address_type, " + "iaid, " + "option_universe, " + "option_code, " + "option_value, " + "option_formatted_value, " + "option_space, " + "option_is_persistent, " + "option_client_class, " + "option_subnet_id, " + "option_user_context, " + "option_scope_id " + "FROM host_reservations " + "WHERE host_ipv4_subnet_id = ? AND TOKEN(id) > TOKEN(?) " + "LIMIT ? " + "ALLOW FILTERING " + }}, + + {GET_HOST_BY_IPV6_SUBNET_ID_LIMIT, + {GET_HOST_BY_IPV6_SUBNET_ID_LIMIT, + "SELECT " + "id, " + "host_identifier, " + "host_identifier_type, " + "host_ipv4_subnet_id, " + "host_ipv6_subnet_id, " + "host_ipv4_address, " + "host_ipv4_next_server, " + "host_ipv4_server_hostname, " + "host_ipv4_boot_file_name, " + "auth_key, " + "hostname, " + "user_context, " + "host_ipv4_client_classes, " + "host_ipv6_client_classes, " + "reserved_ipv6_prefix_address, " + "reserved_ipv6_prefix_length, " + "reserved_ipv6_prefix_address_type, " + "iaid, " + "option_universe, " + "option_code, " + "option_value, " + "option_formatted_value, " + "option_space, " + "option_is_persistent, " + "option_client_class, " + "option_subnet_id, " + "option_user_context, " + "option_scope_id " + "FROM host_reservations " + "WHERE host_ipv6_subnet_id = ? " + "LIMIT ? " + "ALLOW FILTERING " + }}, + + {GET_HOST_BY_IPV6_SUBNET_ID_PAGE, + {GET_HOST_BY_IPV6_SUBNET_ID_PAGE, + "SELECT " + "id, " + "host_identifier, " + "host_identifier_type, " + "host_ipv4_subnet_id, " + "host_ipv6_subnet_id, " + "host_ipv4_address, " + "host_ipv4_next_server, " + "host_ipv4_server_hostname, " + "host_ipv4_boot_file_name, " + "auth_key, " + "hostname, " + "user_context, " + "host_ipv4_client_classes, " + "host_ipv6_client_classes, " + "reserved_ipv6_prefix_address, " + "reserved_ipv6_prefix_length, " + "reserved_ipv6_prefix_address_type, " + "iaid, " + "option_universe, " + "option_code, " + "option_value, " + "option_formatted_value, " + "option_space, " + "option_is_persistent, " + "option_client_class, " + "option_subnet_id, " + "option_user_context, " + "option_scope_id " + "FROM host_reservations " + "WHERE host_ipv6_subnet_id = ? AND TOKEN(id) > TOKEN(?) " + "LIMIT ? " + "ALLOW FILTERING " }} }; @@ -1526,6 +1698,32 @@ public: /// @param subnet_id identifier of the subnet to which hosts belong virtual ConstHostCollection getAll6(const SubnetID& subnet_id) const; + /// @brief Implementation of @ref CqlHostDataSource::getPage4() + /// + /// See @ref CqlHostDataSource::getPage4() for parameter details. + /// + /// @param subnet_id identifier of the subnet to which hosts belong + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + virtual ConstHostCollection + getPage4(const SubnetID& subnet_id, + uint64_t lower_host_id, + const HostPageSize& page_size) const; + + /// @brief Implementation of @ref CqlHostDataSource::getPage6() + /// + /// See @ref CqlHostDataSource::getPage6() for parameter details. + /// + /// @param subnet_id identifier of the subnet to which hosts belong + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + virtual ConstHostCollection + getPage6(const SubnetID& subnet_id, + uint64_t lower_host_id, + const HostPageSize& page_size) const; + /// @brief Implementation of @ref CqlHostDataSource::getAll4() /// /// See @ref CqlHostDataSource::getAll4() for parameter details. @@ -1945,6 +2143,67 @@ CqlHostDataSourceImpl::getAll6(const SubnetID& subnet_id) const { return (result); } +ConstHostCollection +CqlHostDataSourceImpl::getPage4(const SubnetID& subnet_id, + uint64_t lower_host_id, + const HostPageSize& page_size) const { + // Convert to CQL data types. + cass_int32_t host_ipv4_subnet_id = static_cast(subnet_id); + + // Bind to array. + AnyArray where_values; + where_values.add(&host_ipv4_subnet_id); + + cass_int64_t id = static_cast(lower_host_id); + if (id) { + where_values.add(&id); + } + + cass_int32_t page_size_data = + static_cast(page_size.page_size_); + where_values.add(&page_size_data); + + // Run statement. + ConstHostCollection result = + getHostCollection(id == 0 ? + CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_LIMIT : + CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_PAGE, + where_values); + + return (result); +} + +ConstHostCollection +CqlHostDataSourceImpl::getPage6(const SubnetID& subnet_id, + uint64_t lower_host_id, + const HostPageSize& page_size) const { + // Convert to CQL data types. + cass_int32_t host_ipv6_subnet_id = static_cast(subnet_id); + + // Bind to array. + AnyArray where_values; + where_values.add(&host_ipv6_subnet_id); + + cass_int64_t id = static_cast(lower_host_id); + if (id) { + where_values.add(&id); + } + + cass_int32_t page_size_data = + static_cast(page_size.page_size_); + where_values.add(&page_size_data); + + // Run statement. + ConstHostCollection result = + getHostCollection(id == 0 ? + CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_LIMIT : + CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_PAGE, + where_values); + + return (result); +} + + ConstHostCollection CqlHostDataSourceImpl::getAll4(const asiolink::IOAddress& address) const { // Convert to CQL data types. @@ -2245,6 +2504,26 @@ CqlHostDataSource::getAll6(const SubnetID& subnet_id) const { return (impl_->getAll6(subnet_id)); } +ConstHostCollection +CqlHostDataSource::getPage4(const SubnetID& subnet_id, + size_t& /*source_index*/, + uint64_t lower_host_id, + const HostPageSize& page_size) const { + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_HOST_GET_ALL); + + return (impl_->getPage4(subnet_id, lower_host_id, page_size)); +} + +ConstHostCollection +CqlHostDataSource::getPage6(const SubnetID& subnet_id, + size_t& /*source_index*/, + uint64_t lower_host_id, + const HostPageSize& page_size) const { + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_HOST_GET_ALL); + + return (impl_->getPage6(subnet_id, lower_host_id, page_size)); +} + ConstHostCollection CqlHostDataSource::getAll4(const asiolink::IOAddress& address) const { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_HOST_GET_ALL); diff --git a/src/lib/dhcpsrv/cql_host_data_source.h b/src/lib/dhcpsrv/cql_host_data_source.h index c657d9c394..d5dc713736 100644 --- a/src/lib/dhcpsrv/cql_host_data_source.h +++ b/src/lib/dhcpsrv/cql_host_data_source.h @@ -190,6 +190,42 @@ public: virtual ConstHostCollection getAll6(const SubnetID& subnet_id) const override; + /// @brief Returns range of hosts in a DHCPv4 subnet. + /// + /// This method returns a page of @c Host objects which represent + /// reservations in a specified subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source (unused). + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Collection of const @c Host objects (may be empty). + virtual ConstHostCollection + getPage4(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const override; + + /// @brief Returns range of hosts in a DHCPv6 subnet. + /// + /// This method returns a page of @c Host objects which represent + /// reservations in a specified subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source (unused). + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Collection of const @c Host objects (may be empty). + virtual ConstHostCollection + getPage6(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const override; + /// @brief Returns a collection of hosts using the specified IPv4 address. /// /// This method may return multiple @ref Host objects if they are connected diff --git a/src/lib/dhcpsrv/host_container.h b/src/lib/dhcpsrv/host_container.h index 442a2ea78c..ae21449c4e 100644 --- a/src/lib/dhcpsrv/host_container.h +++ b/src/lib/dhcpsrv/host_container.h @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -81,6 +81,13 @@ typedef boost::multi_index_container< // Index using values returned by the @c Host::getIPv6SubnetID boost::multi_index::const_mem_fun + >, + + // Fifth index is used to search by increasing host id + boost::multi_index::ordered_unique< + // Index using values returned by the @c Host::getHostId + boost::multi_index::const_mem_fun > > > HostContainer; @@ -125,6 +132,15 @@ typedef HostContainer::nth_index<3>::type HostContainerIndex3; typedef std::pair HostContainerIndex3Range; +/// @brief Fifth index type in the @c HostContainer. +/// +/// This index allows for searching for @c Host objects using a host id. +typedef HostContainer::nth_index<4>::type HostContainerIndex4; + +/// @brief Results range returned using the @c HostContainerIndex4. +typedef std::pair HostContainerIndex4Range; + /// @brief Defines one entry for the Host Container for v6 hosts /// /// It's essentially a pair of (IPv6 reservation, Host pointer). diff --git a/src/lib/dhcpsrv/host_mgr.cc b/src/lib/dhcpsrv/host_mgr.cc index 777fceb4d2..9c256577df 100644 --- a/src/lib/dhcpsrv/host_mgr.cc +++ b/src/lib/dhcpsrv/host_mgr.cc @@ -131,7 +131,66 @@ HostMgr::getAll6(const SubnetID& subnet_id) const { return (hosts); } - +ConstHostCollection +HostMgr::getPage4(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const { + for (;;) { + if (source_index > alternate_sources_.size()) { + return (ConstHostCollection()); + } + ConstHostCollection hosts; + if (source_index == 0) { + hosts = getCfgHosts()->getPage4(subnet_id, + source_index, + lower_host_id, + page_size); + } else { + hosts = alternate_sources_[source_index]->getPage4(subnet_id, + source_index, + lower_host_id, + page_size); + } + if (!hosts.empty()) { + return (hosts); + } else { + ++source_index; + continue; + } + } +} + +ConstHostCollection +HostMgr::getPage6(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const { + for (;;) { + if (source_index > alternate_sources_.size()) { + return (ConstHostCollection()); + } + ConstHostCollection hosts; + if (source_index == 0) { + hosts = getCfgHosts()->getPage6(subnet_id, + source_index, + lower_host_id, + page_size); + } else { + hosts = alternate_sources_[source_index]->getPage6(subnet_id, + source_index, + lower_host_id, + page_size); + } + if (!hosts.empty()) { + return (hosts); + } else { + ++source_index; + continue; + } + } +} + ConstHostCollection HostMgr::getAll4(const IOAddress& address) const { ConstHostCollection hosts = getCfgHosts()->getAll4(address); diff --git a/src/lib/dhcpsrv/host_mgr.h b/src/lib/dhcpsrv/host_mgr.h index a5e90a02c4..27f73b6ccf 100644 --- a/src/lib/dhcpsrv/host_mgr.h +++ b/src/lib/dhcpsrv/host_mgr.h @@ -160,6 +160,66 @@ public: virtual ConstHostCollection getAll6(const SubnetID& subnet_id) const; + /// @brief Returns range of hosts in a DHCPv4 subnet. + /// + /// This method returns a page of @c Host objects representing + /// reservations in a specified subnet as documented in the + /// @c BaseHostDataSource::getPage4 + /// + /// The typical usage of this method is as follows: + /// - Get the first page of hosts by specifying zero index and id + /// as the beginning of the range. + /// - Index and last id of the returned range should be used as + /// starting index and id for the next page in the subsequent call. + /// - All returned hosts are from the same source so if the number of + /// hosts returned is lower than the page size, it does not indicate + /// that the last page has been retrieved. + /// - If there are no hosts returned it indicates that the previous page + /// was the last page. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source. + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Host collection (may be empty). + virtual ConstHostCollection + getPage4(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const; + + /// @brief Returns range of hosts in a DHCPv6 subnet. + /// + /// This method returns a page of @c Host objects representing + /// reservations in a specified subnet as documented in the + /// @c BaseHostDataSource::getPage6 + /// + /// The typical usage of this method is as follows: + /// - Get the first page of hosts by specifying zero index and id + /// as the beginning of the range. + /// - Index and last id of the returned range should be used as + /// starting index and id for the next page in the subsequent call. + /// - All returned hosts are from the same source so if the number of + /// hosts returned is lower than the page size, it does not indicate + /// that the last page has been retrieved. + /// - If there are no hosts returned it indicates that the previous page + /// was the last page. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source. + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Host collection (may be empty). + virtual ConstHostCollection + getPage6(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const; + /// @brief Returns a collection of hosts using the specified IPv4 address. /// /// This method may return multiple @c Host objects if they are connected to diff --git a/src/lib/dhcpsrv/mysql_host_data_source.cc b/src/lib/dhcpsrv/mysql_host_data_source.cc index 448bceca19..ec1d6508c0 100644 --- a/src/lib/dhcpsrv/mysql_host_data_source.cc +++ b/src/lib/dhcpsrv/mysql_host_data_source.cc @@ -1953,6 +1953,8 @@ public: DEL_HOST_SUBID6_ID, // Delete v6 host (subnet-id, ident.type, identifier) GET_HOST_SUBID4, // Gets host by IPv4 SubnetID GET_HOST_SUBID6, // Gets host by IPv6 SubnetID + GET_HOST_SUBID4_PAGE, // Gets host by IPv4 SubnetID beginning by HID + GET_HOST_SUBID6_PAGE, // Gets host by IPv6 SubnetID beginning by HID NUM_STATEMENTS // Number of statements }; @@ -2366,8 +2368,43 @@ TaggedStatementArray tagged_statements = { { "LEFT JOIN ipv6_reservations AS r " "ON h.host_id = r.host_id " "WHERE h.dhcp6_subnet_id = ? " - "ORDER BY h.host_id, o.option_id, r.reservation_id"} + "ORDER BY h.host_id, o.option_id, r.reservation_id"}, + + {MySqlHostDataSourceImpl::GET_HOST_SUBID4_PAGE, + "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, " + "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, " + "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, " + "h.dhcp4_next_server, h.dhcp4_server_hostname, " + "h.dhcp4_boot_file_name, h.auth_key, " + "o.option_id, o.code, o.value, o.formatted_value, o.space, " + "o.persistent, o.user_context " + "FROM hosts AS h " + "LEFT JOIN dhcp4_options AS o " + "ON h.host_id = o.host_id " + "WHERE h.dhcp4_subnet_id = ? AND h.host_id > ? " + "ORDER BY h.host_id, o.option_id " + "LIMIT ?"}, + + {MySqlHostDataSourceImpl::GET_HOST_SUBID6_PAGE, + "SELECT h.host_id, h.dhcp_identifier, " + "h.dhcp_identifier_type, h.dhcp4_subnet_id, " + "h.dhcp6_subnet_id, h.ipv4_address, h.hostname, " + "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, " + "h.dhcp4_next_server, h.dhcp4_server_hostname, " + "h.dhcp4_boot_file_name, h.auth_key, " + "o.option_id, o.code, o.value, o.formatted_value, o.space, " + "o.persistent, o.user_context, " + "r.reservation_id, r.address, r.prefix_len, r.type, " + "r.dhcp6_iaid " + "FROM hosts AS h " + "LEFT JOIN dhcp6_options AS o " + "ON h.host_id = o.host_id " + "LEFT JOIN ipv6_reservations AS r " + "ON h.host_id = r.host_id " + "WHERE h.dhcp6_subnet_id = ? AND h.host_id > ? " + "ORDER BY h.host_id, o.option_id, r.reservation_id" + "LIMIT ?"} } }; @@ -2940,6 +2977,74 @@ MySqlHostDataSource::getAll6(const SubnetID& subnet_id) const { return (result); } +ConstHostCollection +MySqlHostDataSource::getPage4(const SubnetID& subnet_id, + size_t& /*source_index*/, + uint64_t lower_host_id, + const HostPageSize& page_size) const { + // Set up the WHERE clause value + MYSQL_BIND inbind[3]; + memset(inbind, 0, sizeof(inbind)); + + // Bind subnet id + uint32_t subnet = subnet_id; + inbind[0].buffer_type = MYSQL_TYPE_LONG; + inbind[0].buffer = reinterpret_cast(&subnet); + inbind[0].is_unsigned = MLM_TRUE; + + // Bind lower host id + uint32_t host_id = lower_host_id; + inbind[1].buffer_type = MYSQL_TYPE_LONG; + inbind[1].buffer = reinterpret_cast(&host_id); + inbind[1].is_unsigned = MLM_TRUE; + + // Bind page size value + uint32_t page_size_data = page_size.page_size_; + inbind[2].buffer_type = MYSQL_TYPE_LONG; + inbind[2].buffer = reinterpret_cast(&page_size_data); + inbind[2].is_unsigned = MLM_TRUE; + + ConstHostCollection result; + impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_SUBID4_PAGE, + inbind, impl_->host_exchange_, + result, false); + return (result); +} + +ConstHostCollection +MySqlHostDataSource::getPage6(const SubnetID& subnet_id, + size_t& /*source_index*/, + uint64_t lower_host_id, + const HostPageSize& page_size) const { + // Set up the WHERE clause value + MYSQL_BIND inbind[3]; + memset(inbind, 0, sizeof(inbind)); + + // Bind subnet id + uint32_t subnet = subnet_id; + inbind[0].buffer_type = MYSQL_TYPE_LONG; + inbind[0].buffer = reinterpret_cast(&subnet); + inbind[0].is_unsigned = MLM_TRUE; + + // Bind lower host id + uint32_t host_id = lower_host_id; + inbind[1].buffer_type = MYSQL_TYPE_LONG; + inbind[1].buffer = reinterpret_cast(&host_id); + inbind[1].is_unsigned = MLM_TRUE; + + // Bind page size value + uint32_t page_size_data = page_size.page_size_; + inbind[2].buffer_type = MYSQL_TYPE_LONG; + inbind[2].buffer = reinterpret_cast(&page_size_data); + inbind[2].is_unsigned = MLM_TRUE; + + ConstHostCollection result; + impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_SUBID6_PAGE, + inbind, impl_->host_ipv6_exchange_, + result, false); + return (result); +} + ConstHostCollection MySqlHostDataSource::getAll4(const asiolink::IOAddress& address) const { diff --git a/src/lib/dhcpsrv/mysql_host_data_source.h b/src/lib/dhcpsrv/mysql_host_data_source.h index 2d9509710c..6f1e3b5c67 100644 --- a/src/lib/dhcpsrv/mysql_host_data_source.h +++ b/src/lib/dhcpsrv/mysql_host_data_source.h @@ -153,6 +153,42 @@ public: virtual ConstHostCollection getAll6(const SubnetID& subnet_id) const; + /// @brief Returns range of hosts in a DHCPv4 subnet. + /// + /// This method returns a page of @c Host objects which represent + /// reservations in a specified subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source (unused). + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Collection of const @c Host objects (may be empty). + virtual ConstHostCollection + getPage4(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const; + + /// @brief Returns range of hosts in a DHCPv6 subnet. + /// + /// This method returns a page of @c Host objects which represent + /// reservations in a specified subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source (unused). + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Collection of const @c Host objects (may be empty). + virtual ConstHostCollection + getPage6(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const; + /// @brief Returns a collection of hosts using the specified IPv4 address. /// /// This method may return multiple @c Host objects if they are connected diff --git a/src/lib/dhcpsrv/pgsql_host_data_source.cc b/src/lib/dhcpsrv/pgsql_host_data_source.cc index 0edb189939..9145ba4cbc 100644 --- a/src/lib/dhcpsrv/pgsql_host_data_source.cc +++ b/src/lib/dhcpsrv/pgsql_host_data_source.cc @@ -1295,6 +1295,8 @@ public: DEL_HOST_SUBID6_ID, // Delete v6 host (subnet-id, ident.type, identifier) GET_HOST_SUBID4, // Gets host by IPv4 SubnetID GET_HOST_SUBID6, // Gets host by IPv6 SubnetID + GET_HOST_SUBID4_PAGE, // Gets host by IPv4 SubnetID beginning by HID + GET_HOST_SUBID6_PAGE, // Gets host by IPv6 SubnetID beginning by HID NUM_STATEMENTS // Number of statements }; @@ -1760,6 +1762,54 @@ TaggedStatementArray tagged_statements = { { "LEFT JOIN ipv6_reservations AS r ON h.host_id = r.host_id " "WHERE h.dhcp6_subnet_id = $1 " "ORDER BY h.host_id, o.option_id, r.reservation_id" + }, + + // PgSqlHostDataSourceImpl::GET_HOST_SUBID4_PAGE + // Retrieves host information along with the DHCPv4 options associated with + // it. Left joining the dhcp4_options table results in multiple rows being + // returned for the same host. The host is retrieved by subnet id. + {3, + { OID_INT8, OID_INT8, OID_INT8 }, + "get_host_subid4_page", + "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, " + " h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, " + " h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, " + " h.dhcp4_next_server, h.dhcp4_server_hostname, " + " h.dhcp4_boot_file_name, h.auth_key, " + " o.option_id, o.code, o.value, o.formatted_value, o.space, " + " o.persistent, o.user_context " + "FROM hosts AS h " + "LEFT JOIN dhcp4_options AS o ON h.host_id = o.host_id " + "WHERE h.dhcp4_subnet_id = $1 AND h.host_id > $2 " + "ORDER BY h.host_id, o.option_id " + "LIMIT $3" + }, + + // PgSqlHostDataSourceImpl::GET_HOST_SUBID6_PAGE + // Retrieves host information, IPv6 reservations and DHCPv6 options + // associated with a host using IPv6 subnet id. This query returns + // host information for a single host. However, multiple rows are + // returned due to left joining IPv6 reservations and DHCPv6 options. + // The number of rows returned is multiplication of number of existing + // IPv6 reservations and DHCPv6 options. + {3, + { OID_INT8, OID_INT8, OID_INT8 }, + "get_host_subid6_page", + "SELECT h.host_id, h.dhcp_identifier, " + " h.dhcp_identifier_type, h.dhcp4_subnet_id, " + " h.dhcp6_subnet_id, h.ipv4_address, h.hostname, " + " h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, " + " h.dhcp4_next_server, h.dhcp4_server_hostname, " + " h.dhcp4_boot_file_name, h.auth_key, " + " o.option_id, o.code, o.value, o.formatted_value, o.space, " + " o.persistent, o.user_context, " + " r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid " + "FROM hosts AS h " + "LEFT JOIN dhcp6_options AS o ON h.host_id = o.host_id " + "LEFT JOIN ipv6_reservations AS r ON h.host_id = r.host_id " + "WHERE h.dhcp6_subnet_id = $1 AND h.host_id > $2 " + "ORDER BY h.host_id, o.option_id, r.reservation_id " + "LIMIT $3" } } }; @@ -2175,6 +2225,60 @@ PgSqlHostDataSource::getAll6(const SubnetID& subnet_id) const { return (result); } +ConstHostCollection +PgSqlHostDataSource::getPage4(const SubnetID& subnet_id, + size_t& /*source_index*/, + uint64_t lower_host_id, + const HostPageSize& page_size) const { + // Set up the WHERE clause value + PsqlBindArrayPtr bind_array(new PsqlBindArray()); + + // Add the subnet id. + bind_array->add(subnet_id); + + // Add the lower bound host id. + bind_array->add(lower_host_id); + + // Add the page size value. + string page_size_data = + boost::lexical_cast(page_size.page_size_); + bind_array->add(page_size_data); + + ConstHostCollection result; + impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID4_PAGE, + bind_array, impl_->host_exchange_, + result, false); + + return (result); +} + +ConstHostCollection +PgSqlHostDataSource::getPage6(const SubnetID& subnet_id, + size_t& /*source_index*/, + uint64_t lower_host_id, + const HostPageSize& page_size) const { + // Set up the WHERE clause value + PsqlBindArrayPtr bind_array(new PsqlBindArray()); + + // Add the subnet id. + bind_array->add(subnet_id); + + // Add the lower bound host id. + bind_array->add(lower_host_id); + + // Add the page size value. + string page_size_data = + boost::lexical_cast(page_size.page_size_); + bind_array->add(page_size_data); + + ConstHostCollection result; + impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID6_PAGE, + bind_array, impl_->host_exchange_, + result, false); + + return (result); +} + ConstHostCollection PgSqlHostDataSource::getAll4(const asiolink::IOAddress& address) const { diff --git a/src/lib/dhcpsrv/pgsql_host_data_source.h b/src/lib/dhcpsrv/pgsql_host_data_source.h index e93f4f9e1f..e5094e1011 100644 --- a/src/lib/dhcpsrv/pgsql_host_data_source.h +++ b/src/lib/dhcpsrv/pgsql_host_data_source.h @@ -180,6 +180,42 @@ public: virtual ConstHostCollection getAll6(const SubnetID& subnet_id) const; + /// @brief Returns range of hosts in a DHCPv4 subnet. + /// + /// This method returns a page of @c Host objects which represent + /// reservations in a specified subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source (unused). + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Collection of const @c Host objects (may be empty). + virtual ConstHostCollection + getPage4(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const; + + /// @brief Returns range of hosts in a DHCPv6 subnet. + /// + /// This method returns a page of @c Host objects which represent + /// reservations in a specified subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source (unused). + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Collection of const @c Host objects (may be empty). + virtual ConstHostCollection + getPage6(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const; + /// @brief Returns a collection of hosts using the specified IPv4 address. /// /// This method may return multiple @c Host objects if they are connected diff --git a/src/lib/dhcpsrv/tests/host_cache_unittest.cc b/src/lib/dhcpsrv/tests/host_cache_unittest.cc index 91eca09960..d24f249d06 100644 --- a/src/lib/dhcpsrv/tests/host_cache_unittest.cc +++ b/src/lib/dhcpsrv/tests/host_cache_unittest.cc @@ -611,6 +611,16 @@ public: return (getCollection()); } + ConstHostCollection getPage4(const SubnetID&, size_t&, uint64_t, + const HostPageSize&) const { + return (getCollection()); + } + + ConstHostCollection getPage6(const SubnetID&, size_t&, uint64_t, + const HostPageSize&) const { + return (getCollection()); + } + ConstHostCollection getAll4(const IOAddress&) const { return (getCollection()); } diff --git a/src/lib/dhcpsrv/testutils/memory_host_data_source.cc b/src/lib/dhcpsrv/testutils/memory_host_data_source.cc index fd07827c65..7a465b5c59 100644 --- a/src/lib/dhcpsrv/testutils/memory_host_data_source.cc +++ b/src/lib/dhcpsrv/testutils/memory_host_data_source.cc @@ -46,6 +46,22 @@ MemHostDataSource::getAll6(const SubnetID& subnet_id) const { return (hosts); } +ConstHostCollection +MemHostDataSource::getPage4(const SubnetID& /*subnet_id*/, + size_t& /*source_index*/, + uint64_t /*lower_host_id*/, + const HostPageSize& /*page_size*/) const { + return (ConstHostCollection()); +} + +ConstHostCollection +MemHostDataSource::getPage6(const SubnetID& /*subnet_id*/, + size_t& /*source_index*/, + uint64_t /*lower_host_id*/, + const HostPageSize& /*page_size*/) const { + return (ConstHostCollection()); +} + ConstHostCollection MemHostDataSource::getAll4(const asiolink::IOAddress& /*address*/) const { return (ConstHostCollection()); diff --git a/src/lib/dhcpsrv/testutils/memory_host_data_source.h b/src/lib/dhcpsrv/testutils/memory_host_data_source.h index 370e5fe6eb..43fc74fe0c 100644 --- a/src/lib/dhcpsrv/testutils/memory_host_data_source.h +++ b/src/lib/dhcpsrv/testutils/memory_host_data_source.h @@ -58,6 +58,36 @@ public: virtual ConstHostCollection getAll6(const SubnetID& subnet_id) const; + /// @brief Return range of hosts in a DHCPv4 subnet. + /// + /// Currently not implemented. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source (unused). + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + virtual ConstHostCollection + getPage4(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const; + + /// @brief Return range of hosts in a DHCPv6 subnet. + /// + /// Currently not implemented. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source (unused). + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + virtual ConstHostCollection + getPage6(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) const; + /// @brief Returns a collection of hosts using the specified IPv4 address. /// /// Currently not implemented. diff --git a/src/lib/dhcpsrv/writable_host_data_source.h b/src/lib/dhcpsrv/writable_host_data_source.h index d3965c9e2f..1a398064f3 100644 --- a/src/lib/dhcpsrv/writable_host_data_source.h +++ b/src/lib/dhcpsrv/writable_host_data_source.h @@ -57,6 +57,36 @@ public: virtual HostCollection getAll6(const SubnetID& subnet_id) = 0; + /// @brief Returns range of hosts in a DHCPv4 subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source. + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Collection of non-const @c Host objects. + virtual HostCollection + getPage4(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) = 0; + + /// @brief Returns range of hosts in a DHCPv6 subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param source_index Index of the source. + /// @param lower_host_id Host identifier used as lower bound for the + /// returned range. + /// @param page_size maximum size of the page returned. + /// + /// @return Collection of non-const @c Host objects. + virtual HostCollection + getPage6(const SubnetID& subnet_id, + size_t& source_index, + uint64_t lower_host_id, + const HostPageSize& page_size) = 0; + /// @brief Returns a collection of hosts using the specified IPv4 address. /// /// This method may return multiple @c Host objects if they are connected