From: Razvan Becheriu Date: Wed, 23 Oct 2019 15:03:08 +0000 (+0300) Subject: [#884,!567] use thread_local when creating exchanges X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=82e46e2359995f7d184e5642a351ce437466ad34;p=thirdparty%2Fkea.git [#884,!567] use thread_local when creating exchanges --- diff --git a/src/lib/dhcpsrv/base_host_data_source.h b/src/lib/dhcpsrv/base_host_data_source.h index b7c6af6b4f..0fd11f7e35 100644 --- a/src/lib/dhcpsrv/base_host_data_source.h +++ b/src/lib/dhcpsrv/base_host_data_source.h @@ -301,8 +301,7 @@ public: /// /// @return Const @c Host object using a specified IPv6 address/prefix. virtual ConstHostPtr - get6(const SubnetID& subnet_id, const asiolink::IOAddress& address) const = - 0; + get6(const SubnetID& subnet_id, const asiolink::IOAddress& address) const = 0; /// @brief Adds a new host to the collection. /// diff --git a/src/lib/dhcpsrv/mysql_host_data_source.cc b/src/lib/dhcpsrv/mysql_host_data_source.cc index 5340070881..c84bb0e2e3 100644 --- a/src/lib/dhcpsrv/mysql_host_data_source.cc +++ b/src/lib/dhcpsrv/mysql_host_data_source.cc @@ -2040,7 +2040,7 @@ public: /// @param single A boolean value indicating if a single host is /// expected to be returned, or multiple hosts. void getHostCollection(StatementIndex stindex, MYSQL_BIND* bind, - boost::shared_ptr exchange, + std::shared_ptr exchange, ConstHostCollection& result, bool single) const; /// @brief Retrieves a host by subnet and client's unique identifier. @@ -2064,7 +2064,7 @@ public: const uint8_t* identifier_begin, const size_t identifier_len, StatementIndex stindex, - boost::shared_ptr exchange) const; + std::shared_ptr exchange) const; /// @brief Throws exception if database is read only. /// @@ -2075,28 +2075,6 @@ public: /// @throw DbReadOnly if backend is operating in read only mode. void checkReadOnly() const; - /// @brief Pointer to the object representing an exchange which - /// can be used to retrieve hosts and DHCPv4 options. - boost::shared_ptr host_exchange_; - - /// @brief Pointer to an object representing an exchange which can - /// be used to retrieve hosts, DHCPv6 options and IPv6 reservations. - boost::shared_ptr host_ipv6_exchange_; - - /// @brief Pointer to an object representing an exchange which can - /// be used to retrieve hosts, DHCPv4 and DHCPv6 options, and - /// IPv6 reservations using a single query. - boost::shared_ptr host_ipv46_exchange_; - - /// @brief Pointer to an object representing an exchange which can - /// be used to insert new IPv6 reservation. - boost::shared_ptr host_ipv6_reservation_exchange_; - - /// @brief Pointer to an object representing an exchange which can - /// be used to insert DHCPv4 or DHCPv6 option into dhcp4_options - /// or dhcp6_options table. - boost::shared_ptr host_option_exchange_; - /// @brief MySQL connection MySqlConnection conn_; @@ -2255,7 +2233,6 @@ TaggedStatementArray tagged_statements = { { "h.dhcp_identifier_type, h.dhcp4_subnet_id, " "h.dhcp6_subnet_id, h.ipv4_address, h.hostname, " "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, " - "h.dhcp4_next_server, h.dhcp4_server_hostname, " "h.dhcp4_boot_file_name, h.auth_key, " "o.option_id, o.code, o.value, o.formatted_value, o.space, " @@ -2296,7 +2273,6 @@ TaggedStatementArray tagged_statements = { { "h.dhcp_identifier_type, h.dhcp4_subnet_id, " "h.dhcp6_subnet_id, h.ipv4_address, h.hostname, " "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, " - "h.dhcp4_next_server, h.dhcp4_server_hostname, " "h.dhcp4_boot_file_name, h.auth_key, " "o.option_id, o.code, o.value, o.formatted_value, o.space, " @@ -2409,7 +2385,6 @@ TaggedStatementArray tagged_statements = { { "h.dhcp_identifier_type, h.dhcp4_subnet_id, " "h.dhcp6_subnet_id, h.ipv4_address, h.hostname, " "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, " - "h.dhcp4_next_server, h.dhcp4_server_hostname, " "h.dhcp4_boot_file_name, h.auth_key, " "o.option_id, o.code, o.value, o.formatted_value, o.space, " @@ -2474,15 +2449,8 @@ TaggedStatementArray tagged_statements = { { }; // anonymous namespace MySqlHostDataSourceImpl:: -MySqlHostDataSourceImpl(const MySqlConnection::ParameterMap& parameters) - : host_exchange_(new MySqlHostWithOptionsExchange(MySqlHostWithOptionsExchange::DHCP4_ONLY)), - host_ipv6_exchange_(new MySqlHostIPv6Exchange(MySqlHostWithOptionsExchange::DHCP6_ONLY)), - host_ipv46_exchange_(new MySqlHostIPv6Exchange(MySqlHostWithOptionsExchange:: - DHCP4_AND_DHCP6)), - host_ipv6_reservation_exchange_(new MySqlIPv6ReservationExchange()), - host_option_exchange_(new MySqlOptionExchange()), - conn_(parameters), - is_readonly_(false) { +MySqlHostDataSourceImpl(const MySqlConnection::ParameterMap& parameters) : + conn_(parameters), is_readonly_(false) { // Open the database. conn_.openDatabase(); @@ -2562,12 +2530,14 @@ MySqlHostDataSourceImpl::getVersion() const { const char* version_sql = "SELECT version, minor FROM schema_version"; int status = mysql_stmt_prepare(stmt, version_sql, strlen(version_sql)); if (status != 0) { + mysql_stmt_close(stmt); isc_throw(DbOperationError, "unable to prepare MySQL statement <" << version_sql << ">, reason: " << mysql_errno(conn_.mysql_)); } // 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_errno(conn_.mysql_)); } @@ -2606,7 +2576,6 @@ MySqlHostDataSourceImpl::getVersion() const { return (std::make_pair(major, minor)); } - void MySqlHostDataSourceImpl::addStatement(StatementIndex stindex, std::vector& bind) { @@ -2649,8 +2618,11 @@ MySqlHostDataSourceImpl::delStatement(StatementIndex stindex, void MySqlHostDataSourceImpl::addResv(const IPv6Resrv& resv, const HostID& id) { + thread_local std::shared_ptr host_ipv6_reservation_exchange( + std::make_shared()); + std::vector bind = - host_ipv6_reservation_exchange_->createBindForSend(resv, id); + host_ipv6_reservation_exchange->createBindForSend(resv, id); addStatement(INSERT_V6_RESRV, bind); } @@ -2661,9 +2633,11 @@ MySqlHostDataSourceImpl::addOption(const StatementIndex& stindex, const std::string& opt_space, const Optional& subnet_id, const HostID& id) { + thread_local std::shared_ptr host_option_exchange( + std::make_shared()); + std::vector bind = - host_option_exchange_->createBindForSend(opt_desc, opt_space, - subnet_id, id); + host_option_exchange->createBindForSend(opt_desc, opt_space, subnet_id, id); addStatement(stindex, bind); } @@ -2704,7 +2678,7 @@ checkError(const int status, const StatementIndex index, void MySqlHostDataSourceImpl:: getHostCollection(StatementIndex stindex, MYSQL_BIND* bind, - boost::shared_ptr exchange, + std::shared_ptr exchange, ConstHostCollection& result, bool single) const { // Bind the selection parameters to the statement @@ -2770,7 +2744,7 @@ getHost(const SubnetID& subnet_id, const uint8_t* identifier_begin, const size_t identifier_len, StatementIndex stindex, - boost::shared_ptr exchange) const { + std::shared_ptr exchange) const { // Set up the WHERE clause value MYSQL_BIND inbind[3]; @@ -2801,8 +2775,9 @@ getHost(const SubnetID& subnet_id, // Return single record if present, else clear the host. ConstHostPtr result; - if (!collection.empty()) + if (!collection.empty()) { result = *collection.begin(); + } return (result); } @@ -2829,6 +2804,9 @@ MySqlHostDataSource::add(const HostPtr& host) { // If operating in read-only mode, throw exception. impl_->checkReadOnly(); + thread_local std::shared_ptr host_ipv4_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP4_ONLY)); + // Initiate MySQL transaction as we will have to make multiple queries // to insert host information into multiple tables. If that fails on // any stage, the transaction will be rolled back by the destructor of @@ -2836,7 +2814,7 @@ MySqlHostDataSource::add(const HostPtr& host) { MySqlTransaction transaction(impl_->conn_); // Create the MYSQL_BIND array for the host - std::vector bind = impl_->host_exchange_->createBindForSend(host); + std::vector bind = host_ipv4_exchange->createBindForSend(host); // ... and insert the host. impl_->addStatement(MySqlHostDataSourceImpl::INSERT_HOST, bind); @@ -2896,7 +2874,7 @@ MySqlHostDataSource::del(const SubnetID& subnet_id, const asiolink::IOAddress& a } // v6 - ConstHostPtr host = get6(subnet_id, addr); + ConstHostPtr host(get6(subnet_id, addr)); if (!host) { return (false); } @@ -2982,6 +2960,9 @@ ConstHostCollection MySqlHostDataSource::getAll(const Host::IdentifierType& identifier_type, const uint8_t* identifier_begin, const size_t identifier_len) const { + thread_local std::shared_ptr host_ipv46_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP4_AND_DHCP6)); + // Set up the WHERE clause value MYSQL_BIND inbind[2]; memset(inbind, 0, sizeof(inbind)); @@ -3002,14 +2983,16 @@ MySqlHostDataSource::getAll(const Host::IdentifierType& identifier_type, inbind[0].length = &length; ConstHostCollection result; - impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_DHCPID, inbind, - impl_->host_ipv46_exchange_, - result, false); + impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_DHCPID, + inbind, host_ipv46_exchange, result, false); return (result); } ConstHostCollection MySqlHostDataSource::getAll4(const SubnetID& subnet_id) const { + thread_local std::shared_ptr host_ipv4_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP4_ONLY)); + // Set up the WHERE clause value MYSQL_BIND inbind[1]; memset(inbind, 0, sizeof(inbind)); @@ -3020,13 +3003,15 @@ MySqlHostDataSource::getAll4(const SubnetID& subnet_id) const { ConstHostCollection result; impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_SUBID4, - inbind, impl_->host_exchange_, - result, false); + inbind, host_ipv4_exchange, result, false); return (result); } ConstHostCollection MySqlHostDataSource::getAll6(const SubnetID& subnet_id) const { + thread_local std::shared_ptr host_ipv6_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP6_ONLY)); + // Set up the WHERE clause value MYSQL_BIND inbind[1]; memset(inbind, 0, sizeof(inbind)); @@ -3037,13 +3022,15 @@ MySqlHostDataSource::getAll6(const SubnetID& subnet_id) const { ConstHostCollection result; impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_SUBID6, - inbind, impl_->host_ipv6_exchange_, - result, false); + inbind, host_ipv6_exchange, result, false); return (result); } ConstHostCollection MySqlHostDataSource::getAllbyHostname(const std::string& hostname) const { + thread_local std::shared_ptr host_ipv46_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP4_AND_DHCP6)); + // Set up the WHERE clause value MYSQL_BIND inbind[1]; memset(inbind, 0, sizeof(inbind)); @@ -3059,14 +3046,16 @@ MySqlHostDataSource::getAllbyHostname(const std::string& hostname) const { ConstHostCollection result; impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_HOSTNAME, - inbind, impl_->host_ipv46_exchange_, - result, false); + inbind, host_ipv46_exchange, result, false); return (result); } ConstHostCollection MySqlHostDataSource::getAllbyHostname4(const std::string& hostname, const SubnetID& subnet_id) const { + thread_local std::shared_ptr host_ipv4_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP4_ONLY)); + // Set up the WHERE clause value MYSQL_BIND inbind[2]; memset(inbind, 0, sizeof(inbind)); @@ -3088,14 +3077,16 @@ MySqlHostDataSource::getAllbyHostname4(const std::string& hostname, ConstHostCollection result; impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID4, - inbind, impl_->host_exchange_, - result, false); + inbind, host_ipv4_exchange, result, false); return (result); } ConstHostCollection MySqlHostDataSource::getAllbyHostname6(const std::string& hostname, const SubnetID& subnet_id) const { + thread_local std::shared_ptr host_ipv6_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP6_ONLY)); + // Set up the WHERE clause value MYSQL_BIND inbind[2]; memset(inbind, 0, sizeof(inbind)); @@ -3117,8 +3108,7 @@ MySqlHostDataSource::getAllbyHostname6(const std::string& hostname, ConstHostCollection result; impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID6, - inbind, impl_->host_ipv6_exchange_, - result, false); + inbind, host_ipv6_exchange, result, false); return (result); } @@ -3127,6 +3117,9 @@ MySqlHostDataSource::getPage4(const SubnetID& subnet_id, size_t& /*source_index*/, uint64_t lower_host_id, const HostPageSize& page_size) const { + thread_local std::shared_ptr host_ipv4_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP4_ONLY)); + // Set up the WHERE clause value MYSQL_BIND inbind[3]; memset(inbind, 0, sizeof(inbind)); @@ -3151,8 +3144,7 @@ MySqlHostDataSource::getPage4(const SubnetID& subnet_id, ConstHostCollection result; impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_SUBID4_PAGE, - inbind, impl_->host_exchange_, - result, false); + inbind, host_ipv4_exchange, result, false); return (result); } @@ -3161,6 +3153,9 @@ MySqlHostDataSource::getPage6(const SubnetID& subnet_id, size_t& /*source_index*/, uint64_t lower_host_id, const HostPageSize& page_size) const { + thread_local std::shared_ptr host_ipv6_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP6_ONLY)); + // Set up the WHERE clause value MYSQL_BIND inbind[3]; memset(inbind, 0, sizeof(inbind)); @@ -3185,13 +3180,14 @@ MySqlHostDataSource::getPage6(const SubnetID& subnet_id, ConstHostCollection result; impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_SUBID6_PAGE, - inbind, impl_->host_ipv6_exchange_, - result, false); + inbind, host_ipv6_exchange, result, false); return (result); } ConstHostCollection MySqlHostDataSource::getAll4(const asiolink::IOAddress& address) const { + thread_local std::shared_ptr host_ipv4_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP4_ONLY)); // Set up the WHERE clause value MYSQL_BIND inbind[1]; @@ -3203,8 +3199,8 @@ MySqlHostDataSource::getAll4(const asiolink::IOAddress& address) const { inbind[0].is_unsigned = MLM_TRUE; ConstHostCollection result; - impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_ADDR, inbind, - impl_->host_exchange_, result, false); + impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_ADDR, + inbind, host_ipv4_exchange, result, false); return (result); } @@ -3214,21 +3210,25 @@ MySqlHostDataSource::get4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type, const uint8_t* identifier_begin, const size_t identifier_len) const { + thread_local std::shared_ptr host_ipv4_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP4_ONLY)); return (impl_->getHost(subnet_id, identifier_type, identifier_begin, identifier_len, MySqlHostDataSourceImpl::GET_HOST_SUBID4_DHCPID, - impl_->host_exchange_)); + host_ipv4_exchange)); } ConstHostPtr MySqlHostDataSource::get4(const SubnetID& subnet_id, const asiolink::IOAddress& address) const { - // Check that address is IPv4, not IPv6. if (!address.isV4()) { - isc_throw(BadValue, "MySqlHostDataSource::get4(2): wrong address type, " - "address supplied is not an IPv4 address"); + isc_throw(BadValue, "MySqlHostDataSource::get4(id, address): " + "wrong address type, address supplied is an IPv6 address"); } + thread_local std::shared_ptr host_ipv4_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP4_ONLY)); + // Set up the WHERE clause value MYSQL_BIND inbind[2]; uint32_t subnet = subnet_id; @@ -3244,12 +3244,13 @@ MySqlHostDataSource::get4(const SubnetID& subnet_id, ConstHostCollection collection; impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_SUBID_ADDR, - inbind, impl_->host_exchange_, collection, true); + inbind, host_ipv4_exchange, collection, true); // Return single record if present, else clear the host. ConstHostPtr result; - if (!collection.empty()) + if (!collection.empty()) { result = *collection.begin(); + } return (result); } @@ -3259,16 +3260,24 @@ MySqlHostDataSource::get6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type, const uint8_t* identifier_begin, const size_t identifier_len) const { + thread_local std::shared_ptr host_ipv6_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP6_ONLY)); return (impl_->getHost(subnet_id, identifier_type, identifier_begin, identifier_len, MySqlHostDataSourceImpl::GET_HOST_SUBID6_DHCPID, - impl_->host_ipv6_exchange_)); + host_ipv6_exchange)); } ConstHostPtr MySqlHostDataSource::get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const { - /// @todo: Check that prefix is v6 address, not v4. + if (!prefix.isV6()) { + isc_throw(BadValue, "MySqlHostDataSource::get6(prefix, prefix_len): " + "wrong address type, address supplied is an IPv4 address"); + } + + thread_local std::shared_ptr host_ipv6_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP6_ONLY)); // Set up the WHERE clause value MYSQL_BIND inbind[2]; @@ -3290,8 +3299,7 @@ MySqlHostDataSource::get6(const asiolink::IOAddress& prefix, ConstHostCollection collection; impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_PREFIX, - inbind, impl_->host_ipv6_exchange_, - collection, true); + inbind, host_ipv6_exchange, collection, true); // Return single record if present, else clear the host. ConstHostPtr result; @@ -3305,6 +3313,14 @@ MySqlHostDataSource::get6(const asiolink::IOAddress& prefix, ConstHostPtr MySqlHostDataSource::get6(const SubnetID& subnet_id, const asiolink::IOAddress& address) const { + if (!address.isV6()) { + isc_throw(BadValue, "MySqlHostDataSource::get6(id, address): " + "wrong address type, address supplied is an IPv4 address"); + } + + thread_local std::shared_ptr host_ipv6_exchange( + std::make_shared(MySqlHostWithOptionsExchange::DHCP6_ONLY)); + // Set up the WHERE clause value MYSQL_BIND inbind[2]; memset(inbind, 0, sizeof(inbind)); @@ -3325,8 +3341,7 @@ MySqlHostDataSource::get6(const SubnetID& subnet_id, ConstHostCollection collection; impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_SUBID6_ADDR, - inbind, impl_->host_ipv6_exchange_, - collection, true); + inbind, host_ipv6_exchange, collection, true); // Return single record if present, else clear the host. ConstHostPtr result; @@ -3339,7 +3354,8 @@ MySqlHostDataSource::get6(const SubnetID& subnet_id, // Miscellaneous database methods. -std::string MySqlHostDataSource::getName() const { +std::string +MySqlHostDataSource::getName() const { std::string name = ""; try { name = impl_->conn_.getParameter("name"); @@ -3349,7 +3365,8 @@ std::string MySqlHostDataSource::getName() const { return (name); } -std::string MySqlHostDataSource::getDescription() const { +std::string +MySqlHostDataSource::getDescription() const { return (std::string("Host data source that stores host information" "in MySQL database")); } diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.cc b/src/lib/dhcpsrv/mysql_lease_mgr.cc index 599045c860..102bc73981 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.cc +++ b/src/lib/dhcpsrv/mysql_lease_mgr.cc @@ -307,19 +307,19 @@ tagged_statements = { { {MySqlLeaseMgr::ALL_LEASE6_STATS, "SELECT subnet_id, lease_type, state, leases as state_count" - " FROM lease6_stat ORDER BY subnet_id, lease_type, state" }, + " FROM lease6_stat ORDER BY subnet_id, lease_type, state"}, {MySqlLeaseMgr::SUBNET_LEASE6_STATS, "SELECT subnet_id, lease_type, state, leases as state_count" " FROM lease6_stat " " WHERE subnet_id = ? " - " ORDER BY lease_type, state" }, + " ORDER BY lease_type, state"}, {MySqlLeaseMgr::SUBNET_RANGE_LEASE6_STATS, "SELECT subnet_id, lease_type, state, leases as state_count" " FROM lease6_stat " " WHERE subnet_id >= ? and subnet_id <= ? " - " ORDER BY subnet_id, lease_type, state" } + " ORDER BY subnet_id, lease_type, state"} } }; @@ -529,7 +529,7 @@ public: bind_[2].buffer_length = client_id_length_; bind_[2].length = &client_id_length_; // bind_[2].is_null = &MLM_FALSE; // commented out for performance - // reasons, see memset() above + // reasons, see memset() above } else { bind_[2].buffer_type = MYSQL_TYPE_NULL; // According to http://dev.mysql.com/doc/refman/5.5/en/ @@ -595,7 +595,7 @@ public: // bind_[8].is_null = &MLM_FALSE; // commented out for performance // reasons, see memset() above - // state: uint32_t. + // state: uint32_t bind_[9].buffer_type = MYSQL_TYPE_LONG; bind_[9].buffer = reinterpret_cast(&lease_->state_); bind_[9].is_unsigned = MLM_TRUE; @@ -721,7 +721,7 @@ public: // bind_[8].is_null = &MLM_FALSE; // commented out for performance // reasons, see memset() above - // state: uint32_t + // state: uint32_t bind_[9].buffer_type = MYSQL_TYPE_LONG; bind_[9].buffer = reinterpret_cast(&state_); bind_[9].is_unsigned = MLM_TRUE; @@ -1126,7 +1126,7 @@ public: bind_[14].is_null = &hwaddr_null_; } - // state: uint32_t + // state: uint32_t bind_[15].buffer_type = MYSQL_TYPE_LONG; bind_[15].buffer = reinterpret_cast(&lease_->state_); bind_[15].is_unsigned = MLM_TRUE; @@ -1293,7 +1293,7 @@ public: bind_[14].buffer = reinterpret_cast(&hwaddr_source_); bind_[14].is_unsigned = MLM_TRUE; - // state: uint32_t + // state: uint32_t bind_[15].buffer_type = MYSQL_TYPE_LONG; bind_[15].buffer = reinterpret_cast(&state_); bind_[15].is_unsigned = MLM_TRUE; @@ -1683,8 +1683,8 @@ private: // MySqlLeaseMgr Constructor and Destructor -MySqlLeaseMgr::MySqlLeaseMgr(const MySqlConnection::ParameterMap& parameters) - : conn_(parameters) { +MySqlLeaseMgr::MySqlLeaseMgr(const MySqlConnection::ParameterMap& parameters) : + conn_(parameters) { // Open the database. conn_.openDatabase(); @@ -1694,11 +1694,10 @@ MySqlLeaseMgr::MySqlLeaseMgr(const MySqlConnection::ParameterMap& parameters) MYSQL_SCHEMA_VERSION_MINOR); std::pair db_version = getVersion(); if (code_version != db_version) { - isc_throw(DbOpenError, - "MySQL schema version mismatch: need version: " - << code_version.first << "." << code_version.second - << " found version: " << db_version.first << "." - << db_version.second); + isc_throw(DbOpenError, "MySQL schema version mismatch: need version: " + << code_version.first << "." << code_version.second + << " found version: " << db_version.first << "." + << db_version.second); } // Enable autocommit. To avoid a flush to disk on every commit, the global @@ -1713,11 +1712,6 @@ MySqlLeaseMgr::MySqlLeaseMgr(const MySqlConnection::ParameterMap& parameters) // Prepare all statements likely to be used. conn_.prepareStatements(tagged_statements.begin(), tagged_statements.end()); - - // Create the exchange objects for use in exchanging data between the - // program and the database. - exchange4_.reset(new MySqlLease4Exchange()); - exchange6_.reset(new MySqlLease6Exchange()); } MySqlLeaseMgr::~MySqlLeaseMgr() { @@ -1765,11 +1759,14 @@ MySqlLeaseMgr::addLeaseCommon(StatementIndex stindex, bool MySqlLeaseMgr::addLease(const Lease4Ptr& lease) { + thread_local std::shared_ptr exchange4( + std::make_shared()); + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_ADD_ADDR4).arg(lease->addr_.toText()); // Create the MYSQL_BIND array for the lease - std::vector bind = exchange4_->createBindForSend(lease); + std::vector bind = exchange4->createBindForSend(lease); // ... and drop to common code. return (addLeaseCommon(INSERT_LEASE4, bind)); @@ -1777,12 +1774,15 @@ MySqlLeaseMgr::addLease(const Lease4Ptr& lease) { bool MySqlLeaseMgr::addLease(const Lease6Ptr& lease) { + thread_local std::shared_ptr exchange6( + std::make_shared()); + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_ADD_ADDR6).arg(lease->addr_.toText()) .arg(lease->type_); // Create the MYSQL_BIND array for the lease - std::vector bind = exchange6_->createBindForSend(lease); + std::vector bind = exchange6->createBindForSend(lease); // ... and drop to common code. return (addLeaseCommon(INSERT_LEASE6, bind)); @@ -1877,15 +1877,32 @@ void MySqlLeaseMgr::getLeaseCollection(StatementIndex stindex, } } +void MySqlLeaseMgr::getLeaseCollection(StatementIndex stindex, MYSQL_BIND* bind, + Lease4Collection& result) const { + thread_local std::shared_ptr exchange4( + std::make_shared()); + getLeaseCollection(stindex, bind, exchange4, result); +} + +void MySqlLeaseMgr::getLeaseCollection(StatementIndex stindex, MYSQL_BIND* bind, + Lease6Collection& result) const { + thread_local std::shared_ptr exchange6( + std::make_shared()); + getLeaseCollection(stindex, bind, exchange6, result); +} + void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* bind, Lease4Ptr& result) const { + thread_local std::shared_ptr exchange4( + std::make_shared()); + // Create appropriate collection object and get all leases matching // the selection criteria. The "single" parameter is true to indicate // that the called method should throw an exception if multiple // matching records are found: this particular method is called when only // one or zero matches is expected. Lease4Collection collection; - getLeaseCollection(stindex, bind, exchange4_, collection, true); + getLeaseCollection(stindex, bind, exchange4, collection, true); // Return single record if present, else clear the lease. if (collection.empty()) { @@ -1897,13 +1914,16 @@ void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* bind, void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* bind, Lease6Ptr& result) const { + thread_local std::shared_ptr exchange6( + std::make_shared()); + // Create appropriate collection object and get all leases matching // the selection criteria. The "single" parameter is true to indicate // that the called method should throw an exception if multiple // matching records are found: this particular method is called when only // one or zero matches is expected. Lease6Collection collection; - getLeaseCollection(stindex, bind, exchange6_, collection, true); + getLeaseCollection(stindex, bind, exchange6, collection, true); // Return single record if present, else clear the lease. if (collection.empty()) { @@ -2520,13 +2540,16 @@ MySqlLeaseMgr::updateLeaseCommon(StatementIndex stindex, MYSQL_BIND* bind, void MySqlLeaseMgr::updateLease4(const Lease4Ptr& lease) { + thread_local std::shared_ptr exchange4( + std::make_shared()); + const StatementIndex stindex = UPDATE_LEASE4; LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_UPDATE_ADDR4).arg(lease->addr_.toText()); // Create the MYSQL_BIND array for the data being updated - std::vector bind = exchange4_->createBindForSend(lease); + std::vector bind = exchange4->createBindForSend(lease); // Set up the WHERE clause and append it to the MYSQL_BIND array MYSQL_BIND where; @@ -2544,6 +2567,9 @@ MySqlLeaseMgr::updateLease4(const Lease4Ptr& lease) { void MySqlLeaseMgr::updateLease6(const Lease6Ptr& lease) { + thread_local std::shared_ptr exchange6( + std::make_shared()); + const StatementIndex stindex = UPDATE_LEASE6; LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, @@ -2551,7 +2577,7 @@ MySqlLeaseMgr::updateLease6(const Lease6Ptr& lease) { .arg(lease->type_); // Create the MYSQL_BIND array for the data being updated - std::vector bind = exchange6_->createBindForSend(lease); + std::vector bind = exchange6->createBindForSend(lease); // Set up the WHERE clause value MYSQL_BIND where; @@ -2775,12 +2801,14 @@ MySqlLeaseMgr::getVersion() const { const char* version_sql = "SELECT version, minor FROM schema_version"; int status = mysql_stmt_prepare(stmt, version_sql, strlen(version_sql)); if (status != 0) { + mysql_stmt_close(stmt); isc_throw(DbOperationError, "unable to prepare MySQL statement <" << version_sql << ">, reason: " << mysql_error(conn_.mysql_)); } // 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_errno(conn_.mysql_)); } diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.h b/src/lib/dhcpsrv/mysql_lease_mgr.h index 1524d06676..8a3ceffd01 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.h +++ b/src/lib/dhcpsrv/mysql_lease_mgr.h @@ -679,9 +679,7 @@ private: /// @throw isc::db::MultipleRecords Multiple records were retrieved /// from the database where only one was expected. void getLeaseCollection(StatementIndex stindex, MYSQL_BIND* bind, - Lease4Collection& result) const { - getLeaseCollection(stindex, bind, exchange4_, result); - } + Lease4Collection& result) const; /// @brief Get Lease Collection /// @@ -699,9 +697,7 @@ private: /// @throw isc::db::MultipleRecords Multiple records were retrieved /// from the database where only one was expected. void getLeaseCollection(StatementIndex stindex, MYSQL_BIND* bind, - Lease6Collection& result) const { - getLeaseCollection(stindex, bind, exchange6_, result); - } + Lease6Collection& result) const; /// @brief Get Lease4 Common Code /// @@ -809,15 +805,6 @@ private: void checkError(int status, StatementIndex index, const char* what) const; - // Members - - /// The exchange objects are used for transfer of data to/from the database. - /// They are pointed-to objects as the contents may change in "const" calls, - /// while the rest of this object does not. (At alternative would be to - /// declare them as "mutable".) - boost::scoped_ptr exchange4_; ///< Exchange object - boost::scoped_ptr exchange6_; ///< Exchange object - /// @brief MySQL connection db::MySqlConnection conn_; };