From: Tomek Mrugalski Date: Fri, 29 Dec 2017 11:36:00 +0000 (+0100) Subject: [github35] Many comments updated after review. X-Git-Tag: trac5494_base~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f2b088d0f811c618133fa7485bfe8a5c96fbc7f7;p=thirdparty%2Fkea.git [github35] Many comments updated after review. --- diff --git a/src/lib/dhcpsrv/cql_connection.cc b/src/lib/dhcpsrv/cql_connection.cc index ead885196f..2598f404d9 100644 --- a/src/lib/dhcpsrv/cql_connection.cc +++ b/src/lib/dhcpsrv/cql_connection.cc @@ -22,8 +22,6 @@ #include #include -#include // for std::unique_ptr - namespace isc { namespace dhcp { @@ -39,14 +37,15 @@ CqlConnection::~CqlConnection() { CassError rc = CASS_OK; std::string error; + // Let's free the prepared statements. for (StatementMapEntry s : statements_) { - // typeid(s.second.first) is CassPrepared* CqlTaggedStatement statement = s.second; if (statement.prepared_statement_) { cass_prepared_free(statement.prepared_statement_); } } + // If there's a session, tear it down and free the resources. if (session_) { cass_schema_meta_free(schema_meta_); CassFuture* close_future = cass_session_close(session_); @@ -60,6 +59,7 @@ CqlConnection::~CqlConnection() { session_ = NULL; } + // Free the cluster if there's one. if (cluster_) { cass_cluster_free(cluster_); cluster_ = NULL; diff --git a/src/lib/dhcpsrv/cql_connection.h b/src/lib/dhcpsrv/cql_connection.h index 38eb33f277..1cf864c56c 100644 --- a/src/lib/dhcpsrv/cql_connection.h +++ b/src/lib/dhcpsrv/cql_connection.h @@ -34,12 +34,15 @@ namespace isc { namespace dhcp { /// @brief Pair containing major and minor versions +/// @todo: This is already defined in lease_mgr.h. Need to have one +/// definition. May need to move it if necessary. typedef std::pair VersionPair; /// @brief Statement index representing the statement name typedef char const* const StatementTag; -/// @brief Define CQL backend version: 2.3 +/// @brief Define CQL backend version. The CASS_VERSION_* constants +/// are defined in a header provided by cpp-driver. /// @{ constexpr uint32_t CQL_DRIVER_VERSION_MAJOR = CASS_VERSION_MAJOR; constexpr uint32_t CQL_DRIVER_VERSION_MINOR = CASS_VERSION_MINOR; @@ -52,31 +55,33 @@ constexpr uint32_t CQL_SCHEMA_VERSION_MINOR = 0u; /// @} /// @brief Defines a single statement or query -/// -/// @param name_ short description of the query -/// @param text_ text representation of the actual query -/// @param prepared_statement_ internal Cassandra object representing the -/// prepared statement -/// @param is_raw_statement_ shows if statement should be executed rawly or with -/// binds struct CqlTaggedStatement { + + /// Short description of the query StatementTag name_; + + /// Text representation of the actual query char const* const text_; + + /// Internal Cassandra object representing the prepared statement const CassPrepared* prepared_statement_; - bool is_raw_statement_; + + /// Should the statement be executed raw or with binds? + bool is_raw_; /// @brief Constructor + /// @param name brief name of the query + /// @param text text (CQL) representation of the query CqlTaggedStatement(StatementTag name, char const* const text) - : name_(name), text_(text), prepared_statement_(NULL), - is_raw_statement_(false) { + : name_(name), text_(text), prepared_statement_(NULL), is_raw_(false) { } /// @brief Constructor - CqlTaggedStatement(StatementTag name, - char const* const text, - bool const& is_raw_statement) - : name_(name), text_(text), prepared_statement_(NULL), - is_raw_statement_(is_raw_statement) { + /// @param name brief name of the query + /// @param text text (CQL) representation of the query + /// @param is_raw should the statement be executed raw? + CqlTaggedStatement(StatementTag name, char const* const text, bool const& is_raw) + : name_(name), text_(text), prepared_statement_(NULL), is_raw_(is_raw) { } }; @@ -96,30 +101,26 @@ struct StatementTagEqual { } }; -/// @brief Contains all statements. -typedef std::unordered_map - StatementMap; +/// @brief A container for all statements. +typedef std::unordered_map StatementMap; +/// @brief A type for a single entry on the statements map typedef std::pair StatementMapEntry; /// @brief Common CQL connector pool /// /// Provides common operations for the Cassandra database connection used by -/// CqlLeaseMgr, CqlHostDataSource and CqlSrvConfigMgr. Manages the -/// connection -/// to the Cassandra database and preparing of compiled statements. Its -/// fields -/// are public because they are used (both set and retrieved) in classes -/// that +/// CqlLeaseMgr, CqlHostDataSource and CqlSrvConfigMgr. Manages the connection +/// to the Cassandra database and preparing of compiled statements. Its fields +/// are public because they are used (both set and retrieved) in classes that /// use instances of CqlConnection. class CqlConnection : public DatabaseConnection { public: /// @brief Constructor /// /// Initialize CqlConnection object with parameters needed for connection. + /// @param parameters specify the connection details (username, ip addresses etc.) explicit CqlConnection(const ParameterMap& parameters); /// @brief Destructor @@ -129,6 +130,7 @@ public: /// /// Creates the prepared statements for all of the CQL statements used /// by the CQL backend. + /// @param statements statements to be prepared /// /// @throw isc::dhcp::DbOperationError if an operation on the open database /// has failed @@ -140,7 +142,16 @@ public: /// /// Opens the database using the information supplied in the parameters /// passed to the constructor. If no parameters are supplied, the default - /// values will be used (e.g. keyspace 'keatest', port 9042). + /// values will be used. The defaults are: + /// - contact points: 127.0.0.1 + /// - port 9042 + /// - no user, no password + /// - keyspace keatest + /// - reconnect-wait-time 2000 + /// - connect-timeout 5000 + /// - request-timeout 12000 + /// - tcp-keepalive no + /// - tcp-nodelay no /// /// @throw DbOpenError error opening the database void openDatabase(); @@ -159,7 +170,14 @@ public: /// @brief Check for errors /// - /// Check for errors on the current database operation. + /// Check for errors on the current database operation and returns text + /// description of what happened. In case of success, also returns + /// some logging friendly text. + /// + /// @param what text description of the operation + /// @param future the structure that holds the status of operation + /// @param statement_tag statement that was used (optional) + /// @return text description of the error static const std::string checkFutureError(const std::string& what, CassFuture* future, diff --git a/src/lib/dhcpsrv/cql_exchange.cc b/src/lib/dhcpsrv/cql_exchange.cc index c45c4ec921..c84d7b72f4 100644 --- a/src/lib/dhcpsrv/cql_exchange.cc +++ b/src/lib/dhcpsrv/cql_exchange.cc @@ -47,6 +47,8 @@ namespace dhcp { } \ } +/// @brief a helper structure with a function call operator that returns +/// key value in a format expected by std::hash. struct ExchangeDataTypeHash { public: size_t operator()(const ExchangeDataType& key) const { @@ -54,13 +56,14 @@ public: } }; +/// @brief Defines a type for storing aux. Cassandra functions typedef std::unordered_map CqlFunctionMap; extern CqlFunctionMap CQL_FUNCTIONS; /// @brief hash function for CassTypeMap /// -/// Required by c++ versions 5 and below. +/// Required by g++ versions 5 and below. /// /// @param key being hashed /// @@ -72,9 +75,12 @@ hash_value(const CassValueType& key) { /// @brief Map types used to determine exchange type /// @{ + +/// @brief Defines type that maps specific type to an enum typedef std::unordered_map AnyTypeMap; -// Declare uint8_t as key here for compatibility with c++-5. Ideally, it would -// be CassValueType + +// Declare uint8_t as key here for compatibility with g++ version 5. Ideally, +// it would be CassValueType typedef std::unordered_map CassTypeMap; /// @} @@ -89,8 +95,8 @@ static AnyTypeMap ANY_TYPE_MAP = { {typeid(std::string*), EXCHANGE_DATA_TYPE_STRING}, {typeid(CassBlob*), EXCHANGE_DATA_TYPE_BYTES}, {typeid(CassUuid*), EXCHANGE_DATA_TYPE_UUID}, - {typeid(Udt*), EXCHANGE_DATA_TYPE_UDT}, - {typeid(Collection*), EXCHANGE_DATA_TYPE_COLLECTION}}; + {typeid(Udt*), EXCHANGE_DATA_TYPE_UDT}, // user data type + {typeid(AnyCollection*), EXCHANGE_DATA_TYPE_COLLECTION}}; /// @brief Maps Cassandra type to exchange type static CassTypeMap CASS_TYPE_MAP = { @@ -121,7 +127,7 @@ static CassTypeMap CASS_TYPE_MAP = { {CASS_VALUE_TYPE_UDT, EXCHANGE_DATA_TYPE_UDT}, {CASS_VALUE_TYPE_TUPLE, EXCHANGE_DATA_TYPE_UDT}}; -/// @brief Udt method implementations +/// @brief Udt (user data type) method implementations /// @{ Udt::Udt(const CqlConnection& connection, const std::string& name) : AnyArray(), connection_(connection), name_(name) { @@ -142,6 +148,8 @@ Udt::Udt(const CqlConnection& connection, const std::string& name) } Udt::~Udt() { + /// @todo: Need to get back to this issue. This is likely a memory leak. + // // Bug: it seems that if there is no call to // cass_user_type_set_*(cass_user_type_), then // cass_user_type_free(cass_user_type_) might SIGSEGV, so we never @@ -250,7 +258,14 @@ CqlBindUdt(const boost::any& value, CassStatement* statement) { Udt* udt = boost::any_cast(value); + if (!udt) { + isc_throw(BadValue, "Invalid value specified, not an Udt object"); + } + size_t i = 0u; + + // Let's iterate over all elements in udt and check that we indeed + // can assign the set function for each specified type. for (boost::any& element : *udt) { try { KEA_CASS_CHECK( @@ -275,11 +290,13 @@ static CassError CqlBindCollection(const boost::any& value, const size_t& index, CassStatement* statement) { - Collection* elements = boost::any_cast(value); + AnyCollection* elements = boost::any_cast(value); CassCollection* collection = cass_collection_new(CASS_COLLECTION_TYPE_SET, elements->size()); + // Iterate over all elements and assign appropriate append function + // for each. for (boost::any& element : *elements) { ExchangeDataType type = exchangeType(element); KEA_CASS_CHECK(CQL_FUNCTIONS[type].cqlCollectionAppendFunction_( @@ -555,11 +572,15 @@ CqlGetUdt(const boost::any& data, const CassValue* value) { static CassError CqlGetCollection(const boost::any& data, const CassValue* value) { - Collection* collection = boost::any_cast(data); + AnyCollection* collection = boost::any_cast(data); + if (!collection) { + isc_throw(DbOperationError, "CqlGetCollection(): column is not a collection"); + } + BOOST_ASSERT(collection->size() == 1); - // @todo: Create a copy of the underlying object rather than referencing to - // it. + /// @todo: Create a copy of the underlying object rather than referencing to + /// it. boost::any underlying_object = *collection->begin(); collection->clear(); @@ -580,7 +601,7 @@ CqlGetCollection(const boost::any& data, const CassValue* value) { collection->push_back(underlying_object); KEA_CASS_CHECK(CQL_FUNCTIONS[exchangeType(type)].cqlGetFunction_( *collection->rbegin(), item_value)); - // If cqlGetFunction_() returns != CASS_OK, don't + // If cqlGetFunction_() returns != CASS_OK, don't call // cass_iterator_free(items_iterator) because we're returning from this // function and throwing from the callee. } @@ -738,29 +759,33 @@ void CqlExchange::convertFromDatabaseTime(const cass_int64_t& expire, const cass_int64_t& valid_lifetime, time_t& cltt) { + /// @todo: Although 2037 is still far away, there are people who use infinite + /// lifetimes. Cassandra doesn't have to support it right now, but at least + /// we should be able to detect a problem. + // Convert to local time cltt = static_cast(expire - valid_lifetime); } AnyArray -CqlExchange::executeSelect(const CqlConnection& connection, - const AnyArray& data, - StatementTag statement_tag, - const bool& single /* = false */) { +CqlExchange::executeSelect(const CqlConnection& connection, const AnyArray& data, + StatementTag statement_tag, const bool& single /* = false */) { CassError rc; CassStatement* statement = NULL; CassFuture* future = NULL; AnyArray local_data = data; - StatementMap::const_iterator it = - connection.statements_.find(statement_tag); + // Find the query statement first. + StatementMap::const_iterator it = connection.statements_.find(statement_tag); if (it == connection.statements_.end()) { isc_throw(DbOperationError, "CqlExchange::executeSelect(): Statement " << statement_tag << "has not been prepared."); } + + // Bind the data before the query is executed. CqlTaggedStatement tagged_statement = it->second; - if (tagged_statement.is_raw_statement_) { + if (tagged_statement.is_raw_) { // The entire query is the first element in data. std::string* query = boost::any_cast(local_data.back()); local_data.pop_back(); @@ -774,6 +799,7 @@ CqlExchange::executeSelect(const CqlConnection& connection, } } + // Set specific level of consistency if we're told to do so. if (connection.force_consistency_) { rc = cass_statement_set_consistency(statement, connection.consistency_); if (rc != CASS_OK) { @@ -788,6 +814,7 @@ CqlExchange::executeSelect(const CqlConnection& connection, CqlCommon::bindData(local_data, statement); + // Everything's ready. Call the actual statement. future = cass_session_execute(connection.session_, statement); if (!future) { cass_statement_free(statement); @@ -795,6 +822,8 @@ CqlExchange::executeSelect(const CqlConnection& connection, "CqlExchange::executeSelect(): no CassFuture for statement " << tagged_statement.name_); } + + // Wait for the statement execution to complete. cass_future_wait(future); const std::string error = connection.checkFutureError( "CqlExchange::executeSelect(): cass_session_execute() != CASS_OK", @@ -840,21 +869,20 @@ CqlExchange::executeSelect(const CqlConnection& connection, } void -CqlExchange::executeMutation( - const CqlConnection& connection, - const AnyArray& data, - StatementTag statement_tag) { +CqlExchange::executeMutation(const CqlConnection& connection, const AnyArray& data, + StatementTag statement_tag) { CassError rc; CassStatement* statement = NULL; CassFuture* future = NULL; + // Find the statement on a list of prepared statements. StatementMap::const_iterator it = connection.statements_.find(statement_tag); if (it == connection.statements_.end()) { - isc_throw(DbOperationError, - "CqlExchange::executeSelect(): Statement " - << statement_tag << "has not been prepared."); + isc_throw(DbOperationError, "CqlExchange::executeSelect(): Statement " + << statement_tag << "has not been prepared."); } + // Bind the statement. CqlTaggedStatement tagged_statement = it->second; statement = cass_prepared_bind(tagged_statement.prepared_statement_); if (!statement) { @@ -863,15 +891,14 @@ CqlExchange::executeMutation( << tagged_statement.name_); } + // Set specific level of consistency, if told to do so. if (connection.force_consistency_) { rc = cass_statement_set_consistency(statement, connection.consistency_); if (rc != CASS_OK) { cass_statement_free(statement); - isc_throw(DbOperationError, - "CqlExchange::executeMutation(): unable to set statement " - "consistency for statement " - << tagged_statement.name_ - << ", Cassandra error code: " << cass_error_desc(rc)); + isc_throw(DbOperationError, "CqlExchange::executeMutation(): unable to set" + " statement consistency for statement " << tagged_statement.name_ + << ", Cassandra error code: " << cass_error_desc(rc)); } } @@ -885,9 +912,8 @@ CqlExchange::executeMutation( << tagged_statement.name_); } cass_future_wait(future); - const std::string error = connection.checkFutureError( - "CqlExchange::executeMutation(): cass_session_execute() != CASS_OK", - future, statement_tag); + const std::string error = connection.checkFutureError("CqlExchange::executeMutation():" + "cass_session_execute() != CASS_OK", future, statement_tag); rc = cass_future_error_code(future); if (rc != CASS_OK) { cass_future_free(future); @@ -896,7 +922,7 @@ CqlExchange::executeMutation( } // Check if statement has been applied. - bool applied = hasStatementBeenApplied(future); + bool applied = statementApplied(future); // Free resources. cass_future_free(future); @@ -911,10 +937,14 @@ CqlExchange::executeMutation( } bool -CqlExchange::hasStatementBeenApplied(CassFuture* future, +CqlExchange::statementApplied(CassFuture* future, size_t* row_count, size_t* column_count) { const CassResult* result_collection = cass_future_get_result(future); + if (!result_collection) { + isc_throw(DbOperationError, "CqlExchange::statementApplied(): unable to get" + " results collection"); + } if (row_count) { *row_count = cass_result_row_count(result_collection); } @@ -938,11 +968,7 @@ CqlExchange::hasStatementBeenApplied(CassFuture* future, constexpr StatementTag CqlVersionExchange::GET_VERSION; StatementMap CqlVersionExchange::tagged_statements_ = { - {GET_VERSION, // - {GET_VERSION, // - "SELECT " - "version, minor " - "FROM schema_version "}} // + {GET_VERSION, {GET_VERSION, "SELECT version, minor FROM schema_version "}} }; CqlVersionExchange::CqlVersionExchange() { @@ -952,14 +978,10 @@ CqlVersionExchange::~CqlVersionExchange() { } void -CqlVersionExchange::createBindForSelect( - AnyArray& data, StatementTag /* statement_tag = NULL */) { - // Start with a fresh array. - data.clear(); - // id: blob - data.add(&version_); - // host_identifier: blob - data.add(&minor_); +CqlVersionExchange::createBindForSelect(AnyArray& data, StatementTag) { + data.clear(); // Start with a fresh array. + data.add(&version_); // first column is a major version + data.add(&minor_); // second column is a minor version } boost::any diff --git a/src/lib/dhcpsrv/cql_exchange.h b/src/lib/dhcpsrv/cql_exchange.h index 798d319957..c99f762e41 100644 --- a/src/lib/dhcpsrv/cql_exchange.h +++ b/src/lib/dhcpsrv/cql_exchange.h @@ -59,7 +59,7 @@ public: // @brief Representation of a Cassandra User Defined Type class Udt : public AnyArray { public: - /// @brief Paramterized constructor + /// @brief Parameterized constructor Udt(const CqlConnection& connection, const std::string& name); /// @brief Destructor @@ -85,25 +85,37 @@ public: CassUserType* cass_user_type_; }; -typedef AnyArray Collection; +/// @brief Defines an array of arbitrary objects (used by Cassandra backend) +typedef AnyArray AnyCollection; /// @brief Binds a C++ object to a Cassandra statement's parameter. Used in all /// statements. +/// @param value the value to be set or retreived +/// @param index offset of the value being processed +/// @param statement pointer to the parent statement being used typedef CassError (*CqlBindFunction)(const boost::any& value, const size_t& index, CassStatement* statement); /// @brief Sets a member in a UDT. Used in INSERT & UPDATE statements. -typedef CassError (*CqlUdtSetFunction)(const boost::any& udt_member, - const size_t& position, +/// @param value the value to be set or retreived +/// @param index offset of the value being processed +/// @param cass_user_type pointer to the user type that uses this member +typedef CassError (*CqlUdtSetFunction)(const boost::any& value, + const size_t& index, CassUserType* cass_user_type); /// @brief Sets an item in a collection. Used in INSERT & UPDATE statements. +/// @param value pointer to a value to be inserted or updated +/// @param collection pointer to collection to be inserted or updated typedef CassError (*CqlCollectionAppendFunction)(const boost::any& value, CassCollection* collection); /// @brief Converts a single Cassandra column value to a C++ object. Used in /// SELECT statements. +/// +/// @param data the result will be stored here (this pointer will be updated) +/// @param value this value will be converted typedef CassError (*CqlGetFunction)(const boost::any& data, const CassValue* value); @@ -138,9 +150,19 @@ public: /// @name Time conversion: /// @{ + /// @brief Converts time to Cassandra format + /// + /// @param cltt timestamp of last client transmission time to be converted + /// @param valid_lifetime lifetime of a lease + /// @param expire expiration time (result will be stored here) static void convertToDatabaseTime(const time_t& cltt, const uint32_t& valid_lifetime, cass_int64_t& expire); + + /// @brief Converts time from Cassandra format + /// @param expire expiration time in Cassandra format + /// @param valid_lifetime lifetime of a lease + /// @param cltt client last transmission time (result will be stored here) static void convertFromDatabaseTime(const cass_int64_t& expire, const cass_int64_t& valid_lifetime, time_t& cltt); @@ -196,9 +218,8 @@ public: /// same priumary key. /// /// @return true if statement has been succesfully applied, false otherwise - bool hasStatementBeenApplied(CassFuture* future, - size_t* row_count = NULL, - size_t* column_count = NULL); + bool statementApplied(CassFuture* future, size_t* row_count = NULL, + size_t* column_count = NULL); /// @brief Copy received data into the derived class' object. /// @@ -269,9 +290,9 @@ private: /// @brief Common operations in Cassandra exchanges class CqlCommon { public: - /// @brief Give values to every column of an INSERT or an UPDATE statement. + /// @brief Assigns values to every column of an INSERT or an UPDATE statement. /// - /// Calls cqlBindFunction_() for every column with it's respective type. + /// Calls cqlBindFunction_() for every column with its respective type. /// /// @param data array containing column values to be passed to the statement /// being executed @@ -281,7 +302,7 @@ public: /// @brief Retrieves data returned by Cassandra. /// - /// Calls cqlGetFunction_() for every column with it's respective type. + /// Calls cqlGetFunction_() for every column with its respective type. /// /// @param row internal Cassandra object containing data returned by /// Cassandra diff --git a/src/lib/dhcpsrv/cql_lease_mgr.cc b/src/lib/dhcpsrv/cql_lease_mgr.cc index d35184acba..9722ffe665 100644 --- a/src/lib/dhcpsrv/cql_lease_mgr.cc +++ b/src/lib/dhcpsrv/cql_lease_mgr.cc @@ -35,12 +35,15 @@ static constexpr size_t ADDRESS6_TEXT_MAX_LEN = 39u; /// @brief Common CQL and Lease Data Methods /// -/// The CqlLease4Exchange and CqlLease6Exchange classes provide the +/// The @ref CqlLease4Exchange and @ref CqlLease6Exchange classes provide the /// functionality to set up binding information between variables in the /// program and data extracted from the database. This class is the common /// base to both of them, containing some common methods. class CqlLeaseExchange : public CqlExchange { public: + /// @brief Constructor + /// + /// @param connection already open Cassandra connection. CqlLeaseExchange(const CqlConnection &connection) : connection_(connection), valid_lifetime_(0), expire_(0), subnet_id_(0), fqdn_fwd_(cass_false), fqdn_rev_(cass_false), @@ -80,13 +83,13 @@ protected: /// @brief Lease expiry time cass_int64_t expire_; - /// @brief Subnet identification + /// @brief Subnet identifier cass_int32_t subnet_id_; - /// @brief Has forward DNS update been performed + /// @brief Has forward DNS update been performed? cass_bool_t fqdn_fwd_; - /// @brief Has reverse DNS update been performed + /// @brief Has reverse DNS update been performed? cass_bool_t fqdn_rev_; /// @brief Client hostname @@ -96,7 +99,7 @@ protected: cass_int32_t state_; }; -/// @brief Exchange CQL and Lease4 Data +/// @brief Exchange Lease4 information between Kea and CQL /// /// On any CQL operation, arrays of CQL BIND structures must be built to /// describe the parameters in the prepared statements. Where information is @@ -114,18 +117,27 @@ public: /// /// The initialization of the variables here is only to satisfy cppcheck - /// all variables are initialized/set in the methods before they are used. + /// + /// @param connection connection used for this query explicit CqlLease4Exchange(const CqlConnection &connection); /// @brief Create CQL_BIND objects for Lease4 Pointer /// /// Fills in the CQL_BIND array for sending data in the Lease4 object to /// the database. Used for INSERT statements. + /// + /// @param lease The lease information to be inserted + /// @param data Lease info will be stored here in CQL format void createBindForInsert(const Lease4Ptr &lease, AnyArray &data); /// @brief Create CQL_BIND objects for Lease4 Pointer /// /// Fills in the CQL_BIND array for sending data in the Lease4 object to /// the database. Used for UPDATE statements. + /// + /// @param lease Updated lease information. + /// @param data lease info in CQL format will be stored here + /// @param statement_tag tag identifying the query (optional) void createBindForUpdate(const Lease4Ptr &lease, AnyArray &data, StatementTag statement_tag = NULL); @@ -134,6 +146,10 @@ public: /// /// Fills in the CQL_BIND array for sending data in the Lease4 object to /// the database. Used for DELETE statements. + /// + /// @param address address of the lease to be deleted + /// @param data lease info in CQL format will be stored here + /// @param statement_tag tag identifying the query (optional) void createBindForDelete(const IOAddress &address, AnyArray &data, StatementTag statement_tag = NULL); @@ -141,21 +157,41 @@ public: /// @brief Create BIND array to receive data /// /// Creates a CQL_BIND array to receive Lease4 data from the database. + /// + /// @param data info returned by CQL will be stored here + /// @param statement_tag tag identifying the query (optional) virtual void - createBindForSelect(AnyArray &data, - StatementTag statement_tag = NULL) override; + createBindForSelect(AnyArray &data, StatementTag statement_tag = NULL) override; + /// @brief Retrieves the Lease4 object in Kea format + /// + /// @return C++ representation of the object being returned virtual boost::any retrieve() override; - void getLeaseCollection(StatementTag &statement_tag, - AnyArray &data, + /// @brief Retrieves zero or more IPv4 leases + /// + /// @param statement_tag query to be executed + /// @param data parameters for the query + /// @param result this lease collection will be updated + void getLeaseCollection(StatementTag &statement_tag, AnyArray &data, Lease4Collection &result); + /// @brief Retrieves one IPv4 lease + /// + /// @param statement_tag query to be executed + /// @param data parameters for the query + /// @param result pointer to the lease being returned (or null) void getLease(StatementTag &statement_tag, AnyArray &data, Lease4Ptr &result); - void getExpiredLeases(const size_t &max_leases, - Lease4Collection &expired_leases); + /// @brief Returns expired leases. + /// + /// This method returns up to specified number (see max_leases) of + /// expired leases. + /// + /// @param max_leases at most this number of leases will be returned + /// @param expired_leases expired leases will be stored here + void getExpiredLeases(const size_t &max_leases, Lease4Collection &expired_leases); /// @brief Cassandra statements static StatementMap tagged_statements_; @@ -205,8 +241,9 @@ constexpr StatementTag CqlLease4Exchange::GET_LEASE4_HWADDR_SUBID; StatementMap CqlLease4Exchange::tagged_statements_{ - {INSERT_LEASE4, // - {INSERT_LEASE4, // + // Inserts new IPv4 lease + {INSERT_LEASE4, + {INSERT_LEASE4, "INSERT INTO lease4( " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, state " @@ -215,8 +252,9 @@ StatementMap CqlLease4Exchange::tagged_statements_{ ") " "IF NOT EXISTS "}}, - {UPDATE_LEASE4, // - {UPDATE_LEASE4, // + // Updates existing IPv4 lease + {UPDATE_LEASE4, + {UPDATE_LEASE4, "UPDATE lease4 SET " "hwaddr = ?, " "client_id = ?, " @@ -230,14 +268,16 @@ StatementMap CqlLease4Exchange::tagged_statements_{ "WHERE address = ? " "IF EXISTS "}}, - {DELETE_LEASE4, // - {DELETE_LEASE4, // + // Deletes existing IPv4 lease + {DELETE_LEASE4, + {DELETE_LEASE4, "DELETE FROM lease4 " "WHERE address = ? " "IF EXISTS "}}, - {GET_LEASE4_EXPIRE, // - {GET_LEASE4_EXPIRE, // + // Gets up to a certain number of expired IPv4 leases + {GET_LEASE4_EXPIRE, + {GET_LEASE4_EXPIRE, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, state " @@ -247,16 +287,18 @@ StatementMap CqlLease4Exchange::tagged_statements_{ "LIMIT ? " "ALLOW FILTERING "}}, - {GET_LEASE4_ADDR, // - {GET_LEASE4_ADDR, // + // Gets an IPv4 lease with specified IPv4 address + {GET_LEASE4_ADDR, + {GET_LEASE4_ADDR, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, state " "FROM lease4 " "WHERE address = ? "}}, - {GET_LEASE4_CLIENTID, // - {GET_LEASE4_CLIENTID, // + // Gets an IPv4 lease(s) with specified client-id + {GET_LEASE4_CLIENTID, + {GET_LEASE4_CLIENTID, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, state " @@ -264,8 +306,9 @@ StatementMap CqlLease4Exchange::tagged_statements_{ "WHERE client_id = ? " "ALLOW FILTERING "}}, - {GET_LEASE4_CLIENTID_SUBID, // - {GET_LEASE4_CLIENTID_SUBID, // + // Gets an IPv4 lease with specified client-id and subnet-id + {GET_LEASE4_CLIENTID_SUBID, + {GET_LEASE4_CLIENTID_SUBID, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, state " @@ -274,8 +317,9 @@ StatementMap CqlLease4Exchange::tagged_statements_{ "AND subnet_id = ? " "ALLOW FILTERING "}}, - {GET_LEASE4_HWADDR, // - {GET_LEASE4_HWADDR, // + // Gets all IPv4 leases with specified hardware address + {GET_LEASE4_HWADDR, + {GET_LEASE4_HWADDR, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, state " @@ -283,8 +327,9 @@ StatementMap CqlLease4Exchange::tagged_statements_{ "WHERE hwaddr = ? " "ALLOW FILTERING "}}, - {GET_LEASE4_HWADDR_SUBID, // - {GET_LEASE4_HWADDR_SUBID, // + // Gets an IPv4 lease with specified hardware addr and subnet-id + {GET_LEASE4_HWADDR_SUBID, + {GET_LEASE4_HWADDR_SUBID, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, state " @@ -394,12 +439,8 @@ CqlLease4Exchange::createBindForInsert(const Lease4Ptr &lease, AnyArray &data) { } void -CqlLease4Exchange::createBindForUpdate( - const Lease4Ptr &lease, - AnyArray &data, - StatementTag statement_tag /* = NULL */) { - (void)statement_tag; // [maybe_unused] - +CqlLease4Exchange::createBindForUpdate(const Lease4Ptr &lease, AnyArray &data, + StatementTag /* unused */) { if (!lease) { isc_throw(BadValue, "CqlLease4Exchange::createBindForUpdate(): " "Lease4 object is NULL"); @@ -493,12 +534,8 @@ CqlLease4Exchange::createBindForUpdate( } void -CqlLease4Exchange::createBindForDelete( - const IOAddress &address, - AnyArray &data, - StatementTag statement_tag /* = NULL */) { - (void)statement_tag; // [maybe_unused] - +CqlLease4Exchange::createBindForDelete(const IOAddress &address, AnyArray &data, + StatementTag /* unused */) { // Set up the structures for the various components of the lease4 // structure. @@ -520,12 +557,8 @@ CqlLease4Exchange::createBindForDelete( } } -/// @brief Create BIND array to receive data -/// -/// Creates a CQL_BIND array to receive Lease4 data from the database. void -CqlLease4Exchange::createBindForSelect( - AnyArray &data, StatementTag /* statement_tag = NULL */) { +CqlLease4Exchange::createBindForSelect(AnyArray &data, StatementTag /* unused */) { // Start with a fresh array. data.clear(); @@ -603,7 +636,7 @@ CqlLease4Exchange::retrieve() { result->state_ = state_; - return result; + return (result); } catch (const Exception &ex) { isc_throw(DbOperationError, "CqlLease4Exchange::retrieveLease(): " @@ -613,8 +646,7 @@ CqlLease4Exchange::retrieve() { } void -CqlLease4Exchange::getLeaseCollection(StatementTag &statement_tag, - AnyArray &data, +CqlLease4Exchange::getLeaseCollection(StatementTag &statement_tag, AnyArray &data, Lease4Collection &result) { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_ADDR4) .arg(statement_tag); @@ -628,8 +660,7 @@ CqlLease4Exchange::getLeaseCollection(StatementTag &statement_tag, } void -CqlLease4Exchange::getLease(StatementTag &statement_tag, - AnyArray &data, +CqlLease4Exchange::getLease(StatementTag &statement_tag, AnyArray &data, Lease4Ptr &result) { // This particular method is called when only one or zero matches is // expected. @@ -639,11 +670,10 @@ CqlLease4Exchange::getLease(StatementTag &statement_tag, // Return single record if present, else clear the lease. const size_t collection_size = collection.size(); if (collection_size >= 2u) { - isc_throw( - MultipleRecords, - "CqlLease4Exchange::getLease(): multiple records were found in " - "the database where only one was expected for statement " - << statement_tag); + isc_throw(MultipleRecords, + "CqlLease4Exchange::getLease(): multiple records were found in " + "the database where only one was expected for statement " + << statement_tag); } else if (collection_size == 0u) { result.reset(); } else { @@ -686,7 +716,7 @@ CqlLease4Exchange::getExpiredLeases(const size_t &max_leases, } } -/// @brief Exchange CQL and Lease6 Data +/// @brief Exchange Lease6 information between Kea and CQL /// /// On any CQL operation, arrays of CQL BIND structures must be built to /// describe the parameters in the prepared statements. Where information is @@ -703,50 +733,81 @@ public: /// @brief Constructor /// /// The initialization of the variables here is nonly to satisfy - /// cppcheck - - /// all variables are initialized/set in the methods before they are - /// used. + /// cppcheck - all variables are initialized/set in the methods before + /// they are used. + /// + /// @param connection connection used for this query explicit CqlLease6Exchange(const CqlConnection &connection); - /// @brief Create CQL_BIND objects for Lease4 Pointer + /// @brief Create CQL_BIND objects for Lease6 Pointer /// /// Fills in the CQL_BIND array for sending data in the Lease4 object to /// the database. Used for INSERT statements. + /// + /// @param lease The lease information to be inserted + /// @param data Lease info will be stored here in CQL format void createBindForInsert(const Lease6Ptr &lease, AnyArray &data); - /// @brief Create CQL_BIND objects for Lease4 Pointer + /// @brief Create CQL_BIND objects for Lease6 Pointer /// /// Fills in the CQL_BIND array for sending data in the Lease4 object to /// the database. Used for UPDATE statements. - void createBindForUpdate(const Lease6Ptr &lease, - AnyArray &data, + /// + /// @param lease Updated lease information. + /// @param data lease info in CQL format will be stored here + /// @param statement_tag tag identifying the query (optional) + void createBindForUpdate(const Lease6Ptr &lease, AnyArray &data, StatementTag statement_tag = NULL); /// @brief Create CQL_BIND objects for Lease4 Pointer /// /// Fills in the CQL_BIND array for sending data in the Lease4 object to /// the database. Used for DELETE statements. - void createBindForDelete(const IOAddress &lease, - AnyArray &data, + /// + /// @param address address of the lease to be deleted + /// @param data lease info in CQL format will be stored here + /// @param statement_tag tag identifying the query (optional) + void createBindForDelete(const IOAddress &address, AnyArray &data, StatementTag statement_tag = NULL); /// @brief Create BIND array to receive data /// /// Creates a CQL_BIND array to receive Lease6 data from the database. + /// + /// @param data info returned by CQL will be stored here + /// @param statement_tag tag identifying the query (optional) void createBindForSelect(AnyArray &data, StatementTag statement_tag = NULL) override; + /// @brief Retrieves the Lease6 object in Kea format + /// + /// @return C++ representation of the object being returned boost::any retrieve() override; - void getLeaseCollection(StatementTag &statement_tag, - AnyArray &data, + /// @brief Retrieves zero or more IPv6 leases + /// + /// @param statement_tag query to be executed + /// @param data parameters for the query + /// @param result this lease collection will be updated + void getLeaseCollection(StatementTag &statement_tag, AnyArray &data, Lease6Collection &result); + /// @brief Retrieves one IPv6 lease + /// + /// @param statement_tag query to be executed + /// @param data parameters for the query + /// @param result pointer to the lease being returned (or null) void getLease(StatementTag &statement_tag, AnyArray &data, Lease6Ptr &result); - void getExpiredLeases(const size_t &max_leases, - Lease6Collection &expired_leases); + /// @brief Returns expired leases. + /// + /// This method returns up to specified number (see max_leases) of + /// expired leases. + /// + /// @param max_leases at most this number of leases will be returned + /// @param expired_leases expired leases will be stored here + void getExpiredLeases(const size_t &max_leases, Lease6Collection &expired_leases); /// @brief Cassandra statements static StatementMap tagged_statements_; @@ -759,8 +820,7 @@ public: static constexpr StatementTag GET_LEASE6_EXPIRE = "GET_LEASE6_EXPIRE"; static constexpr StatementTag GET_LEASE6_ADDR = "GET_LEASE6_ADDR"; static constexpr StatementTag GET_LEASE6_DUID_IAID = "GET_LEASE6_DUID_IAID"; - static constexpr StatementTag GET_LEASE6_DUID_IAID_SUBID = - "GET_LEASE6_DUID_IAID_SUBID"; + static constexpr StatementTag GET_LEASE6_DUID_IAID_SUBID = "GET_LEASE6_DUID_IAID_SUBID"; // @} private: @@ -779,7 +839,7 @@ private: /// @brief Identity association identifier cass_int32_t iaid_; - /// @brief Lease type + /// @brief Lease type (NA, TA or PD) cass_int32_t lease_type_; /// @brief Prefix length @@ -802,8 +862,9 @@ constexpr StatementTag CqlLease6Exchange::GET_LEASE6_DUID_IAID_SUBID; StatementMap CqlLease6Exchange::tagged_statements_ = { - {INSERT_LEASE6, // - {INSERT_LEASE6, // + // Inserts new IPv6 lease + {INSERT_LEASE6, + {INSERT_LEASE6, "INSERT INTO lease6(" "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, " "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, " @@ -813,8 +874,9 @@ StatementMap CqlLease6Exchange::tagged_statements_ = { ") " "IF NOT EXISTS "}}, - {UPDATE_LEASE6, // - {UPDATE_LEASE6, // + // Updates existing IPv6 lease + {UPDATE_LEASE6, + {UPDATE_LEASE6, "UPDATE lease6 SET " "valid_lifetime = ?, " "expire = ?, " @@ -834,14 +896,16 @@ StatementMap CqlLease6Exchange::tagged_statements_ = { "WHERE address = ? " "IF EXISTS "}}, - {DELETE_LEASE6, // - {DELETE_LEASE6, // + // Deletes existing IPv6 lease + {DELETE_LEASE6, + {DELETE_LEASE6, "DELETE FROM lease6 " "WHERE address = ? " "IF EXISTS "}}, - {GET_LEASE6_EXPIRE, // - {GET_LEASE6_EXPIRE, // + // Gets up to a certain number of expired IPv6 leases + {GET_LEASE6_EXPIRE, + {GET_LEASE6_EXPIRE, "SELECT " "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, " "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, " @@ -852,8 +916,9 @@ StatementMap CqlLease6Exchange::tagged_statements_ = { "LIMIT ? " "ALLOW FILTERING "}}, - {GET_LEASE6_ADDR, // - {GET_LEASE6_ADDR, // + // Gets an IPv6 lease with specified IPv4 address + {GET_LEASE6_ADDR, + {GET_LEASE6_ADDR, "SELECT " "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, " "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, " @@ -863,8 +928,9 @@ StatementMap CqlLease6Exchange::tagged_statements_ = { "AND lease_type = ? " "ALLOW FILTERING "}}, - {GET_LEASE6_DUID_IAID, // - {GET_LEASE6_DUID_IAID, // + // Gets an IPv6 lease(s) with specified duid and iaid + {GET_LEASE6_DUID_IAID, + {GET_LEASE6_DUID_IAID, "SELECT " "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, " "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, " @@ -874,8 +940,9 @@ StatementMap CqlLease6Exchange::tagged_statements_ = { "AND lease_type = ? " "ALLOW FILTERING "}}, - {GET_LEASE6_DUID_IAID_SUBID, // - {GET_LEASE6_DUID_IAID_SUBID, // + // Gets an IPv6 lease with specified duid, iaid and subnet-id + {GET_LEASE6_DUID_IAID_SUBID, + {GET_LEASE6_DUID_IAID_SUBID, "SELECT " "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, " "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, " @@ -888,20 +955,11 @@ StatementMap CqlLease6Exchange::tagged_statements_ = { }; -/// @brief Constructor -/// -/// The initialization of the variables here is not only to satisfy -/// cppcheck - -/// all variables are initialized/set in the methods before they are -/// used. CqlLease6Exchange::CqlLease6Exchange(const CqlConnection &connection) : CqlLeaseExchange(connection), pref_lifetime_(0), iaid_(0), lease_type_(0), prefix_len_(0), hwtype_(0), hwaddr_source_(0) { } -/// @brief Create CQL_BIND objects for Lease6 Pointer -/// -/// Fills in the CQL_BIND array for sending data in the Lease6 object to -/// the database. + void CqlLease6Exchange::createBindForInsert(const Lease6Ptr &lease, AnyArray &data) { if (!lease) { @@ -916,10 +974,8 @@ CqlLease6Exchange::createBindForInsert(const Lease6Ptr &lease, AnyArray &data) { // address: varchar address_ = lease_->addr_.toText(); if (address_.size() > ADDRESS6_TEXT_MAX_LEN) { - isc_throw(BadValue, - "address " << address_ << " of length " << address_.size() - << " exceeds maximum allowed length of " - << ADDRESS6_TEXT_MAX_LEN); + isc_throw(BadValue, "address " << address_ << " of length " << address_.size() + << " exceeds maximum allowed length of " << ADDRESS6_TEXT_MAX_LEN); } // valid lifetime: bigint @@ -931,8 +987,7 @@ CqlLease6Exchange::createBindForInsert(const Lease6Ptr &lease, AnyArray &data) { // For convenience for external tools, this is converted to lease // expiry time (expire). The relationship is given by: // expire = cltt_ + valid_lft_ - CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_, - expire_); + CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_, expire_); // subnet_id: int subnet_id_ = static_cast(lease_->subnet_id_); @@ -942,9 +997,8 @@ CqlLease6Exchange::createBindForInsert(const Lease6Ptr &lease, AnyArray &data) { // duid: blob if (!lease_->duid_) { - isc_throw(DbOperationError, - "lease6 with address " << address_ - << " is missing mandatory duid"); + isc_throw(DbOperationError, "lease6 with address " << address_ + << " is missing mandatory duid"); } duid_ = lease_->duid_->getDuid(); @@ -965,23 +1019,18 @@ CqlLease6Exchange::createBindForInsert(const Lease6Ptr &lease, AnyArray &data) { // hostname: varchar if (lease_->hostname_.size() > HOSTNAME_MAX_LEN) { - isc_throw(BadValue, - "hostname" << lease_->hostname_ << " of length " - << lease_->hostname_.size() - << " exceeds maximum allowed length of " - << HOSTNAME_MAX_LEN); + isc_throw(BadValue, "hostname" << lease_->hostname_ << " of length " + << lease_->hostname_.size() << " exceeds maximum allowed length of " + << HOSTNAME_MAX_LEN); } hostname_ = lease_->hostname_; // hwaddr: blob if (lease_->hwaddr_ && lease->hwaddr_->hwaddr_.size() > 0) { if (lease_->hwaddr_->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) { - isc_throw(DbOperationError, - "hardware address " - << lease_->hwaddr_->toText() << " of length " - << lease_->hwaddr_->hwaddr_.size() - << " exceeds maximum allowed length of " - << HWAddr::MAX_HWADDR_LEN); + isc_throw(DbOperationError, "hardware address " << lease_->hwaddr_->toText() + << " of length " << lease_->hwaddr_->hwaddr_.size() + << " exceeds maximum allowed length of " << HWAddr::MAX_HWADDR_LEN); } hwaddr_ = lease_->hwaddr_->hwaddr_; } else { @@ -1028,23 +1077,15 @@ CqlLease6Exchange::createBindForInsert(const Lease6Ptr &lease, AnyArray &data) { data.add(&state_); } catch (const Exception &ex) { - isc_throw(DbOperationError, - "CqlLease6Exchange::createBindForInsert(): " - "could not create bind array from Lease6: " - << lease_->addr_.toText() << ", reason: " << ex.what()); + isc_throw(DbOperationError, "CqlLease6Exchange::createBindForInsert(): " + "could not create bind array from Lease6: " << lease_->addr_.toText() + << ", reason: " << ex.what()); } } -/// @brief Create CQL_BIND objects for Lease6 Pointer -/// -/// Fills in the CQL_BIND array for sending data in the Lease6 object to -/// the database. -void -CqlLease6Exchange::createBindForUpdate( - const Lease6Ptr &lease, - AnyArray &data, - StatementTag statement_tag /* = NULL */) { - (void)statement_tag; // [maybe_unused] +void +CqlLease6Exchange::createBindForUpdate(const Lease6Ptr &lease, AnyArray &data, + StatementTag /* unused */) { if (!lease) { isc_throw(BadValue, "Lease6 object is NULL"); } @@ -1176,16 +1217,9 @@ CqlLease6Exchange::createBindForUpdate( } } -/// @brief Create CQL_BIND objects for Lease6 Pointer -/// -/// Fills in the CQL_BIND array for sending data in the Lease6 object to -/// the database. void -CqlLease6Exchange::createBindForDelete( - const IOAddress &address, - AnyArray &data, - StatementTag statement_tag /* = NULL */) { - (void)statement_tag; // [maybe_unused] +CqlLease6Exchange::createBindForDelete(const IOAddress &address, AnyArray &data, + StatementTag /* unused */) { // Set up the structures for the various components of the lease4 // structure. @@ -1207,12 +1241,8 @@ CqlLease6Exchange::createBindForDelete( } } -/// @brief Create BIND array to receive data -/// -/// Creates a CQL_BIND array to receive Lease6 data from the database. void -CqlLease6Exchange::createBindForSelect( - AnyArray &data, StatementTag /* statement_tag = NULL */) { +CqlLease6Exchange::createBindForSelect(AnyArray &data, StatementTag /* unused */) { // Start with a fresh array. data.clear(); @@ -1337,8 +1367,7 @@ CqlLease6Exchange::retrieve() { } void -CqlLease6Exchange::getLeaseCollection(StatementTag &statement_tag, - AnyArray &data, +CqlLease6Exchange::getLeaseCollection(StatementTag &statement_tag, AnyArray &data, Lease6Collection &result) { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_ADDR4) .arg(statement_tag); @@ -1352,8 +1381,7 @@ CqlLease6Exchange::getLeaseCollection(StatementTag &statement_tag, } void -CqlLease6Exchange::getLease(StatementTag &statement_tag, - AnyArray &data, +CqlLease6Exchange::getLease(StatementTag &statement_tag, AnyArray &data, Lease6Ptr &result) { // This particular method is called when only one or zero matches is // expected. @@ -1428,7 +1456,7 @@ CqlLeaseMgr::getDBVersion() { std::stringstream tmp; tmp << "CQL backend " << CQL_SCHEMA_VERSION_MAJOR; tmp << "." << CQL_SCHEMA_VERSION_MINOR; - tmp << ", library cassandra_static"; + tmp << ", library cassandra"; return tmp.str(); } @@ -1443,11 +1471,9 @@ CqlLeaseMgr::addLease(const Lease4Ptr &lease) { new CqlLease4Exchange(dbconn_)); exchange4->createBindForInsert(lease, data); try { - exchange4->executeMutation(dbconn_, data, - CqlLease4Exchange::INSERT_LEASE4); + exchange4->executeMutation(dbconn_, data, CqlLease4Exchange::INSERT_LEASE4); } catch (const Exception &exception) { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_CQL_LEASE_EXCEPTION_THROWN) + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_LEASE_EXCEPTION_THROWN) .arg(exception.what()); return false; } @@ -1461,15 +1487,12 @@ CqlLeaseMgr::addLease(const Lease6Ptr &lease) { AnyArray data; - std::unique_ptr exchange6( - new CqlLease6Exchange(dbconn_)); + std::unique_ptr exchange6(new CqlLease6Exchange(dbconn_)); exchange6->createBindForInsert(lease, data); try { - exchange6->executeMutation(dbconn_, data, - CqlLease6Exchange::INSERT_LEASE6); + exchange6->executeMutation(dbconn_, data, CqlLease6Exchange::INSERT_LEASE6); } catch (const Exception &exception) { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_CQL_LEASE_EXCEPTION_THROWN) + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_LEASE_EXCEPTION_THROWN) .arg(exception.what()); return false; } @@ -1490,11 +1513,10 @@ CqlLeaseMgr::getLease4(const IOAddress &addr) const { // Get the data. Lease4Ptr result; - std::unique_ptr exchange4( - new CqlLease4Exchange(dbconn_)); + std::unique_ptr exchange4(new CqlLease4Exchange(dbconn_)); exchange4->getLease(CqlLease4Exchange::GET_LEASE4_ADDR, data, result); - return result; + return (result); } Lease4Collection @@ -1510,12 +1532,10 @@ CqlLeaseMgr::getLease4(const HWAddr &hwaddr) const { // Get the data. Lease4Collection result; - std::unique_ptr exchange4( - new CqlLease4Exchange(dbconn_)); - exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_HWADDR, data, - result); + std::unique_ptr exchange4(new CqlLease4Exchange(dbconn_)); + exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_HWADDR, data, result); - return result; + return (result); } Lease4Ptr @@ -1536,18 +1556,15 @@ CqlLeaseMgr::getLease4(const HWAddr &hwaddr, SubnetID subnet_id) const { // Get the data. Lease4Ptr result; - std::unique_ptr exchange4( - new CqlLease4Exchange(dbconn_)); - exchange4->getLease(CqlLease4Exchange::GET_LEASE4_HWADDR_SUBID, data, - result); + std::unique_ptr exchange4(new CqlLease4Exchange(dbconn_)); + exchange4->getLease(CqlLease4Exchange::GET_LEASE4_HWADDR_SUBID, data, result); - return result; + return (result); } Lease4Collection CqlLeaseMgr::getLease4(const ClientId &clientid) const { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_CQL_GET_CLIENTID) + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_CLIENTID) .arg(clientid.toText()); // Set up the WHERE clause value @@ -1558,35 +1575,31 @@ CqlLeaseMgr::getLease4(const ClientId &clientid) const { // Get the data. Lease4Collection result; - std::unique_ptr exchange4( - new CqlLease4Exchange(dbconn_)); - exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_CLIENTID, data, - result); + std::unique_ptr exchange4(new CqlLease4Exchange(dbconn_)); + exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_CLIENTID, data, result); return result; } Lease4Ptr -CqlLeaseMgr::getLease4(const ClientId &clientid, - const HWAddr &hwaddr, +CqlLeaseMgr::getLease4(const ClientId &clientid, const HWAddr &hwaddr, SubnetID subnet_id) const { + /// @todo: Remove this method in this and all other implementations. /// This method is currently not implemented because allocation engine /// searches for the lease using HW address or client identifier. /// It never uses both parameters in the same time. We need to /// consider if this method is needed at all. - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_CQL_GET_CLIENTID_HWADDR_SUBID) + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_CLIENTID_HWADDR_SUBID) .arg(clientid.toText()) .arg(hwaddr.toText()) .arg(subnet_id); - isc_throw(NotImplemented, "CqlLeaseMgr::getLease4() not implemented yet"); + isc_throw(NotImplemented, "CqlLeaseMgr::getLease4() is obsolete"); } Lease4Ptr CqlLeaseMgr::getLease4(const ClientId &clientid, SubnetID subnet_id) const { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_CQL_GET_SUBID_CLIENTID) + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_SUBID_CLIENTID) .arg(subnet_id) .arg(clientid.toText()); @@ -1601,12 +1614,10 @@ CqlLeaseMgr::getLease4(const ClientId &clientid, SubnetID subnet_id) const { // Get the data. Lease4Ptr result; - std::unique_ptr exchange4( - new CqlLease4Exchange(dbconn_)); - exchange4->getLease(CqlLease4Exchange::GET_LEASE4_CLIENTID_SUBID, data, - result); + std::unique_ptr exchange4(new CqlLease4Exchange(dbconn_)); + exchange4->getLease(CqlLease4Exchange::GET_LEASE4_CLIENTID_SUBID, data, result); - return result; + return (result); } Lease6Ptr @@ -1633,19 +1644,15 @@ CqlLeaseMgr::getLease6(Lease::Type lease_type, const IOAddress &addr) const { data.add(&lease_type_data); Lease6Ptr result; - std::unique_ptr exchange6( - new CqlLease6Exchange(dbconn_)); + std::unique_ptr exchange6(new CqlLease6Exchange(dbconn_)); exchange6->getLease(CqlLease6Exchange::GET_LEASE6_ADDR, data, result); - return result; + return (result); } Lease6Collection -CqlLeaseMgr::getLeases6(Lease::Type lease_type, - const DUID &duid, - uint32_t iaid) const { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_CQL_GET_IAID_DUID) +CqlLeaseMgr::getLeases6(Lease::Type lease_type, const DUID &duid, uint32_t iaid) const { + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_IAID_DUID) .arg(iaid) .arg(duid.toText()) .arg(lease_type); @@ -1664,21 +1671,16 @@ CqlLeaseMgr::getLeases6(Lease::Type lease_type, // Get the data. Lease6Collection result; - std::unique_ptr exchange6( - new CqlLease6Exchange(dbconn_)); - exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_DUID_IAID, data, - result); + std::unique_ptr exchange6(new CqlLease6Exchange(dbconn_)); + exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_DUID_IAID, data, result); return result; } Lease6Collection -CqlLeaseMgr::getLeases6(Lease::Type lease_type, - const DUID &duid, - uint32_t iaid, +CqlLeaseMgr::getLeases6(Lease::Type lease_type, const DUID &duid, uint32_t iaid, SubnetID subnet_id) const { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_CQL_GET_IAID_SUBID_DUID) + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_IAID_SUBID_DUID) .arg(iaid) .arg(subnet_id) .arg(duid.toText()) @@ -1701,31 +1703,25 @@ CqlLeaseMgr::getLeases6(Lease::Type lease_type, // Get the data. Lease6Collection result; - std::unique_ptr exchange6( - new CqlLease6Exchange(dbconn_)); - exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_DUID_IAID_SUBID, - data, result); - - return result; + std::unique_ptr exchange6(new CqlLease6Exchange(dbconn_)); + exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_DUID_IAID_SUBID, data, result); + return (result); } void CqlLeaseMgr::getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_CQL_GET_EXPIRED4) + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_EXPIRED4) .arg(max_leases); - std::unique_ptr exchange4( - new CqlLease4Exchange(dbconn_)); + std::unique_ptr exchange4(new CqlLease4Exchange(dbconn_)); exchange4->getExpiredLeases(max_leases, expired_leases); } void CqlLeaseMgr::getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_CQL_GET_EXPIRED6) + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_EXPIRED6) .arg(max_leases); std::unique_ptr exchange6( @@ -1735,19 +1731,15 @@ CqlLeaseMgr::getExpiredLeases6(Lease6Collection &expired_leases, void CqlLeaseMgr::updateLease4(const Lease4Ptr &lease) { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_CQL_UPDATE_ADDR4) + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_UPDATE_ADDR4) .arg(lease->addr_.toText()); - std::unique_ptr exchange4( - new CqlLease4Exchange(dbconn_)); + std::unique_ptr exchange4(new CqlLease4Exchange(dbconn_)); try { AnyArray data; - exchange4->createBindForUpdate(lease, data, - CqlLease4Exchange::UPDATE_LEASE4); - exchange4->executeMutation(dbconn_, data, - CqlLease4Exchange::UPDATE_LEASE4); + exchange4->createBindForUpdate(lease, data, CqlLease4Exchange::UPDATE_LEASE4); + exchange4->executeMutation(dbconn_, data, CqlLease4Exchange::UPDATE_LEASE4); } catch (const StatementNotApplied &exception) { isc_throw(NoSuchLease, exception.what()); } @@ -1755,19 +1747,15 @@ CqlLeaseMgr::updateLease4(const Lease4Ptr &lease) { void CqlLeaseMgr::updateLease6(const Lease6Ptr &lease) { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_CQL_UPDATE_ADDR6) + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_UPDATE_ADDR6) .arg(lease->addr_.toText()); - std::unique_ptr exchange6( - new CqlLease6Exchange(dbconn_)); + std::unique_ptr exchange6(new CqlLease6Exchange(dbconn_)); try { AnyArray data; - exchange6->createBindForUpdate(lease, data, - CqlLease6Exchange::UPDATE_LEASE6); - exchange6->executeMutation(dbconn_, data, - CqlLease6Exchange::UPDATE_LEASE6); + exchange6->createBindForUpdate(lease, data, CqlLease6Exchange::UPDATE_LEASE6); + exchange6->executeMutation(dbconn_, data, CqlLease6Exchange::UPDATE_LEASE6); } catch (const StatementNotApplied &exception) { isc_throw(NoSuchLease, exception.what()); } @@ -1784,25 +1772,18 @@ CqlLeaseMgr::deleteLease(const IOAddress &addr) { try { if (addr.isV4()) { - std::unique_ptr exchange4( - new CqlLease4Exchange(dbconn_)); - exchange4->createBindForDelete(addr, data, - CqlLease4Exchange::DELETE_LEASE4); - exchange4->executeMutation(dbconn_, data, - CqlLease4Exchange::DELETE_LEASE4); + std::unique_ptr exchange4(new CqlLease4Exchange(dbconn_)); + exchange4->createBindForDelete(addr, data, CqlLease4Exchange::DELETE_LEASE4); + exchange4->executeMutation(dbconn_, data, CqlLease4Exchange::DELETE_LEASE4); } else if (addr.isV6()) { - std::unique_ptr exchange6( - new CqlLease6Exchange(dbconn_)); - exchange6->createBindForDelete(addr, data, - CqlLease6Exchange::DELETE_LEASE6); - exchange6->executeMutation(dbconn_, data, - CqlLease6Exchange::DELETE_LEASE6); + std::unique_ptr exchange6(new CqlLease6Exchange(dbconn_)); + exchange6->createBindForDelete(addr, data, CqlLease6Exchange::DELETE_LEASE6); + exchange6->executeMutation(dbconn_, data, CqlLease6Exchange::DELETE_LEASE6); } else { return false; } } catch (const Exception &exception) { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_CQL_LEASE_EXCEPTION_THROWN) + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_LEASE_EXCEPTION_THROWN) .arg(exception.what()); return false; } @@ -1815,33 +1796,29 @@ CqlLeaseMgr::deleteExpiredReclaimedLeases4(const uint32_t secs) { DHCPSRV_CQL_DELETE_EXPIRED_RECLAIMED4) .arg(secs); AnyArray data; - uint64_t n_of_deleted_leases = 0u; + uint64_t deleted = 0u; cass_int32_t limit = 1024; // State is reclaimed. - cass_int32_t state = - static_cast(Lease::STATE_EXPIRED_RECLAIMED); + cass_int32_t state = static_cast(Lease::STATE_EXPIRED_RECLAIMED); data.add(&state); // Expiration timestamp. - cass_int64_t expiration = - static_cast(time(NULL) - static_cast(secs)); + cass_int64_t expiration = static_cast(time(NULL) - static_cast(secs)); data.add(&expiration); data.add(&limit); // Get the data. Lease4Collection leases; - std::unique_ptr exchange4( - new CqlLease4Exchange(dbconn_)); - exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_EXPIRE, data, - leases); + std::unique_ptr exchange4(new CqlLease4Exchange(dbconn_)); + exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_EXPIRE, data, leases); for (Lease4Ptr &lease : leases) { if (deleteLease(lease->addr_)) { - ++n_of_deleted_leases; + ++deleted; } } - return n_of_deleted_leases; + return (deleted); } uint64_t @@ -1854,23 +1831,19 @@ CqlLeaseMgr::deleteExpiredReclaimedLeases6(const uint32_t secs) { cass_int32_t limit = 1024; // State is reclaimed. - cass_int32_t state = - static_cast(Lease::STATE_EXPIRED_RECLAIMED); + cass_int32_t state = static_cast(Lease::STATE_EXPIRED_RECLAIMED); data.add(&state); // Expiration timestamp. - cass_int64_t expiration = - static_cast(time(NULL) - static_cast(secs)); + cass_int64_t expiration = static_cast(time(NULL) - static_cast(secs)); data.add(&expiration); data.add(&limit); // Get the data. Lease6Collection leases; - std::unique_ptr exchange6( - new CqlLease6Exchange(dbconn_)); - exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_EXPIRE, data, - leases); + std::unique_ptr exchange6(new CqlLease6Exchange(dbconn_)); + exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_EXPIRE, data, leases); for (Lease6Ptr &lease : leases) { if (deleteLease(lease->addr_)) { ++n_of_deleted_leases; @@ -1881,14 +1854,14 @@ CqlLeaseMgr::deleteExpiredReclaimedLeases6(const uint32_t secs) { size_t CqlLeaseMgr::wipeLeases4(const SubnetID & /*subnet_id*/) { - isc_throw(NotImplemented, - "wipeLeases4 is not implemented for Cassandra backend"); + /// @todo: Need to implement this, so wipe leases would work. + isc_throw(NotImplemented, "wipeLeases4 is not implemented for Cassandra backend"); } size_t CqlLeaseMgr::wipeLeases6(const SubnetID & /*subnet_id*/) { - isc_throw(NotImplemented, - "wipeLeases6 is not implemented for Cassandra backend"); + /// @todo: Need to implement this, so wipe leases would work. + isc_throw(NotImplemented, "wipeLeases6 is not implemented for Cassandra backend"); } std::string @@ -1909,11 +1882,9 @@ CqlLeaseMgr::getDescription() const { VersionPair CqlLeaseMgr::getVersion() const { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_CQL_GET_VERSION); + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_VERSION); - std::unique_ptr version_exchange( - new CqlVersionExchange()); + std::unique_ptr version_exchange(new CqlVersionExchange()); return version_exchange->retrieveVersion(dbconn_); } diff --git a/src/lib/dhcpsrv/cql_lease_mgr.h b/src/lib/dhcpsrv/cql_lease_mgr.h index 5dd8dba965..878f209393 100644 --- a/src/lib/dhcpsrv/cql_lease_mgr.h +++ b/src/lib/dhcpsrv/cql_lease_mgr.h @@ -39,7 +39,7 @@ class CqlLease6Exchange; /// @brief Cassandra Lease Manager /// -/// This class provides the \ref isc::dhcp::LeaseMgr interface to the Cassandra +/// This class provides the @ref isc::dhcp::LeaseMgr interface to the Cassandra /// database. Use of this backend implies that a CQL database is available /// and that the Kea schema has been created within it. class CqlLeaseMgr : public LeaseMgr { @@ -47,15 +47,18 @@ public: /// @brief Constructor /// /// Uses the following keywords in the parameters passed to it to - /// connect to the database: - /// - name - Name of the database to which to connect (mandatory) - /// - host - Host to which to connect (optional, defaults to "localhost") - /// - user - Username under which to connect (optional) - /// - password - Password for "user" on the database (optional) - /// - /// If the database is successfully opened, the version number in the - /// schema_version table will be checked against hard-coded value in - /// the implementation file. + /// connect to the Cassandra cluster (if omitted, defaults specified in + /// parentheses): + /// - name - Name of the keyspace to to connect to ("keatest") + /// - contact-points - IP addresses to connect ("127.0.0.1") + /// - user - Username under which to connect (empty) + /// - password - Password for "user" on the database (empty) + /// - port - TCP port (9042) + /// - reconnect-wait-time (2000) + /// - connect-timeout (5000) + /// - request-timeout (12000) + /// - tcp-keepalive (no) + /// - tcp-nodelay (no) /// /// Finally, all the CQL commands are pre-compiled. /// @@ -138,7 +141,7 @@ public: /// and a subnet /// /// There can be at most one lease for a given HW address in a single - /// pool, so this method with either return a single lease or NULL. + /// subnet, so this method with either return a single lease or NULL. /// /// @param hwaddr hardware address of the client /// @param subnet_id identifier of the subnet that lease must belong to