Commit e68fed52 authored by Stephen Morris's avatar Stephen Morris
Browse files

[2342] Encapsulate mysql_stmt_free_result in a temporary object

... to ensure that it is always called when a method terminates.
parent 9fa65c78
...@@ -392,7 +392,37 @@ private: ...@@ -392,7 +392,37 @@ private:
/// can be made, but when all the data is retrieved, mysql_stmt_free_result /// can be made, but when all the data is retrieved, mysql_stmt_free_result
/// must be called to free up the resources allocated. /// must be called to free up the resources allocated.
/// ///
/// This class acts as a wrapper around mysql_stmt_fect /// Created prior to the first fetch, this class's destructor calls
/// mysql_stmt_free_result, so eliminating the need for an explicit release
/// in the method using mysql_stmt_free_result. In this way, it guarantees
/// that the resources are released even if the MySqlLeaseMgr method concerned
/// exits via an exception.
class MySqlFreeResult {
public:
/// @brief Constructor
///
/// Store the pointer to the statement for which data is being fetched.
///
/// Note that according to the MySQL documentation, mysql_stmt_free_result
/// only releases resources if a cursor has been allocated for the
/// statement. This implies that it is a no-op if none have been. Either
/// way, any error from mysql_stmt_free_result is ignored. (Generating
/// an exception is not much help, as it will only confuse things if the
/// method calling mysql_stmt_fetch is exiting via an exception.)
MySqlFreeResult(MYSQL_STMT* statement) : statement_(statement)
{}
/// @brief Destructor
///
/// Frees up fetch context if a fetch has been successfully executed.
~MySqlFreeResult() {
(void) mysql_stmt_free_result(statement_);
}
private:
MYSQL_STMT* statement_; ///< Statement for which results are freed
};
// MySqlLeaseMgr Methods // MySqlLeaseMgr Methods
...@@ -745,7 +775,9 @@ MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const { ...@@ -745,7 +775,9 @@ MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
// to fields in the exchange object, then execute the prepared statement. // to fields in the exchange object, then execute the prepared statement.
bind6AndExecute(stindex, inbind); bind6AndExecute(stindex, inbind);
// Fetch the data. // Fetch the data and set up the "release" object to release associated
// resources when this method exits.
MySqlFreeResult fetch_release(statements_[stindex]);
int status = mysql_stmt_fetch(statements_[stindex]); int status = mysql_stmt_fetch(statements_[stindex]);
Lease6Ptr result; Lease6Ptr result;
...@@ -753,9 +785,6 @@ MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const { ...@@ -753,9 +785,6 @@ MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
try { try {
result = exchange6_->getLeaseData(); result = exchange6_->getLeaseData();
} catch (const isc::BadValue& ex) { } catch (const isc::BadValue& ex) {
// Free up result set.
(void) mysql_stmt_free_result(statements_[stindex]);
// Lease type is returned, to rethrow the exception with a bit // Lease type is returned, to rethrow the exception with a bit
// more data. // more data.
isc_throw(BadValue, ex.what() << ". Statement is <" << isc_throw(BadValue, ex.what() << ". Statement is <" <<
...@@ -776,8 +805,6 @@ MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const { ...@@ -776,8 +805,6 @@ MySqlLeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
// This has already been set, so no action is needed. // This has already been set, so no action is needed.
} }
// Free data structures associated with information returned.
(void) mysql_stmt_free_result(statements_[stindex]);
return (result); return (result);
} }
...@@ -819,15 +846,17 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid) const { ...@@ -819,15 +846,17 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid) const {
// Fetch the data. There could be multiple rows, so we need to iterate // Fetch the data. There could be multiple rows, so we need to iterate
// until all data has been retrieved. // until all data has been retrieved.
Lease6Collection result; Lease6Collection result;
// 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(statements_[stindex]);
while ((status = mysql_stmt_fetch(statements_[stindex])) == 0) { while ((status = mysql_stmt_fetch(statements_[stindex])) == 0) {
try { try {
Lease6Ptr lease = exchange6_->getLeaseData(); Lease6Ptr lease = exchange6_->getLeaseData();
result.push_back(lease); result.push_back(lease);
} catch (const isc::BadValue& ex) { } catch (const isc::BadValue& ex) {
// Free up result set.
(void) mysql_stmt_free_result(statements_[stindex]);
// Rethrow the exception with a bit more data. // Rethrow the exception with a bit more data.
isc_throw(BadValue, ex.what() << ". Statement is <" << isc_throw(BadValue, ex.what() << ". Statement is <" <<
text_statements_[stindex] << ">"); text_statements_[stindex] << ">");
...@@ -843,8 +872,6 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid) const { ...@@ -843,8 +872,6 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid) const {
; ;
} }
// Free up resources assoicated with the fetched data.
(void) mysql_stmt_free_result(statements_[stindex]);
return (result); return (result);
} }
...@@ -882,7 +909,10 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid, ...@@ -882,7 +909,10 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
// to fields in the exchange object, then execute the prepared statement. // to fields in the exchange object, then execute the prepared statement.
bind6AndExecute(stindex, inbind); bind6AndExecute(stindex, inbind);
// Fetch the data and set up the "release" object to release associated
// resources when this method exits then retrieve the data.
Lease6Ptr result; Lease6Ptr result;
MySqlFreeResult fetch_release(statements_[stindex]);
int status = mysql_stmt_fetch(statements_[stindex]); int status = mysql_stmt_fetch(statements_[stindex]);
if (status == 0) { if (status == 0) {
try { try {
...@@ -892,9 +922,6 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid, ...@@ -892,9 +922,6 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
// ignore the excess and take the first. // ignore the excess and take the first.
} catch (const isc::BadValue& ex) { } catch (const isc::BadValue& ex) {
// Free up result set.
(void) mysql_stmt_free_result(statements_[stindex]);
// Lease type is returned, to rethrow the exception with a bit // Lease type is returned, to rethrow the exception with a bit
// more data. // more data.
isc_throw(BadValue, ex.what() << ". Statement is <" << isc_throw(BadValue, ex.what() << ". Statement is <" <<
...@@ -915,8 +942,6 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid, ...@@ -915,8 +942,6 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
// This has already been set, so the action is a no-op. // This has already been set, so the action is a no-op.
} }
// Free data structures associated with information returned.
(void) mysql_stmt_free_result(statements_[stindex]);
return (result); return (result);
} }
...@@ -1066,15 +1091,15 @@ MySqlLeaseMgr::getVersion() const { ...@@ -1066,15 +1091,15 @@ MySqlLeaseMgr::getVersion() const {
mysql_error(mysql_)); mysql_error(mysql_));
} }
// Get the result // Fetch the data and set up the "release" object to release associated
// resources when this method exits then retrieve the data.
MySqlFreeResult fetch_release(statements_[stindex]);
status = mysql_stmt_fetch(statements_[stindex]); status = mysql_stmt_fetch(statements_[stindex]);
if (status != 0) { if (status != 0) {
(void) mysql_stmt_free_result(statements_[stindex]);
isc_throw(DbOperationError, "unable to obtain result set: " << isc_throw(DbOperationError, "unable to obtain result set: " <<
mysql_error(mysql_)); mysql_error(mysql_));
} }
(void) mysql_stmt_free_result(statements_[stindex]);
return (std::make_pair(major, minor)); return (std::make_pair(major, minor));
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment