From: Andrei Pavel Date: Fri, 18 Aug 2017 14:41:22 +0000 (+0300) Subject: boost::any for CHDS X-Git-Tag: trac5425a_base~11^2~1^2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=765c0d79adc2d0bda1d46c5f57dd5b0b626c3ace;p=thirdparty%2Fkea.git boost::any for CHDS --- diff --git a/src/lib/dhcpsrv/cql_connection.h b/src/lib/dhcpsrv/cql_connection.h index 70db2f2be0..a3b88d8c15 100644 --- a/src/lib/dhcpsrv/cql_connection.h +++ b/src/lib/dhcpsrv/cql_connection.h @@ -89,10 +89,6 @@ struct StatementTagHash { } }; -/// Define CQL schema version: 2.0 -const uint32_t CQL_SCHEMA_VERSION_MAJOR = 2; -const uint32_t CQL_SCHEMA_VERSION_MINOR = 0; - /// @brief Equality function for StatementMap keys struct StatementTagEqual { bool operator()(StatementTag const& lhs, StatementTag const& rhs) const { diff --git a/src/lib/dhcpsrv/cql_host_data_source.cc b/src/lib/dhcpsrv/cql_host_data_source.cc index 43bebf0459..87ab9a2a2c 100644 --- a/src/lib/dhcpsrv/cql_host_data_source.cc +++ b/src/lib/dhcpsrv/cql_host_data_source.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2016 Deutsche Telekom AG. +// Copyright (C) 2016-2017 Deutsche Telekom AG. // // Author: Andrei Pavel // @@ -16,29 +16,31 @@ #include +#include + #include #include #include #include #include -#include -#include +#include #include #include #include #include -#include -#include -#include -#include +#include // for MD5_DIGEST_LENGTH +#include // for uint64_t -#include +#include // for boost::is_any_of +#include // for split +#include // for BOOST_ASSERT +#include // for std::unordered_map -#include -#include +#include // for size_t, std::stringstream +#include // for std::unique_ptr +#include // for std::string -using namespace isc; using namespace isc::asiolink; using namespace isc::dhcp; using namespace isc::util; @@ -48,72 +50,85 @@ namespace { /// @brief Host identifier consisting of DUID or hardware address typedef std::vector HostIdentifier; -/// @brief Host identifier converted to Cassandra data type -typedef std::vector CassHostIdentifier; - -/// @brief Host identifier converted to Cassandra data type -typedef std::vector CassOptionBuffer; - /// @brief key for HostMap containing objects which uniquely identify a /// host: host identifier, host identifier type, subnets for IPv4 and IPv6 -typedef boost::tuple - HostKey; +/// and the IPv4 reservation +typedef std:: + tuple + HostKey; + +enum HostKeyComponent { + HOST_IDENTIFIER, + HOST_IDENTIFIER_TYPE, + IPv4_SUBNET_ID, + IPv6_SUBNET_ID, + IPv4_RESERVATION +}; /// @brief Map used to merge reservations and options into a single host on /// retrieve from database -typedef boost::unordered_map > HostMap; +typedef std::unordered_map> HostMap; + +typedef std::pair HostPair; + +/// @brief Wrapper used to specify option space alongside option descriptor +struct OptionWrapper { + OptionWrapper(OptionDescriptorPtr option_descriptor, + std::string option_space) + : option_descriptor_(option_descriptor), option_space_(option_space) { + } + OptionDescriptorPtr option_descriptor_; + std::string option_space_; +}; /// @brief Maximum size of an IPv4 address represented as a text string. 12 /// digits plus 3 full stops (dots). -static const size_t ADDRESS4_TEXT_MAX_LENGTH = 15U; +static constexpr size_t ADDRESS4_TEXT_MAX_LENGTH = 15u; /// @brief Maximum size of an IPv6 address represented as a text string. 32 /// hexadecimal characters written in 8 groups of four, plus 7 colon /// separators. -static const size_t ADDRESS6_TEXT_MAX_LENGTH = 39U; +static constexpr size_t ADDRESS6_TEXT_MAX_LENGTH = 39u; /// @brief Maximum length of classes stored in a host_ipv4/6_client_classes /// column. -static const size_t CLIENT_CLASSES_MAX_LENGTH = 255U; +static constexpr size_t CLIENT_CLASSES_MAX_LENGTH = 255u; /// @brief Maximum length of the hostname stored in DNS. This length is /// restricted by the length of the domain-name carried in the Client FQDN /// Option (see RFC4702 and RFC4704). -static const size_t HOSTNAME_MAX_LENGTH = 255U; +static constexpr size_t HOSTNAME_MAX_LENGTH = 255u; /// @brief Maximum length of option value -static const size_t OPTION_VALUE_MAX_LENGTH = 4096U; +static constexpr size_t OPTION_VALUE_MAX_LENGTH = 4096u; /// @brief Maximum length of option value specified in textual format -static const size_t OPTION_FORMATTED_VALUE_MAX_LENGTH = 8192U; +static constexpr size_t OPTION_FORMATTED_VALUE_MAX_LENGTH = 8192u; /// @brief Maximum length of option space name -static const size_t OPTION_SPACE_MAX_LENGTH = 128U; +static constexpr size_t OPTION_SPACE_MAX_LENGTH = 128u; /// @brief Numeric value representing the last supported identifier. This value /// is used to validate whether the identifier type stored in a database is /// within bounds of supported identifiers. -static const cass_int8_t MAX_IDENTIFIER_TYPE = - static_cast(Host::IDENT_CIRCUIT_ID); +static constexpr cass_int32_t MAX_IDENTIFIER_TYPE = + static_cast(Host::IDENT_CIRCUIT_ID); /// @{ /// @brief Invalid values in the Cassandra database -static const char NULL_RESERVED_IPV6_PREFIX_ADDRESS[] = ""; -static const cass_int32_t NULL_RESERVED_IPV6_PREFIX_LENGTH = 0; -static const cass_int32_t NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE = -1; -static const cass_int32_t NULL_IAID = -1; -static const cass_int32_t NULL_OPTION_UNIVERSE = -1; -static const cass_int32_t NULL_OPTION_CODE = -1; -static const CassOptionBuffer NULL_OPTION_VALUE = CassOptionBuffer(); -static const char NULL_OPTION_FORMATTED_VALUE[] = ""; -static const char NULL_OPTION_SPACE[] = ""; -static const cass_bool_t NULL_OPTION_IS_PERSISTENT = cass_false; -static const char NULL_OPTION_CLIENT_CLASS[] = ""; -static const cass_int32_t NULL_OPTION_SUBNET_ID = -1; +static constexpr char NULL_RESERVED_IPV6_PREFIX_ADDRESS[] = "::"; +static constexpr cass_int32_t NULL_RESERVED_IPV6_PREFIX_LENGTH = 0; +static constexpr cass_int32_t NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE = -1; +static constexpr cass_int32_t NULL_IAID = -1; +static constexpr cass_int32_t NULL_OPTION_UNIVERSE = -1; +static constexpr cass_int32_t NULL_OPTION_CODE = -1; +static const CassBlob NULL_OPTION_VALUE = CassBlob(); +static constexpr char NULL_OPTION_FORMATTED_VALUE[] = ""; +static constexpr char NULL_OPTION_SPACE[] = ""; +static constexpr cass_bool_t NULL_OPTION_IS_PERSISTENT = cass_false; +static constexpr char NULL_OPTION_CLIENT_CLASS[] = ""; +static constexpr cass_int32_t NULL_OPTION_SUBNET_ID = -1; +// static constexpr CassCollection* NULL_COLLECTION = NULL; /// @} /// @brief Invalid reservation used to check for an invalid IPv6Resrv formed @@ -121,377 +136,19 @@ static const cass_int32_t NULL_OPTION_SUBNET_ID = -1; static const IPv6Resrv NULL_IPV6_RESERVATION = IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("::"), 128); -} // anonymous namespace +} // namespace namespace isc { namespace dhcp { -/// @{ -/// @brief Statement parameters -// INSERT_HOST -static const char* INSERT_HOST_PARAMS[] = { - static_cast("id"), - static_cast("host_identifier"), - static_cast("host_identifier_type"), - static_cast("host_ipv4_subnet_id"), - static_cast("host_ipv6_subnet_id"), - static_cast("host_ipv4_address"), - static_cast("hostname"), - static_cast("host_ipv4_client_classes"), - static_cast("host_ipv6_client_classes"), - static_cast("reserved_ipv6_prefix_address"), - static_cast("reserved_ipv6_prefix_length"), - static_cast("reserved_ipv6_prefix_address_type"), - static_cast("iaid"), - static_cast("option_universe"), - static_cast("option_code"), - static_cast("option_value"), - static_cast("option_formatted_value"), - static_cast("option_space"), - static_cast("option_is_persistent"), - static_cast("option_client_class"), - static_cast("option_subnet_id"), - NULL}; -// GET_HOST_BY_HOST_ID -static const char* GET_HOST_BY_HOST_ID_PARAMS[] = { - static_cast("host_identifier"), - static_cast("host_identifier_type"), - NULL}; -// GET_HOST_BY_IPV4_ADDRESS -static const char* GET_HOST_BY_IPV4_ADDRESS_PARAMS[] = { - static_cast("host_ipv4_address"), - NULL}; -// GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID -static const char* GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID_PARAMS[] = { - static_cast("host_ipv4_subnet_id"), - static_cast("host_identifier"), - static_cast("host_identifier_type"), - NULL}; -// GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID, -static const char* GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID_PARAMS[] = { - static_cast("host_ipv6_subnet_id"), - static_cast("host_identifier"), - static_cast("host_identifier_type"), - NULL}; -// GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS, -static const char* GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS_PARAMS[] = { - static_cast("host_ipv4_subnet_id"), - static_cast("host_ipv4_address"), - NULL}; -// GET_HOST_BY_IPV6_PREFIX -static const char* GET_HOST_BY_IPV6_PREFIX_PARAMS[] = { - static_cast("reserved_ipv6_prefix_address"), - static_cast("reserved_ipv6_prefix_length"), - NULL}; -// GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS -static const char* GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS_PARAMS[] = { - static_cast("host_ipv6_subnet_id"), - static_cast("reserved_ipv6_prefix_address"), - NULL}; -// GET_VERSION -static const char* GET_VERSION_PARAMS[] = {NULL}; -/// @} - -/// @brief Prepared CQL statements used by the backend to insert and retrieve -/// hosts from the database. -static CqlTaggedStatement tagged_statements[] = { - // INSERT_HOST - {INSERT_HOST_PARAMS, "INSERT_HOST", - "INSERT INTO host_reservations ( " - "id, " - "host_identifier, " - "host_identifier_type, " - "host_ipv4_subnet_id, " - "host_ipv6_subnet_id, " - "host_ipv4_address, " - "hostname, " - "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 " - ") " - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " - "IF NOT EXISTS " - }, - - // GET_HOST_BY_HOST_ID - {GET_HOST_BY_HOST_ID_PARAMS, "GET_HOST_BY_HOST_ID", - "SELECT " - "id, " - "host_identifier, " - "host_identifier_type, " - "host_ipv4_subnet_id, " - "host_ipv6_subnet_id, " - "host_ipv4_address, " - "hostname, " - "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 " - "FROM host_reservations " - "WHERE host_identifier = ? " - "AND host_identifier_type = ? " - "ALLOW FILTERING " - }, - - // GET_HOST_BY_IPV4_ADDRESS - {GET_HOST_BY_IPV4_ADDRESS_PARAMS, "GET_HOST_BY_IPV4_ADDRESS", - "SELECT " - "id, " - "host_identifier, " - "host_identifier_type, " - "host_ipv4_subnet_id, " - "host_ipv6_subnet_id, " - "host_ipv4_address, " - "hostname, " - "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 " - "FROM host_reservations " - "WHERE host_ipv4_address = ? " - "ALLOW FILTERING " - }, - - // GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID - {GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID_PARAMS, - "GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID", - "SELECT " - "id, " - "host_identifier, " - "host_identifier_type, " - "host_ipv4_subnet_id, " - "host_ipv6_subnet_id, " - "host_ipv4_address, " - "hostname, " - "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 " - "FROM host_reservations " - "WHERE host_ipv4_subnet_id = ? " - "AND host_identifier = ? " - "AND host_identifier_type = ? " - "ALLOW FILTERING " - }, - - // GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID - {GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID_PARAMS, - "GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID", - "SELECT " - "id, " - "host_identifier, " - "host_identifier_type, " - "host_ipv4_subnet_id, " - "host_ipv6_subnet_id, " - "host_ipv4_address, " - "hostname, " - "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 " - "FROM host_reservations " - "WHERE host_ipv6_subnet_id = ? " - "AND host_identifier = ? " - "AND host_identifier_type = ? " - "ALLOW FILTERING " - }, - - // GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS - {GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS_PARAMS, - "GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS", - "SELECT " - "id, " - "host_identifier, " - "host_identifier_type, " - "host_ipv4_subnet_id, " - "host_ipv6_subnet_id, " - "host_ipv4_address, " - "hostname, " - "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 " - "FROM host_reservations " - "WHERE host_ipv4_subnet_id = ? " - "AND host_ipv4_address = ? " - "ALLOW FILTERING " - }, - - // GET_HOST_BY_IPV6_PREFIX - {GET_HOST_BY_IPV6_PREFIX_PARAMS, "GET_HOST_BY_IPV6_PREFIX", - "SELECT " - "id, " - "host_identifier, " - "host_identifier_type, " - "host_ipv4_subnet_id, " - "host_ipv6_subnet_id, " - "host_ipv4_address, " - "hostname, " - "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 " - "FROM host_reservations " - "WHERE reserved_ipv6_prefix_address = ? " - "AND reserved_ipv6_prefix_length = ? " - "ALLOW FILTERING " - }, - - // GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS - {GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS_PARAMS, - "GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS", - "SELECT " - "id, " - "host_identifier, " - "host_identifier_type, " - "host_ipv4_subnet_id, " - "host_ipv6_subnet_id, " - "host_ipv4_address, " - "hostname, " - "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 " - "FROM host_reservations " - "WHERE host_ipv6_subnet_id = ? " - "AND reserved_ipv6_prefix_address = ? " - "ALLOW FILTERING " - }, - - // GET_VERSION - {GET_VERSION_PARAMS, "GET_VERSION", - "SELECT version, minor FROM schema_version"}, - - // End of list sentinel - {NULL, NULL, NULL}}; // tagged_statements - /// @brief Provides mechanisms for sending and retrieving data from the /// host_reservations table. class CqlHostExchange : public virtual CqlExchange { public: - /// @brief Statement Tags - /// - /// The contents of the enum are indexes into the list of CQL statements - enum StatementIndex { - // Inserts all options belonging to any reservation from a single host. - INSERT_HOST, - // Retrieves host information, IPv6 reservations and both IPv4 and IPv6 - // options associated with the host. - GET_HOST_BY_HOST_ID, - // Retrieves host information along with the IPv4 options associated - // with it. - GET_HOST_BY_IPV4_ADDRESS, - // Retrieves host information and IPv4 options using subnet identifier - // and client's identifier (i.e. hardware address or DUID). - GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID, - // Retrieves host information, IPv6 reservations and IPv6 options - // associated with a host using subnet identifier and client's - // identifier (i.e. hardware address or DUID). - GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID, - // Retrieves host information and IPv4 options for the host using subnet - // identifier and IPv4 reservation. - GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS, - // Retrieves host information, IPv6 reservations and IPv6 options - // associated with a host using prefix and prefix length. This query - // returns host information for a single host. However, multiple rows - // are returned due to left joining IPv6 reservations and IPv6 options. - // The number of rows returned is multiplication of number of existing - // IPv6 reservations and IPv6 options. - GET_HOST_BY_IPV6_PREFIX, - // Retrieves host information and IPv6 options for the host using subnet - // identifier and IPv6 reservation. - GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS, - // Get CQL schema version. - GET_VERSION, - // Number of statements - NUM_STATEMENTS - }; - /// @brief Constructor /// /// Specifies table columns. - CqlHostExchange(); + CqlHostExchange(CqlConnection& connection); /// @brief Virtual destructor. virtual ~CqlHostExchange(); @@ -501,13 +158,14 @@ public: /// Creates a bind array to receive @ref Host data from the Cassandra /// database. After data is successfully received, @ref retrieve() can be /// called to retrieve the @ref Host object. Called in @ref - /// CqlExchange::executeRead(). + /// CqlExchange::executeSelect(). /// /// @param data array of objects representing data being retrieved - /// @param statement_index prepared statement being executed; defaults to an + /// @param statement_tag prepared statement being executed; defaults to an /// invalid statement - virtual void createBindForReceive(CqlDataArray& data, - const int statement_index = -1); + virtual void + createBindForSelect(AnyArray& data, + StatementTag statement_tag = NULL) override; /// @brief Binds @ref Host to data array to send data to the Cassandra /// database. @@ -521,12 +179,14 @@ public: /// @param option_space option space /// @param option_descriptor structure used to hold option information /// @param data array being filled with data from to the Host object - void createBindForSend(const HostPtr& host, - const OptionalValue& subnet_id, - const IPv6Resrv* const reservation, - const std::string& option_space, - const OptionDescriptor& option_descriptor, - CqlDataArray& data); + /// @param statement_tag tag of the statement being executed + void createBindForMutation(const HostPtr& host, + const OptionalValue& subnet_id, + const IPv6Resrv* const reservation, + const std::string& option_space, + const OptionDescriptor& option_descriptor, + StatementTag statement_tag, + AnyArray& data); /// @brief Create unique hash for storage in table id. /// @@ -542,34 +202,85 @@ public: /// @brief Copy received data into Host object /// /// Copies information about the host into a newly created @ref Host object - /// Called in @ref executeRead after @ref createBindForReceive(). + /// Called in @ref executeSelect after @ref createBindForSelect(). /// /// @return Host Pointer to a @ref HostPtr object holding a pointer to the /// @ref Host object returned. - virtual void* retrieve(); + virtual boost::any retrieve() override; /// @brief Creates IPv6 reservation from the data contained in the - /// currently processed row. + /// currently processed row. /// - /// Called after createBindForReceive(). + /// Called after createBindForSelect(). /// /// @return IPv6Resrv object (containing IPv6 address or prefix reservation) const IPv6Resrv retrieveReservation() const; /// @brief Retrieves option from members. - OptionDescriptorPtr retrieveOption() const; + /// + /// Called after createBindForSelect(). + /// + /// @return OptionDescriptorPtr object (containing the option from the + /// database) + const OptionWrapper retrieveOption() const; + + /// @brief Statement tags definitions + /// @{ + // Inserts all options belonging to any reservation from a single host. + static constexpr StatementTag INSERT_HOST = "INSERT_HOST"; + + // Retrieves host information, IPv6 reservations and both IPv4 and IPv6 + // options associated with the host. + static constexpr StatementTag GET_HOST_BY_HOST_ID = "GET_HOST_BY_HOST_ID"; + + // Retrieves host information along with the IPv4 options associated + // with it. + static constexpr StatementTag GET_HOST_BY_IPV4_ADDRESS = + "GET_HOST_BY_IPV4_ADDRESS"; + // Retrieves host information and IPv4 options using subnet identifier + // and client's identifier (i.e. hardware address or DUID). + static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID = + "GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID"; + // Retrieves host information; IPv6 reservations and IPv6 options + // associated with a host using subnet identifier and client's + // identifier (i.e. hardware address or DUID). + static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID = + "GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID"; + // Retrieves host information and IPv4 options for the host using subnet + // identifier and IPv4 reservation. + static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS = + "GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS"; + // Retrieves host information, IPv6 reservations and IPv6 options + // associated with a host using prefix and prefix length. This query + // returns host information for a single host. However, multiple rows + // are returned due to left joining IPv6 reservations and IPv6 options. + // The number of rows returned is multiplication of number of existing + // IPv6 reservations and IPv6 options. + static constexpr StatementTag GET_HOST_BY_IPV6_PREFIX = + "GET_HOST_BY_IPV6_PREFIX"; + // Retrieves host information and IPv6 options for the host using subnet + // identifier and IPv6 reservation. + static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS = + "GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS"; + /// @} + + /// @brief Cassandra statements + static StatementMap tagged_statements_; private: /// Pointer to Host object holding information being inserted into database. HostPtr host_; + /// @brief Connection to the Cassandra database + CqlConnection& connection_; + /// @brief Primary key. Aggregates: host_identifier, host_identifier_type, /// reserved_ipv6_prefix_address, reserved_ipv6_prefix_length, option_code, /// option_space. cass_int64_t id_; /// @brief Client's identifier (e.g. DUID, HW address) in binary format - CassHostIdentifier host_identifier_; + CassBlob host_identifier_; /// @brief Type of the identifier in the host_identifier_ /// This value corresponds to the @ref Host::IdentifierType value. @@ -578,7 +289,7 @@ private: /// @brief IPv4 subnet identifier cass_int32_t host_ipv4_subnet_id_; - /// @brief Ipv6 subnet identifier + /// @brief IPv6 subnet identifier cass_int32_t host_ipv6_subnet_id_; /// @brief Reserved IPv4 address @@ -614,7 +325,7 @@ private: cass_int32_t option_code_; /// @brief Option value - CassOptionBuffer option_value_; + CassBlob option_value_; /// @brief The textual value of an option std::string option_formatted_value_; @@ -632,140 +343,346 @@ private: cass_int32_t option_subnet_id_; }; // CqlHostExchange -CqlHostExchange::CqlHostExchange() - : host_identifier_type_(0), host_ipv4_subnet_id_(0), - host_ipv6_subnet_id_(0), host_ipv4_address_(0), - reserved_ipv6_prefix_length_(0), reserved_ipv6_prefix_address_type_(0), - iaid_(0), option_universe_(0), option_code_(0), - option_is_persistent_(cass_false), option_subnet_id_(0) { - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "id", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_INT64))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "host_identifier", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_BYTES))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "host_identifier_type", parameters_.size(), - EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "host_ipv4_subnet_id", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_INT32))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "host_ipv6_subnet_id", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_INT32))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "host_ipv4_address", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_INT32))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "hostname", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_STRING))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "host_ipv4_client_classes", parameters_.size(), - EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_STRING))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "host_ipv6_client_classes", parameters_.size(), - EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_STRING))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "reserved_ipv6_prefix_address", parameters_.size(), - EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_STRING))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "reserved_ipv6_prefix_length", parameters_.size(), - EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "reserved_ipv6_prefix_address_type", parameters_.size(), - EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "iaid", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_INT32))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "option_universe", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_INT32))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "option_code", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_INT32))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "option_value", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_BYTES))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "option_formatted_value", parameters_.size(), - EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_STRING))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "option_space", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_STRING))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "option_is_persistent", parameters_.size(), - EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BOOL))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "option_client_class", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_STRING))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "option_subnet_id", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_INT32))); - parameters_.push_back(ExchangeColumnInfoPtr(new ExchangeColumnInfo( - "[applied]", parameters_.size(), EXCHANGE_DATA_TYPE_IO_IN_OUT, - EXCHANGE_DATA_TYPE_BOOL))); - BOOST_ASSERT(parameters_.size() == 22U); +constexpr StatementTag CqlHostExchange::INSERT_HOST; +constexpr StatementTag CqlHostExchange::GET_HOST_BY_HOST_ID; +constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_ADDRESS; +constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID; +constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID; +constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS; +constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_PREFIX; +constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS; + +StatementMap CqlHostExchange::tagged_statements_ = { + {INSERT_HOST, // + {INSERT_HOST, // + "INSERT INTO host_reservations ( " + "id, " + "host_identifier, " + "host_identifier_type, " + "host_ipv4_subnet_id, " + "host_ipv6_subnet_id, " + "host_ipv4_address, " + "hostname, " + "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 " + ") VALUES ( " + // id + "?, " + // host + "?, ?, ?, ?, ?, ?, ?, ?, " + // denormalized reservation, option + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? " + ") " + "IF NOT EXISTS " + }}, + + {GET_HOST_BY_HOST_ID, // + {GET_HOST_BY_HOST_ID, // + "SELECT " + "id, " + "host_identifier, " + "host_identifier_type, " + "host_ipv4_subnet_id, " + "host_ipv6_subnet_id, " + "host_ipv4_address, " + "hostname, " + "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 " + "FROM host_reservations " + "WHERE host_identifier = ? " + "AND host_identifier_type = ? " + "ALLOW FILTERING " + }}, + + {GET_HOST_BY_IPV4_ADDRESS, // + {GET_HOST_BY_IPV4_ADDRESS, // + "SELECT " + "id, " + "host_identifier, " + "host_identifier_type, " + "host_ipv4_subnet_id, " + "host_ipv6_subnet_id, " + "host_ipv4_address, " + "hostname, " + "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 " + "FROM host_reservations " + "WHERE host_ipv4_address = ? " + "ALLOW FILTERING " + }}, + + {GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID, // + {GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID, // + "SELECT " + "id, " + "host_identifier, " + "host_identifier_type, " + "host_ipv4_subnet_id, " + "host_ipv6_subnet_id, " + "host_ipv4_address, " + "hostname, " + "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 " + "FROM host_reservations " + "WHERE host_ipv4_subnet_id = ? " + "AND host_identifier = ? " + "AND host_identifier_type = ? " + "ALLOW FILTERING " + }}, + + {GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID, // + {GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID, // + "SELECT " + "id, " + "host_identifier, " + "host_identifier_type, " + "host_ipv4_subnet_id, " + "host_ipv6_subnet_id, " + "host_ipv4_address, " + "hostname, " + "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 " + "FROM host_reservations " + "WHERE host_ipv6_subnet_id = ? " + "AND host_identifier = ? " + "AND host_identifier_type = ? " + "ALLOW FILTERING " + }}, + + {GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS, // + {GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS, // + "SELECT " + "id, " + "host_identifier, " + "host_identifier_type, " + "host_ipv4_subnet_id, " + "host_ipv6_subnet_id, " + "host_ipv4_address, " + "hostname, " + "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 " + "FROM host_reservations " + "WHERE host_ipv4_subnet_id = ? " + "AND host_ipv4_address = ? " + "ALLOW FILTERING " + }}, + + {GET_HOST_BY_IPV6_PREFIX, // + {GET_HOST_BY_IPV6_PREFIX, // + "SELECT " + "id, " + "host_identifier, " + "host_identifier_type, " + "host_ipv4_subnet_id, " + "host_ipv6_subnet_id, " + "host_ipv4_address, " + "hostname, " + "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 " + "FROM host_reservations " + "WHERE reserved_ipv6_prefix_address = ? " + "AND reserved_ipv6_prefix_length = ? " + "ALLOW FILTERING " + }}, + + {GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS, // + {GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS, // + "SELECT " + "id, " + "host_identifier, " + "host_identifier_type, " + "host_ipv4_subnet_id, " + "host_ipv6_subnet_id, " + "host_ipv4_address, " + "hostname, " + "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 " + "FROM host_reservations " + "WHERE host_ipv6_subnet_id = ? " + "AND reserved_ipv6_prefix_address = ? " + "ALLOW FILTERING " + }}, + +}; + +CqlHostExchange::CqlHostExchange(CqlConnection& connection) + : host_(NULL), connection_(connection), id_(0), host_identifier_type_(0), + host_ipv4_subnet_id_(0), host_ipv6_subnet_id_(0), host_ipv4_address_(0), + reserved_ipv6_prefix_length_(NULL_RESERVED_IPV6_PREFIX_LENGTH), + reserved_ipv6_prefix_address_type_( + NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE), + iaid_(NULL_IAID), option_universe_(NULL_OPTION_UNIVERSE), + option_code_(NULL_OPTION_CODE), + option_is_persistent_(NULL_OPTION_IS_PERSISTENT), + option_subnet_id_(NULL_OPTION_SUBNET_ID) { } CqlHostExchange::~CqlHostExchange() { } void -CqlHostExchange::createBindForReceive(CqlDataArray& data, - const int /* statement_index = -1 */) { +CqlHostExchange::createBindForSelect(AnyArray& data, + StatementTag /* statement_tag = NULL */) { // Start with a fresh array. data.clear(); + // id: blob - data.add(reinterpret_cast(&id_)); + data.add(&id_); + // host_identifier: blob - data.add(reinterpret_cast(&host_identifier_)); + data.add(&host_identifier_); // host_identifier_type: int - data.add(reinterpret_cast(&host_identifier_type_)); + data.add(&host_identifier_type_); // host_ipv4_subnet_id: int - data.add(reinterpret_cast(&host_ipv4_subnet_id_)); + data.add(&host_ipv4_subnet_id_); // host_ipv6_subnet_id: int - data.add(reinterpret_cast(&host_ipv6_subnet_id_)); + data.add(&host_ipv6_subnet_id_); // host_ipv4_address: int - data.add(reinterpret_cast(&host_ipv4_address_)); + data.add(&host_ipv4_address_); // hostname: text - data.add(reinterpret_cast(&hostname_)); + data.add(&hostname_); // host_ipv4_client_classes: text - data.add(reinterpret_cast(&host_ipv4_client_classes_)); + data.add(&host_ipv4_client_classes_); // host_ipv6_client_classes: text - data.add(reinterpret_cast(&host_ipv6_client_classes_)); + data.add(&host_ipv6_client_classes_); + /// @brief Denormalized reservation columns + /// @{ // reserved_ipv6_prefix_address: text - data.add(reinterpret_cast(&reserved_ipv6_prefix_address_)); - // reserved_ipv6_prefix_length: int - data.add(reinterpret_cast(&reserved_ipv6_prefix_length_)); + data.add(&reserved_ipv6_prefix_address_); // reserved_ipv6_prefix_length: int - data.add(reinterpret_cast(&reserved_ipv6_prefix_address_type_)); + data.add(&reserved_ipv6_prefix_length_); + // reserved_ipv6_prefix_address_type: int + data.add(&reserved_ipv6_prefix_address_type_); // iaid: int - data.add(reinterpret_cast(&iaid_)); + data.add(&iaid_); + /// @} + + /// @brief Denormalized option columns + /// @{ // option_universe: int - data.add(reinterpret_cast(&option_universe_)); + data.add(&option_universe_); // option_code: int - data.add(reinterpret_cast(&option_code_)); + data.add(&option_code_); // option_value: blob - data.add(reinterpret_cast(&option_value_)); + data.add(&option_value_); // option_formatted_value: text - data.add(reinterpret_cast(&option_formatted_value_)); + data.add(&option_formatted_value_); // option_space: text - data.add(reinterpret_cast(&option_space_)); + data.add(&option_space_); // option_is_persistent: boolean - data.add(reinterpret_cast(&option_is_persistent_)); + data.add(&option_is_persistent_); // option_client_class: text - data.add(reinterpret_cast(&option_client_class_)); + data.add(&option_client_class_); // option_subnet_id: int - data.add(reinterpret_cast(&option_subnet_id_)); + data.add(&option_subnet_id_); + /// @} } void -CqlHostExchange::createBindForSend(const HostPtr& host, - const OptionalValue& subnet_id, - const IPv6Resrv* const reservation, - const std::string& option_space, - const OptionDescriptor& option_descriptor, - CqlDataArray& data) { +CqlHostExchange::createBindForMutation( + const HostPtr& host, + const OptionalValue& subnet_id, + const IPv6Resrv* const reservation, + const std::string& option_space, + const OptionDescriptor& option_descriptor, + StatementTag statement_tag, + AnyArray& data) { // Store host object to ensure it remains valid. host_ = host; @@ -773,24 +690,28 @@ CqlHostExchange::createBindForSend(const HostPtr& host, // structure. try { // host_identifier: blob - // Convert from std::vector to std::vector. + // Convert from std::vector to + // std::vector. HostIdentifier host_identifier = host->getIdentifier(); - host_identifier_ = CassHostIdentifier(host_identifier.begin(), - host_identifier.end()); + host_identifier_ = + CassBlob(host_identifier.begin(), host_identifier.end()); if (host_identifier_.size() > DUID::MAX_DUID_LEN) { - isc_throw(BadValue, "host identifier " - << host_identifier_.data() << " of length " - << host_identifier_.size() - << " is greater than allowed of " - << DUID::MAX_DUID_LEN); + isc_throw( + BadValue, + "CqlHostExchange::createBindForMutation(): host identifier " + << host_identifier_.data() << " of length " + << host_identifier_.size() << " is greater than allowed of " + << DUID::MAX_DUID_LEN); } - // host_identifier_type: int + // host_identifier_type: tinyint host_identifier_type_ = static_cast(host->getIdentifierType()); if (host_identifier_type_ > MAX_IDENTIFIER_TYPE) { - isc_throw(BadValue, "invalid host identifier type returned: " - << host_identifier_type_); + isc_throw(BadValue, + "CqlHostExchange::createBindForMutation(): invalid " + "host identifier type returned: " + << host_identifier_type_); } // host_ipv4_subnet_id: int @@ -808,37 +729,43 @@ CqlHostExchange::createBindForSend(const HostPtr& host, // hostname: text hostname_ = host->getHostname(); if (hostname_.size() > HOSTNAME_MAX_LENGTH) { - isc_throw(BadValue, "hostname " << hostname_ << " of length " - << hostname_.size() - << " is greater than allowed of " - << HOSTNAME_MAX_LENGTH); + isc_throw(BadValue, + "CqlHostExchange::createBindForMutation(): hostname " + << hostname_ << " of length " << hostname_.size() + << " is greater than allowed of " + << HOSTNAME_MAX_LENGTH); } // host_ipv4_client_classes: text host_ipv4_client_classes_ = host->getClientClasses4().toText(","); if (host_ipv4_client_classes_.size() > CLIENT_CLASSES_MAX_LENGTH) { - isc_throw(BadValue, "IPv4 client classes " - << host_ipv4_client_classes_ - << " of length " - << host_ipv4_client_classes_.size() - << " is greater than allowed of " - << CLIENT_CLASSES_MAX_LENGTH); + isc_throw(BadValue, + "CqlHostExchange::createBindForMutation(): " + "IPv4 client classes " + << host_ipv4_client_classes_ << " of length " + << host_ipv4_client_classes_.size() + << " is greater than allowed of " + << CLIENT_CLASSES_MAX_LENGTH); } // host_ipv6_client_classes: text host_ipv6_client_classes_ = host->getClientClasses6().toText(","); if (host_ipv6_client_classes_.size() > CLIENT_CLASSES_MAX_LENGTH) { - isc_throw(BadValue, "IPv6 client classes " - << host_ipv6_client_classes_ - << " of length " - << host_ipv6_client_classes_.size() - << " is greater than allowed of " - << CLIENT_CLASSES_MAX_LENGTH); + isc_throw(BadValue, + "CqlHostExchange::createBindForMutation(): " + "IPv6 client classes " + << host_ipv6_client_classes_ << " of length " + << host_ipv6_client_classes_.size() + << " is greater than allowed of " + << CLIENT_CLASSES_MAX_LENGTH); } if (reservation == NULL) { + // reserved_ipv6_prefix_address: text reserved_ipv6_prefix_address_ = NULL_RESERVED_IPV6_PREFIX_ADDRESS; + // reserved_ipv6_prefix_length: int reserved_ipv6_prefix_length_ = NULL_RESERVED_IPV6_PREFIX_LENGTH; + // reserved_ipv6_prefix_address_type: int reserved_ipv6_prefix_address_type_ = NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE; iaid_ = NULL_IAID; @@ -850,7 +777,7 @@ CqlHostExchange::createBindForSend(const HostPtr& host, reserved_ipv6_prefix_length_ = static_cast(reservation->getPrefixLen()); - // reserved_ipv6_prefix_address: int + // reserved_ipv6_prefix_address_type: int reserved_ipv6_prefix_address_type_ = reservation->getType() == IPv6Resrv::TYPE_NA ? 0 : 2; @@ -924,31 +851,39 @@ CqlHostExchange::createBindForSend(const HostPtr& host, // Add all parameters to bind array. data.clear(); - data.add(reinterpret_cast(&id_)); - data.add(reinterpret_cast(&host_identifier_)); - data.add(reinterpret_cast(&host_identifier_type_)); - data.add(reinterpret_cast(&host_ipv4_subnet_id_)); - data.add(reinterpret_cast(&host_ipv6_subnet_id_)); - data.add(reinterpret_cast(&host_ipv4_address_)); - data.add(reinterpret_cast(&hostname_)); - data.add(reinterpret_cast(&host_ipv4_client_classes_)); - data.add(reinterpret_cast(&host_ipv6_client_classes_)); - data.add(reinterpret_cast(&reserved_ipv6_prefix_address_)); - data.add(reinterpret_cast(&reserved_ipv6_prefix_length_)); - data.add(reinterpret_cast(&reserved_ipv6_prefix_address_type_)); - data.add(reinterpret_cast(&iaid_)); - data.add(reinterpret_cast(&option_universe_)); - data.add(reinterpret_cast(&option_code_)); - data.add(reinterpret_cast(&option_value_)); - data.add(reinterpret_cast(&option_formatted_value_)); - data.add(reinterpret_cast(&option_space_)); - data.add(reinterpret_cast(&option_is_persistent_)); - data.add(reinterpret_cast(&option_client_class_)); - data.add(reinterpret_cast(&option_subnet_id_)); - } catch (const std::exception& ex) { - isc_throw(DbOperationError, "could not create bind array from host " - << host->getHostname() - << ", reason: " << ex.what()); + + if (statement_tag == CqlHostExchange::INSERT_HOST) { + data.add(&id_); + data.add(&host_identifier_); + data.add(&host_identifier_type_); + data.add(&host_ipv4_subnet_id_); + data.add(&host_ipv6_subnet_id_); + data.add(&host_ipv4_address_); + data.add(&hostname_); + data.add(&host_ipv4_client_classes_); + data.add(&host_ipv6_client_classes_); + } + // Reservation + data.add(&reserved_ipv6_prefix_address_); + data.add(&reserved_ipv6_prefix_length_); + data.add(&reserved_ipv6_prefix_address_type_); + data.add(&iaid_); + + // Option + data.add(&option_universe_); + data.add(&option_code_); + data.add(&option_value_); + data.add(&option_formatted_value_); + data.add(&option_space_); + data.add(&option_is_persistent_); + data.add(&option_client_class_); + data.add(&option_subnet_id_); + + } catch (const Exception& ex) { + isc_throw(DbOperationError, + "CqlHostExchange::createBindForMutation(): " + "could not create bind array from host " + << host->getHostname() << ", reason: " << ex.what()); } } @@ -977,30 +912,33 @@ CqlHostExchange::hashIntoId() const { // Get key. std::stringstream key_stream; - key_stream << std::setw(10) << std::setfill('0') << host_ipv4_subnet_id_; - key_stream << std::setw(10) << std::setfill('0') << host_ipv6_subnet_id_; - key_stream << std::setw(ADDRESS4_TEXT_MAX_LENGTH) << host_ipv4_address_; - key_stream << std::setw(ADDRESS6_TEXT_MAX_LENGTH) + key_stream << std::setw(10) << std::setfill('-') << host_ipv4_subnet_id_; + key_stream << std::setw(10) << std::setfill('-') << host_ipv6_subnet_id_; + key_stream << std::setw(ADDRESS4_TEXT_MAX_LENGTH) << std::setfill('-') + << host_ipv4_address_; + key_stream << std::setw(ADDRESS6_TEXT_MAX_LENGTH) << std::setfill('-') << reserved_ipv6_prefix_address_; - key_stream << std::setw(4) << std::setfill('0') + key_stream << std::setw(4) << std::setfill('-') << reserved_ipv6_prefix_length_; - key_stream << std::setw(4) << std::setfill('0') << option_code_; - key_stream << std::setw(OPTION_SPACE_MAX_LENGTH) << option_space_; + key_stream << std::setw(4) << std::setfill('-') << option_code_; + key_stream << std::setw(OPTION_SPACE_MAX_LENGTH) << std::setfill('-') + << option_space_; const std::string key = key_stream.str(); - const uint64_t md5 = md5Hash(key); + const cass_int64_t md5 = static_cast(md5Hash(key)); - return static_cast(md5); + return md5; } -void* +boost::any CqlHostExchange::retrieve() { - uint64_t id = static_cast(id_); + const uint64_t id = static_cast(id_); HostIdentifier host_identifier = HostIdentifier(host_identifier_.begin(), host_identifier_.end()); - // Set the host identifier type in a variable of the appropriate data type. + // Set the host identifier type in a variable of the appropriate + // data type. Host::IdentifierType host_identifier_type = static_cast(host_identifier_type_); @@ -1012,7 +950,7 @@ CqlHostExchange::retrieve() { // Set IPv4 address reservation. asiolink::IOAddress ipv4_reservation = - asiolink::IOAddress(host_ipv4_address_); + asiolink::IOAddress(static_cast(host_ipv4_address_)); Host* host = new Host(host_identifier.data(), host_identifier.size(), host_identifier_type, ipv4_subnet_id, ipv6_subnet_id, @@ -1026,22 +964,25 @@ CqlHostExchange::retrieve() { host->addReservation(reservation); } - OptionDescriptorPtr option_descriptor_ptr = retrieveOption(); - if (option_descriptor_ptr) { - if (option_descriptor_ptr->option_->getUniverse() == Option::V4) { - host->getCfgOption4()->add(*option_descriptor_ptr, option_space_); - } else if (option_descriptor_ptr->option_->getUniverse() == + OptionWrapper option_wrapper = retrieveOption(); + if (option_wrapper.option_descriptor_) { + if (option_wrapper.option_descriptor_->option_->getUniverse() == + Option::V4) { + host->getCfgOption4()->add(*option_wrapper.option_descriptor_, + option_wrapper.option_space_); + } else if (option_wrapper.option_descriptor_->option_->getUniverse() == Option::V6) { - host->getCfgOption6()->add(*option_descriptor_ptr, option_space_); + host->getCfgOption6()->add(*option_wrapper.option_descriptor_, + option_wrapper.option_space_); } } - return reinterpret_cast(host); + return host; } const IPv6Resrv CqlHostExchange::retrieveReservation() const { - // Set the IPv6 Reservation type (0 = IA_NA, 2 = IA_PD) + // Set the IPv6 Reservation type (0 = IA_NA, 2 = IA_PD). IPv6Resrv::Type type; switch (reserved_ipv6_prefix_address_type_) { case 0: @@ -1054,7 +995,8 @@ CqlHostExchange::retrieveReservation() const { return NULL_IPV6_RESERVATION; default: isc_throw(BadValue, - "invalid IPv6 reservation type returned: " + "CqlHostExchange::retrieveReservation(): invalid IPv6 " + "reservation type returned: " << reserved_ipv6_prefix_address_type_ << ". Only 0 (IA_NA) or 2 (IA_PD) are allowed."); } @@ -1063,7 +1005,7 @@ CqlHostExchange::retrieveReservation() const { reserved_ipv6_prefix_length_); } -OptionDescriptorPtr +const OptionWrapper CqlHostExchange::retrieveOption() const { // Options are held in a binary or textual format in the database. // This is similar to having an option specified in a server @@ -1075,7 +1017,7 @@ CqlHostExchange::retrieveOption() const { // this is most likely a standard option, for which we have a // definition created within libdhcp++. if (option_space_.empty() || option_universe_ == NULL_OPTION_UNIVERSE) { - return OptionDescriptorPtr(); + return OptionWrapper(OptionDescriptorPtr(), ""); } OptionDefinitionPtr option_definition_ptr = @@ -1108,8 +1050,10 @@ CqlHostExchange::retrieveOption() const { static_cast(option_code_), option_buffer.begin(), option_buffer.end())); } else { - // The option value may be specified in textual or binary format in the - // database. If formatted_value is empty, the binary format is used. + // The option value may be specified in textual or binary format + // in the + // database. If formatted_value is empty, the binary format is + // used. // Depending on the format we use a different variant of @ref // optionFactory(). if (option_formatted_value_.empty()) { @@ -1120,7 +1064,8 @@ CqlHostExchange::retrieveOption() const { static_cast(option_code_), option_buffer.begin(), option_buffer.end()); } else { - // Spit the value specified in comma separated values format. + // Spit the value specified in comma separated values + // format. std::vector split_vector; boost::split(split_vector, option_formatted_value_, boost::is_any_of(",")); @@ -1130,8 +1075,10 @@ CqlHostExchange::retrieveOption() const { } } - return OptionDescriptorPtr(new OptionDescriptor( - option, option_is_persistent_, option_formatted_value_)); + return OptionWrapper( + OptionDescriptorPtr(new OptionDescriptor(option, option_is_persistent_, + option_formatted_value_)), + option_space_); } /// @brief Implementation of the @ref CqlHostDataSource. @@ -1139,7 +1086,8 @@ class CqlHostDataSourceImpl { public: /// @brief Constructor. /// - /// This constructor opens database connection and initializes prepared + /// This constructor opens database connection and initializes + /// prepared /// statements used in the queries. explicit CqlHostDataSourceImpl( const CqlConnection::ParameterMap& parameters); @@ -1148,53 +1096,113 @@ public: virtual ~CqlHostDataSourceImpl(); /// @brief Implementation of @ref CqlHostDataSource::add() + /// + /// See @ref CqlHostDataSource::add() for parameter details. + /// + /// @param host virtual void add(const HostPtr& host); /// @brief Implementation of @ref CqlHostDataSource::get4() + /// + /// See @ref CqlHostDataSource::get4() for parameter details. + /// + /// @param subnet_id + /// @param address virtual ConstHostPtr get4(const SubnetID& subnet_id, const asiolink::IOAddress& address) const; /// @brief Implementation of @ref CqlHostDataSource::get4() + /// + /// See @ref CqlHostDataSource::get4() for parameter details. + /// + /// @param subnet_id + /// @param hwaddr + /// @param duid virtual ConstHostPtr get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr, const DuidPtr& duid = DuidPtr()) const; /// @brief Implementation of @ref CqlHostDataSource::get4() + /// + /// See @ref CqlHostDataSource::get4() for parameter details. + /// + /// @param subnet_id + /// @param identifier_type + /// @param identifier_begin + /// @param identifier_len virtual ConstHostPtr get4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type, const uint8_t* identifier_begin, const size_t identifier_len) const; /// @brief Implementation of @ref CqlHostDataSource::get6() + /// + /// See @ref CqlHostDataSource::get6() for parameter details. + /// + /// @param prefix + /// @param prefix_len virtual ConstHostPtr get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const; /// @brief Implementation of @ref CqlHostDataSource::get6() + /// + /// See @ref CqlHostDataSource::get6() for parameter details. + /// + /// @param subnet_id + /// @param duid + /// @param hwaddr virtual ConstHostPtr get6(const SubnetID& subnet_id, const DuidPtr& duid, const HWAddrPtr& hwaddr = HWAddrPtr()) const; /// @brief Implementation of @ref CqlHostDataSource::get6() + /// + /// See @ref CqlHostDataSource::get6() for parameter details. + /// + /// @param subnet_id + /// @param identifier_type + /// @param identifier_begin + /// @param identifier_len virtual ConstHostPtr get6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type, const uint8_t* identifier_begin, const size_t identifier_len) const; /// @brief Implementation of @ref CqlHostDataSource::get6() + /// + /// See @ref CqlHostDataSource::get6() for parameter details. + /// + /// @param subnet_id + /// @param address virtual ConstHostPtr get6(const SubnetID& subnet_id, const asiolink::IOAddress& address) const; - /// @brief Implementation of @ref CqlHostDataSource::getAll + /// @brief Implementation of @ref CqlHostDataSource::getAll() + /// + /// See @ref CqlHostDataSource::getAll() for parameter details. + /// + /// @param hwaddr + /// @param duid virtual ConstHostCollection getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid = DuidPtr()) const; /// @brief Implementation of @ref CqlHostDataSource::getAll() + /// + /// See @ref CqlHostDataSource::getAll() for parameter details. + /// + /// @param identifier_type + /// @param identifier_begin + /// @param identifier_len virtual ConstHostCollection getAll(const Host::IdentifierType& identifier_type, const uint8_t* identifier_begin, const size_t identifier_len) const; /// @brief Implementation of @ref CqlHostDataSource::getAll4() + /// + /// See @ref CqlHostDataSource::getAll4() for parameter details. + /// + /// @param address virtual ConstHostCollection getAll4(const asiolink::IOAddress& address) const; @@ -1211,14 +1219,18 @@ public: virtual void rollback(); protected: - /// @brief Adds any options found in the @ref Host object to a separate + /// @brief Adds any options found in the @ref Host object to a + /// separate /// table entry. /// - /// @param host @ref Host object from which options are retrieved and + /// @param host @ref Host object from which options are retrieved + /// and /// inserted into the Cassandra database - /// @param reservation reservation for the current denormalized table entry + /// @param reservation reservation for the current denormalized + /// table entry /// @param option_spaces list of option spaces to search for - /// @param cfg_option option configuration used to match option spaces in + /// @param cfg_option option configuration used to match option + /// spaces in /// order to obtain actual options virtual void insertHostWithOptions( const HostPtr& host, @@ -1226,19 +1238,26 @@ protected: const std::list& option_spaces = std::list(), const ConstCfgOptionPtr cfg_option = ConstCfgOptionPtr()); - /// @brief Adds any reservations found in the @ref Host object to a separate + /// @brief Adds any reservations found in the @ref Host object to a + /// separate /// table entry. /// - /// @param host @ref Host object from which reservations are retrieved and + /// @param host @ref Host object from which reservations are + /// retrieved and /// inserted into the Cassandra database - /// @param reservation reservation for the current denormalized table entry - /// @param option_spaces4 list of option spaces for universe Option::V4 to + /// @param reservation reservation for the current denormalized + /// table entry + /// @param option_spaces4 list of option spaces for universe + /// Option::V4 to /// search in - /// @param cfg_option4 option configuration for universe Option::V4 used to + /// @param cfg_option4 option configuration for universe Option::V4 + /// used to /// match option spaces in order to obtain actual options - /// @param option_spaces6 list of option spaces for universe Option::V6 to + /// @param option_spaces6 list of option spaces for universe + /// Option::V6 to /// search in - /// @param cfg_option6 option configuration for universe Option::V6 used to + /// @param cfg_option6 option configuration for universe Option::V6 + /// used to /// match option spaces in order to obtain actual options virtual void insertHostWithReservations(const HostPtr& host, @@ -1250,43 +1269,49 @@ protected: /// @brief Retrieves a single host. /// - /// Calls @ref getHostCollection() and checks if a single host was returned. + /// Calls @ref getHostCollection() and checks if a single host was + /// returned. /// - /// @param where_values array of bound objects used to filter the results - /// @param statement_index prepared statement being executed + /// @param where_values array of bound objects used to filter the + /// results + /// @param statement_tag prepared statement being executed /// /// @return one host or a null pointer to a host /// - /// @throw MultipleRecords exception if two or more hosts are returned - virtual ConstHostPtr - getHost(const CqlDataArray& where_values, - const CqlHostExchange::StatementIndex statement_index) const; + /// @throw MultipleRecords exception if two or more hosts are + /// returned + virtual ConstHostPtr getHost(StatementTag statement_tag, + AnyArray& where_values) const; /// @brief Retrieves a collection of hosts. /// - /// Calls @ref CqlExchange::executeRead(). + /// Calls @ref CqlExchange::executeSelect(). /// - /// @param where_values array of bound objects used to filter the results - /// @param statement_index prepared statement being executed + /// @param where_values array of bound objects used to filter the + /// results + /// @param statement_tag prepared statement being executed /// /// @return a collection of hosts containing one or more hosts - virtual ConstHostCollection getHostCollection( - const CqlDataArray& where_values, - const CqlHostExchange::StatementIndex statement_index) const; + virtual ConstHostCollection getHostCollection(StatementTag statement_tag, + AnyArray& where_values) const; /// @brief Inserts a single host. /// /// All information is available here. Calls @ref - /// CqlExchange::executeWrite(). + /// CqlExchange::executeMutation(). /// - /// @param host @ref Host object from which options are retrieved and + /// @param host @ref Host object from which options are retrieved + /// and /// inserted into the Cassandra database - /// @param subnet_id identifier of the subnet to which the host belongs - /// @param reservation reservation for the current denormalized table entry - /// @param option_space option space for the current denormalized table + /// @param subnet_id identifier of the subnet to which the host + /// belongs + /// @param reservation reservation for the current denormalized + /// table entry + /// @param option_space option space for the current denormalized + /// table /// entry's option - /// @param option_descriptor option descriptor containing information for - /// the current denormalized table entry's option + /// @param option_descriptor option descriptor containing + /// information for the current denormalized table entry's option virtual void insertHost( const HostPtr& host, const OptionalValue& subnet_id = OptionalValue(), @@ -1294,27 +1319,25 @@ protected: const std::string& option_space = NULL_OPTION_SPACE, const OptionDescriptor& option_descriptor = OptionDescriptor(false)); - /// @brief Merge denormalized table entries that belong to the same host + /// @brief Merge denormalized table entries that belong to the same + /// host /// into a single host, one by one. /// - /// @param target_host host which can contain multiple reservations and - /// options to which other distinct reservations and options are added. - /// @param source_host host that is being search for new reservations and + /// @param target_host host which can contain multiple reservations + /// and + /// options to which other distinct reservations and options are + /// added. + /// @param source_host host that is being search for new + /// reservations and /// options that will be merged into the old host. - virtual void mergeHosts(HostPtr& target_host, - const ConstHostPtr& source_host) const; + virtual void mergeHosts(const ConstHostPtr& source_host, + HostPtr& target_host) const; private: - /// @brief pointer to the exchange responsible for trading host information - boost::shared_ptr host_exchange_; - /// @brief pointer to the exchange responsible for retrieving schema version - boost::shared_ptr version_exchange_; - /// @brief CQL connection mutable CqlConnection dbconn_; }; // class CqlHostDataSourceImpl - /// @brief hash function for HostMap /// /// @param key being hashed @@ -1324,14 +1347,17 @@ std::size_t hash_value(const HostKey& key) { // Get key. std::stringstream key_stream; - HostIdentifier host_identifier = key.get<0>(); + HostIdentifier host_identifier = std::get(key); key_stream << std::setw(DUID::MAX_DUID_LEN) << std::setfill('0') << DUID(host_identifier).toText(); - key_stream << std::setw(2) << std::setfill('0') << key.get<1>(); - key_stream << std::setw(10) << std::setfill('0') << key.get<2>(); - key_stream << std::setw(10) << std::setfill('0') << key.get<3>(); + key_stream << std::setw(2) << std::setfill('0') + << std::get(key); + key_stream << std::setw(10) << std::setfill('0') + << std::get(key); + key_stream << std::setw(10) << std::setfill('0') + << std::get(key); key_stream << std::setw(ADDRESS4_TEXT_MAX_LENGTH) << std::setfill('0') - << key.get<4>(); + << std::get(key); const std::string key_string = key_stream.str(); const uint64_t md5 = md5Hash(key_string); @@ -1347,19 +1373,23 @@ hash_value(const HostKey& key) { /// @return true if keys are equal. Deep comparison is made. bool operator==(const HostKey& key1, const HostKey& key2) { - return key1.get<0>() == key2.get<0>() && key1.get<1>() == key2.get<1>() && - key1.get<2>() == key2.get<2>() && key1.get<3>() == key2.get<3>() && - key1.get<4>() == key2.get<4>(); + return std::get(key1) == std::get(key2) && + std::get(key1) == + std::get(key2) && + std::get(key1) == std::get(key2) && + std::get(key1) == std::get(key2) && + std::get(key1) == std::get(key2); } CqlHostDataSourceImpl::CqlHostDataSourceImpl( const CqlConnection::ParameterMap& parameters) - : host_exchange_(new CqlHostExchange()), - version_exchange_(new CqlVersionExchange()), dbconn_(parameters) { + : dbconn_(parameters) { // Open the database. dbconn_.openDatabase(); + // Prepare all possible statements. - dbconn_.prepareStatements(tagged_statements); + dbconn_.prepareStatements(CqlHostExchange::tagged_statements_); + dbconn_.prepareStatements(CqlVersionExchange::tagged_statements_); } CqlHostDataSourceImpl::~CqlHostDataSourceImpl() { @@ -1369,10 +1399,8 @@ CqlHostDataSourceImpl::~CqlHostDataSourceImpl() { void CqlHostDataSourceImpl::add(const HostPtr& host) { - // Start transaction. - CqlTransaction transaction(dbconn_); - - // Get option space names and vendor space names and combine them within a + // Get option space names and vendor space names and combine them + // within a // single list. // For IPv4: ConstCfgOptionPtr cfg_option4 = host->getCfgOption4(); @@ -1390,7 +1418,8 @@ CqlHostDataSourceImpl::add(const HostPtr& host) { option_spaces6.insert(option_spaces6.end(), vendor_spaces6.begin(), vendor_spaces6.end()); - // For every IPv6 reservation, add each of their options to the database. + // For every IPv6 reservation, add each of their options to the + // database. IPv6ResrvRange reservations = host->getIPv6Reservations(); if (std::distance(reservations.first, reservations.second) > 0) { for (IPv6ResrvIterator it = reservations.first; @@ -1400,12 +1429,12 @@ CqlHostDataSourceImpl::add(const HostPtr& host) { cfg_option6); } } else { - // If host has no reservation, add entries with null reservation. + // If host has no reservation, add entries with null + // reservation. // Options could still be present. insertHostWithReservations(host, NULL, option_spaces4, cfg_option4, option_spaces6, cfg_option6); } - transaction.commit(); } ConstHostPtr @@ -1422,20 +1451,24 @@ CqlHostDataSourceImpl::get4(const SubnetID& subnet_id, static_cast(address.toUint32()); // Bind to array. - CqlDataArray where_values; - where_values.add(reinterpret_cast(&host_ipv4_subnet_id)); - where_values.add(reinterpret_cast(&host_ipv4_address)); + AnyArray where_values; + where_values.add(&host_ipv4_subnet_id); + where_values.add(&host_ipv4_address); + // Run statement. - return getHost(*const_cast(&where_values), - CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS); + ConstHostPtr result = getHost( + CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS, where_values); + + return result; } ConstHostPtr CqlHostDataSourceImpl::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr, const DuidPtr& duid) const { - /// @todo: Rethink the logic in BaseHostDataSource::get4(subnet, hwaddr, + /// @todo: Rethink the logic in BaseHostDataSource::get4(subnet, + /// hwaddr, /// duid) if (hwaddr && duid) { isc_throw(BadValue, "CqlHostDataSource::get4(3) called with both " @@ -1444,17 +1477,26 @@ CqlHostDataSourceImpl::get4(const SubnetID& subnet_id, isc_throw(BadValue, "CqlHostDataSource::get4(3) called with neither " "hwaddr or duid specified, one of them is " "required"); - } else if (duid) { - HostIdentifier duid_vector = duid->getDuid(); - // Delegate to get4(4). - return get4(subnet_id, Host::IDENT_DUID, duid_vector.data(), - duid_vector.size()); + } + + const HostIdentifier* host_identifier; + Host::IdentifierType host_identifier_type; + if (duid) { + host_identifier = &duid->getDuid(); + host_identifier_type = Host::IDENT_DUID; } else if (hwaddr) { - // Delegate to get4(4). - return get4(subnet_id, Host::IDENT_HWADDR, hwaddr->hwaddr_.data(), - hwaddr->hwaddr_.size()); + host_identifier = &hwaddr->hwaddr_; + host_identifier_type = Host::IDENT_HWADDR; + } else { + return ConstHostPtr(); } - return ConstHostPtr(); + + // Delegate to get4(4). + ConstHostPtr result = + get4(subnet_id, host_identifier_type, host_identifier->data(), + host_identifier->size()); + + return result; } ConstHostPtr @@ -1463,21 +1505,24 @@ CqlHostDataSourceImpl::get4(const SubnetID& subnet_id, const uint8_t* identifier_begin, const size_t identifier_len) const { // Convert to CQL data types. - cass_int32_t host_ipv4_subnet_id = static_cast(subnet_id); - CassHostIdentifier host_identifier(identifier_begin, - identifier_begin + identifier_len); + CassBlob host_identifier(identifier_begin, + identifier_begin + identifier_len); cass_int32_t host_identifier_type = static_cast(identifier_type); + cass_int32_t host_ipv4_subnet_id = static_cast(subnet_id); // Bind to array. - CqlDataArray where_values; - where_values.add(reinterpret_cast(&host_ipv4_subnet_id)); - where_values.add(reinterpret_cast(&host_identifier)); - where_values.add(reinterpret_cast(&host_identifier_type)); + AnyArray where_values; + where_values.add(&host_ipv4_subnet_id); + where_values.add(&host_identifier); + where_values.add(&host_identifier_type); + // Run statement. - return getHost(*const_cast(&where_values), - CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID); + ConstHostPtr result = getHost( + CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID, where_values); + + return result; } ConstHostPtr @@ -1487,14 +1532,15 @@ CqlHostDataSourceImpl::get6(const asiolink::IOAddress& prefix, std::string reserved_ipv6_prefix_address = prefix.toText(); cass_int32_t reserved_ipv6_prefix_length = prefix_len; + ConstHostPtr host; // Bind to array. - CqlDataArray where_values; - where_values.add(reinterpret_cast(&reserved_ipv6_prefix_address)); - where_values.add(reinterpret_cast(&reserved_ipv6_prefix_length)); + AnyArray where_values; + where_values.add(&reserved_ipv6_prefix_address); + where_values.add(&reserved_ipv6_prefix_length); + // Get host id. - ConstHostPtr host = getHost(*const_cast(&where_values), - CqlHostExchange::GET_HOST_BY_IPV6_PREFIX); + host = getHost(CqlHostExchange::GET_HOST_BY_IPV6_PREFIX, where_values); if (host == ConstHostPtr()) { return ConstHostPtr(); @@ -1502,6 +1548,7 @@ CqlHostDataSourceImpl::get6(const asiolink::IOAddress& prefix, // Get host. HostIdentifier host_identifier = host->getIdentifier(); + // Delegate to getAll(3). ConstHostCollection collection = getAll(host->getIdentifierType(), host_identifier.data(), host_identifier.size()); @@ -1510,24 +1557,25 @@ CqlHostDataSourceImpl::get6(const asiolink::IOAddress& prefix, return ConstHostPtr(); } - if (collection.size() >= 2U) { - isc_throw( - MultipleRecords, - "CqlHostDataSource::get6(2): multiple records were found in the " - "database where only one was expected for statement " - << dbconn_ - .tagged_statements_[CqlHostExchange::GET_HOST_BY_HOST_ID] - .name_); + if (collection.size() >= 2u) { + isc_throw(MultipleRecords, + "CqlHostDataSource::get6(2): multiple records were " + "found in the " + "database where only one was expected for statement " + << CqlHostExchange::GET_HOST_BY_IPV6_PREFIX); } - return *collection.begin(); + ConstHostPtr result = *collection.begin(); + + return result; } ConstHostPtr CqlHostDataSourceImpl::get6(const SubnetID& subnet_id, const DuidPtr& duid, const HWAddrPtr& hwaddr) const { - /// @todo: Rethink the logic in BaseHostDataSource::get6(subnet, hwaddr, + /// @todo: Rethink the logic in BaseHostDataSource::get6(subnet, + /// hwaddr, /// duid) if (hwaddr && duid) { isc_throw(BadValue, "CqlHostDataSource::get6(3): both hardware address " @@ -1536,17 +1584,26 @@ CqlHostDataSourceImpl::get6(const SubnetID& subnet_id, } else if (!hwaddr && !duid) { isc_throw(BadValue, "CqlHostDataSource::get6(3): both hardware address " "and DUID are specified, one of them is required"); - } else if (duid) { - HostIdentifier duid_vector = duid->getDuid(); - // Delegate to get6(4). - return get6(subnet_id, Host::IDENT_DUID, duid_vector.data(), - duid_vector.size()); + } + + const HostIdentifier* host_identifier; + Host::IdentifierType host_identifier_type; + if (duid) { + host_identifier = &duid->getDuid(); + host_identifier_type = Host::IDENT_DUID; } else if (hwaddr) { - // Delegate to get6(4). - return get6(subnet_id, Host::IDENT_HWADDR, hwaddr->hwaddr_.data(), - hwaddr->hwaddr_.size()); + host_identifier = &hwaddr->hwaddr_; + host_identifier_type = Host::IDENT_HWADDR; + } else { + return ConstHostPtr(); } - return ConstHostPtr(); + + // Delegate to get6(4). + ConstHostPtr result = + get6(subnet_id, host_identifier_type, host_identifier->data(), + host_identifier->size()); + + return result; } ConstHostPtr @@ -1556,20 +1613,23 @@ CqlHostDataSourceImpl::get6(const SubnetID& subnet_id, const size_t identifier_len) const { // Convert to CQL data types. cass_int32_t host_ipv6_subnet_id = static_cast(subnet_id); - CassHostIdentifier host_identifier(identifier_begin, - identifier_begin + identifier_len); + CassBlob host_identifier(identifier_begin, + identifier_begin + identifier_len); cass_int32_t host_identifier_type = static_cast(identifier_type); // Bind to array. - CqlDataArray where_values; - where_values.add(reinterpret_cast(&host_ipv6_subnet_id)); - where_values.add(reinterpret_cast(&host_identifier)); - where_values.add(reinterpret_cast(&host_identifier_type)); + AnyArray where_values; + where_values.add(&host_ipv6_subnet_id); + where_values.add(&host_identifier); + where_values.add(&host_identifier_type); + // Run statement. - return getHost(*const_cast(&where_values), - CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID); + ConstHostPtr result = getHost( + CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID, where_values); + + return result; } ConstHostPtr @@ -1580,13 +1640,16 @@ CqlHostDataSourceImpl::get6(const SubnetID& subnet_id, std::string reserved_ipv6_prefix_address = address.toText(); // Bind to array. - CqlDataArray where_values; - where_values.add(reinterpret_cast(&host_ipv6_subnet_id)); - where_values.add(reinterpret_cast(&reserved_ipv6_prefix_address)); + AnyArray where_values; + where_values.add(&host_ipv6_subnet_id); + where_values.add(&reserved_ipv6_prefix_address); + // Run statement. - return getHost(*const_cast(&where_values), - CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS); + ConstHostPtr result = getHost( + CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS, where_values); + + return result; } ConstHostCollection @@ -1597,27 +1660,29 @@ CqlHostDataSourceImpl::getAll(const HWAddrPtr& hwaddr, } // Convert to CQL data types. - CassHostIdentifier host_identifier; cass_int32_t host_identifier_type; + CassBlob host_identifier; if (duid) { HostIdentifier duid_vector = duid->getDuid(); - host_identifier = - CassHostIdentifier(duid_vector.begin(), duid_vector.end()); + host_identifier = CassBlob(duid_vector.begin(), duid_vector.end()); host_identifier_type = static_cast(Host::IDENT_DUID); } else if (hwaddr) { - host_identifier = CassHostIdentifier(hwaddr->hwaddr_.begin(), - hwaddr->hwaddr_.end()); + host_identifier = + CassBlob(hwaddr->hwaddr_.begin(), hwaddr->hwaddr_.end()); host_identifier_type = static_cast(Host::IDENT_HWADDR); } // Bind to array. - CqlDataArray where_values; - where_values.add(reinterpret_cast(&host_identifier)); - where_values.add(reinterpret_cast(&host_identifier_type)); + AnyArray where_values; + where_values.add(&host_identifier); + where_values.add(&host_identifier_type); + // Run statement. - return getHostCollection(*const_cast(&where_values), - CqlHostExchange::GET_HOST_BY_HOST_ID); + ConstHostCollection result = + getHostCollection(CqlHostExchange::GET_HOST_BY_HOST_ID, where_values); + + return result; } ConstHostCollection @@ -1625,19 +1690,22 @@ CqlHostDataSourceImpl::getAll(const Host::IdentifierType& identifier_type, const uint8_t* identifier_begin, const size_t identifier_len) const { // Convert to CQL data types. - CassHostIdentifier host_identifier(identifier_begin, - identifier_begin + identifier_len); + CassBlob host_identifier(identifier_begin, + identifier_begin + identifier_len); cass_int32_t host_identifier_type = static_cast(identifier_type); // Bind to array. - CqlDataArray where_values; - where_values.add(reinterpret_cast(&host_identifier)); - where_values.add(reinterpret_cast(&host_identifier_type)); + AnyArray where_values; + where_values.add(&host_identifier); + where_values.add(&host_identifier_type); + // Run statement. - return getHostCollection(*const_cast(&where_values), - CqlHostExchange::GET_HOST_BY_HOST_ID); + ConstHostCollection result = + getHostCollection(CqlHostExchange::GET_HOST_BY_HOST_ID, where_values); + + return result; } ConstHostCollection @@ -1647,29 +1715,33 @@ CqlHostDataSourceImpl::getAll4(const asiolink::IOAddress& address) const { static_cast(address.toUint32()); // Bind to array. - CqlDataArray where_values; - where_values.add(reinterpret_cast(&host_ipv4_address)); + AnyArray where_values; + where_values.add(&host_ipv4_address); + // Run statement. - return getHostCollection(*const_cast(&where_values), - CqlHostExchange::GET_HOST_BY_IPV4_ADDRESS); + ConstHostCollection result = getHostCollection( + CqlHostExchange::GET_HOST_BY_IPV4_ADDRESS, where_values); + + return result; } std::string CqlHostDataSourceImpl::getName() const { - std::string name = ""; + std::string name = NULL; try { name = dbconn_.getParameter("name"); } catch (...) { - // Return an empty name + // Return an empty name. } return name; } VersionPair CqlHostDataSourceImpl::getVersion() const { - return version_exchange_->retrieveVersion(dbconn_, - CqlHostExchange::GET_VERSION); + std::unique_ptr version_exchange( + new CqlVersionExchange()); + return version_exchange->retrieveVersion(dbconn_); } void @@ -1689,22 +1761,22 @@ CqlHostDataSourceImpl::insertHostWithOptions( const std::list& option_spaces /* = std::list() */, const ConstCfgOptionPtr cfg_option /* = ConstCfgOptionPtr() */) { - // For each option space retrieve all options and insert them into the - // database. + // For each option space retrieve all options and insert them into + // the database. bool option_found = false; - for (std::list::const_iterator space = option_spaces.begin(); - space != option_spaces.end(); ++space) { - OptionContainerPtr options = cfg_option->getAll(*space); + for (const std::string& space : option_spaces) { + OptionContainerPtr options = cfg_option->getAll(space); if (options && !options->empty()) { - for (OptionContainer::const_iterator option = options->begin(); - option != options->end(); ++option) { + for (const OptionDescriptor& option : *options) { option_found = true; - insertHost(host, OptionalValue(), reservation, *space, - *option); + // @todo: Assign actual value to subnet id. + insertHost(host, OptionalValue(), reservation, space, + option); } } } if (!option_found) { + // @todo: Assign actual value to subnet id. insertHost(host, OptionalValue(), reservation); } } @@ -1732,61 +1804,61 @@ CqlHostDataSourceImpl::insertHostWithReservations( } ConstHostPtr -CqlHostDataSourceImpl::getHost( - const CqlDataArray& where_values, - const CqlHostExchange::StatementIndex statement_index) const { +CqlHostDataSourceImpl::getHost(StatementTag statement_tag, + AnyArray& where_values) const { ConstHostCollection collection = - getHostCollection(where_values, statement_index); + getHostCollection(statement_tag, where_values); if (collection.empty()) { return ConstHostPtr(); } - if (collection.size() >= 2U) { + if (collection.size() >= 2u) { isc_throw(MultipleRecords, - "multiple records were found in the database where only one " + "CqlHostDataSourceImpl::getHost(): multiple records were " + "found in the database where only one " "was expected for statement " - << dbconn_.tagged_statements_[statement_index].name_); + << statement_tag); } return *collection.begin(); } ConstHostCollection -CqlHostDataSourceImpl::getHostCollection( - const CqlDataArray& where_values, - const CqlHostExchange::StatementIndex statement_index) const { +CqlHostDataSourceImpl::getHostCollection(StatementTag statement_tag, + AnyArray& where_values) const { // Run statement. - CqlDataArray collection = host_exchange_->executeRead( - dbconn_, where_values, statement_index, false); + std::unique_ptr host_exchange( + new CqlHostExchange(dbconn_)); + AnyArray collection = host_exchange->executeSelect(dbconn_, where_values, + statement_tag, false); // Form HostPtr objects. HostCollection host_collection; - for (std::vector::const_iterator it = collection.begin(); - it != collection.end(); ++it) { - host_collection.push_back(HostPtr(reinterpret_cast(*it))); + for (boost::any& host : collection) { + host_collection.push_back(HostPtr(boost::any_cast(host))); } - // Merge the denormalized table entries that belong to the same host into a + // Merge the denormalized table entries that belong to the same host + // into a // single host. HostMap map; - for (HostCollection::iterator it = host_collection.begin(); - it != host_collection.end(); ++it) { - HostKey key = - HostKey((*it)->getIdentifier(), (*it)->getIdentifierType(), - (*it)->getIPv4SubnetID(), (*it)->getIPv6SubnetID(), - (*it)->getIPv4Reservation()); + for (HostPtr& host : host_collection) { + + HostKey key = HostKey(host->getIdentifier(), host->getIdentifierType(), + host->getIPv4SubnetID(), host->getIPv6SubnetID(), + host->getIPv4Reservation()); if (map.find(key) == map.end()) { - map[key] = *it; + map[key] = host; } else { - mergeHosts(map[key], *it); + mergeHosts(host, map[key]); } } ConstHostCollection result_collection; - for (HostMap::const_iterator it = map.begin(); it != map.end(); ++it) { - result_collection.push_back(it->second); + for (HostPair pair : map) { + result_collection.push_back(pair.second); } return result_collection; } @@ -1794,24 +1866,31 @@ CqlHostDataSourceImpl::getHostCollection( void CqlHostDataSourceImpl::insertHost( const HostPtr& host, - const OptionalValue& subnet_id - /* = OptionalValue() */, + const OptionalValue& subnet_id /* = OptionalValue() */, const IPv6Resrv* const reservation /* = NULL */, const std::string& option_space /* = NULL_OPTION_SPACE */, - const OptionDescriptor& option_descriptor - /* = OptionDescriptorPtr */) { - CqlDataArray assigned_values; - // @todo: Assign actual value to subnet id. - host_exchange_->createBindForSend(host, subnet_id, reservation, - option_space, option_descriptor, - assigned_values); - host_exchange_->executeWrite(dbconn_, assigned_values, - CqlHostExchange::INSERT_HOST); + const OptionDescriptor& option_descriptor /* = OptionDescriptorPtr */) { + AnyArray assigned_values; + + std::unique_ptr host_exchange( + new CqlHostExchange(dbconn_)); + + try { + host_exchange->createBindForMutation( + host, subnet_id, reservation, option_space, option_descriptor, + CqlHostExchange::INSERT_HOST, assigned_values); + + + host_exchange->executeMutation(dbconn_, assigned_values, + CqlHostExchange::INSERT_HOST); + } catch (const StatementNotApplied& exception) { + isc_throw(DuplicateEntry, exception.what()); + } } void -CqlHostDataSourceImpl::mergeHosts(HostPtr& target_host, - const ConstHostPtr& source_host) const { +CqlHostDataSourceImpl::mergeHosts(const ConstHostPtr& source_host, + HostPtr& target_host) const { // Merge reservations. const IPv6ResrvRange reservations_range = source_host->getIPv6Reservations(); @@ -1939,6 +2018,38 @@ CqlHostDataSource::get6(const SubnetID& subnet_id, return impl_->get6(subnet_id, address); } +bool +CqlHostDataSource::del(const SubnetID& subnet_id, + const asiolink::IOAddress& addr) { + (void)subnet_id; + (void)addr; + isc_throw(NotImplemented, "CqlHostDataSource::del NotImplemented"); +} + +bool +CqlHostDataSource::del4(const SubnetID& subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len) { + (void)subnet_id; + (void)identifier_type; + (void)identifier_begin; + (void)identifier_len; + isc_throw(NotImplemented, "CqlHostDataSource::del4 NotImplemented"); +} + +bool +CqlHostDataSource::del6(const SubnetID& subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len) { + (void)subnet_id; + (void)identifier_type; + (void)identifier_begin; + (void)identifier_len; + isc_throw(NotImplemented, "CqlHostDataSource::del6 NotImplemented"); +} + std::string CqlHostDataSource::getType() const { return std::string("cql"); @@ -1951,8 +2062,8 @@ CqlHostDataSource::getName() const { std::string CqlHostDataSource::getDescription() const { - return std::string( - "Host data source that stores host information in the CQL database"); + return std::string("Host data source that stores host information " + "in the CQL database"); } VersionPair @@ -1977,5 +2088,5 @@ CqlHostDataSource::rollback() { impl_->rollback(); } -}; // namespace dhcp -}; // namespace isc +} // namespace dhcp +} // namespace isc diff --git a/src/lib/dhcpsrv/cql_host_data_source.h b/src/lib/dhcpsrv/cql_host_data_source.h index e22e1eddb4..d2dcf67eb4 100644 --- a/src/lib/dhcpsrv/cql_host_data_source.h +++ b/src/lib/dhcpsrv/cql_host_data_source.h @@ -1,4 +1,4 @@ -// Copyright (C) 2016 Deutsche Telekom AG. +// Copyright (C) 2016-2017 Deutsche Telekom AG. // // Author: Andrei Pavel // @@ -20,15 +20,13 @@ #include #include -#include - #include -#include +#include namespace isc { namespace dhcp { -/// Forward declaration to the implementation of @ref CqlHostDataSource. +/// @brief Forward declaration to the implementation of @ref CqlHostDataSource. class CqlHostDataSourceImpl; /// @brief Cassandra host data source @@ -53,7 +51,7 @@ public: /// /// Finally, all the CQL commands are pre-compiled. /// - /// @param parameters A data structure relating keywords and values + /// @param parameters a data structure relating keywords and values /// concerned with the database. /// /// @throw isc::dhcp::NoDatabaseName Mandatory database name not given @@ -68,8 +66,7 @@ public: /// Releases prepared CQL statements used by the backend. virtual ~CqlHostDataSource(); - /// @brief Adds a new @ref Host to the Cassandra database along with it's - /// reservations and options. + /// @brief Adds a new host to the collection. /// /// The implementations of this method should guard against duplicate /// reservations for the same @ref Host, where possible. For example, when @@ -80,7 +77,7 @@ public: /// @ref DUID. /// /// @param host pointer to the new @ref Host being added. - virtual void add(const HostPtr& host); + virtual void add(const HostPtr& host) override; /// @brief Retrieves a single @ref Host connected to an IPv4 subnet. /// @@ -100,14 +97,14 @@ public: /// @throw BadValue if both or neither of subnet_id and duid are specified virtual ConstHostPtr get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr, - const DuidPtr& duid = DuidPtr()) const; + const DuidPtr& duid = DuidPtr()) const override; /// @brief Retrieves a @ref Host connected to an IPv4 subnet. /// /// @param subnet_id subnet identifier to filter by /// @param identifier_type identifier type to filter by - /// @param identifier_begin pointer to the beginning of a buffer containing a - /// host identifier to filter by + /// @param identifier_begin pointer to the beginning of a buffer containing + /// a host identifier to filter by /// @param identifier_len length of the host identifier buffer /// /// @return @ref Host object for which a reservation has been made using the @@ -115,7 +112,7 @@ public: virtual ConstHostPtr get4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type, const uint8_t* identifier_begin, - const size_t identifier_len) const; + const size_t identifier_len) const override; /// @brief Retrieves a @ref Host connected to an IPv4 subnet. /// @@ -130,8 +127,9 @@ public: /// @return Const @ref Host object /// /// @throw BadValue if address in not a valid IPv4address - virtual ConstHostPtr get4(const SubnetID& subnet_id, - const asiolink::IOAddress& address) const; + virtual ConstHostPtr + get4(const SubnetID& subnet_id, + const asiolink::IOAddress& address) const override; /// @brief Retrieves a @ref Host connected to an IPv6 subnet. /// @@ -148,16 +146,17 @@ public: /// @return @ref Host object using a specified @ref HWAddr or @ref DUID /// /// @throw BadValue if both or neither of subnet_id and duid are specified - virtual ConstHostPtr get6(const SubnetID& subnet_id, - const DuidPtr& duid, - const HWAddrPtr& hwaddr = HWAddrPtr()) const; + virtual ConstHostPtr + get6(const SubnetID& subnet_id, + const DuidPtr& duid, + const HWAddrPtr& hwaddr = HWAddrPtr()) const override; /// @brief Returns a @ref Host connected to an IPv6 subnet. /// /// @param subnet_id subnet identifier to filter by /// @param identifier_type identifier type to filter by - /// @param identifier_begin pointer to the beginning of a buffer containing a - /// host identifier to filter by + /// @param identifier_begin pointer to the beginning of a buffer containing + /// a host identifier to filter by /// @param identifier_len length of the host identifier buffer /// /// @return Const @ref Host object for which reservation has been made using @@ -165,7 +164,7 @@ public: virtual ConstHostPtr get6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type, const uint8_t* identifier_begin, - const size_t identifier_len) const; + const size_t identifier_len) const override; /// @brief Returns a @ref Host with the specified reservation prefix. /// @@ -177,7 +176,7 @@ public: /// @throw MultipleRecords if two or more rows are returned from the /// Cassandra database virtual ConstHostPtr get6(const asiolink::IOAddress& prefix, - const uint8_t prefix_len) const; + const uint8_t prefix_len) const override; /// @brief Returns a host connected to the IPv6 subnet and having /// a reservation for a specified IPv6 address or prefix. @@ -186,8 +185,9 @@ public: /// @param address reserved IPv6 address/prefix. /// /// @return Const @c Host object using a specified IPv6 address/prefix. - virtual ConstHostPtr get6(const SubnetID& subnet_id, - const asiolink::IOAddress& address) const; + virtual ConstHostPtr + get6(const SubnetID& subnet_id, + const asiolink::IOAddress& address) const override; /// @brief Return all @ref Host objects for the specified @ref HWAddr or /// @ref DUID. @@ -211,8 +211,9 @@ public: /// @param duid client id or NULL if not available, e.g. DHCPv4 client case. /// /// @return collection of const @ref Host objects. - virtual ConstHostCollection getAll(const HWAddrPtr& hwaddr, - const DuidPtr& duid = DuidPtr()) const; + virtual ConstHostCollection + getAll(const HWAddrPtr& hwaddr, + const DuidPtr& duid = DuidPtr()) const override; /// @brief Return all hosts connected to any subnet for which reservations /// have been made using a specified identifier. @@ -223,14 +224,14 @@ public: /// /// @param identifier_type Identifier type. /// @param identifier_begin Pointer to a beginning of a buffer containing - /// an identifier. + /// an identifier. /// @param identifier_len Identifier length. /// /// @return Collection of const @ref Host objects. virtual ConstHostCollection getAll(const Host::IdentifierType& identifier_type, const uint8_t* identifier_begin, - const size_t identifier_len) const; + const size_t identifier_len) const override; /// @brief Returns a collection of hosts using the specified IPv4 address. /// @@ -241,7 +242,55 @@ public: /// /// @return Collection of const @ref Host objects. virtual ConstHostCollection - getAll4(const asiolink::IOAddress& address) const; + getAll4(const asiolink::IOAddress& address) const override; + + /// @brief Attempts to delete a host by (subnet-id, address) + /// + /// This method supports both v4 and v6. + /// + /// @param subnet_id subnet identfier. + /// @param addr specified address. + /// @return true if deletion was successful, false if the host was not + /// there. + /// @throw various exceptions in case of errors + virtual bool del(const SubnetID& subnet_id, + const asiolink::IOAddress& addr); + + /// @brief Attempts to delete a host by (subnet-id4, identifier, + /// identifier-type) + /// + /// This method supports both v4 hosts only. + /// + /// @param subnet_id IPv4 Subnet identifier. + /// @param identifier_type Identifier type. + /// @param identifier_begin Pointer to a beginning of a buffer containing + /// an identifier. + /// @param identifier_len Identifier length. + /// @return true if deletion was successful, false if the host was not + /// there. + /// @throw various exceptions in case of errors + virtual bool del4(const SubnetID& subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len); + + /// @brief Attempts to delete a host by (subnet-id6, identifier, + /// identifier-type) + /// + /// This method supports both v6 hosts only. + /// + /// @param subnet_id IPv6 Subnet identifier. + /// @param identifier_type Identifier type. + /// @param identifier_begin Pointer to a beginning of a buffer containing + /// an identifier. + /// @param identifier_len Identifier length. + /// @return true if deletion was successful, false if the host was not + /// there. + /// @throw various exceptions in case of errors + virtual bool del6(const SubnetID& subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len); /// @brief Returns description of the backend. /// @@ -258,7 +307,7 @@ public: /// @brief Return backend type /// /// @return backend type "cql" - virtual std::string getType() const; + virtual std::string getType() const override; /// @brief Retrieves schema version. /// @@ -268,24 +317,24 @@ public: /// /// @throw isc::dhcp::DbOperationError An operation on the open database /// has failed. - virtual std::pair getVersion() const; + virtual VersionPair getVersion() const; /// @brief Commit Transactions /// /// Commits all pending database operations. - virtual void commit(); + virtual void commit() override; /// @brief Rollback Transactions /// /// Rolls back all pending database operations. - virtual void rollback(); + virtual void rollback() override; private: /// @brief Pointer to the implementation of the @ref CqlHostDataSource. CqlHostDataSourceImpl* impl_; }; // class CqlHostDataSource -}; // namespace dhcp -}; // namespace isc +} // namespace dhcp +} // namespace isc #endif // CQL_HOST_DATA_SOURCE_H diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.mes b/src/lib/dhcpsrv/dhcpsrv_messages.mes index 04df354a09..c91eff65da 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.mes +++ b/src/lib/dhcpsrv/dhcpsrv_messages.mes @@ -197,9 +197,6 @@ V6) is about to open a Cassandra lease database. The parameters of the connection including database name and username needed to access it (but not the password if any) are logged. -% DHCPSRV_CQL_COMMIT committing to Cassandra database. -A commit call been issued on the server. For Cassandra, this is a no-op. - % DHCPSRV_CQL_CONNECTION_COMMIT committing to Cassandra database on current connection. A commit call been issued on the server. For Cassandra, this is a no-op. @@ -231,9 +228,6 @@ The server has issued a rollback transaction call on an opened transaction. % DHCPSRV_CQL_TRANSACTION_MGR_TRANSACTION_NOT_FOUND failed to select a transaction. The server failed to select a transaction to operate on. -% DHCPSRV_CQL_BEGIN_TRANSACTION begin transaction. -The server has issued a begin transaction call. - % DHCPSRV_CQL_CONNECTION_BEGIN_TRANSACTION begin transaction on current connection. The server has issued a begin transaction call. @@ -246,12 +240,6 @@ The server has issued a commit transaction call. % DHCPSRV_CQL_TRANSACTION_MGR_ROLLBACK_TRANSACTION rollback transaction action has been initiated. The server has issued a rollback transaction call. -% DHCPSRV_CQL_DB opening Cassandra lease database: %1 -This informational message is logged when a DHCP server (either V4 or -V6) is about to open a Cassandra lease database. The parameters of -the connection including database name and username needed to access it -(but not the password if any) are logged. - % DHCPSRV_CQL_DELETE_ADDR deleting lease for address %1 A debug message issued when the server is attempting to delete a lease from the Cassandra database for the specified address. diff --git a/src/lib/dhcpsrv/host_data_source_factory.cc b/src/lib/dhcpsrv/host_data_source_factory.cc index e84f7f31d3..7a4591fd48 100644 --- a/src/lib/dhcpsrv/host_data_source_factory.cc +++ b/src/lib/dhcpsrv/host_data_source_factory.cc @@ -4,7 +4,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include "config.h" +#include #include #include @@ -38,7 +38,6 @@ using namespace std; namespace isc { namespace dhcp { - HostDataSourcePtr& HostDataSourceFactory::getHostDataSourcePtr() { static HostDataSourcePtr hostDataSourcePtr; @@ -115,5 +114,5 @@ HostDataSourceFactory::instance() { } #endif -}; // namespace dhcp -}; // namespace isc +} // namespace dhcp +} // namespace isc diff --git a/src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc b/src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc index 684b76db8c..754f86b661 100644 --- a/src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc +++ b/src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2015-2017 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 @@ -20,25 +20,21 @@ #include #include -#include #include #include #include +namespace { + using namespace isc; using namespace isc::asiolink; using namespace isc::dhcp; using namespace isc::dhcp::test; -using namespace std; - -namespace { class CqlHostDataSourceTest : public GenericHostDataSourceTest { public: - /// @brief Constructor - /// - /// Deletes everything from the database and opens it. - CqlHostDataSourceTest() { + /// @brief Clears the database and opens connection to it. + void initializeTest() { // Ensure schema is the correct one. destroyCqlSchema(false, true); createCqlSchema(false, true); @@ -58,15 +54,31 @@ public: hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr(); } + /// @brief Destroys the HDS and the schema. + void destroyTest() { + try { + hdsptr_->rollback(); + } catch (...) { + // Rollback may fail if backend is in read only mode. That's ok. + } + HostDataSourceFactory::destroy(); + destroyCqlSchema(false, true); + } + + /// @brief Constructor + /// + /// Deletes everything from the database and opens it. + CqlHostDataSourceTest() { + initializeTest(); + } + /// @brief Destructor /// /// Rolls back all pending transactions. The deletion of myhdsptr_ will /// close the database. Then reopen it and delete everything created by the /// test. virtual ~CqlHostDataSourceTest() { - hdsptr_->rollback(); - HostDataSourceFactory::destroy(); - destroyCqlSchema(false, true); + destroyTest(); } /// @brief Reopen the database @@ -169,7 +181,7 @@ TEST(CqlHostDataSource, OpenDatabase) { destroyCqlSchema(false, true); } -/// @brief Check conversion functions +/// @brief Check conversion methods /// /// The server works using cltt and valid_filetime. In the database, the /// information is stored as expire_time and valid-lifetime, which are @@ -475,8 +487,7 @@ TEST_F(CqlHostDataSourceTest, testAddRollback) { CqlConnection connection(params); ASSERT_NO_THROW(connection.openDatabase()); - // Drop every table so we make sure host_ipv6_reservation_options doesn't - // exist anymore + // Drop every table so we make sure host_reservations doesn't exist anymore. destroyCqlSchema(false, true); // Create a host with a reservation. diff --git a/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.cc b/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.cc index bc431ed938..3a1301fd97 100644 --- a/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.cc +++ b/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.cc @@ -5,26 +5,29 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include + +#include +#include #include #include #include #include -#include #include +#include #include +#include #include #include #include #include -#include -#include -#include -#include #include +#include + +#include #include #include -#include #include +#include #include using namespace std; @@ -35,13 +38,13 @@ namespace isc { namespace dhcp { namespace test { -GenericHostDataSourceTest::GenericHostDataSourceTest() - :hdsptr_() { +GenericHostDataSourceTest::GenericHostDataSourceTest() : hdsptr_() { LibDHCP::clearRuntimeOptionDefs(); } GenericHostDataSourceTest::~GenericHostDataSourceTest() { LibDHCP::clearRuntimeOptionDefs(); + hdsptr_.reset(); } std::vector @@ -70,12 +73,11 @@ GenericHostDataSourceTest::generateIdentifier(const bool new_identifier) { // Let's use something that is easily printable. That's convenient // if you need to enter MySQL queries by hand. - static uint8_t ident[] = { 65, 66, 67, 68, 69, 70, 71, 72, 73, 74 }; + static uint8_t ident[] = {65, 66, 67, 68, 69, 70, 71, 72, 73, 74}; - // Increase the identifier for the next time we use it. - // This is primitive, but will work for 65k unique - // identifiers. if (new_identifier) { + // Increase the identifier for the next time we use it. + // This is primitive, but will work for 65k unique identifiers. ident[sizeof(ident) - 1]++; if (ident[sizeof(ident) - 1] == 0) { ident[sizeof(ident) - 2]++; @@ -90,7 +92,6 @@ GenericHostDataSourceTest::initializeHost4(const std::string& address, std::vector ident; if (id == Host::IDENT_HWADDR) { ident = generateHWAddr(); - } else { ident = generateIdentifier(); } @@ -109,10 +110,11 @@ GenericHostDataSourceTest::initializeHost4(const std::string& address, return (host); } -HostPtr GenericHostDataSourceTest::initializeHost6(std::string address, - Host::IdentifierType identifier, - bool prefix, - bool new_identifier) { +HostPtr +GenericHostDataSourceTest::initializeHost6(std::string address, + Host::IdentifierType identifier, + bool prefix, + bool new_identifier) { std::vector ident; switch (identifier) { case Host::IDENT_HWADDR: @@ -134,8 +136,8 @@ HostPtr GenericHostDataSourceTest::initializeHost6(std::string address, subnet4++; subnet6++; - HostPtr host(new Host(&ident[0], ident.size(), identifier, subnet4, - subnet6, IOAddress("0.0.0.0"))); + HostPtr host(new Host(&ident[0], ident.size(), identifier, subnet4, subnet6, + IOAddress("0.0.0.0"))); if (!prefix) { // Create IPv6 reservation (for an address) @@ -149,6 +151,17 @@ HostPtr GenericHostDataSourceTest::initializeHost6(std::string address, return (host); } +bool +GenericHostDataSourceTest::reservationExists(const IPv6Resrv& resrv, + const IPv6ResrvRange& range) { + for (IPv6ResrvIterator it = range.first; it != range.second; ++it) { + if (resrv == it->second) { + return true; + } + } + return false; +} + void GenericHostDataSourceTest::compareHwaddrs(const ConstHostPtr& host1, const ConstHostPtr& host2, @@ -159,13 +172,12 @@ GenericHostDataSourceTest::compareHwaddrs(const ConstHostPtr& host1, // Compare if both have or have not HWaddress set. if ((host1->getHWAddress() && !host2->getHWAddress()) || (!host1->getHWAddress() && host2->getHWAddress())) { - // One host has hardware address set while the other has not. // Let's see if it's a problem. if (expect_match) { ADD_FAILURE() << "Host comparison failed: host1 hwaddress=" - << host1->getHWAddress() << ", host2 hwaddress=" - << host2->getHWAddress(); + << host1->getHWAddress() + << ", host2 hwaddress=" << host2->getHWAddress(); } return; } @@ -173,7 +185,6 @@ GenericHostDataSourceTest::compareHwaddrs(const ConstHostPtr& host1, // Now we know that either both or neither have hw address set. // If host1 has it, we can proceed to value comparison. if (host1->getHWAddress()) { - if (expect_match) { // Compare the actual address if they match. EXPECT_TRUE(*host1->getHWAddress() == *host2->getHWAddress()); @@ -197,13 +208,12 @@ GenericHostDataSourceTest::compareDuids(const ConstHostPtr& host1, // compare if both have or have not DUID set if ((host1->getDuid() && !host2->getDuid()) || (!host1->getDuid() && host2->getDuid())) { - // One host has a DUID and the other doesn't. // Let's see if it's a problem. if (expect_match) { ADD_FAILURE() << "DUID comparison failed: host1 duid=" - << host1->getDuid() << ", host2 duid=" - << host2->getDuid(); + << host1->getDuid() + << ", host2 duid=" << host2->getDuid(); } return; } @@ -211,7 +221,6 @@ GenericHostDataSourceTest::compareDuids(const ConstHostPtr& host1, // Now we know that either both or neither have DUID set. // If host1 has it, we can proceed to value comparison. if (host1->getDuid()) { - if (expect_match) { EXPECT_TRUE(*host1->getDuid() == *host2->getDuid()); } else { @@ -224,9 +233,9 @@ GenericHostDataSourceTest::compareDuids(const ConstHostPtr& host1, } } -void GenericHostDataSourceTest::compareHosts(const ConstHostPtr& host1, - const ConstHostPtr& host2) { - +void +GenericHostDataSourceTest::compareHosts(const ConstHostPtr& host1, + const ConstHostPtr& host2) { // Let's compare HW addresses and expect match. compareHwaddrs(host1, host2, true); @@ -262,18 +271,18 @@ void GenericHostDataSourceTest::compareHosts(const ConstHostPtr& host1, compareOptions(host1->getCfgOption6(), host2->getCfgOption6()); } -bool GenericHostDataSourceTest::compareHostsForSort4( - const ConstHostPtr& host1, - const ConstHostPtr& host2) { +bool +GenericHostDataSourceTest::compareHostsForSort4(const ConstHostPtr& host1, + const ConstHostPtr& host2) { if (host1->getIPv4SubnetID() < host2->getIPv4SubnetID()) { return true; } return false; } -bool GenericHostDataSourceTest::compareHostsForSort6( - const ConstHostPtr& host1, - const ConstHostPtr& host2) { +bool +GenericHostDataSourceTest::compareHostsForSort6(const ConstHostPtr& host1, + const ConstHostPtr& host2) { if (host1->getIPv6SubnetID() < host2->getIPv6SubnetID()) { return true; } @@ -298,16 +307,14 @@ GenericHostDataSourceTest::DuidToHWAddr(const DuidPtr& duid) { return (HWAddrPtr(new HWAddr(duid->getDuid(), HTYPE_ETHER))); } - void GenericHostDataSourceTest::compareReservations6(IPv6ResrvRange resrv1, IPv6ResrvRange resrv2) { - // Compare number of reservations for both hosts if (std::distance(resrv1.first, resrv1.second) != - std::distance(resrv2.first, resrv2.second)){ - ADD_FAILURE()<< "Reservation comparison failed, " - "hosts got different number of reservations."; + std::distance(resrv2.first, resrv2.second)) { + ADD_FAILURE() << "Reservation comparison failed, " + "hosts got different number of reservations."; return; } @@ -333,16 +340,19 @@ GenericHostDataSourceTest::compareReservations6(IPv6ResrvRange resrv1, for (; resrv1.first != resrv1.second; resrv1.first++) { IPv6ResrvIterator iter = resrv2.first; while (iter != resrv2.second) { - if((resrv1.first->second.getType() == iter->second.getType()) && - (resrv1.first->second.getPrefixLen() == iter->second.getPrefixLen()) && - (resrv1.first->second.getPrefix() == iter->second.getPrefix())) { + if ((resrv1.first->second.getType() == + iter->second.getType()) && + (resrv1.first->second.getPrefixLen() == + iter->second.getPrefixLen()) && + (resrv1.first->second.getPrefix() == + iter->second.getPrefix())) { break; } iter++; if (iter == resrv2.second) { - ADD_FAILURE()<< "Reservation comparison failed, " - "no match for reservation: " - << resrv1.first->second.getPrefix().toText(); + ADD_FAILURE() << "Reservation comparison failed, " + "no match for reservation: " + << resrv1.first->second.getPrefix().toText(); } } } @@ -373,7 +383,7 @@ GenericHostDataSourceTest::compareOptions(const ConstCfgOptionPtr& cfg1, EXPECT_EQ(vendor_spaces.size(), cfg1->getVendorIdsSpaceNames().size()); // Iterate over all option spaces existing in cfg2. - BOOST_FOREACH(std::string space, option_spaces) { + BOOST_FOREACH (std::string space, option_spaces) { // Retrieve options belonging to the current option space. OptionContainerPtr options1 = cfg1->getAll(space); OptionContainerPtr options2 = cfg2->getAll(space); @@ -385,14 +395,16 @@ GenericHostDataSourceTest::compareOptions(const ConstCfgOptionPtr& cfg1, << "failed for option space " << space; // Iterate over all options within this option space. - BOOST_FOREACH(OptionDescriptor desc1, *options1) { + BOOST_FOREACH (OptionDescriptor desc1, *options1) { OptionDescriptor desc2 = cfg2->get(space, desc1.option_->getType()); // Compare persistent flag. EXPECT_EQ(desc1.persistent_, desc2.persistent_) - << "failed for option " << space << "." << desc1.option_->getType(); + << "failed for option " << space << "." + << desc1.option_->getType(); // Compare formatted value. EXPECT_EQ(desc1.formatted_value_, desc2.formatted_value_) - << "failed for option " << space << "." << desc1.option_->getType(); + << "failed for option " << space << "." + << desc1.option_->getType(); // Retrieve options. Option* option1 = desc1.option_.get(); @@ -402,11 +414,10 @@ GenericHostDataSourceTest::compareOptions(const ConstCfgOptionPtr& cfg1, // the Option class. EXPECT_TRUE(typeid(*option1) == typeid(*option2)) << "Compared DHCP options, having option code " - << desc1.option_->getType() << " and belonging to the " - << space << " option space, are represented " - "by different C++ classes: " - << typeid(*option1).name() << " vs " - << typeid(*option2).name(); + << desc1.option_->getType() << " and belonging to the " << space + << " option space, are represented " + "by different C++ classes: " + << typeid(*option1).name() << " vs " << typeid(*option2).name(); // Because we use different C++ classes to represent different // options, the simplest way to make sure that the options are @@ -417,9 +428,12 @@ GenericHostDataSourceTest::compareOptions(const ConstCfgOptionPtr& cfg1, ASSERT_NO_THROW(option2->pack(buf2)); ASSERT_EQ(buf1.getLength(), buf2.getLength()) - << "failed for option " << space << "." << desc1.option_->getType(); - EXPECT_EQ(0, memcmp(buf1.getData(), buf2.getData(), buf1.getLength())) - << "failed for option " << space << "." << desc1.option_->getType(); + << "failed for option " << space << "." + << desc1.option_->getType(); + EXPECT_EQ(0, + memcmp(buf1.getData(), buf2.getData(), buf1.getLength())) + << "failed for option " << space << "." + << desc1.option_->getType(); } } } @@ -433,7 +447,6 @@ GenericHostDataSourceTest::createEmptyOption(const Option::Universe& universe, return (desc); } - OptionDescriptor GenericHostDataSourceTest::createVendorOption(const Option::Universe& universe, const bool persist, @@ -453,10 +466,10 @@ GenericHostDataSourceTest::createVendorOption(const Option::Universe& universe, } void -GenericHostDataSourceTest::addTestOptions(const HostPtr& host, - const bool formatted, - const AddedOptions& added_options) const { - +GenericHostDataSourceTest::addTestOptions( + const HostPtr& host, + const bool formatted, + const AddedOptions& added_options) const { OptionDefSpaceContainer defs; if ((added_options == DHCP4_ONLY) || (added_options == DHCP4_AND_DHCP6)) { @@ -468,36 +481,40 @@ GenericHostDataSourceTest::addTestOptions(const HostPtr& host, opts->add(createOption(Option::V4, DHO_DEFAULT_IP_TTL, false, formatted, 64), DHCP4_OPTION_SPACE); - opts->add(createOption(Option::V4, 1, false, formatted, 312131), - "vendor-encapsulated-options"); - opts->add(createAddressOption(254, false, formatted, "192.0.2.3"), + opts->add( + createOption(Option::V4, 1, false, formatted, 312131), + "vendor-encapsulated-options"); + opts->add(createAddressOption(254, false, formatted, + "192.0.2.3"), DHCP4_OPTION_SPACE); opts->add(createEmptyOption(Option::V4, 1, true), "isc"); - opts->add(createAddressOption(2, false, formatted, "10.0.0.5", - "10.0.0.3", "10.0.3.4"), + opts->add(createAddressOption( + 2, false, formatted, "10.0.0.5", "10.0.0.3", "10.0.3.4"), "isc"); // Add definitions for DHCPv4 non-standard options. - defs.addItem(OptionDefinitionPtr(new OptionDefinition("vendor-encapsulated-1", - 1, "uint32")), + defs.addItem(OptionDefinitionPtr(new OptionDefinition( + "vendor-encapsulated-1", 1, "uint32")), "vendor-encapsulated-options"); - defs.addItem(OptionDefinitionPtr(new OptionDefinition("option-254", 254, - "ipv4-address", true)), + defs.addItem(OptionDefinitionPtr(new OptionDefinition( + "option-254", 254, "ipv4-address", true)), DHCP4_OPTION_SPACE); - defs.addItem(OptionDefinitionPtr(new OptionDefinition("isc-1", 1, "empty")), - "isc"); - defs.addItem(OptionDefinitionPtr(new OptionDefinition("isc-2", 2, - "ipv4-address", true)), + defs.addItem( + OptionDefinitionPtr(new OptionDefinition("isc-1", 1, "empty")), + "isc"); + defs.addItem(OptionDefinitionPtr(new OptionDefinition( + "isc-2", 2, "ipv4-address", true)), "isc"); } if ((added_options == DHCP6_ONLY) || (added_options == DHCP4_AND_DHCP6)) { // Add DHCPv6 options. CfgOptionPtr opts = host->getCfgOption6(); - opts->add(createOption(Option::V6, D6O_BOOTFILE_URL, - true, formatted, "my-boot-file"), + opts->add(createOption(Option::V6, D6O_BOOTFILE_URL, true, + formatted, "my-boot-file"), DHCP6_OPTION_SPACE); - opts->add(createOption(Option::V6, D6O_INFORMATION_REFRESH_TIME, + opts->add(createOption(Option::V6, + D6O_INFORMATION_REFRESH_TIME, false, formatted, 3600), DHCP6_OPTION_SPACE); opts->add(createVendorOption(Option::V6, false, formatted, 2495), @@ -506,18 +523,19 @@ GenericHostDataSourceTest::addTestOptions(const HostPtr& host, "2001:db8:1::1"), DHCP6_OPTION_SPACE); opts->add(createEmptyOption(Option::V6, 1, true), "isc2"); - opts->add(createAddressOption(2, false, formatted, "3000::1", - "3000::2", "3000::3"), + opts->add(createAddressOption( + 2, false, formatted, "3000::1", "3000::2", "3000::3"), "isc2"); // Add definitions for DHCPv6 non-standard options. - defs.addItem(OptionDefinitionPtr(new OptionDefinition("option-1024", 1024, - "ipv6-address", true)), + defs.addItem(OptionDefinitionPtr(new OptionDefinition( + "option-1024", 1024, "ipv6-address", true)), DHCP6_OPTION_SPACE); - defs.addItem(OptionDefinitionPtr(new OptionDefinition("option-1", 1, "empty")), - "isc2"); - defs.addItem(OptionDefinitionPtr(new OptionDefinition("option-2", 2, - "ipv6-address", true)), + defs.addItem( + OptionDefinitionPtr(new OptionDefinition("option-1", 1, "empty")), + "isc2"); + defs.addItem(OptionDefinitionPtr(new OptionDefinition( + "option-2", 2, "ipv6-address", true)), "isc2"); } @@ -542,21 +560,18 @@ GenericHostDataSourceTest::testReadOnlyDatabase(const char* valid_db_type) { // Make sure that the host has been inserted and that the data can be // retrieved. - ConstHostPtr host_by_id = hdsptr_->get6(subnet_id, host->getIdentifierType(), - &host->getIdentifier()[0], - host->getIdentifier().size()); + ConstHostPtr host_by_id = + hdsptr_->get6(subnet_id, host->getIdentifierType(), + &host->getIdentifier()[0], host->getIdentifier().size()); ASSERT_TRUE(host_by_id); ASSERT_NO_FATAL_FAILURE(compareHosts(host, host_by_id)); // Close the database connection and reopen in "read-only" mode as // specified by the "VALID_READONLY_DB" parameter. HostDataSourceFactory::destroy(); - HostDataSourceFactory::create(connectionString(valid_db_type, - VALID_NAME, - VALID_HOST, - VALID_READONLY_USER, - VALID_PASSWORD, - VALID_READONLY_DB)); + HostDataSourceFactory::create(connectionString( + valid_db_type, VALID_NAME, VALID_HOST, VALID_READONLY_USER, + VALID_PASSWORD, VALID_READONLY_DB)); hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr(); @@ -569,20 +584,21 @@ GenericHostDataSourceTest::testReadOnlyDatabase(const char* valid_db_type) { ASSERT_THROW(hdsptr_->rollback(), ReadOnlyDb); // Reading from the database should still be possible, though. - host_by_id = hdsptr_->get6(subnet_id, host->getIdentifierType(), - &host->getIdentifier()[0], - host->getIdentifier().size()); + host_by_id = + hdsptr_->get6(subnet_id, host->getIdentifierType(), + &host->getIdentifier()[0], host->getIdentifier().size()); ASSERT_TRUE(host_by_id); ASSERT_NO_FATAL_FAILURE(compareHosts(host, host_by_id)); } -void GenericHostDataSourceTest::testBasic4(const Host::IdentifierType& id) { +void +GenericHostDataSourceTest::testBasic4(const Host::IdentifierType& id) { // Make sure we have the pointer to the host data source. ASSERT_TRUE(hdsptr_); // Create a host reservation. HostPtr host = initializeHost4("192.0.2.1", id); - ASSERT_TRUE(host); // Make sure the host is generate properly. + ASSERT_TRUE(host); // Make sure the host is generate properly. SubnetID subnet = host->getIPv4SubnetID(); // Try to add it to the host data source. @@ -600,8 +616,8 @@ void GenericHostDataSourceTest::testBasic4(const Host::IdentifierType& id) { compareHosts(host, from_hds); } - -void GenericHostDataSourceTest::testGetByIPv4(const Host::IdentifierType& id) { +void +GenericHostDataSourceTest::testGetByIPv4(const Host::IdentifierType& id) { // Make sure we have a pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -646,7 +662,8 @@ void GenericHostDataSourceTest::testGetByIPv4(const Host::IdentifierType& id) { } void -GenericHostDataSourceTest::testGet4ByIdentifier(const Host::IdentifierType& identifier_type) { +GenericHostDataSourceTest::testGet4ByIdentifier( + const Host::IdentifierType& identifier_type) { // Make sure we have a pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -663,15 +680,13 @@ GenericHostDataSourceTest::testGet4ByIdentifier(const Host::IdentifierType& iden SubnetID subnet1 = host1->getIPv4SubnetID(); SubnetID subnet2 = host2->getIPv4SubnetID(); - ConstHostPtr from_hds1 = hdsptr_->get4(subnet1, - identifier_type, - &host1->getIdentifier()[0], - host1->getIdentifier().size()); + ConstHostPtr from_hds1 = + hdsptr_->get4(subnet1, identifier_type, &host1->getIdentifier()[0], + host1->getIdentifier().size()); - ConstHostPtr from_hds2 = hdsptr_->get4(subnet2, - identifier_type, - &host2->getIdentifier()[0], - host2->getIdentifier().size()); + ConstHostPtr from_hds2 = + hdsptr_->get4(subnet2, identifier_type, &host2->getIdentifier()[0], + host2->getIdentifier().size()); // Now let's check if we got what we expected. ASSERT_TRUE(from_hds1); @@ -680,7 +695,8 @@ GenericHostDataSourceTest::testGet4ByIdentifier(const Host::IdentifierType& iden compareHosts(host2, from_hds2); } -void GenericHostDataSourceTest::testHWAddrNotClientId() { +void +GenericHostDataSourceTest::testHWAddrNotClientId() { // Make sure we have a pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -697,21 +713,22 @@ void GenericHostDataSourceTest::testHWAddrNotClientId() { DuidPtr duid = HWAddrToDuid(host->getHWAddress()); // Get the host by HW address (should succeed) - ConstHostPtr by_hwaddr = hdsptr_->get4(subnet, Host::IDENT_HWADDR, - &host->getIdentifier()[0], - host->getIdentifier().size()); + ConstHostPtr by_hwaddr = + hdsptr_->get4(subnet, Host::IDENT_HWADDR, &host->getIdentifier()[0], + host->getIdentifier().size()); // Get the host by DUID (should fail) - ConstHostPtr by_duid = hdsptr_->get4(subnet, Host::IDENT_DUID, - &host->getIdentifier()[0], - host->getIdentifier().size()); + ConstHostPtr by_duid = + hdsptr_->get4(subnet, Host::IDENT_DUID, &host->getIdentifier()[0], + host->getIdentifier().size()); // Now let's check if we got what we expected. EXPECT_TRUE(by_hwaddr); EXPECT_FALSE(by_duid); } -void GenericHostDataSourceTest::testClientIdNotHWAddr() { +void +GenericHostDataSourceTest::testClientIdNotHWAddr() { // Make sure we have a pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -728,15 +745,14 @@ void GenericHostDataSourceTest::testClientIdNotHWAddr() { HWAddrPtr hwaddr = DuidToHWAddr(host->getDuid()); // Get the host by DUID (should succeed) - ConstHostPtr by_duid = hdsptr_->get4(subnet, Host::IDENT_DUID, - &host->getIdentifier()[0], - host->getIdentifier().size()); - + ConstHostPtr by_duid = + hdsptr_->get4(subnet, Host::IDENT_DUID, &host->getIdentifier()[0], + host->getIdentifier().size()); // Get the host by HW address (should fail) - ConstHostPtr by_hwaddr = hdsptr_->get4(subnet, Host::IDENT_HWADDR, - &host->getIdentifier()[0], - host->getIdentifier().size()); + ConstHostPtr by_hwaddr = + hdsptr_->get4(subnet, Host::IDENT_HWADDR, &host->getIdentifier()[0], + host->getIdentifier().size()); // Now let's check if we got what we expected. EXPECT_TRUE(by_duid); @@ -745,7 +761,6 @@ void GenericHostDataSourceTest::testClientIdNotHWAddr() { void GenericHostDataSourceTest::testHostname(std::string name, int num) { - // Make sure we have a pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -757,7 +772,6 @@ GenericHostDataSourceTest::testHostname(std::string name, int num) { // Prepare a vector of hosts with unique hostnames for (int i = 0; i < num; ++i) { - addr = IOAddress::increase(addr); HostPtr host = initializeHost4(addr.toText(), Host::IDENT_DUID); @@ -774,21 +788,19 @@ GenericHostDataSourceTest::testHostname(std::string name, int num) { } // Now add them all to the host data source. - for (vector::const_iterator it = hosts.begin(); - it != hosts.end(); ++it) { + for (vector::const_iterator it = hosts.begin(); it != hosts.end(); + ++it) { // Try to add both of the to the host data source. ASSERT_NO_THROW(hdsptr_->add(*it)); } // And finally retrieve them one by one and check // if the hostname was preserved. - for (vector::const_iterator it = hosts.begin(); - it != hosts.end(); ++it) { - + for (vector::const_iterator it = hosts.begin(); it != hosts.end(); + ++it) { ConstHostPtr from_hds; - ASSERT_NO_THROW(from_hds = hdsptr_->get4( - (*it)->getIPv4SubnetID(), - (*it)->getIPv4Reservation())); + ASSERT_NO_THROW(from_hds = hdsptr_->get4((*it)->getIPv4SubnetID(), + (*it)->getIPv4Reservation())); ASSERT_TRUE(from_hds); EXPECT_EQ((*it)->getHostname(), from_hds->getHostname()); @@ -798,7 +810,6 @@ GenericHostDataSourceTest::testHostname(std::string name, int num) { void GenericHostDataSourceTest::testMultipleSubnets(int subnets, const Host::IdentifierType& id) { - // Make sure we have a pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -815,16 +826,15 @@ GenericHostDataSourceTest::testMultipleSubnets(int subnets, // Now check that the reservations can be retrieved by IPv4 address from // each subnet separately. for (int i = 0; i < subnets; ++i) { - // Try to retrieve the host by IPv4 address. - ConstHostPtr from_hds = hdsptr_->get4(i + 1000, host->getIPv4Reservation()); + ConstHostPtr from_hds = + hdsptr_->get4(i + 1000, host->getIPv4Reservation()); ASSERT_TRUE(from_hds); EXPECT_EQ(i + 1000, from_hds->getIPv4SubnetID()); // Try to retrieve the host by either HW address of client-id - from_hds = hdsptr_->get4(i + 1000, - id, &host->getIdentifier()[0], + from_hds = hdsptr_->get4(i + 1000, id, &host->getIdentifier()[0], host->getIdentifier().size()); ASSERT_TRUE(from_hds); EXPECT_EQ(i + 1000, from_hds->getIPv4SubnetID()); @@ -849,9 +859,8 @@ GenericHostDataSourceTest::testMultipleSubnets(int subnets, } // Finally, check that the hosts can be retrieved by HW address or DUID - ConstHostCollection all_by_id = - hdsptr_->getAll(id, &host->getIdentifier()[0], - host->getIdentifier().size()); + ConstHostCollection all_by_id = hdsptr_->getAll( + id, &host->getIdentifier()[0], host->getIdentifier().size()); ASSERT_EQ(subnets, all_by_id.size()); // Check that the returned values are as expected. @@ -869,7 +878,8 @@ GenericHostDataSourceTest::testMultipleSubnets(int subnets, } } -void GenericHostDataSourceTest::testGet6ByHWAddr() { +void +GenericHostDataSourceTest::testGet6ByHWAddr() { // Make sure we have the pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -890,13 +900,13 @@ void GenericHostDataSourceTest::testGet6ByHWAddr() { SubnetID subnet1 = host1->getIPv6SubnetID(); SubnetID subnet2 = host2->getIPv6SubnetID(); - ConstHostPtr from_hds1 = hdsptr_->get6(subnet1, Host::IDENT_HWADDR, - &host1->getIdentifier()[0], - host1->getIdentifier().size()); + ConstHostPtr from_hds1 = + hdsptr_->get6(subnet1, Host::IDENT_HWADDR, &host1->getIdentifier()[0], + host1->getIdentifier().size()); - ConstHostPtr from_hds2 = hdsptr_->get6(subnet2, Host::IDENT_HWADDR, - &host2->getIdentifier()[0], - host2->getIdentifier().size()); + ConstHostPtr from_hds2 = + hdsptr_->get6(subnet2, Host::IDENT_HWADDR, &host2->getIdentifier()[0], + host2->getIdentifier().size()); // Now let's check if we got what we expected. ASSERT_TRUE(from_hds1); @@ -905,7 +915,8 @@ void GenericHostDataSourceTest::testGet6ByHWAddr() { compareHosts(host2, from_hds2); } -void GenericHostDataSourceTest::testGet6ByClientId() { +void +GenericHostDataSourceTest::testGet6ByClientId() { // Make sure we have the pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -926,13 +937,13 @@ void GenericHostDataSourceTest::testGet6ByClientId() { SubnetID subnet1 = host1->getIPv6SubnetID(); SubnetID subnet2 = host2->getIPv6SubnetID(); - ConstHostPtr from_hds1 = hdsptr_->get6(subnet1, Host::IDENT_DUID, - &host1->getIdentifier()[0], - host1->getIdentifier().size()); + ConstHostPtr from_hds1 = + hdsptr_->get6(subnet1, Host::IDENT_DUID, &host1->getIdentifier()[0], + host1->getIdentifier().size()); - ConstHostPtr from_hds2 = hdsptr_->get6(subnet2, Host::IDENT_DUID, - &host2->getIdentifier()[0], - host2->getIdentifier().size()); + ConstHostPtr from_hds2 = + hdsptr_->get6(subnet2, Host::IDENT_DUID, &host2->getIdentifier()[0], + host2->getIdentifier().size()); // Now let's check if we got what we expected. ASSERT_TRUE(from_hds1); @@ -943,7 +954,6 @@ void GenericHostDataSourceTest::testGet6ByClientId() { void GenericHostDataSourceTest::testSubnetId6(int subnets, Host::IdentifierType id) { - // Make sure we have a pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -967,18 +977,18 @@ GenericHostDataSourceTest::testSubnetId6(int subnets, Host::IdentifierType id) { // Check that the reservations can be retrieved from each subnet separately. for (int i = 0; i < subnets; ++i) { - // Try to retrieve the host - ConstHostPtr from_hds = hdsptr_->get6(i + 1000, id, &host->getIdentifier()[0], - host->getIdentifier().size()); + ConstHostPtr from_hds = + hdsptr_->get6(i + 1000, id, &host->getIdentifier()[0], + host->getIdentifier().size()); ASSERT_TRUE(from_hds) << "failed for i=" << i; EXPECT_EQ(i + 1000, from_hds->getIPv6SubnetID()); } // Check that the hosts can all be retrieved by HW address or DUID - ConstHostCollection all_by_id = hdsptr_->getAll(id, &host->getIdentifier()[0], - host->getIdentifier().size()); + ConstHostCollection all_by_id = hdsptr_->getAll( + id, &host->getIdentifier()[0], host->getIdentifier().size()); ASSERT_EQ(subnets, all_by_id.size()); // Check that the returned values are as expected. @@ -995,8 +1005,8 @@ GenericHostDataSourceTest::testSubnetId6(int subnets, Host::IdentifierType id) { } } -void GenericHostDataSourceTest::testGetByIPv6(Host::IdentifierType id, - bool prefix) { +void +GenericHostDataSourceTest::testGetByIPv6(Host::IdentifierType id, bool prefix) { // Make sure we have a pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -1038,7 +1048,8 @@ void GenericHostDataSourceTest::testGetByIPv6(Host::IdentifierType id, EXPECT_FALSE(hdsptr_->get6(IOAddress("2001:db8::5"), len)); } -void GenericHostDataSourceTest::testGetBySubnetIPv6() { +void +GenericHostDataSourceTest::testGetBySubnetIPv6() { // Make sure we have a pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -1055,14 +1066,14 @@ void GenericHostDataSourceTest::testGetBySubnetIPv6() { ASSERT_NO_THROW(hdsptr_->add(host4)); // And then try to retrieve them back. - ConstHostPtr from_hds1 = hdsptr_->get6(host1->getIPv6SubnetID(), - IOAddress("2001:db8:1::")); - ConstHostPtr from_hds2 = hdsptr_->get6(host2->getIPv6SubnetID(), - IOAddress("2001:db8:2::")); - ConstHostPtr from_hds3 = hdsptr_->get6(host3->getIPv6SubnetID(), - IOAddress("2001:db8:3::")); - ConstHostPtr from_hds4 = hdsptr_->get6(host4->getIPv6SubnetID(), - IOAddress("2001:db8:4::")); + ConstHostPtr from_hds1 = + hdsptr_->get6(host1->getIPv6SubnetID(), IOAddress("2001:db8:1::")); + ConstHostPtr from_hds2 = + hdsptr_->get6(host2->getIPv6SubnetID(), IOAddress("2001:db8:2::")); + ConstHostPtr from_hds3 = + hdsptr_->get6(host3->getIPv6SubnetID(), IOAddress("2001:db8:3::")); + ConstHostPtr from_hds4 = + hdsptr_->get6(host4->getIPv6SubnetID(), IOAddress("2001:db8:4::")); // Make sure we got something back. ASSERT_TRUE(from_hds1); @@ -1077,8 +1088,8 @@ void GenericHostDataSourceTest::testGetBySubnetIPv6() { compareHosts(host4, from_hds4); } - -void GenericHostDataSourceTest::testAddDuplicate6WithSameDUID() { +void +GenericHostDataSourceTest::testAddDuplicate6WithSameDUID() { // Make sure we have the pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -1092,7 +1103,8 @@ void GenericHostDataSourceTest::testAddDuplicate6WithSameDUID() { ASSERT_THROW(hdsptr_->add(host), DuplicateEntry); } -void GenericHostDataSourceTest::testAddDuplicate6WithSameHWAddr() { +void +GenericHostDataSourceTest::testAddDuplicate6WithSameHWAddr() { // Make sure we have the pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -1106,7 +1118,8 @@ void GenericHostDataSourceTest::testAddDuplicate6WithSameHWAddr() { ASSERT_THROW(hdsptr_->add(host), DuplicateEntry); } -void GenericHostDataSourceTest::testAddDuplicate4() { +void +GenericHostDataSourceTest::testAddDuplicate4() { // Make sure we have the pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -1131,7 +1144,8 @@ void GenericHostDataSourceTest::testAddDuplicate4() { EXPECT_NO_THROW(hdsptr_->add(host)); } -void GenericHostDataSourceTest::testAddr6AndPrefix(){ +void +GenericHostDataSourceTest::testAddr6AndPrefix() { // Make sure we have the pointer to the host data source. ASSERT_TRUE(hdsptr_); @@ -1146,10 +1160,9 @@ void GenericHostDataSourceTest::testAddr6AndPrefix(){ ASSERT_NO_THROW(hdsptr_->add(host)); // Get this host by DUID - ConstHostPtr from_hds = hdsptr_->get6(host->getIPv6SubnetID(), - Host::IDENT_DUID, - &host->getIdentifier()[0], - host->getIdentifier().size()); + ConstHostPtr from_hds = + hdsptr_->get6(host->getIPv6SubnetID(), Host::IDENT_DUID, + &host->getIdentifier()[0], host->getIdentifier().size()); // Make sure we got something back ASSERT_TRUE(from_hds); @@ -1159,7 +1172,8 @@ void GenericHostDataSourceTest::testAddr6AndPrefix(){ from_hds->getIPv6Reservations()); } -void GenericHostDataSourceTest::testMultipleReservations(){ +void +GenericHostDataSourceTest::testMultipleReservations() { // Make sure we have the pointer to the host data source. ASSERT_TRUE(hdsptr_); uint8_t len = 128; @@ -1179,7 +1193,6 @@ void GenericHostDataSourceTest::testMultipleReservations(){ ASSERT_NO_THROW(hdsptr_->add(host)); - ConstHostPtr from_hds = hdsptr_->get6(IOAddress("2001:db8::1"), len); // Make sure we got something back @@ -1189,7 +1202,8 @@ void GenericHostDataSourceTest::testMultipleReservations(){ compareHosts(host, from_hds); } -void GenericHostDataSourceTest::testMultipleReservationsDifferentOrder(){ +void +GenericHostDataSourceTest::testMultipleReservationsDifferentOrder() { // Make sure we have the pointer to the host data source. ASSERT_TRUE(hdsptr_); uint8_t len = 128; @@ -1214,11 +1228,12 @@ void GenericHostDataSourceTest::testMultipleReservationsDifferentOrder(){ host2->addReservation(resv1); // Check if reservations are the same - compareReservations6(host1->getIPv6Reservations(), host2->getIPv6Reservations()); - + compareReservations6(host1->getIPv6Reservations(), + host2->getIPv6Reservations()); } -void GenericHostDataSourceTest::testOptionsReservations4(const bool formatted) { +void +GenericHostDataSourceTest::testOptionsReservations4(const bool formatted) { HostPtr host = initializeHost4("192.0.2.5", Host::IDENT_HWADDR); // Add a bunch of DHCPv4 and DHCPv6 options for the host. ASSERT_NO_THROW(addTestOptions(host, formatted, DHCP4_ONLY)); @@ -1228,23 +1243,25 @@ void GenericHostDataSourceTest::testOptionsReservations4(const bool formatted) { SubnetID subnet_id = host->getIPv4SubnetID(); // getAll4(address) - ConstHostCollection hosts_by_addr = hdsptr_->getAll4(host->getIPv4Reservation()); + ConstHostCollection hosts_by_addr = + hdsptr_->getAll4(host->getIPv4Reservation()); ASSERT_EQ(1, hosts_by_addr.size()); ASSERT_NO_FATAL_FAILURE(compareHosts(host, *hosts_by_addr.begin())); // get4(subnet_id, identifier_type, identifier, identifier_size) - ConstHostPtr host_by_id = hdsptr_->get4(subnet_id, - host->getIdentifierType(), - &host->getIdentifier()[0], - host->getIdentifier().size()); + ConstHostPtr host_by_id = + hdsptr_->get4(subnet_id, host->getIdentifierType(), + &host->getIdentifier()[0], host->getIdentifier().size()); ASSERT_NO_FATAL_FAILURE(compareHosts(host, host_by_id)); // get4(subnet_id, address) - ConstHostPtr host_by_addr = hdsptr_->get4(subnet_id, IOAddress("192.0.2.5")); + ConstHostPtr host_by_addr = + hdsptr_->get4(subnet_id, IOAddress("192.0.2.5")); ASSERT_NO_FATAL_FAILURE(compareHosts(host, host_by_addr)); } -void GenericHostDataSourceTest::testOptionsReservations6(const bool formatted) { +void +GenericHostDataSourceTest::testOptionsReservations6(const bool formatted) { HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_DUID, false); // Add a bunch of DHCPv4 and DHCPv6 options for the host. ASSERT_NO_THROW(addTestOptions(host, formatted, DHCP6_ONLY)); @@ -1254,9 +1271,9 @@ void GenericHostDataSourceTest::testOptionsReservations6(const bool formatted) { SubnetID subnet_id = host->getIPv6SubnetID(); // get6(subnet_id, identifier_type, identifier, identifier_size) - ConstHostPtr host_by_id = hdsptr_->get6(subnet_id, host->getIdentifierType(), - &host->getIdentifier()[0], - host->getIdentifier().size()); + ConstHostPtr host_by_id = + hdsptr_->get6(subnet_id, host->getIdentifierType(), + &host->getIdentifier()[0], host->getIdentifier().size()); ASSERT_NO_FATAL_FAILURE(compareHosts(host, host_by_id)); // get6(address, prefix_len) @@ -1264,7 +1281,8 @@ void GenericHostDataSourceTest::testOptionsReservations6(const bool formatted) { ASSERT_NO_FATAL_FAILURE(compareHosts(host, host_by_addr)); } -void GenericHostDataSourceTest::testOptionsReservations46(const bool formatted) { +void +GenericHostDataSourceTest::testOptionsReservations46(const bool formatted) { HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_HWADDR, false); // Add a bunch of DHCPv4 and DHCPv6 options for the host. @@ -1273,9 +1291,9 @@ void GenericHostDataSourceTest::testOptionsReservations46(const bool formatted) ASSERT_NO_THROW(hdsptr_->add(host)); // getAll(identifier_type, identifier, identifier_size) - ConstHostCollection hosts_by_id = hdsptr_->getAll(host->getIdentifierType(), - &host->getIdentifier()[0], - host->getIdentifier().size()); + ConstHostCollection hosts_by_id = + hdsptr_->getAll(host->getIdentifierType(), &host->getIdentifier()[0], + host->getIdentifier().size()); ASSERT_EQ(1, hosts_by_id.size()); ASSERT_NO_FATAL_FAILURE(compareHosts(host, *hosts_by_id.begin())); } @@ -1309,8 +1327,9 @@ GenericHostDataSourceTest::testMultipleClientClasses4() { // Fetch the host via: // getAll(const Host::IdentifierType, const uint8_t* identifier_begin, // const size_t identifier_len) const; - hosts_by_id = hdsptr_->getAll(host->getIdentifierType(), &host->getIdentifier()[0], - host->getIdentifier().size()); + hosts_by_id = + hdsptr_->getAll(host->getIdentifierType(), &host->getIdentifier()[0], + host->getIdentifier().size()); ASSERT_EQ(1, hosts_by_id.size()); ASSERT_NO_FATAL_FAILURE(compareHosts(host, *hosts_by_id.begin())); @@ -1328,10 +1347,12 @@ GenericHostDataSourceTest::testMultipleClientClasses4() { ASSERT_NO_FATAL_FAILURE(compareHosts(host, from_hds)); // Fetch the host via - // get4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type, + // get4(const SubnetID& subnet_id, const Host::IdentifierType& + // identifier_type, // const uint8_t* identifier_begin, const size_t identifier_len) const; - from_hds = hdsptr_->get4(subnet_id, host->getIdentifierType(), &host->getIdentifier()[0], - host->getIdentifier().size()); + from_hds = + hdsptr_->get4(subnet_id, host->getIdentifierType(), + &host->getIdentifier()[0], host->getIdentifier().size()); ASSERT_TRUE(from_hds); ASSERT_NO_FATAL_FAILURE(compareHosts(host, from_hds)); @@ -1371,23 +1392,26 @@ GenericHostDataSourceTest::testMultipleClientClasses6() { // getAll(const Host::IdentifierType& identifier_type, // const uint8_t* identifier_begin, // const size_t identifier_len) const; - hosts_by_id = hdsptr_->getAll(host->getIdentifierType(), &host->getIdentifier()[0], - host->getIdentifier().size()); + hosts_by_id = + hdsptr_->getAll(host->getIdentifierType(), &host->getIdentifier()[0], + host->getIdentifier().size()); ASSERT_EQ(1, hosts_by_id.size()); ASSERT_NO_FATAL_FAILURE(compareHosts(host, *hosts_by_id.begin())); // get6(const SubnetID& subnet_id, const DuidPtr& duid, // const HWAddrPtr& hwaddr = HWAddrPtr()) const; - ConstHostPtr from_hds = hdsptr_->get6(subnet_id, DuidPtr(), host->getHWAddress()); + ConstHostPtr from_hds = + hdsptr_->get6(subnet_id, DuidPtr(), host->getHWAddress()); ASSERT_TRUE(from_hds); ASSERT_NO_FATAL_FAILURE(compareHosts(host, from_hds)); // Fetch the host via: - // get6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type, + // get6(const SubnetID& subnet_id, const Host::IdentifierType& + // identifier_type, // const uint8_t* identifier_begin, const size_t identifier_len) const; - from_hds = hdsptr_->get6(subnet_id, Host::IDENT_HWADDR, - &host->getIdentifier()[0], - host->getIdentifier().size()); + from_hds = + hdsptr_->get6(subnet_id, Host::IDENT_HWADDR, &host->getIdentifier()[0], + host->getIdentifier().size()); ASSERT_TRUE(from_hds); ASSERT_NO_FATAL_FAILURE(compareHosts(host, from_hds)); @@ -1429,9 +1453,9 @@ GenericHostDataSourceTest::testMultipleClientClassesBoth() { SubnetID subnet_id = host->getIPv6SubnetID(); // Fetch the host from the source. - ConstHostPtr from_hds = hdsptr_->get6(subnet_id, Host::IDENT_HWADDR, - &host->getIdentifier()[0], - host->getIdentifier().size()); + ConstHostPtr from_hds = + hdsptr_->get6(subnet_id, Host::IDENT_HWADDR, &host->getIdentifier()[0], + host->getIdentifier().size()); ASSERT_TRUE(from_hds); // Verify they match. @@ -1466,8 +1490,9 @@ GenericHostDataSourceTest::testMessageFields4() { // Fetch the host via: // getAll(const Host::IdentifierType, const uint8_t* identifier_begin, // const size_t identifier_len) const; - hosts_by_id = hdsptr_->getAll(host->getIdentifierType(), &host->getIdentifier()[0], - host->getIdentifier().size()); + hosts_by_id = + hdsptr_->getAll(host->getIdentifierType(), &host->getIdentifier()[0], + host->getIdentifier().size()); ASSERT_EQ(1, hosts_by_id.size()); ASSERT_NO_FATAL_FAILURE(compareHosts(host, *hosts_by_id.begin())); @@ -1485,10 +1510,12 @@ GenericHostDataSourceTest::testMessageFields4() { ASSERT_NO_FATAL_FAILURE(compareHosts(host, from_hds)); // Fetch the host via - // get4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type, + // get4(const SubnetID& subnet_id, const Host::IdentifierType& + // identifier_type, // const uint8_t* identifier_begin, const size_t identifier_len) const; - from_hds = hdsptr_->get4(subnet_id, host->getIdentifierType(), &host->getIdentifier()[0], - host->getIdentifier().size()); + from_hds = + hdsptr_->get4(subnet_id, host->getIdentifierType(), + &host->getIdentifier()[0], host->getIdentifier().size()); ASSERT_TRUE(from_hds); ASSERT_NO_FATAL_FAILURE(compareHosts(host, from_hds)); @@ -1694,4 +1721,3 @@ void GenericHostDataSourceTest::testDeleteById6Options() { } // namespace test } // namespace dhcp } // namespace isc - diff --git a/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.h b/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.h index 3ce890956d..49f0c7277c 100644 --- a/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.h +++ b/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.h @@ -86,6 +86,13 @@ public: /// @return Identifier in textual form acceptable by Host constructor std::vector generateIdentifier(const bool new_identifier = true); + /// @brief Checks if the reservation is in the range of reservations. + /// + /// @param resrv Reservation to be searched for. + /// @param range Range of reservations returned by the @c Host object + /// in which the reservation will be searched + bool reservationExists(const IPv6Resrv& resrv, const IPv6ResrvRange& range); + /// @brief Compares hardware addresses of the two hosts. /// /// This method compares two hardware address and uses gtest @@ -122,11 +129,11 @@ public: /// @param host2 second host to compare void compareHosts(const ConstHostPtr& host1, const ConstHostPtr& host2); - /// @ brief Used to sort a host collection by IPv4 subnet id. + /// @brief Used to sort a host collection by IPv4 subnet id. static bool compareHostsForSort4(const ConstHostPtr& host1, const ConstHostPtr& host2); - /// @ brief Used to sort a host collection by IPv6 subnet id. + /// @brief Used to sort a host collection by IPv6 subnet id. static bool compareHostsForSort6(const ConstHostPtr& host1, const ConstHostPtr& host2); @@ -434,7 +441,7 @@ public: void testClientIdNotHWAddr(); /// @brief Test adds specified number of hosts with unique hostnames, then - /// retrieves them and checks that the hostnames are set properly. + /// retrives them and checks that the hostnames are set properly. /// /// Uses gtest macros to report failures. ///