2
0
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:
Thomas Markwalder
2016-08-12 14:02:35 -04:00
parent 901a83c6b3
commit a8f85f2508
19 changed files with 773 additions and 40 deletions

View File

@@ -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);