mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-01 14:35:29 +00:00
[4294] Memfile and MySql now support recalulating IPv4 lease statistics
src/lib/dhcpsrv/cfg_subnets4.cc CfgSubnets4::removeStatistics() - added removal of all lease statistics per subnet, and global declined address stats CfgSubnets4::updateStatistics() - added call to LeaseMgr::recountAddressStats4 src/lib/dhcpsrv/lease.cc src/lib/dhcpsrv/lease.h Replaces lease state constants with LeaseState enumeration. src/lib/dhcpsrv/lease_mgr.cc src/lib/dhcpsrv/lease_mgr.h struct AddressStatsRow4 - contains the content of one row of the IPv4 lease statistical data result set class AddressStatsQuery4 - base class for constructing the IPv4 lease statistical data result set for an IPv4 lease storage LeaseMgr::recountAddressStats4() - new method which recalculates per-subnet and global stats for IPv4 leases LeaseMgr::startAddressStatsQuery4() - new virtual method that fetches the IPv4 lease statistical data result set src/lib/dhcpsrv/lease_mgr_factory.h src/lib/dhcpsrv/lease_mgr_factory.cc LeaseMgrFactory::haveInstance() - new static method which indicates whether or not the lease manager singleton exists src/lib/dhcpsrv/memfile_lease_mgr.h src/lib/dhcpsrv/memfile_lease_mgr.cc MemfileAddressStatsQuery4 - Derivation of AddressStatsQuery4, it constructs the IPv4 lease statistical data by iterating over IPv4 lease storage Memfile_LeaseMgr::startAddressStatsQuery4() - new virtual method which creates, starts, and returns a MemfileAddressStatsQuery4 src/lib/dhcpsrv/memfile_lease_storage.h Added an a per subnet_ID index to IPv4 storage src/lib/dhcpsrv/mysql_lease_mgr.h src/lib/dhcpsrv/mysql_lease_mgr.cc - Added RECOUNT_LEASE4_STATS query MySqlAddressStatsQuery4 Derivation of AddressStatsQuery4, it constructs the IPv4 lease statistical data by executing RECOUNT_LEASE4_STATS MySqlLeaseMgr::startAddressStatsQuery4() - new virtual method which creates, starts, and returns a MySqlAddressStatsQuery4 src/lib/dhcpsrv/tests/alloc_engine_utils.cc AllocEngine6Test::AllocEngine6Test() AllocEngine4Test::AllocEngine4Test() - moved lease mgr create up above configuration commit src/lib/dhcpsrv/tests/cfg_db_access_unittest.cc ~CfgMySQLDbAccessTest() - added destruction of lease manager singleton, otherwise subsequent tests can fail src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.h src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc GenericLeaseMgrTest::checkStat() - new method for comparing a stat GenericLeaseMgrTest::checkAddressStats4() - new method for comparing a list of stats GenericLeaseMgrTest::makeLease4() - new method for making a minimal lease GenericLeaseMgrTest::testRecountAddressStats4() - new method which tests a lease manager's ability to recalculate the IPv4 lease statistics src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc TEST_F(MemfileLeaseMgrTest, recountAddressStats4) - new test which tests Memfile_LeaseMgr's ability to recalculate IPv4 lease statistics src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc TEST_F(MySqlLeaseMgrTest, recountAddressStats4) - new test which tests MySqlLeaseMgr's ability to recalculate IPv4 lease statistics
This commit is contained in:
@@ -205,6 +205,9 @@ TaggedStatement tagged_statements[] = {
|
||||
"hostname = ?, hwaddr = ?, hwtype = ?, hwaddr_source = ?, "
|
||||
"state = ? "
|
||||
"WHERE address = ?"},
|
||||
{MySqlLeaseMgr::RECOUNT_LEASE4_STATS,
|
||||
"SELECT subnet_id, state, count(state) as state_count "
|
||||
"FROM lease4 group by subnet_id, state"},
|
||||
// End of list sentinel
|
||||
{MySqlLeaseMgr::NUM_STATEMENTS, NULL}
|
||||
};
|
||||
@@ -1214,6 +1217,143 @@ private:
|
||||
uint32_t state_; ///< Lease state.
|
||||
};
|
||||
|
||||
/// @brief MySql derivation of the IPv4 statistical lease data query
|
||||
///
|
||||
/// This class is used to recalculate IPv4 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 MySqlAddressStatsQuery4 : public AddressStatsQuery4 {
|
||||
public:
|
||||
/// @brief Constructor
|
||||
///
|
||||
/// @param conn A open connection to the database housing the lease data
|
||||
MySqlAddressStatsQuery4(MySqlConnection& conn);
|
||||
|
||||
/// @brief Destructor
|
||||
virtual ~MySqlAddressStatsQuery4();
|
||||
|
||||
/// @brief Creates the IPv4 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_LEASE4_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(AddressStatsRow4& 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 Member struct that is bound to the statement;
|
||||
AddressStatsRow4 stat_row_;
|
||||
};
|
||||
|
||||
MySqlAddressStatsQuery4::MySqlAddressStatsQuery4(MySqlConnection& conn)
|
||||
: conn_(conn), statement_(conn_.statements_[MySqlLeaseMgr
|
||||
::RECOUNT_LEASE4_STATS]),
|
||||
bind_(3) {
|
||||
}
|
||||
|
||||
MySqlAddressStatsQuery4::~MySqlAddressStatsQuery4() {
|
||||
(void) mysql_stmt_free_result(statement_);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MySqlAddressStatsQuery4::start() {
|
||||
// subnet_id: unsigned int
|
||||
bind_[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind_[0].buffer = reinterpret_cast<char*>(&stat_row_.subnet_id_);
|
||||
bind_[0].is_unsigned = MLM_TRUE;
|
||||
|
||||
// state: uint32_t
|
||||
bind_[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind_[1].buffer = reinterpret_cast<char*>(&stat_row_.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*>(&stat_row_.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 setup failed");
|
||||
}
|
||||
|
||||
bool
|
||||
MySqlAddressStatsQuery4::getNextRow(AddressStatsRow4& row) {
|
||||
bool have_row = false;
|
||||
int status = mysql_stmt_fetch(statement_);
|
||||
if (status == MLM_MYSQL_FETCH_SUCCESS) {
|
||||
row = stat_row_;
|
||||
have_row = true;
|
||||
} else if (status != MYSQL_NO_DATA) {
|
||||
checkError(status, "RECOUNT_LEASE4_STATS: getNextRow failed");
|
||||
}
|
||||
|
||||
return (have_row);
|
||||
}
|
||||
|
||||
void
|
||||
MySqlAddressStatsQuery4::checkError(int status, const char* what) const {
|
||||
conn_.checkError(status, MySqlLeaseMgr::RECOUNT_LEASE4_STATS, what);
|
||||
}
|
||||
|
||||
AddressStatsQuery4Ptr
|
||||
MySqlLeaseMgr::startAddressStatsQuery4() {
|
||||
AddressStatsQuery4Ptr query(new MySqlAddressStatsQuery4(conn_));
|
||||
query->start();
|
||||
return(query);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2025,7 +2165,6 @@ MySqlLeaseMgr::getVersion() const {
|
||||
return (std::make_pair(major, minor));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MySqlLeaseMgr::commit() {
|
||||
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_COMMIT);
|
||||
|
Reference in New Issue
Block a user