mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 14:05:33 +00:00
[4294] PostgreSQL now supports IPv6 lease stats recounting
src/lib/dhcpsrv/pgsql_lease_mgr.h src/lib/dhcpsrv/pgsql_lease_mgr.cc - Added TaggedStatement RECOUNT_LEASE6_STATS - PgSqlAddressStatsQuery6 - new class PgSql derivation of the IPv6 statistical lease data query - PgSqlLeaseMgr::startAddressStatsQuery6() - new virtual method which creates and runs the IPv6 lease stats query src/lib/dhcpsrv/tests/pgsql_lease_mgr_unittest.cc TEST_F(PgSqlLeaseMgrTest, recountAddressStats6) - new test
This commit is contained in:
@@ -1379,8 +1379,8 @@ public:
|
|||||||
/// @brief Creates the IPv6 lease statistical data result set
|
/// @brief Creates the IPv6 lease statistical data result set
|
||||||
///
|
///
|
||||||
/// The result set is populated by executing an SQL query against the
|
/// The result set is populated by executing an SQL query against the
|
||||||
/// lease4 table which sums the leases per lease state per subnet id.
|
/// lease6 table which sums the leases per lease state per lease type
|
||||||
/// The query used is the prepared statement identified by
|
/// per subnet id. The query used is the prepared statement identified by
|
||||||
/// MySqlLeaseMgr::RECOUNT_LEASE6_STATS. This method creates the binds
|
/// MySqlLeaseMgr::RECOUNT_LEASE6_STATS. This method creates the binds
|
||||||
/// the statement to the output bind array and then executes the
|
/// the statement to the output bind array and then executes the
|
||||||
/// statement.
|
/// statement.
|
||||||
|
@@ -207,6 +207,13 @@ PgSqlTaggedStatement tagged_statements[] = {
|
|||||||
"SELECT subnet_id, state, count(state) as state_count "
|
"SELECT subnet_id, state, count(state) as state_count "
|
||||||
"FROM lease4 GROUP BY subnet_id, state ORDER BY subnet_id"},
|
"FROM lease4 GROUP BY subnet_id, state ORDER BY subnet_id"},
|
||||||
|
|
||||||
|
// RECOUNT_LEASE6_STATS,
|
||||||
|
{ 0, { OID_NONE },
|
||||||
|
"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
|
// End of list sentinel
|
||||||
{ 0, { 0 }, NULL, NULL}
|
{ 0, { 0 }, NULL, NULL}
|
||||||
};
|
};
|
||||||
@@ -778,16 +785,19 @@ PgSqlAddressStatsQuery4::getNextRow(AddressStatsRow4& row) {
|
|||||||
// Fetch the subnet id.
|
// Fetch the subnet id.
|
||||||
uint32_t col = 0;
|
uint32_t col = 0;
|
||||||
uint32_t subnet_id;
|
uint32_t subnet_id;
|
||||||
PgSqlExchange::getColumnValue(*result_set_, next_row_, 0, subnet_id);
|
PgSqlExchange::getColumnValue(*result_set_, next_row_, col, subnet_id);
|
||||||
row.subnet_id_ = static_cast<SubnetID>(subnet_id);
|
row.subnet_id_ = static_cast<SubnetID>(subnet_id);
|
||||||
|
++col;
|
||||||
|
|
||||||
// Fetch the lease state.
|
// Fetch the lease state.
|
||||||
uint32_t state;
|
uint32_t state;
|
||||||
PgSqlExchange::getColumnValue(*result_set_, next_row_ , 1, state);
|
PgSqlExchange::getColumnValue(*result_set_, next_row_ , col, state);
|
||||||
row.lease_state_ = static_cast<Lease::LeaseState>(state);
|
row.lease_state_ = static_cast<Lease::LeaseState>(state);
|
||||||
|
++col;
|
||||||
|
|
||||||
// Fetch the state count.
|
// Fetch the state count.
|
||||||
PgSqlExchange::getColumnValue(*result_set_, next_row_, 2, row.state_count_);
|
PgSqlExchange::getColumnValue(*result_set_, next_row_, col,
|
||||||
|
row.state_count_);
|
||||||
|
|
||||||
// Point to the next row.
|
// Point to the next row.
|
||||||
++next_row_;
|
++next_row_;
|
||||||
@@ -802,6 +812,128 @@ PgSqlLeaseMgr::startAddressStatsQuery4() {
|
|||||||
return(query);
|
return(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief PgSql 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 PgSqlAddressStatsQuery6 : public AddressStatsQuery6 {
|
||||||
|
public:
|
||||||
|
/// @brief Constructor
|
||||||
|
///
|
||||||
|
/// @param conn A open connection to the database housing the lease data
|
||||||
|
PgSqlAddressStatsQuery6(PgSqlConnection& conn);
|
||||||
|
|
||||||
|
/// @brief Destructor
|
||||||
|
virtual ~PgSqlAddressStatsQuery6() {};
|
||||||
|
|
||||||
|
/// @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
|
||||||
|
/// PgSqlLeaseMgr::RECOUNT_LEASE6_STATS. This method executes the
|
||||||
|
/// statement which creates the result set.
|
||||||
|
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 PgSqlConnection: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
|
||||||
|
PgSqlConnection& conn_;
|
||||||
|
|
||||||
|
/// @brief The query's prepared statement
|
||||||
|
PgSqlTaggedStatement& statement_;
|
||||||
|
|
||||||
|
/// @brief The result set returned by Postgres.
|
||||||
|
boost::shared_ptr<PgSqlResult> result_set_;
|
||||||
|
|
||||||
|
/// @brief Index of the next row to fetch
|
||||||
|
uint32_t next_row_;
|
||||||
|
};
|
||||||
|
|
||||||
|
PgSqlAddressStatsQuery6::PgSqlAddressStatsQuery6(PgSqlConnection& conn)
|
||||||
|
: conn_(conn), statement_(tagged_statements[PgSqlLeaseMgr
|
||||||
|
::RECOUNT_LEASE6_STATS]),
|
||||||
|
result_set_(), next_row_(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PgSqlAddressStatsQuery6::start() {
|
||||||
|
// The query has no parameters, so we only need it's name.
|
||||||
|
result_set_.reset(new PgSqlResult(PQexecPrepared(conn_, statement_.name,
|
||||||
|
0, NULL, NULL, NULL, 0)));
|
||||||
|
|
||||||
|
conn_.checkStatementError(*result_set_, statement_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PgSqlAddressStatsQuery6::getNextRow(AddressStatsRow6& row) {
|
||||||
|
// If we're past the end, punt.
|
||||||
|
if (next_row_ >= result_set_->getRows()) {
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the subnet id.
|
||||||
|
uint32_t col = 0;
|
||||||
|
uint32_t subnet_id;
|
||||||
|
PgSqlExchange::getColumnValue(*result_set_, next_row_, col, subnet_id);
|
||||||
|
row.subnet_id_ = static_cast<SubnetID>(subnet_id);
|
||||||
|
++col;
|
||||||
|
|
||||||
|
// Fetch the lease type.
|
||||||
|
uint32_t lease_type;
|
||||||
|
PgSqlExchange::getColumnValue(*result_set_, next_row_ , col, lease_type);
|
||||||
|
row.lease_type_ = static_cast<Lease::Type>(lease_type);
|
||||||
|
++col;
|
||||||
|
|
||||||
|
// Fetch the lease state.
|
||||||
|
uint32_t state;
|
||||||
|
PgSqlExchange::getColumnValue(*result_set_, next_row_ , col, state);
|
||||||
|
row.lease_state_ = static_cast<Lease::LeaseState>(state);
|
||||||
|
++col;
|
||||||
|
|
||||||
|
// Fetch the state count.
|
||||||
|
PgSqlExchange::getColumnValue(*result_set_, next_row_, col, row.state_count_);
|
||||||
|
|
||||||
|
// Point to the next row.
|
||||||
|
++next_row_;
|
||||||
|
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressStatsQuery6Ptr
|
||||||
|
PgSqlLeaseMgr::startAddressStatsQuery6() {
|
||||||
|
AddressStatsQuery6Ptr query(new PgSqlAddressStatsQuery6(conn_));
|
||||||
|
query->start();
|
||||||
|
return(query);
|
||||||
|
}
|
||||||
|
|
||||||
PgSqlLeaseMgr::PgSqlLeaseMgr(const DatabaseConnection::ParameterMap& parameters)
|
PgSqlLeaseMgr::PgSqlLeaseMgr(const DatabaseConnection::ParameterMap& parameters)
|
||||||
: LeaseMgr(), exchange4_(new PgSqlLease4Exchange()),
|
: LeaseMgr(), exchange4_(new PgSqlLease4Exchange()),
|
||||||
|
@@ -327,6 +327,16 @@ public:
|
|||||||
/// @return The populated query as a pointer to an AddressStatsQuery4
|
/// @return The populated query as a pointer to an AddressStatsQuery4
|
||||||
virtual AddressStatsQuery4Ptr startAddressStatsQuery4();
|
virtual AddressStatsQuery4Ptr startAddressStatsQuery4();
|
||||||
|
|
||||||
|
/// @brief Creates and runs the IPv6 lease stats query
|
||||||
|
///
|
||||||
|
/// It creates an instance of a PgSqlAddressStatsQuery6 and then
|
||||||
|
/// invokes its start method, which fetches its statistical data
|
||||||
|
/// result set by executing the RECOUNT_LEASE_STATS6 query.
|
||||||
|
/// The query object is then returned.
|
||||||
|
///
|
||||||
|
/// @return The populated query as a pointer to an AddressStatsQuery6
|
||||||
|
virtual AddressStatsQuery6Ptr startAddressStatsQuery6();
|
||||||
|
|
||||||
/// @brief Return backend type
|
/// @brief Return backend type
|
||||||
///
|
///
|
||||||
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
|
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
|
||||||
@@ -396,6 +406,7 @@ public:
|
|||||||
UPDATE_LEASE4, // Update a Lease4 entry
|
UPDATE_LEASE4, // Update a Lease4 entry
|
||||||
UPDATE_LEASE6, // Update a Lease6 entry
|
UPDATE_LEASE6, // Update a Lease6 entry
|
||||||
RECOUNT_LEASE4_STATS, // Fetch IPv4 lease statistical data
|
RECOUNT_LEASE4_STATS, // Fetch IPv4 lease statistical data
|
||||||
|
RECOUNT_LEASE6_STATS, // Fetch IPv4 lease statistical data
|
||||||
NUM_STATEMENTS // Number of statements
|
NUM_STATEMENTS // Number of statements
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -407,5 +407,9 @@ TEST_F(PgSqlLeaseMgrTest, recountAddressStats4) {
|
|||||||
testRecountAddressStats4();
|
testRecountAddressStats4();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verifies that IPv6 lease statistics can be recalculated.
|
||||||
|
TEST_F(PgSqlLeaseMgrTest, recountAddressStats6) {
|
||||||
|
testRecountAddressStats6();
|
||||||
|
}
|
||||||
|
|
||||||
}; // namespace
|
}; // namespace
|
||||||
|
Reference in New Issue
Block a user