From: Razvan Becheriu Date: Mon, 6 May 2019 10:06:46 +0000 (+0300) Subject: use as few calls to handle function as possible X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f9c73739516e450453139341cb316a3743168f4c;p=thirdparty%2Fkea.git use as few calls to handle function as possible --- diff --git a/src/lib/dhcpsrv/mysql_host_data_source.cc b/src/lib/dhcpsrv/mysql_host_data_source.cc index 0c263ec54b..71e4c6defb 100644 --- a/src/lib/dhcpsrv/mysql_host_data_source.cc +++ b/src/lib/dhcpsrv/mysql_host_data_source.cc @@ -2462,11 +2462,13 @@ MySqlHostDataSourceImpl::getVersion() const { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_HOST_DB_GET_VERSION); + MySqlHolder& holderHandle = conn_.handle(); + // Allocate a new statement. - MYSQL_STMT *stmt = mysql_stmt_init(conn_.handle()); + MYSQL_STMT *stmt = mysql_stmt_init(holderHandle); if (stmt == NULL) { isc_throw(DbOperationError, "unable to allocate MySQL prepared " - "statement structure, reason: " << mysql_error(conn_.handle())); + "statement structure, reason: " << mysql_error(holderHandle)); } // Prepare the statement from SQL text. @@ -2475,14 +2477,14 @@ MySqlHostDataSourceImpl::getVersion() const { if (status != 0) { mysql_stmt_close(stmt); isc_throw(DbOperationError, "unable to prepare MySQL statement <" - << version_sql << ">, reason: " << mysql_error(conn_.handle())); + << version_sql << ">, reason: " << mysql_error(holderHandle)); } // Execute the prepared statement. if (mysql_stmt_execute(stmt) != 0) { mysql_stmt_close(stmt); isc_throw(DbOperationError, "cannot execute schema version query <" - << version_sql << ">, reason: " << mysql_error(conn_.handle())); + << version_sql << ">, reason: " << mysql_error(holderHandle)); } // Bind the output of the statement to the appropriate variables. @@ -2503,14 +2505,14 @@ MySqlHostDataSourceImpl::getVersion() const { if (mysql_stmt_bind_result(stmt, bind)) { isc_throw(DbOperationError, "unable to bind result set for <" - << version_sql << ">, reason: " << mysql_error(conn_.handle())); + << version_sql << ">, reason: " << mysql_error(holderHandle)); } // Fetch the data. if (mysql_stmt_fetch(stmt)) { mysql_stmt_close(stmt); isc_throw(DbOperationError, "unable to bind result set for <" - << version_sql << ">, reason: " << mysql_error(conn_.handle())); + << version_sql << ">, reason: " << mysql_error(holderHandle)); } // Discard the statement and its resources @@ -2522,17 +2524,18 @@ MySqlHostDataSourceImpl::getVersion() const { void MySqlHostDataSourceImpl::addStatement(StatementIndex stindex, std::vector& bind) { + MySqlHolder& holderHandle = conn_.handle(); // Bind the parameters to the statement - int status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], &bind[0]); + int status = mysql_stmt_bind_param(holderHandle.statements_[stindex], &bind[0]); checkError(status, stindex, "unable to bind parameters"); // Execute the statement - status = mysql_stmt_execute(conn_.handle().statements_[stindex]); + status = mysql_stmt_execute(holderHandle.statements_[stindex]); if (status != 0) { // Failure: check for the special case of duplicate entry. - if (mysql_errno(conn_.handle()) == ER_DUP_ENTRY) { + if (mysql_errno(holderHandle) == ER_DUP_ENTRY) { isc_throw(DuplicateEntry, "Database duplicate entry error"); } checkError(status, stindex, "unable to execute"); @@ -2542,19 +2545,21 @@ MySqlHostDataSourceImpl::addStatement(StatementIndex stindex, bool MySqlHostDataSourceImpl::delStatement(StatementIndex stindex, MYSQL_BIND* bind) { + MySqlHolder& holderHandle = conn_.handle(); + // Bind the parameters to the statement - int status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], &bind[0]); + int status = mysql_stmt_bind_param(holderHandle.statements_[stindex], &bind[0]); checkError(status, stindex, "unable to bind parameters"); // Execute the statement - status = mysql_stmt_execute(conn_.handle().statements_[stindex]); + status = mysql_stmt_execute(holderHandle.statements_[stindex]); if (status != 0) { checkError(status, stindex, "unable to execute"); } // Let's check how many hosts were deleted. - my_ulonglong numrows = mysql_stmt_affected_rows(conn_.handle().statements_[stindex]); + my_ulonglong numrows = mysql_stmt_affected_rows(holderHandle.statements_[stindex]); return (numrows != 0); } @@ -2623,32 +2628,33 @@ MySqlHostDataSourceImpl:: getHostCollection(StatementIndex stindex, MYSQL_BIND* bind, boost::shared_ptr exchange, ConstHostCollection& result, bool single) const { + MySqlHolder& holderHandle = conn_.handle(); // Bind the selection parameters to the statement - int status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], bind); + int status = mysql_stmt_bind_param(holderHandle.statements_[stindex], bind); checkError(status, stindex, "unable to bind WHERE clause parameter"); // Set up the MYSQL_BIND array for the data being returned and bind it to // the statement. std::vector outbind = exchange->createBindForReceive(); - status = mysql_stmt_bind_result(conn_.handle().statements_[stindex], &outbind[0]); + status = mysql_stmt_bind_result(holderHandle.statements_[stindex], &outbind[0]); checkError(status, stindex, "unable to bind SELECT clause parameters"); // Execute the statement - status = mysql_stmt_execute(conn_.handle().statements_[stindex]); + status = mysql_stmt_execute(holderHandle.statements_[stindex]); checkError(status, stindex, "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(conn_.handle().statements_[stindex]); + status = mysql_stmt_store_result(holderHandle.statements_[stindex]); checkError(status, stindex, "unable to set up for storing all results"); // Set up the fetch "release" object to release resources associated // with the call to mysql_stmt_fetch when this method exits, then // retrieve the data. mysql_stmt_fetch return value equal to 0 represents // successful data fetch. - MySqlFreeResult fetch_release(conn_.handle().statements_[stindex]); - while ((status = mysql_stmt_fetch(conn_.handle().statements_[stindex])) == + MySqlFreeResult fetch_release(holderHandle.statements_[stindex]); + while ((status = mysql_stmt_fetch(holderHandle.statements_[stindex])) == MLM_MYSQL_FETCH_SUCCESS) { try { exchange->processFetchedData(result); @@ -2744,6 +2750,8 @@ MySqlHostDataSource::~MySqlHostDataSource() { void MySqlHostDataSource::add(const HostPtr& host) { + MySqlHolder& holderHandle = impl_->conn_.handle(); + // If operating in read-only mode, throw exception. impl_->checkReadOnly(); @@ -2763,7 +2771,7 @@ MySqlHostDataSource::add(const HostPtr& host) { impl_->addStatement(MySqlHostDataSourceImpl::INSERT_HOST, bind); // Gets the last inserted hosts id - uint64_t host_id = mysql_insert_id(impl_->conn_.handle()); + uint64_t host_id = mysql_insert_id(holderHandle); // Insert DHCPv4 options. ConstCfgOptionPtr cfg_option4 = host->getCfgOption4(); diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.cc b/src/lib/dhcpsrv/mysql_lease_mgr.cc index 34ecd73b83..38e6fb8d97 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.cc +++ b/src/lib/dhcpsrv/mysql_lease_mgr.cc @@ -1633,12 +1633,14 @@ private: /// Safely fetch the statement from the connection based on statement index /// @throw BadValue if statement index is out of range void validateStatement() { + MySqlHolder& holderHandle = conn_.handle(); + if (statement_index_ >= MySqlLeaseMgr::NUM_STATEMENTS) { isc_throw(BadValue, "MySqlLeaseStatsQuery" " - invalid statement index" << statement_index_); } - statement_ = conn_.handle().statements_[statement_index_]; + statement_ = holderHandle.statements_[statement_index_]; } /// @brief Database connection to use to execute the query @@ -1710,19 +1712,20 @@ MySqlLeaseMgr::getDBVersion() { bool MySqlLeaseMgr::addLeaseCommon(StatementIndex stindex, std::vector& bind) { + MySqlHolder& holderHandle = conn_.handle(); // Bind the parameters to the statement - int status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], &bind[0]); + int status = mysql_stmt_bind_param(holderHandle.statements_[stindex], &bind[0]); checkError(status, stindex, "unable to bind parameters"); // Execute the statement - status = mysql_stmt_execute(conn_.handle().statements_[stindex]); + status = mysql_stmt_execute(holderHandle.statements_[stindex]); if (status != 0) { // Failure: check for the special case of duplicate entry. If this is // the case, we return false to indicate that the row was not added. // Otherwise we throw an exception. - if (mysql_errno(conn_.handle()) == ER_DUP_ENTRY) { + if (mysql_errno(holderHandle) == ER_DUP_ENTRY) { return (false); } checkError(status, stindex, "unable to execute"); @@ -1792,36 +1795,36 @@ void MySqlLeaseMgr::getLeaseCollection(StatementIndex stindex, Exchange& exchange, LeaseCollection& result, bool single) const { - + MySqlHolder& holderHandle = conn_.handle(); int status; if (bind) { // Bind the selection parameters to the statement - status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], bind); + status = mysql_stmt_bind_param(holderHandle.statements_[stindex], bind); checkError(status, stindex, "unable to bind WHERE clause parameter"); } // Set up the MYSQL_BIND array for the data being returned and bind it to // the statement. std::vector outbind = exchange->createBindForReceive(); - status = mysql_stmt_bind_result(conn_.handle().statements_[stindex], &outbind[0]); + status = mysql_stmt_bind_result(holderHandle.statements_[stindex], &outbind[0]); checkError(status, stindex, "unable to bind SELECT clause parameters"); // Execute the statement - status = mysql_stmt_execute(conn_.handle().statements_[stindex]); + status = mysql_stmt_execute(holderHandle.statements_[stindex]); checkError(status, stindex, "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(conn_.handle().statements_[stindex]); + status = mysql_stmt_store_result(holderHandle.statements_[stindex]); checkError(status, stindex, "unable to set up for storing all results"); // Set up the fetch "release" object to release resources associated // with the call to mysql_stmt_fetch when this method exits, then // retrieve the data. - MySqlFreeResult fetch_release(conn_.handle().statements_[stindex]); + MySqlFreeResult fetch_release(holderHandle.statements_[stindex]); int count = 0; - while ((status = mysql_stmt_fetch(conn_.handle().statements_[stindex])) == 0) { + while ((status = mysql_stmt_fetch(holderHandle.statements_[stindex])) == 0) { try { result.push_back(exchange->getLeaseData()); @@ -2442,18 +2445,19 @@ template void MySqlLeaseMgr::updateLeaseCommon(StatementIndex stindex, MYSQL_BIND* bind, const LeasePtr& lease) { + MySqlHolder& holderHandle = conn_.handle(); // Bind the parameters to the statement - int status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], bind); + int status = mysql_stmt_bind_param(holderHandle.statements_[stindex], bind); checkError(status, stindex, "unable to bind parameters"); // Execute - status = mysql_stmt_execute(conn_.handle().statements_[stindex]); + status = mysql_stmt_execute(holderHandle.statements_[stindex]); checkError(status, stindex, "unable to execute"); // See how many rows were affected. The statement should only update a // single row. - int affected_rows = mysql_stmt_affected_rows(conn_.handle().statements_[stindex]); + int affected_rows = mysql_stmt_affected_rows(holderHandle.statements_[stindex]); if (affected_rows == 0) { isc_throw(NoSuchLease, "unable to update lease for address " << lease->addr_ << " as it does not exist"); @@ -2530,18 +2534,19 @@ MySqlLeaseMgr::updateLease6(const Lease6Ptr& lease) { uint64_t MySqlLeaseMgr::deleteLeaseCommon(StatementIndex stindex, MYSQL_BIND* bind) { + MySqlHolder& holderHandle = conn_.handle(); // Bind the input parameters to the statement - int status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], bind); + int status = mysql_stmt_bind_param(holderHandle.statements_[stindex], bind); checkError(status, stindex, "unable to bind WHERE clause parameter"); // Execute - status = mysql_stmt_execute(conn_.handle().statements_[stindex]); + status = mysql_stmt_execute(holderHandle.statements_[stindex]); checkError(status, stindex, "unable to execute"); // See how many rows were affected. Note that the statement may delete // multiple rows. - return (static_cast(mysql_stmt_affected_rows(conn_.handle().statements_[stindex]))); + return (static_cast(mysql_stmt_affected_rows(holderHandle.statements_[stindex]))); } bool @@ -2715,11 +2720,13 @@ MySqlLeaseMgr::getVersion() const { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_GET_VERSION); + MySqlHolder& holderHandle = conn_.handle(); + // Allocate a new statement. - MYSQL_STMT *stmt = mysql_stmt_init(conn_.handle()); + MYSQL_STMT *stmt = mysql_stmt_init(holderHandle); if (stmt == NULL) { isc_throw(DbOperationError, "unable to allocate MySQL prepared " - "statement structure, reason: " << mysql_error(conn_.handle())); + "statement structure, reason: " << mysql_error(holderHandle)); } // Prepare the statement from SQL text. @@ -2728,14 +2735,14 @@ MySqlLeaseMgr::getVersion() const { if (status != 0) { mysql_stmt_close(stmt); isc_throw(DbOperationError, "unable to prepare MySQL statement <" - << version_sql << ">, reason: " << mysql_error(conn_.handle())); + << version_sql << ">, reason: " << mysql_error(holderHandle)); } // Execute the prepared statement. if (mysql_stmt_execute(stmt) != 0) { mysql_stmt_close(stmt); isc_throw(DbOperationError, "cannot execute schema version query <" - << version_sql << ">, reason: " << mysql_error(conn_.handle())); + << version_sql << ">, reason: " << mysql_error(holderHandle)); } // Bind the output of the statement to the appropriate variables. @@ -2756,14 +2763,14 @@ MySqlLeaseMgr::getVersion() const { if (mysql_stmt_bind_result(stmt, bind)) { isc_throw(DbOperationError, "unable to bind result set for <" - << version_sql << ">, reason: " << mysql_error(conn_.handle())); + << version_sql << ">, reason: " << mysql_error(holderHandle)); } // Fetch the data. if (mysql_stmt_fetch(stmt)) { mysql_stmt_close(stmt); isc_throw(DbOperationError, "unable to bind result set for <" - << version_sql << ">, reason: " << mysql_error(conn_.handle())); + << version_sql << ">, reason: " << mysql_error(holderHandle)); } // Discard the statement and its resources @@ -2775,16 +2782,22 @@ MySqlLeaseMgr::getVersion() const { void MySqlLeaseMgr::commit() { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_COMMIT); - if (mysql_commit(conn_.handle()) != 0) { - isc_throw(DbOperationError, "commit failed: " << mysql_error(conn_.handle())); + + MySqlHolder& holderHandle = conn_.handle(); + + if (mysql_commit(holderHandle) != 0) { + isc_throw(DbOperationError, "commit failed: " << mysql_error(holderHandle)); } } void MySqlLeaseMgr::rollback() { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_ROLLBACK); - if (mysql_rollback(conn_.handle()) != 0) { - isc_throw(DbOperationError, "rollback failed: " << mysql_error(conn_.handle())); + + MySqlHolder& holderHandle = conn_.handle(); + + if (mysql_rollback(holderHandle) != 0) { + isc_throw(DbOperationError, "rollback failed: " << mysql_error(holderHandle)); } } diff --git a/src/lib/dhcpsrv/pgsql_host_data_source.cc b/src/lib/dhcpsrv/pgsql_host_data_source.cc index 9cf7f7756b..1a51b345c8 100644 --- a/src/lib/dhcpsrv/pgsql_host_data_source.cc +++ b/src/lib/dhcpsrv/pgsql_host_data_source.cc @@ -1847,8 +1847,10 @@ uint64_t PgSqlHostDataSourceImpl::addStatement(StatementIndex stindex, PsqlBindArrayPtr& bind_array, const bool return_last_id) { + PgSqlHolder& holderHandle = conn_.handle(); uint64_t last_id = 0; - PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name, + + PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name, tagged_statements[stindex].nbparams, &bind_array->values_[0], &bind_array->lengths_[0], @@ -1877,7 +1879,9 @@ PgSqlHostDataSourceImpl::addStatement(StatementIndex stindex, bool PgSqlHostDataSourceImpl::delStatement(StatementIndex stindex, PsqlBindArrayPtr& bind_array) { - PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name, + PgSqlHolder& holderHandle = conn_.handle(); + + PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name, tagged_statements[stindex].nbparams, &bind_array->values_[0], &bind_array->lengths_[0], @@ -1958,9 +1962,10 @@ PgSqlHostDataSourceImpl:: getHostCollection(StatementIndex stindex, PsqlBindArrayPtr bind_array, boost::shared_ptr exchange, ConstHostCollection& result, bool single) const { + PgSqlHolder& holderHandle = conn_.handle(); exchange->clear(); - PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name, + PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name, tagged_statements[stindex].nbparams, &bind_array->values_[0], &bind_array->lengths_[0], @@ -2018,11 +2023,13 @@ PgSqlHostDataSourceImpl::getVersion() const { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_PGSQL_HOST_DB_GET_VERSION); + PgSqlHolder& holderHandle = conn_.handle(); const char* version_sql = "SELECT version, minor FROM schema_version;"; - PgSqlResult r(PQexec(conn_.handle(), version_sql)); + + PgSqlResult r(PQexec(holderHandle, version_sql)); if(PQresultStatus(r) != PGRES_TUPLES_OK) { isc_throw(DbOperationError, "unable to execute PostgreSQL statement <" - << version_sql << ">, reason: " << PQerrorMessage(conn_.handle())); + << version_sql << ">, reason: " << PQerrorMessage(holderHandle)); } uint32_t major; diff --git a/src/lib/dhcpsrv/pgsql_lease_mgr.cc b/src/lib/dhcpsrv/pgsql_lease_mgr.cc index 573e503027..691f867ed8 100644 --- a/src/lib/dhcpsrv/pgsql_lease_mgr.cc +++ b/src/lib/dhcpsrv/pgsql_lease_mgr.cc @@ -986,10 +986,11 @@ public: /// parameters (for all subnets), a subnet id for a single subnet, or /// a first and last subnet id for a subnet range. void start() { + PgSqlHolder& holderHandle = conn_.handle(); if (getSelectMode() == ALL_SUBNETS) { // Run the query with no where clause parameters. - result_set_.reset(new PgSqlResult(PQexecPrepared(conn_.handle(), statement_.name, + result_set_.reset(new PgSqlResult(PQexecPrepared(holderHandle, statement_.name, 0, 0, 0, 0, 0))); } else { // Set up the WHERE clause values @@ -1007,7 +1008,7 @@ public: } // Run the query with where clause parameters. - result_set_.reset(new PgSqlResult(PQexecPrepared(conn_.handle(), statement_.name, + result_set_.reset(new PgSqlResult(PQexecPrepared(holderHandle, statement_.name, parms.size(), &parms.values_[0], &parms.lengths_[0], &parms.formats_[0], 0))); } @@ -1125,7 +1126,9 @@ PgSqlLeaseMgr::getDBVersion() { bool PgSqlLeaseMgr::addLeaseCommon(StatementIndex stindex, PsqlBindArray& bind_array) { - PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name, + PgSqlHolder& holderHandle = conn_.handle(); + + PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name, tagged_statements[stindex].nbparams, &bind_array.values_[0], &bind_array.lengths_[0], @@ -1177,8 +1180,10 @@ void PgSqlLeaseMgr::getLeaseCollection(StatementIndex stindex, Exchange& exchange, LeaseCollection& result, bool single) const { + PgSqlHolder& holderHandle = conn_.handle(); const int n = tagged_statements[stindex].nbparams; - PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name, n, + + PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name, n, n > 0 ? &bind_array.values_[0] : NULL, n > 0 ? &bind_array.lengths_[0] : NULL, n > 0 ? &bind_array.formats_[0] : NULL, 0)); @@ -1663,7 +1668,9 @@ PgSqlLeaseMgr::updateLeaseCommon(StatementIndex stindex, LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_PGSQL_ADD_ADDR4).arg(tagged_statements[stindex].name); - PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name, + PgSqlHolder& holderHandle = conn_.handle(); + + PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name, tagged_statements[stindex].nbparams, &bind_array.values_[0], &bind_array.lengths_[0], @@ -1735,7 +1742,9 @@ PgSqlLeaseMgr::updateLease6(const Lease6Ptr& lease) { uint64_t PgSqlLeaseMgr::deleteLeaseCommon(StatementIndex stindex, PsqlBindArray& bind_array) { - PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name, + PgSqlHolder& holderHandle = conn_.handle(); + + PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name, tagged_statements[stindex].nbparams, &bind_array.values_[0], &bind_array.lengths_[0], @@ -1886,11 +1895,13 @@ PgSqlLeaseMgr::getVersion() const { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_PGSQL_GET_VERSION); + PgSqlHolder& holderHandle = conn_.handle(); const char* version_sql = "SELECT version, minor FROM schema_version;"; - PgSqlResult r(PQexec(conn_.handle(), version_sql)); + + PgSqlResult r(PQexec(holderHandle, version_sql)); if(PQresultStatus(r) != PGRES_TUPLES_OK) { isc_throw(DbOperationError, "unable to execute PostgreSQL statement <" - << version_sql << ">, reason: " << PQerrorMessage(conn_.handle())); + << version_sql << ">, reason: " << PQerrorMessage(holderHandle)); } uint32_t major; diff --git a/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc b/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc index fc75ec707f..73f5faecd6 100644 --- a/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc +++ b/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc @@ -120,12 +120,14 @@ public: MySqlConnection conn(params); conn.openDatabase(); - int status = mysql_query(conn.handle(), query.c_str()); + MySqlHolder& holderHandle = conn.handle(); + + int status = mysql_query(holderHandle, query.c_str()); if (status !=0) { - isc_throw(DbOperationError, "Query failed: " << mysql_error(conn.handle())); + isc_throw(DbOperationError, "Query failed: " << mysql_error(holderHandle)); } - MYSQL_RES * res = mysql_store_result(conn.handle()); + MYSQL_RES * res = mysql_store_result(holderHandle); int numrows = static_cast(mysql_num_rows(res)); mysql_free_result(res); @@ -641,9 +643,10 @@ TEST_F(MySqlHostDataSourceTest, testAddRollback) { MySqlConnection conn(params); ASSERT_NO_THROW(conn.openDatabase()); - int status = mysql_query(conn.handle(), - "DROP TABLE IF EXISTS ipv6_reservations"); - ASSERT_EQ(0, status) << mysql_error(conn.handle()); + MySqlHolder& holderHandle = conn.handle(); + + int status = mysql_query(holderHandle, "DROP TABLE IF EXISTS ipv6_reservations"); + ASSERT_EQ(0, status) << mysql_error(holderHandle); // Create a host with a reservation. HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8:1::1", Host::IDENT_HWADDR, false); diff --git a/src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc b/src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc index 01582ce422..3badd7d777 100644 --- a/src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc +++ b/src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc @@ -119,9 +119,11 @@ public: PgSqlConnection conn(params); conn.openDatabase(); - PgSqlResult r(PQexec(conn.handle(), query.c_str())); + PgSqlHolder& holderHandle = conn.handle(); + + PgSqlResult r(PQexec(holderHandle, query.c_str())); if (PQresultStatus(r) != PGRES_TUPLES_OK) { - isc_throw(DbOperationError, "Query failed:" << PQerrorMessage(conn.handle())); + isc_throw(DbOperationError, "Query failed:" << PQerrorMessage(holderHandle)); } int numrows = PQntuples(r); @@ -626,9 +628,11 @@ TEST_F(PgSqlHostDataSourceTest, testAddRollback) { PgSqlConnection conn(params); ASSERT_NO_THROW(conn.openDatabase()); - PgSqlResult r(PQexec(conn.handle(), "DROP TABLE IF EXISTS ipv6_reservations")); - ASSERT_TRUE (PQresultStatus(r) == PGRES_COMMAND_OK) - << " drop command failed :" << PQerrorMessage(conn.handle()); + PgSqlHolder& holderHandle = conn.handle(); + + PgSqlResult r(PQexec(holderHandle, "DROP TABLE IF EXISTS ipv6_reservations")); + ASSERT_TRUE(PQresultStatus(r) == PGRES_COMMAND_OK) + << " drop command failed :" << PQerrorMessage(holderHandle); // Create a host with a reservation. HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8:1::1", diff --git a/src/lib/mysql/mysql_connection.cc b/src/lib/mysql/mysql_connection.cc index 874b43884d..3c57364610 100644 --- a/src/lib/mysql/mysql_connection.cc +++ b/src/lib/mysql/mysql_connection.cc @@ -200,18 +200,20 @@ MySqlConnection::openDatabase() { // connection after a reconnect as among other things, it drops all our // pre-compiled statements. my_bool auto_reconnect = MLM_FALSE; - int result = mysql_options(handle(), MYSQL_OPT_RECONNECT, &auto_reconnect); + MySqlHolder& holderHandle = handle(); + + int result = mysql_options(holderHandle, MYSQL_OPT_RECONNECT, &auto_reconnect); if (result != 0) { isc_throw(DbOpenError, "unable to set auto-reconnect option: " << - mysql_error(handle())); + mysql_error(holderHandle)); } // Make sure we have a large idle time window ... say 30 days... const char *wait_time = "SET SESSION wait_timeout = 30 * 86400"; - result = mysql_options(handle(), MYSQL_INIT_COMMAND, wait_time); + result = mysql_options(holderHandle, MYSQL_INIT_COMMAND, wait_time); if (result != 0) { isc_throw(DbOpenError, "unable to set wait_timeout " << - mysql_error(handle())); + mysql_error(holderHandle)); } // Set SQL mode options for the connection: SQL mode governs how what @@ -219,18 +221,18 @@ MySqlConnection::openDatabase() { // invalid data. We want to ensure we get the strictest behavior and // to reject invalid data with an error. const char *sql_mode = "SET SESSION sql_mode ='STRICT_ALL_TABLES'"; - result = mysql_options(handle(), MYSQL_INIT_COMMAND, sql_mode); + result = mysql_options(holderHandle, MYSQL_INIT_COMMAND, sql_mode); if (result != 0) { isc_throw(DbOpenError, "unable to set SQL mode options: " << - mysql_error(handle())); + mysql_error(holderHandle)); } // Connection timeout, the amount of time taken for the client to drop // the connection if the server is not responding. - result = mysql_options(handle(), MYSQL_OPT_CONNECT_TIMEOUT, &connect_timeout); + result = mysql_options(holderHandle, MYSQL_OPT_CONNECT_TIMEOUT, &connect_timeout); if (result != 0) { isc_throw(DbOpenError, "unable to set database connection timeout: " << - mysql_error(handle())); + mysql_error(holderHandle)); } // Open the database. @@ -243,10 +245,10 @@ MySqlConnection::openDatabase() { // This makes it hard to distinguish whether the UPDATE changed no rows // because no row matching the WHERE clause was found, or because a // row was found but no data was altered. - MYSQL* status = mysql_real_connect(handle(), host, user, password, name, + MYSQL* status = mysql_real_connect(holderHandle, host, user, password, name, port, NULL, CLIENT_FOUND_ROWS); - if (status != handle()) { - isc_throw(DbOpenError, mysql_error(handle())); + if (status != holderHandle) { + isc_throw(DbOpenError, mysql_error(holderHandle)); } // Enable autocommit. In case transaction is explicitly used, this @@ -256,11 +258,11 @@ MySqlConnection::openDatabase() { // caused issues for some unit tests which were unable to cleanup // the database after the test because of pending transactions. // Use of autocommit will eliminate this problem. - my_bool auto_commit = mysql_autocommit(handle(), 1); + my_bool auto_commit = mysql_autocommit(holderHandle, 1); if (auto_commit != MLM_FALSE) { - isc_throw(DbOperationError, mysql_error(handle())); + isc_throw(DbOperationError, mysql_error(holderHandle)); } - handle().connected_ = true; + holderHandle.connected_ = true; connected_ = true; } @@ -340,28 +342,37 @@ MySqlConnection::startTransaction() { DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, MYSQL_START_TRANSACTION); // We create prepared statements for all other queries, but MySQL // don't support prepared statements for START TRANSACTION. - int status = mysql_query(handle(), "START TRANSACTION"); + + MySqlHolder& holderHandle = handle(); + + int status = mysql_query(holderHandle, "START TRANSACTION"); if (status != 0) { isc_throw(DbOperationError, "unable to start transaction, " - "reason: " << mysql_error(handle())); + "reason: " << mysql_error(holderHandle)); } } void MySqlConnection::commit() { DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, MYSQL_COMMIT); - if (mysql_commit(handle()) != 0) { + + MySqlHolder& holderHandle = handle(); + + if (mysql_commit(holderHandle) != 0) { isc_throw(DbOperationError, "commit failed: " - << mysql_error(handle())); + << mysql_error(holderHandle)); } } void MySqlConnection::rollback() { DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, MYSQL_ROLLBACK); - if (mysql_rollback(handle()) != 0) { + + MySqlHolder& holderHandle = handle(); + + if (mysql_rollback(holderHandle) != 0) { isc_throw(DbOperationError, "rollback failed: " - << mysql_error(handle())); + << mysql_error(holderHandle)); } } diff --git a/src/lib/mysql/mysql_connection.h b/src/lib/mysql/mysql_connection.h index 7ce62009d5..3d9108b961 100644 --- a/src/lib/mysql/mysql_connection.h +++ b/src/lib/mysql/mysql_connection.h @@ -367,6 +367,8 @@ public: const MySqlBindingCollection& in_bindings, MySqlBindingCollection& out_bindings, ConsumeResultFun process_result) { + MySqlHolder& holderHandle = handle(); + // Extract native input bindings. std::vector in_bind_vec; for (MySqlBindingPtr in_binding : in_bindings) { @@ -376,7 +378,7 @@ public: int status = 0; if (!in_bind_vec.empty()) { // Bind parameters to the prepared statement. - status = mysql_stmt_bind_param(handle().statements_[index], &in_bind_vec[0]); + status = mysql_stmt_bind_param(holderHandle.statements_[index], &in_bind_vec[0]); checkError(status, index, "unable to bind parameters for select"); } @@ -386,20 +388,20 @@ public: out_bind_vec.push_back(out_binding->getMySqlBinding()); } if (!out_bind_vec.empty()) { - status = mysql_stmt_bind_result(handle().statements_[index], &out_bind_vec[0]); + status = mysql_stmt_bind_result(holderHandle.statements_[index], &out_bind_vec[0]); checkError(status, index, "unable to bind result parameters for select"); } // Execute query. - status = mysql_stmt_execute(handle().statements_[index]); + status = mysql_stmt_execute(holderHandle.statements_[index]); checkError(status, index, "unable to execute"); - status = mysql_stmt_store_result(handle().statements_[index]); + status = mysql_stmt_store_result(holderHandle.statements_[index]); checkError(status, index, "unable to set up for storing all results"); // Fetch results. - MySqlFreeResult fetch_release(handle().statements_[index]); - while ((status = mysql_stmt_fetch(handle().statements_[index])) == + MySqlFreeResult fetch_release(holderHandle.statements_[index]); + while ((status = mysql_stmt_fetch(holderHandle.statements_[index])) == MLM_MYSQL_FETCH_SUCCESS) { try { // For each returned row call user function which should @@ -443,21 +445,23 @@ public: template void insertQuery(const StatementIndex& index, const MySqlBindingCollection& in_bindings) { + MySqlHolder& holderHandle = handle(); std::vector in_bind_vec; + for (MySqlBindingPtr in_binding : in_bindings) { in_bind_vec.push_back(in_binding->getMySqlBinding()); } // Bind the parameters to the statement - int status = mysql_stmt_bind_param(handle().statements_[index], &in_bind_vec[0]); + int status = mysql_stmt_bind_param(holderHandle.statements_[index], &in_bind_vec[0]); checkError(status, index, "unable to bind parameters"); // Execute the statement - status = mysql_stmt_execute(handle().statements_[index]); + status = mysql_stmt_execute(holderHandle.statements_[index]); if (status != 0) { // Failure: check for the special case of duplicate entry. - if (mysql_errno(handle()) == ER_DUP_ENTRY) { + if (mysql_errno(holderHandle) == ER_DUP_ENTRY) { isc_throw(DuplicateEntry, "Database duplicate entry error"); } checkError(status, index, "unable to execute"); @@ -481,29 +485,31 @@ public: template uint64_t updateDeleteQuery(const StatementIndex& index, const MySqlBindingCollection& in_bindings) { + MySqlHolder& holderHandle = handle(); std::vector in_bind_vec; + for (MySqlBindingPtr in_binding : in_bindings) { in_bind_vec.push_back(in_binding->getMySqlBinding()); } // Bind the parameters to the statement - int status = mysql_stmt_bind_param(handle().statements_[index], &in_bind_vec[0]); + int status = mysql_stmt_bind_param(holderHandle.statements_[index], &in_bind_vec[0]); checkError(status, index, "unable to bind parameters"); // Execute the statement - status = mysql_stmt_execute(handle().statements_[index]); + status = mysql_stmt_execute(holderHandle.statements_[index]); if (status != 0) { // Failure: check for the special case of duplicate entry. - if ((mysql_errno(handle()) == ER_DUP_ENTRY) + if ((mysql_errno(holderHandle) == ER_DUP_ENTRY) #ifdef ER_FOREIGN_DUPLICATE_KEY - || (mysql_errno(handle()) == ER_FOREIGN_DUPLICATE_KEY) + || (mysql_errno(holderHandle) == ER_FOREIGN_DUPLICATE_KEY) #endif #ifdef ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO - || (mysql_errno(handle()) == ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO) + || (mysql_errno(holderHandle) == ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO) #endif #ifdef ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO - || (mysql_errno(handle()) == ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO) + || (mysql_errno(holderHandle) == ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO) #endif ) { isc_throw(DuplicateEntry, "Database duplicate entry error"); @@ -512,7 +518,7 @@ public: } // Let's return how many rows were affected. - return (static_cast(mysql_stmt_affected_rows(handle().statements_[index]))); + return (static_cast(mysql_stmt_affected_rows(holderHandle.statements_[index]))); } @@ -565,8 +571,10 @@ public: template void checkError(const int status, const StatementIndex& index, const char* what) const { + MySqlHolder& holderHandle = handle(); + if (status != 0) { - switch(mysql_errno(handle())) { + switch(mysql_errno(holderHandle)) { // These are the ones we consider fatal. Remember this method is // used to check errors of API calls made subsequent to successfully // connecting. Errors occurring while attempting to connect are @@ -580,8 +588,8 @@ public: DB_LOG_ERROR(db::MYSQL_FATAL_ERROR) .arg(what) .arg(text_statements_[static_cast(index)]) - .arg(mysql_error(handle())) - .arg(mysql_errno(handle())); + .arg(mysql_error(holderHandle)) + .arg(mysql_errno(holderHandle)); // If there's no lost db callback or it returns false, // then we're not attempting to recover so we're done @@ -598,8 +606,8 @@ public: isc_throw(db::DbOperationError, what << " for <" << text_statements_[static_cast(index)] << ">, reason: " - << mysql_error(handle()) << " (error code " - << mysql_errno(handle()) << ")"); + << mysql_error(holderHandle) << " (error code " + << mysql_errno(holderHandle) << ")"); } } } diff --git a/src/lib/mysql/tests/mysql_connection_unittest.cc b/src/lib/mysql/tests/mysql_connection_unittest.cc index 3b3f2daef0..5519160577 100644 --- a/src/lib/mysql/tests/mysql_connection_unittest.cc +++ b/src/lib/mysql/tests/mysql_connection_unittest.cc @@ -119,22 +119,24 @@ public: /// /// @param sql Query in the textual form. void runQuery(const std::string& sql) { - MYSQL_STMT *stmt = mysql_stmt_init(conn_.handle()); + MySqlHolder& holderHandle = conn_.handle(); + + MYSQL_STMT *stmt = mysql_stmt_init(holderHandle); if (stmt == NULL) { isc_throw(DbOperationError, "unable to allocate MySQL prepared " - "statement structure, reason: " << mysql_error(conn_.handle())); + "statement structure, reason: " << mysql_error(holderHandle)); } int status = mysql_stmt_prepare(stmt, sql.c_str(), sql.length()); if (status != 0) { isc_throw(DbOperationError, "unable to prepare MySQL statement <" - << sql << ">, reason: " << mysql_errno(conn_.handle())); + << sql << ">, reason: " << mysql_errno(holderHandle)); } // Execute the prepared statement. if (mysql_stmt_execute(stmt) != 0) { isc_throw(DbOperationError, "cannot execute MySQL query <" - << sql << ">, reason: " << mysql_errno(conn_.handle())); + << sql << ">, reason: " << mysql_errno(holderHandle)); } // Discard the statement and its resources diff --git a/src/lib/pgsql/pgsql_connection.cc b/src/lib/pgsql/pgsql_connection.cc index 9b3257e852..a51fa69cfb 100644 --- a/src/lib/pgsql/pgsql_connection.cc +++ b/src/lib/pgsql/pgsql_connection.cc @@ -307,8 +307,9 @@ PgSqlConnection::openDatabase() { } // We have a valid connection, so let's save it to our holder - handle().setConnection(new_conn); - handle().connected_ = true; + PgSqlHolder& holderHandle = handle(); + holderHandle.setConnection(new_conn); + holderHandle.connected_ = true; connected_ = true; } @@ -329,6 +330,9 @@ PgSqlConnection::checkStatementError(const PgSqlResult& r, // error class. Note, there is a severity field, but it can be // misleadingly returned as fatal. However, a loss of connectivity // can lead to a NULL sqlstate with a status of PGRES_FATAL_ERROR. + + PgSqlHolder& holderHandle = handle(); + const char* sqlstate = PQresultErrorField(r, PG_DIAG_SQLSTATE); if ((sqlstate == NULL) || ((memcmp(sqlstate, "08", 2) == 0) || // Connection Exception @@ -338,7 +342,7 @@ PgSqlConnection::checkStatementError(const PgSqlResult& r, (memcmp(sqlstate, "58", 2) == 0))) { // System error DB_LOG_ERROR(PGSQL_FATAL_ERROR) .arg(statement.name) - .arg(PQerrorMessage(handle())) + .arg(PQerrorMessage(holderHandle)) .arg(sqlstate ? sqlstate : ""); // If there's no lost db callback or it returns false, @@ -354,7 +358,7 @@ PgSqlConnection::checkStatementError(const PgSqlResult& r, } // Apparently it wasn't fatal, so we throw with a helpful message. - const char* error_message = PQerrorMessage(handle()); + const char* error_message = PQerrorMessage(holderHandle); isc_throw(DbOperationError, "Statement exec failed:" << " for: " << statement.name << ", status: " << s << "sqlstate:[ " << (sqlstate ? sqlstate : "") @@ -365,9 +369,12 @@ PgSqlConnection::checkStatementError(const PgSqlResult& r, void PgSqlConnection::startTransaction() { DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, PGSQL_START_TRANSACTION); - PgSqlResult r(PQexec(handle(), "START TRANSACTION")); + + PgSqlHolder& holderHandle = handle(); + + PgSqlResult r(PQexec(holderHandle, "START TRANSACTION")); if (PQresultStatus(r) != PGRES_COMMAND_OK) { - const char* error_message = PQerrorMessage(handle()); + const char* error_message = PQerrorMessage(holderHandle); isc_throw(DbOperationError, "unable to start transaction" << error_message); } @@ -376,9 +383,12 @@ PgSqlConnection::startTransaction() { void PgSqlConnection::commit() { DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, PGSQL_COMMIT); - PgSqlResult r(PQexec(handle(), "COMMIT")); + + PgSqlHolder& holderHandle = handle(); + + PgSqlResult r(PQexec(holderHandle, "COMMIT")); if (PQresultStatus(r) != PGRES_COMMAND_OK) { - const char* error_message = PQerrorMessage(handle()); + const char* error_message = PQerrorMessage(holderHandle); isc_throw(DbOperationError, "commit failed: " << error_message); } } @@ -386,9 +396,12 @@ PgSqlConnection::commit() { void PgSqlConnection::rollback() { DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, PGSQL_ROLLBACK); - PgSqlResult r(PQexec(handle(), "ROLLBACK")); + + PgSqlHolder& holderHandle = handle(); + + PgSqlResult r(PQexec(holderHandle, "ROLLBACK")); if (PQresultStatus(r) != PGRES_COMMAND_OK) { - const char* error_message = PQerrorMessage(handle()); + const char* error_message = PQerrorMessage(holderHandle); isc_throw(DbOperationError, "rollback failed: " << error_message); } } diff --git a/src/lib/pgsql/tests/pgsql_exchange_unittest.cc b/src/lib/pgsql/tests/pgsql_exchange_unittest.cc index cc44a785f2..a1f597c3d7 100644 --- a/src/lib/pgsql/tests/pgsql_exchange_unittest.cc +++ b/src/lib/pgsql/tests/pgsql_exchange_unittest.cc @@ -198,18 +198,22 @@ public: " varchar_col VARCHAR(255) " "); "; - PgSqlResult r(PQexec(conn_->handle(), sql)); + PgSqlHolder& holderHandle = conn_->handle(); + + PgSqlResult r(PQexec(holderHandle, sql)); ASSERT_EQ(PQresultStatus(r), PGRES_COMMAND_OK) - << " create basics table failed: " << PQerrorMessage(conn_->handle()); + << " create basics table failed: " << PQerrorMessage(holderHandle); } /// @brief Destroys the basics table /// Asserts if the destruction fails void destroySchema() { if (conn_) { - PgSqlResult r(PQexec(conn_->handle(), "DROP TABLE IF EXISTS basics;")); + PgSqlHolder& holderHandle = conn_->handle(); + + PgSqlResult r(PQexec(holderHandle, "DROP TABLE IF EXISTS basics;")); ASSERT_EQ(PQresultStatus(r), PGRES_COMMAND_OK) - << " drop basics table failed: " << PQerrorMessage(conn_->handle()); + << " drop basics table failed: " << PQerrorMessage(holderHandle); } } @@ -227,10 +231,12 @@ public: /// Asserts if the result set status does not equal the expected outcome. void runSql(PgSqlResultPtr& r, const std::string& sql, int exp_outcome, int lineno) { - r.reset(new PgSqlResult(PQexec(conn_->handle(), sql.c_str()))); + PgSqlHolder& holderHandle = conn_->handle(); + + r.reset(new PgSqlResult(PQexec(holderHandle, sql.c_str()))); ASSERT_EQ(PQresultStatus(*r), exp_outcome) << " runSql at line: " << lineno << " failed, sql:[" << sql - << "]\n reason: " << PQerrorMessage(conn_->handle()); + << "]\n reason: " << PQerrorMessage(holderHandle); } /// @brief Executes a SQL statement and tests for an expected outcome @@ -250,7 +256,9 @@ public: PgSqlTaggedStatement& statement, PsqlBindArrayPtr bind_array, int exp_outcome, int lineno) { - r.reset(new PgSqlResult(PQexecPrepared(conn_->handle(), statement.name, + PgSqlHolder& holderHandle = conn_->handle(); + + r.reset(new PgSqlResult(PQexecPrepared(holderHandle, statement.name, statement.nbparams, &bind_array->values_[0], &bind_array->lengths_[0], @@ -258,7 +266,7 @@ public: ASSERT_EQ(PQresultStatus(*r), exp_outcome) << " runPreparedStatement at line: " << lineno << " statement name:[" << statement.name - << "]\n reason: " << PQerrorMessage(conn_->handle()); + << "]\n reason: " << PQerrorMessage(holderHandle); } /// @brief Fetches all of the rows currently in the table