2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 21:45:37 +00:00

[4294] Unit tests and MySql now support IPv6 lease stat recounting

src/lib/dhcpsrv/cfg_subnets6.cc
    - CfgSubnets6::removeStatistics() - added removal of declined stats
    - CfgSubnets6::updateStatistics() - added call to recountAddressStats6()

src/lib/dhcpsrv/mysql_lease_mgr.h
src/lib/dhcpsrv/mysql_lease_mgr.cc
    - Added TaggedStatement RECOUNT_LEASE6_STATS
    - MySqlAddressStatsQuery6 - new MySql derivation of AddressStatsQuery6
    - MySqlLeaseMgr::startAddressStatsQuery6() - new virtual method which
    creates and starts a MySqlAddressStatsQuery6

src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.h
src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc
    - GenericLeaseMgrTest::checkAddressStats4 renamed to checkAddressStats as
    it applies to either v4 or v6
    - GenericLeaseMgrTest::makeLease6() - new method which creates a minimal
    IPv6 lease and adds it to lease storage
    - GenericLeaseMgrTest::testRecountAddressStats6() - new method which
    checks IPv6 lease stats recounting

src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
    - TEST_F(MySqlLeaseMgrTest, recountAddressStats6) - new test
This commit is contained in:
Thomas Markwalder
2016-08-16 11:13:17 -04:00
parent 61bc7b004a
commit 6f56be5aa2
7 changed files with 377 additions and 34 deletions

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -206,8 +206,14 @@ TaggedStatement tagged_statements[] = {
"state = ? "
"WHERE address = ?"},
{MySqlLeaseMgr::RECOUNT_LEASE4_STATS,
"SELECT subnet_id, state, count(state) as state_count "
"FROM lease4 GROUP BY subnet_id, state ORDER BY subnet_id"},
"SELECT subnet_id, state, count(state) as state_count "
" FROM lease4 GROUP BY subnet_id, state ORDER BY subnet_id"},
{MySqlLeaseMgr::RECOUNT_LEASE6_STATS,
"SELECT subnet_id, lease_type, state, count(state) as state_count"
" FROM lease6 GROUP BY subnet_id, lease_type, state "
" ORDER BY subnet_id" },
// End of list sentinel
{MySqlLeaseMgr::NUM_STATEMENTS, NULL}
};
@@ -1353,9 +1359,154 @@ MySqlLeaseMgr::startAddressStatsQuery4() {
return(query);
}
/// @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);
/// @brief Destructor
virtual ~MySqlAddressStatsQuery6();
/// @brief Creates the IPv6 lease statistical data result set
///
/// The result set is populated by executing an SQL query against the
/// lease4 table which sums the leases per lease state 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();
/// @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(AddressStatsRow6& 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;
/// @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 type when fetching a row
uint32_t lease_type_;
/// @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_;
};
MySqlAddressStatsQuery6::MySqlAddressStatsQuery6(MySqlConnection& conn)
: conn_(conn), statement_(conn_.statements_[MySqlLeaseMgr
::RECOUNT_LEASE6_STATS]),
bind_(4) {
}
MySqlAddressStatsQuery6::~MySqlAddressStatsQuery6() {
(void) mysql_stmt_free_result(statement_);
}
void
MySqlAddressStatsQuery6::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;
// lease type: uint32_t
bind_[1].buffer_type = MYSQL_TYPE_LONG;
bind_[1].buffer = reinterpret_cast<char*>(&lease_type_);
bind_[1].is_unsigned = MLM_TRUE;
// state: uint32_t
bind_[2].buffer_type = MYSQL_TYPE_LONG;
bind_[2].buffer = reinterpret_cast<char*>(&lease_state_);
bind_[2].is_unsigned = MLM_TRUE;
// state_count_: uint32_t
bind_[3].buffer_type = MYSQL_TYPE_LONG;
bind_[3].buffer = reinterpret_cast<char*>(&state_count_);
bind_[3].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_LEASE6_STATS: outbound binding failed");
// Execute the statement
status = mysql_stmt_execute(statement_);
checkError(status, "RECOUNT_LEASE6_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_LEASE6_STATS: results storage setup failed");
}
bool
MySqlAddressStatsQuery6::getNextRow(AddressStatsRow6& 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_type_ = static_cast<Lease::Type>(lease_type_);
row.lease_state_ = static_cast<Lease::LeaseState>(lease_state_);
row.state_count_ = state_count_;
have_row = true;
} else if (status != MYSQL_NO_DATA) {
checkError(status, "RECOUNT_LEASE6_STATS: getNextRow failed");
}
return (have_row);
}
void
MySqlAddressStatsQuery6::checkError(int status, const char* what) const {
conn_.checkError(status, MySqlLeaseMgr::RECOUNT_LEASE6_STATS, what);
}
AddressStatsQuery6Ptr
MySqlLeaseMgr::startAddressStatsQuery6() {
AddressStatsQuery6Ptr query(new MySqlAddressStatsQuery6(conn_));
query->start();
return(query);
}
// MySqlLeaseMgr Constructor and Destructor