2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-31 14:05:33 +00:00

[4294] Refactored MySql stats classes

src/lib/dhcpsrv/mysql_lease_mgr.h
src/lib/dhcpsrv/mysql_lease_mgr.cc
    Replaced this class heirarchy:
        AddressStatsQuery4 <-- MySqlAddressStatsQuery4
        AddressStatsQuery6 <-- MySqlAddressStatsQuery6

    With this one:
        LeaseStatsQuery <-- MySqlLeaseStatsQuery
This commit is contained in:
Thomas Markwalder
2016-08-24 08:50:47 -04:00
parent 92ffb41363
commit 0833798a33
4 changed files with 73 additions and 182 deletions

View File

@@ -1223,26 +1223,34 @@ private:
uint32_t state_; ///< Lease state. uint32_t state_; ///< Lease state.
}; };
/// @brief MySql derivation of the IPv4 statistical lease data query /// @brief MySql derivation of the statistical lease data query
/// ///
/// This class is used to recalculate IPv4 lease statistics for MySQL /// This class is used to recalculate lease statistics for MySQL
/// lease storage. It does so by executing a query which returns a result /// lease storage. It does so by executing a query which returns a result
/// containining contain one row per monitored state per subnet, ordered /// containining contain one row per monitored state per lease type per
/// by subnet id in ascending order. /// subnet, ordered by subnet id in ascending order.
/// ///
class MySqlAddressStatsQuery4 : public AddressStatsQuery4 { class MySqlLeaseStatsQuery : public LeaseStatsQuery {
public: public:
/// @brief Constructor /// @brief Constructor
/// ///
/// @param conn A open connection to the database housing the lease data /// @param conn A open connection to the database housing the lease data
MySqlAddressStatsQuery4(MySqlConnection& conn) /// @brief statement_index Index of the query's prepared statement
: conn_(conn), statement_(conn_.statements_[MySqlLeaseMgr /// @brief fetch_type Indicates if query supplies lease type
::RECOUNT_LEASE4_STATS]), MySqlLeaseStatsQuery(MySqlConnection& conn, const size_t statement_index,
bind_(3) { const bool fetch_type)
: conn_(conn), statement_index_(statement_index), statement_(NULL),
fetch_type_(fetch_type), bind_(fetch_type_ ? 4 : 3) {
if (statement_index_ >= MySqlLeaseMgr::NUM_STATEMENTS) {
isc_throw(BadValue, "MySqlLeaseStatsQuery"
" - invalid statement index" << statement_index_);
}
statement_ = conn.statements_[statement_index_];
} }
/// @brief Destructor /// @brief Destructor
virtual ~MySqlAddressStatsQuery4() { virtual ~MySqlLeaseStatsQuery() {
(void) mysql_stmt_free_result(statement_); (void) mysql_stmt_free_result(statement_);
} }
@@ -1255,161 +1263,48 @@ public:
/// the statement to the output bind array and then executes the /// the statement to the output bind array and then executes the
/// statement. /// statement.
void start() { void start() {
int col = 0;
// subnet_id: unsigned int // subnet_id: unsigned int
bind_[0].buffer_type = MYSQL_TYPE_LONG; bind_[col].buffer_type = MYSQL_TYPE_LONG;
bind_[0].buffer = reinterpret_cast<char*>(&subnet_id_); bind_[col].buffer = reinterpret_cast<char*>(&subnet_id_);
bind_[0].is_unsigned = MLM_TRUE; bind_[col].is_unsigned = MLM_TRUE;
++col;
// state: uint32_t
bind_[1].buffer_type = MYSQL_TYPE_LONG;
bind_[1].buffer = reinterpret_cast<char*>(&lease_state_);
bind_[1].is_unsigned = MLM_TRUE;
// state_count_: uint32_t
bind_[2].buffer_type = MYSQL_TYPE_LONG;
bind_[2].buffer = reinterpret_cast<char*>(&state_count_);
bind_[2].is_unsigned = MLM_TRUE;
// Set up the MYSQL_BIND array for the data being returned
// and bind it to the statement.
int status = mysql_stmt_bind_result(statement_, &bind_[0]);
checkError(status, "RECOUNT_LEASE4_STATS: outbound binding failed");
// Execute the statement
status = mysql_stmt_execute(statement_);
checkError(status, "RECOUNT_LEASE4_STATS: 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.
status = mysql_stmt_store_result(statement_);
checkError(status, "RECOUNT_LEASE4_STATS: results storage failed");
}
/// @brief Fetches the next row in the result set
///
/// Once the internal result set has been populated by invoking the
/// the start() method, this method is used to iterate over the
/// result set rows. Once the last row has been fetched, subsequent
/// calls will return false.
///
/// @param row Storage for the fetched row
///
/// @return True if the fetch succeeded, false if there are no more
/// rows to fetch.
bool getNextRow(AddressStatsRow4& row) {
bool have_row = false;
int status = mysql_stmt_fetch(statement_);
if (status == MLM_MYSQL_FETCH_SUCCESS) {
row.subnet_id_ = static_cast<SubnetID>(subnet_id_);
row.lease_state_ = lease_state_;
row.state_count_ = state_count_;
have_row = true;
} else if (status != MYSQL_NO_DATA) {
checkError(status, "RECOUNT_LEASE4_STATS: getNextRow failed");
}
return (have_row);
}
private:
/// @brief Analyzes the given statement outcome status
///
/// Wrapper method around the MySqlConnection:checkError() that is
/// used to generate the appropriate exception if the status indicates
/// an error.
////
/// a DbOperation error
/// @param status The MySQL statement execution outcome status
/// @param what invocation context message which will be included in
/// any exception
void checkError(int status, const char* what) const {
conn_.checkError(status, MySqlLeaseMgr::RECOUNT_LEASE4_STATS, what);
}
/// @brief Database connection to use to execute the query
MySqlConnection& conn_;
/// @brief The query's prepared statement
MYSQL_STMT *statement_;
/// @brief Bind array used to store the query result set;
std::vector<MYSQL_BIND> bind_;
/// @brief Receives subnet ID when fetching a row
uint32_t subnet_id_;
/// @brief Receives the lease state when fetching a row
uint32_t lease_state_;
/// @brief Receives the state count when fetching a row
uint32_t state_count_;
};
/// @brief MySql derivation of the IPv6 statistical lease data query
///
/// This class is used to recalculate IPv6 lease statistics for MySQL
/// lease storage. It does so by executing a query which returns a result
/// containining contain one row per monitored state per subnet, ordered
/// by subnet id in ascending order.
///
class MySqlAddressStatsQuery6 : public AddressStatsQuery6 {
public:
/// @brief Constructor
///
/// @param conn A open connection to the database housing the lease data
MySqlAddressStatsQuery6(MySqlConnection& conn)
: conn_(conn), statement_(conn_.statements_[MySqlLeaseMgr
::RECOUNT_LEASE6_STATS]),
bind_(4) {
}
/// @brief Destructor
virtual ~MySqlAddressStatsQuery6() {
(void) mysql_stmt_free_result(statement_);
}
/// @brief Creates the IPv6 lease statistical data result set
///
/// The result set is populated by executing an SQL query against the
/// lease6 table which sums the leases per lease state per lease type
/// per subnet id. The query used is the prepared statement identified by
/// MySqlLeaseMgr::RECOUNT_LEASE6_STATS. This method creates the binds
/// the statement to the output bind array and then executes the
/// statement.
void start() {
// subnet_id: unsigned int
bind_[0].buffer_type = MYSQL_TYPE_LONG;
bind_[0].buffer = reinterpret_cast<char*>(&subnet_id_);
bind_[0].is_unsigned = MLM_TRUE;
// Fetch the lease type if we were told to do so.
if (fetch_type_) {
// lease type: uint32_t // lease type: uint32_t
bind_[1].buffer_type = MYSQL_TYPE_LONG; bind_[col].buffer_type = MYSQL_TYPE_LONG;
bind_[1].buffer = reinterpret_cast<char*>(&lease_type_); bind_[col].buffer = reinterpret_cast<char*>(&lease_type_);
bind_[1].is_unsigned = MLM_TRUE; bind_[col].is_unsigned = MLM_TRUE;
++col;
} else {
fetch_type_ = Lease::TYPE_NA;
}
// state: uint32_t // state: uint32_t
bind_[2].buffer_type = MYSQL_TYPE_LONG; bind_[col].buffer_type = MYSQL_TYPE_LONG;
bind_[2].buffer = reinterpret_cast<char*>(&lease_state_); bind_[col].buffer = reinterpret_cast<char*>(&lease_state_);
bind_[2].is_unsigned = MLM_TRUE; bind_[col].is_unsigned = MLM_TRUE;
++col;
// state_count_: uint32_t // state_count_: uint32_t
bind_[3].buffer_type = MYSQL_TYPE_LONG; bind_[col].buffer_type = MYSQL_TYPE_LONG;
bind_[3].buffer = reinterpret_cast<char*>(&state_count_); bind_[col].buffer = reinterpret_cast<char*>(&state_count_);
bind_[3].is_unsigned = MLM_TRUE; bind_[col].is_unsigned = MLM_TRUE;
// Set up the MYSQL_BIND array for the data being returned // Set up the MYSQL_BIND array for the data being returned
// and bind it to the statement. // and bind it to the statement.
int status = mysql_stmt_bind_result(statement_, &bind_[0]); int status = mysql_stmt_bind_result(statement_, &bind_[0]);
checkError(status, "RECOUNT_LEASE6_STATS: outbound binding failed"); conn_.checkError(status, statement_index_, "outbound binding failed");
// Execute the statement // Execute the statement
status = mysql_stmt_execute(statement_); status = mysql_stmt_execute(statement_);
checkError(status, "RECOUNT_LEASE6_STATS: unable to execute"); conn_.checkError(status, statement_index_, "unable to execute");
// Ensure that all the lease information is retrieved in one go to avoid // Ensure that all the lease information is retrieved in one go to avoid
// overhead of going back and forth between client and server. // overhead of going back and forth between client and server.
status = mysql_stmt_store_result(statement_); status = mysql_stmt_store_result(statement_);
checkError(status, "RECOUNT_LEASE6_STATS: results storage failed"); conn_.checkError(status, statement_index_, "results storage failed");
} }
@@ -1424,7 +1319,7 @@ public:
/// ///
/// @return True if the fetch succeeded, false if there are no more /// @return True if the fetch succeeded, false if there are no more
/// rows to fetch. /// rows to fetch.
bool getNextRow(AddressStatsRow6& row) { bool getNextRow(LeaseStatsRow& row) {
bool have_row = false; bool have_row = false;
int status = mysql_stmt_fetch(statement_); int status = mysql_stmt_fetch(statement_);
if (status == MLM_MYSQL_FETCH_SUCCESS) { if (status == MLM_MYSQL_FETCH_SUCCESS) {
@@ -1434,35 +1329,25 @@ public:
row.state_count_ = state_count_; row.state_count_ = state_count_;
have_row = true; have_row = true;
} else if (status != MYSQL_NO_DATA) { } else if (status != MYSQL_NO_DATA) {
checkError(status, "RECOUNT_LEASE6_STATS: getNextRow failed"); conn_.checkError(status, statement_index_, "getNextRow failed");
} }
return (have_row); return (have_row);
} }
private: private:
/// @brief Analyzes the given statement outcome status
///
/// Wrapper method around the MySqlConnection:checkError() that is
/// used to generate the appropriate exception if the status indicates
/// an error.
////
/// a DbOperation error
/// @param status The MySQL statement execution outcome status
/// @param what invocation context message which will be included in
/// any exception
void checkError(int status, const char* what) const {
conn_.checkError(status, MySqlLeaseMgr::RECOUNT_LEASE6_STATS, what);
}
/// @brief Database connection to use to execute the query /// @brief Database connection to use to execute the query
MySqlConnection& conn_; MySqlConnection& conn_;
/// @brief Index of the query's prepared statement
size_t statement_index_;
/// @brief The query's prepared statement /// @brief The query's prepared statement
MYSQL_STMT *statement_; MYSQL_STMT *statement_;
/// @brief Indicates if query supplies lease type
bool fetch_type_;
/// @brief Bind array used to store the query result set; /// @brief Bind array used to store the query result set;
std::vector<MYSQL_BIND> bind_; std::vector<MYSQL_BIND> bind_;
@@ -2284,16 +2169,20 @@ MySqlLeaseMgr::getVersion() const {
return (std::make_pair(major, minor)); return (std::make_pair(major, minor));
} }
AddressStatsQuery4Ptr LeaseStatsQueryPtr
MySqlLeaseMgr::startAddressStatsQuery4() { MySqlLeaseMgr::startLeaseStatsQuery4() {
AddressStatsQuery4Ptr query(new MySqlAddressStatsQuery4(conn_)); LeaseStatsQueryPtr query(new MySqlLeaseStatsQuery(conn_,
RECOUNT_LEASE4_STATS,
false));
query->start(); query->start();
return(query); return(query);
} }
AddressStatsQuery6Ptr LeaseStatsQueryPtr
MySqlLeaseMgr::startAddressStatsQuery6() { MySqlLeaseMgr::startLeaseStatsQuery6() {
AddressStatsQuery6Ptr query(new MySqlAddressStatsQuery6(conn_)); LeaseStatsQueryPtr query(new MySqlLeaseStatsQuery(conn_,
RECOUNT_LEASE6_STATS,
true));
query->start(); query->start();
return(query); return(query);
} }

View File

@@ -593,23 +593,23 @@ private:
/// @brief Creates and runs the IPv4 lease stats query /// @brief Creates and runs the IPv4 lease stats query
/// ///
/// It creates an instance of a MySqlAddressStatsQuery4 and then /// It creates an instance of a MySqlLeaseStatsQuery4 and then
/// invokes its start method, which fetches its statistical data /// invokes its start method, which fetches its statistical data
/// result set by executing the RECOUNT_LEASE_STATS4 query. /// result set by executing the RECOUNT_LEASE_STATS4 query.
/// The query object is then returned. /// The query object is then returned.
/// ///
/// @return The populated query as a pointer to an AddressStatsQuery4 /// @return The populated query as a pointer to an LeaseStatsQuery
virtual AddressStatsQuery4Ptr startAddressStatsQuery4(); virtual LeaseStatsQueryPtr startLeaseStatsQuery4();
/// @brief Creates and runs the IPv6 lease stats query /// @brief Creates and runs the IPv6 lease stats query
/// ///
/// It creates an instance of a MySqlAddressStatsQuery6 and then /// It creates an instance of a MySqlLeaseStatsQuery6 and then
/// invokes its start method, which fetches its statistical data /// invokes its start method, which fetches its statistical data
/// result set by executing the RECOUNT_LEASE_STATS4 query. /// result set by executing the RECOUNT_LEASE_STATS6 query.
/// The query object is then returned. /// The query object is then returned.
/// ///
/// @return The populated query as a pointer to an AddressStatsQuery6 /// @return The populated query as a pointer to an LeaseStatsQuery
virtual AddressStatsQuery6Ptr startAddressStatsQuery6(); virtual LeaseStatsQueryPtr startLeaseStatsQuery6();
/// @brief Check Error and Throw Exception /// @brief Check Error and Throw Exception
/// ///

View File

@@ -760,6 +760,8 @@ public:
lease_type); lease_type);
row.lease_type_ = static_cast<Lease::Type>(lease_type); row.lease_type_ = static_cast<Lease::Type>(lease_type);
++col; ++col;
} else {
row.lease_type_ = Lease::TYPE_NA;
} }
// Fetch the lease state. // Fetch the lease state.

View File

@@ -478,13 +478,13 @@ TEST_F(MySqlLeaseMgrTest, deleteExpiredReclaimedLeases4) {
} }
// Verifies that IPv4 lease statistics can be recalculated. // Verifies that IPv4 lease statistics can be recalculated.
TEST_F(MySqlLeaseMgrTest, recountAddressStats4) { TEST_F(MySqlLeaseMgrTest, recountLeaseStats4) {
testRecountAddressStats4(); testRecountLeaseStats4();
} }
// Verifies that IPv6 lease statistics can be recalculated. // Verifies that IPv6 lease statistics can be recalculated.
TEST_F(MySqlLeaseMgrTest, recountAddressStats6) { TEST_F(MySqlLeaseMgrTest, recountLeaseStats6) {
testRecountAddressStats6(); testRecountLeaseStats6();
} }
}; // Of anonymous namespace }; // Of anonymous namespace