From: Stephen Morris Date: Mon, 26 Nov 2012 19:17:27 +0000 (+0000) Subject: [2404] Further refactoring and a bit of simplification. X-Git-Tag: bind10-1.0.0-beta-release~39^2~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46cfa0779257292e55c048a3854f0df4fe1cbd08;p=thirdparty%2Fkea.git [2404] Further refactoring and a bit of simplification. Also, included dhcpsrv in the list of directories searched by Doxygen. --- diff --git a/doc/Doxyfile b/doc/Doxyfile index cc3b5959d7..fbd082f745 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -580,8 +580,8 @@ INPUT = ../src/lib/exceptions ../src/lib/cc \ ../src/lib/testutils ../src/lib/cache ../src/lib/server_common/ \ ../src/bin/sockcreator/ ../src/lib/util/ ../src/lib/util/io/ \ ../src/lib/util/threads/ ../src/lib/resolve ../src/lib/acl \ - ../src/lib/statistics ../src/bin/dhcp6 ../src/lib/dhcp ../src/bin/dhcp4 \ - ../tests/tools/perfdhcp devel + ../src/lib/statistics ../src/bin/dhcp6 ../src/lib/dhcp ../src/lib/dhcpsrv \ + ../src/bin/dhcp4 ../tests/tools/perfdhcp devel # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is diff --git a/src/lib/dhcpsrv/database_backends.dox b/src/lib/dhcpsrv/database_backends.dox index 8eeb5c5684..057f7c0434 100644 --- a/src/lib/dhcpsrv/database_backends.dox +++ b/src/lib/dhcpsrv/database_backends.dox @@ -32,6 +32,8 @@ - type - specifies the type of database backend. The following values for the type keyword are supported: + - memfile - In-memory database. Nothing is written to any + external storage, so this should not be used in production. - mysql - Use MySQL as the database The following sections list the database-specific keywords: diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.cc b/src/lib/dhcpsrv/mysql_lease_mgr.cc index aa691edc62..12c6946735 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.cc +++ b/src/lib/dhcpsrv/mysql_lease_mgr.cc @@ -28,6 +28,48 @@ using namespace isc; using namespace isc::dhcp; using namespace std; +/// @file +/// +/// This file holds the implementation of the Lease Manager using MySQL. The +/// implementation uses MySQL's C API, as it comes as standard with the MySQL +/// client libraries. +/// +/// In general, each of the database access methods corresponds to one SQL +/// statement. To avoid the overhead of parsing a statement every time it is +/// used, when the database is opened "prepared statements" are created - +/// essentially doing the SQL parsing up front. Every time a method is used +/// to access data, the corresponding prepared statement is referenced. Each +/// prepared statement contains a set of placeholders for data, each +/// placeholder being for: +/// +/// - data being added to the database (as in adding or updating a lease) +/// - data being retrieved from the database (as in getting lease information) +/// - selection criteria used to determine which records to update/retrieve. +/// +/// All such data is associated with the prepared statment using an array of +/// MYSQL_BIND structures. Each element in the array corresponds to one +/// parameter in the prepared statement - the first element in the array is +/// associated with the first parameter, the second element with the second +/// parameter etc. +/// +/// Within this file, the setting up of the MYSQL_BIND arrays for data being +/// passed to and retrieved from the database is handled in the +/// isc::dhcp::MySqlLease4Exchange and isc::dhcp::MySqlLease6Exchange classes. +/// The classes also hold intermediate variables required for exchanging some +/// of the data. +/// +/// With these exchange objects in place, many of the methods follow similar +/// logic: +/// - Set up the MYSQL_BIND array for data being transferred to/from the +/// database. For data being transferred to the database, some of the +/// data is extracted from the lease to intermediate variables, whilst +/// in other cases the MYSQL_BIND arrays point to the data in the lease. +/// - Set up the MYSQL_BIND array for the data selection parameters. +/// - Bind these arrays to the prepared statement. +/// - Execute the statement. +/// - If there is output, copy the data from the bound variables to the output +/// lease object. + namespace { ///@{ @@ -51,7 +93,8 @@ const size_t CLIENT_ID_MAX_LEN = 128; ///< Max size of a client ID /// /// Declare typed values so as to avoid problems of data conversion. These /// are local to the file but are given the prefix MLM (MySql Lease Manager) to -/// avoid any likely conflicts with variables named TRUE or FALSE. +/// avoid any likely conflicts with variables n header files named TRUE or +/// FALSE. const my_bool MLM_FALSE = 0; ///< False value const my_bool MLM_TRUE = 1; ///< True value @@ -155,8 +198,7 @@ namespace dhcp { /// structure is identical. This class handles the creation of that array. /// /// Owing to the MySQL API, the process requires some intermediate variables -/// to hold things like data length etc. This object holds the intermediate -/// variables as well. +/// to hold things like data length etc. This object holds those variables. /// /// @note There are no unit tests for this class. It is tested indirectly /// in all MySqlLeaseMgr::xxx4() calls where it is used. @@ -229,7 +271,7 @@ public: // // expire = cltt_ + valid_lft_ // - // @TODO Handle overflows - a large enough valid_lft_ could cause + // @todo Handle overflows - a large enough valid_lft_ could cause // an overflow on a 32-bit system. MySqlLeaseMgr::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_, expire_); @@ -256,8 +298,7 @@ public: /// std::vector createBindForReceive() { - // Ensure both the array of MYSQL_BIND structures and the error array - // are clear. + // Initialize MYSQL_BIND array. memset(bind_, 0, sizeof(bind_)); // address: uint32_t @@ -303,7 +344,7 @@ public: /// /// Called after the MYSQL_BIND array created by createBindForReceive() /// has been used, this copies data from the internal member variables - /// into a Lease4 object. + /// into a Lease4 objec. /// /// @return Lease4Ptr Pointer to a Lease6 object holding the relevant /// data. @@ -348,8 +389,7 @@ private: /// structure is identical. This class handles the creation of that array. /// /// Owing to the MySQL API, the process requires some intermediate variables -/// to hold things like data length etc. This object holds the intermediate -/// variables as well. +/// to hold things like data length etc. This object holds those variables. /// /// @note There are no unit tests for this class. It is tested indirectly /// in all MySqlLeaseMgr::xxx6() calls where it is used. @@ -478,8 +518,7 @@ public: /// functions. std::vector createBindForReceive() { - // Ensure both the array of MYSQL_BIND structures and the error array - // are clear. + // Initialize MYSQL_BIND array. memset(bind_, 0, sizeof(bind_)); // address: varchar @@ -542,7 +581,7 @@ public: /// @brief Copy Received Data into Lease6 Object /// /// Called after the MYSQL_BIND array created by createBindForReceive() - /// has been used, this copies data from the internal member vairables + /// has been used, this copies data from the internal member variables /// into a Lease6 object. /// /// @return Lease6Ptr Pointer to a Lease6 object holding the relevant @@ -558,7 +597,7 @@ public: isc::asiolink::IOAddress addr(address); // Set the lease type in a variable of the appropriate data type, which - // has been initialized with an arbitrary but valid value. + // has been initialized with an arbitrary (but valid) value. Lease6::LeaseType type = Lease6::LEASE_IA_NA; switch (lease_type_) { case Lease6::LEASE_IA_NA: @@ -673,8 +712,12 @@ MySqlLeaseMgr::MySqlLeaseMgr(const LeaseMgr::ParameterMap& parameters) // Open the database. openDatabase(); - // Enable autocommit. For maximum speed, the global parameter - // innodb_flush_log_at_trx_commit should be set to 2. + // Enable autocommit. To avoid a flush to disk on every commit, the global + // parameter innodb_flush_log_at_trx_commit should be set to 2. This will + // cause the changes to be written to the log, but flushed to disk in the + // background every second or so. Setting the parameter to that value will + // speed up the system, but at the risk of losing data if the system + // crashes. my_bool result = mysql_autocommit(mysql_, 1); if (result != 0) { isc_throw(DbOperationError, mysql_error(mysql_)); @@ -835,12 +878,12 @@ MySqlLeaseMgr::openDatabase() { } } -// Prepared statement setup. The textual form of the SQL statement is stored +// Prepared statement setup. The textual form of an SQL statement is stored // in a vector of strings (text_statements_) and is used in the output of // error messages. The SQL statement is also compiled into a "prepared // statement" (stored in statements_), which avoids the overhead of compilation -// during use. As these allocate resources, the class destructor explicitly -// destroys the prepared statements. +// during use. As prepared statements have resources allocated to them, the +// class destructor explicitly destroys them. void MySqlLeaseMgr::prepareStatement(StatementIndex index, const char* text) { @@ -884,13 +927,13 @@ MySqlLeaseMgr::prepareStatements() { } } - // Add leases to the database. The two public methods accept a lease object // (of different types), bind the contents to the appropriate prepared // statement, then call common code to execute the statement. bool -MySqlLeaseMgr::addLease(StatementIndex stindex, std::vector& bind) { +MySqlLeaseMgr::addLeaseCommon(StatementIndex stindex, + std::vector& bind) { // Bind the parameters to the statement int status = mysql_stmt_bind_param(statements_[stindex], &bind[0]); @@ -919,7 +962,7 @@ MySqlLeaseMgr::addLease(const Lease4Ptr& lease) { std::vector bind = exchange4_->createBindForSend(lease); // ... and drop to common code. - return (addLease(INSERT_LEASE4, bind)); + return (addLeaseCommon(INSERT_LEASE4, bind)); } bool @@ -928,33 +971,7 @@ MySqlLeaseMgr::addLease(const Lease6Ptr& lease) { std::vector bind = exchange6_->createBindForSend(lease); // ... and drop to common code. - return (addLease(INSERT_LEASE6, bind)); -} - -// A convenience function used in the various getLease() methods. It binds -// the selection parameters to the prepared statement, and binds the variables -// that will receive the data. These are stored in the MySqlLease6Exchange -// object associated with the lease manager and converted to a Lease6 object -// when retrieved. -template -void -MySqlLeaseMgr::bindAndExecute(StatementIndex stindex, Exchange& exchange, - MYSQL_BIND* inbind) const { - - // Bind the input parameters to the statement - int status = mysql_stmt_bind_param(statements_[stindex], inbind); - checkError(status, stindex, "unable to bind WHERE clause parameter"); - - // Set up the SELECT clause - std::vector outbind = exchange->createBindForReceive(); - - // Bind the output parameters to the statement - status = mysql_stmt_bind_result(statements_[stindex], &outbind[0]); - checkError(status, stindex, "unable to bind SELECT caluse parameters"); - - // Execute the statement - status = mysql_stmt_execute(statements_[stindex]); - checkError(status, stindex, "unable to execute"); + return (addLeaseCommon(INSERT_LEASE6, bind)); } // Extraction of leases from the database. @@ -984,18 +1001,28 @@ MySqlLeaseMgr::bindAndExecute(StatementIndex stindex, Exchange& exchange, template void MySqlLeaseMgr::getLeaseCollection(StatementIndex stindex, - MYSQL_BIND* inbind, + MYSQL_BIND* bind, Exchange& exchange, LeaseCollection& result, bool single) const { - // Bind the input parameters to the statement and bind the output - // to fields in the exchange object, then execute the prepared statement. - bindAndExecute(stindex, exchange, inbind); + // Bind the selection parameters to the statement + int status = mysql_stmt_bind_param(statements_[stindex], bind); + checkError(status, stindex, "unable to bind WHERE clause parameter"); + + // Set up the MYSQL_BIND array for the data being returned and bind it to + // the statement. + std::vector outbind = exchange->createBindForReceive(); + status = mysql_stmt_bind_result(statements_[stindex], &outbind[0]); + checkError(status, stindex, "unable to bind SELECT clause parameters"); + + // Execute the statement + status = mysql_stmt_execute(statements_[stindex]); + checkError(status, stindex, "unable to execute"); // Ensure that all the lease information is retrieved in one go to avoid // overhead of going back and forth between client and server. - int status = mysql_stmt_store_result(statements_[stindex]); + status = mysql_stmt_store_result(statements_[stindex]); checkError(status, stindex, "unable to set up for storing all results"); // Initialize for returning the data @@ -1034,7 +1061,7 @@ void MySqlLeaseMgr::getLeaseCollection(StatementIndex stindex, } -void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* inbind, +void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* bind, Lease4Ptr& result) const { // Create appropriate collection object and get all leases matching // the selection criteria. The "single" paraeter is true to indicate @@ -1042,7 +1069,7 @@ void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* inbind, // matching records are found: this particular method is called when only // one or zero matches is expected. Lease4Collection collection; - getLeaseCollection(stindex, inbind, exchange4_, collection, true); + getLeaseCollection(stindex, bind, exchange4_, collection, true); // Return single record if present, else clear the lease. if (collection.empty()) { @@ -1052,7 +1079,8 @@ void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* inbind, } } -void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* inbind, + +void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* bind, Lease6Ptr& result) const { // Create appropriate collection object and get all leases matching // the selection criteria. The "single" paraeter is true to indicate @@ -1060,7 +1088,7 @@ void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* inbind, // matching records are found: this particular method is called when only // one or zero matches is expected. Lease6Collection collection; - getLeaseCollection(stindex, inbind, exchange6_, collection, true); + getLeaseCollection(stindex, bind, exchange6_, collection, true); // Return single record if present, else clear the lease. if (collection.empty()) { @@ -1318,8 +1346,8 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid, template void -MySqlLeaseMgr::updateLease(StatementIndex stindex, MYSQL_BIND* bind, - const LeasePtr& lease) { +MySqlLeaseMgr::updateLeaseCommon(StatementIndex stindex, MYSQL_BIND* bind, + const LeasePtr& lease) { // Bind the parameters to the statement int status = mysql_stmt_bind_param(statements_[stindex], bind); @@ -1362,7 +1390,7 @@ MySqlLeaseMgr::updateLease4(const Lease4Ptr& lease) { bind.push_back(where); // Drop to common update code - updateLease(stindex, &bind[0], lease); + updateLeaseCommon(stindex, &bind[0], lease); } @@ -1389,7 +1417,7 @@ MySqlLeaseMgr::updateLease6(const Lease6Ptr& lease) { bind.push_back(where); // Drop to common update code - updateLease(stindex, &bind[0], lease); + updateLeaseCommon(stindex, &bind[0], lease); } // Delete lease methods. As with other groups of methods, these comprise diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.h b/src/lib/dhcpsrv/mysql_lease_mgr.h index 13d1c3474e..6a39d4b13a 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.h +++ b/src/lib/dhcpsrv/mysql_lease_mgr.h @@ -39,7 +39,10 @@ class MySqlLease6Exchange; /// @brief MySQL Lease Manager /// -/// This is a concrete API for the backend for the MySQL database. +/// This class provides the \ref isc::dhcp::LeaseMgr interface to the MySQL +/// database. Use of this backend presupposes that a MySQL database is +/// available and that the Kea schema has been created within it. + class MySqlLeaseMgr : public LeaseMgr { public: /// @brief Constructor @@ -433,30 +436,7 @@ private: /// /// @throw isc::dhcp::DbOperationError An operation on the open database has /// failed. - bool addLease(StatementIndex stindex, std::vector& bind); - - /// @brief Binds Parameters and Executes - /// - /// This method abstracts a lot of common processing from the getXxxx() - /// methods. It binds the parameters passed to it to the appropriate - /// prepared statement, and binds the variables in the exchange6 object to - /// the output parameters of the statement. It then executes the prepared - /// statement. - /// - /// The data can be retrieved using mysql_stmt_fetch and the getLeaseData() - /// method on the appropriate exchange object. - /// - /// @param stindex Index of prepared statement to be executed - /// @param exchange Exchange object to use - /// @param inbind Array of MYSQL_BIND objects representing the parameters. - /// (Note that the number is determined by the number of parameters - /// in the statement.) - /// - /// @throw isc::dhcp::DbOperationError An operation on the open database has - /// failed. - template - void bindAndExecute(StatementIndex stindex, Exchange& exchange, - MYSQL_BIND* inbind) const; + bool addLeaseCommon(StatementIndex stindex, std::vector& bind); /// @brief Get Lease Collection Common Code /// @@ -464,7 +444,7 @@ private: /// from the database. /// /// @param stindex Index of statement being executed - /// @param inbind MYSQL_BIND array for input parameters + /// @param bind MYSQL_BIND array for input parameters /// @param exchange Exchange object to use /// @param lease LeaseCollection object returned. Note that any data in /// the collection is cleared before new data is added. @@ -478,7 +458,7 @@ private: /// @throw isc::dhcp::MultipleRecords Multiple records were retrieved /// from the database where only one was expected. template - void getLeaseCollection(StatementIndex stindex, MYSQL_BIND* inbind, + void getLeaseCollection(StatementIndex stindex, MYSQL_BIND* bind, Exchange& exchange, LeaseCollection& result, bool single = false) const; @@ -488,7 +468,7 @@ private: /// the get lease collection common code. /// /// @param stindex Index of statement being executed - /// @param inbind MYSQL_BIND array for input parameters + /// @param bind MYSQL_BIND array for input parameters /// @param lease LeaseCollection object returned. Note that any data in /// the collection is cleared before new data is added. /// @@ -497,9 +477,9 @@ private: /// failed. /// @throw isc::dhcp::MultipleRecords Multiple records were retrieved /// from the database where only one was expected. - void getLeaseCollection(StatementIndex stindex, MYSQL_BIND* inbind, + void getLeaseCollection(StatementIndex stindex, MYSQL_BIND* bind, Lease4Collection& result) const { - getLeaseCollection(stindex, inbind, exchange4_, result); + getLeaseCollection(stindex, bind, exchange4_, result); } /// @brief Get Lease Collection @@ -508,7 +488,7 @@ private: /// the get lease collection common code. /// /// @param stindex Index of statement being executed - /// @param inbind MYSQL_BIND array for input parameters + /// @param bind MYSQL_BIND array for input parameters /// @param lease LeaseCollection object returned. Note that any data in /// the collection is cleared before new data is added. /// @@ -517,9 +497,9 @@ private: /// failed. /// @throw isc::dhcp::MultipleRecords Multiple records were retrieved /// from the database where only one was expected. - void getLeaseCollection(StatementIndex stindex, MYSQL_BIND* inbind, + void getLeaseCollection(StatementIndex stindex, MYSQL_BIND* bind, Lease6Collection& result) const { - getLeaseCollection(stindex, inbind, exchange6_, result); + getLeaseCollection(stindex, bind, exchange6_, result); } /// @brief Get Lease6 Common Code @@ -529,9 +509,9 @@ private: /// but retrieveing only a single lease. /// /// @param stindex Index of statement being executed - /// @param inbind MYSQL_BIND array for input parameters + /// @param bind MYSQL_BIND array for input parameters /// @param lease Lease4 object returned - void getLease(StatementIndex stindex, MYSQL_BIND* inbind, + void getLease(StatementIndex stindex, MYSQL_BIND* bind, Lease4Ptr& result) const; /// @brief Get Lease4 Common Code @@ -541,9 +521,9 @@ private: /// but retrieveing only a single lease. /// /// @param stindex Index of statement being executed - /// @param inbind MYSQL_BIND array for input parameters + /// @param bind MYSQL_BIND array for input parameters /// @param lease Lease6 object returned - void getLease(StatementIndex stindex, MYSQL_BIND* inbind, + void getLease(StatementIndex stindex, MYSQL_BIND* bind, Lease6Ptr& result) const; /// @brief Update lease common code @@ -563,8 +543,8 @@ private: /// @throw isc::dhcp::DbOperationError An operation on the open database has /// failed. template - void updateLease(StatementIndex stindex, MYSQL_BIND* bind, - const LeasePtr& lease); + void updateLeaseCommon(StatementIndex stindex, MYSQL_BIND* bind, + const LeasePtr& lease); /// @brief Delete lease common code ///