<< " found version: " << db_version.first << "."
<< db_version.second);
} */
-
- // Enable autocommit. In case transaction is explicitly used, this
- // setting will be overwritten for the transaction. However, there are
- // cases when lack of autocommit could cause transactions to hang
- // until commit or rollback is explicitly called. This already
- // 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 result = mysql_autocommit(conn_.mysql_, 1);
- if (result != MLM_FALSE) {
- isc_throw(DbOperationError, mysql_error(conn_.mysql_));
- }
}
MySqlConfigBackendImpl::~MySqlConfigBackendImpl() {
GET_HOST_SUBID_ADDR, // Gets host by IPv4 SubnetID and IPv4 address
GET_HOST_PREFIX, // Gets host by IPv6 prefix
GET_HOST_SUBID6_ADDR, // Gets host by IPv6 SubnetID and IPv6 prefix
+ GET_HOST_SUBID4, // Get hosts by IPv4 SubnetID
+ GET_HOST_SUBID6, // Get hosts by IPv6 SubnetID
+ GET_HOST_SUBID4_PAGE, // Get hosts by IPv4 SubnetID beginning by HID
+ GET_HOST_SUBID6_PAGE, // Get hosts by IPv6 SubnetID beginning by HID
INSERT_HOST, // Insert new host to collection
INSERT_V6_RESRV, // Insert v6 reservation
INSERT_V4_OPTION, // Insert DHCPv4 option
DEL_HOST_ADDR4, // Delete v4 host (subnet-id, addr4)
DEL_HOST_SUBID4_ID, // Delete v4 host (subnet-id, ident.type, identifier)
DEL_HOST_SUBID6_ID, // Delete v6 host (subnet-id, ident.type, identifier)
- GET_HOST_SUBID4, // Get hosts by IPv4 SubnetID
- GET_HOST_SUBID6, // Get hosts by IPv6 SubnetID
- GET_HOST_SUBID4_PAGE, // Get hosts by IPv4 SubnetID beginning by HID
- GET_HOST_SUBID6_PAGE, // Get hosts by IPv6 SubnetID beginning by HID
NUM_STATEMENTS // Number of statements
};
/// @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<MySqlHostWithOptionsExchange> 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<MySqlHostIPv6Exchange> 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<MySqlHostIPv6Exchange> host_ipv46_exchange_;
-
- /// @brief Pointer to an object representing an exchange which can
- /// be used to insert new IPv6 reservation.
- boost::shared_ptr<MySqlIPv6ReservationExchange> 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<MySqlOptionExchange> host_option_exchange_;
-
/// @brief MySQL connection
MySqlConnection conn_;
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),
+ : conn_(parameters),
is_readonly_(false) {
// Open the database.
<< db_version.second);
}
- // Enable autocommit. In case transaction is explicitly used, this
- // setting will be overwritten for the transaction. However, there are
- // cases when lack of autocommit could cause transactions to hang
- // until commit or rollback is explicitly called. This already
- // 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 result = mysql_autocommit(conn_.mysql_, 1);
- if (result != 0) {
- isc_throw(DbOperationError, mysql_error(conn_.mysql_));
- }
-
// Prepare query statements. Those are will be only used to retrieve
// information from the database, so they can be used even if the
// database is read only for the current user.
void
MySqlHostDataSourceImpl::addResv(const IPv6Resrv& resv,
const HostID& id) {
+ boost::shared_ptr<MySqlIPv6ReservationExchange> host_ipv6_reservation_exchange(
+ new MySqlIPv6ReservationExchange());
+
std::vector<MYSQL_BIND> bind =
- host_ipv6_reservation_exchange_->createBindForSend(resv, id);
+ host_ipv6_reservation_exchange->createBindForSend(resv, id);
addStatement(INSERT_V6_RESRV, bind);
}
const std::string& opt_space,
const Optional<SubnetID>& subnet_id,
const HostID& id) {
+ boost::shared_ptr<MySqlOptionExchange> host_option_exchange(new MySqlOptionExchange());
+
std::vector<MYSQL_BIND> bind =
- host_option_exchange_->createBindForSend(opt_desc, opt_space,
+ host_option_exchange->createBindForSend(opt_desc, opt_space,
subnet_id, id);
addStatement(stindex, bind);
// Return single record if present, else clear the host.
ConstHostPtr result;
- if (!collection.empty())
+ if (!collection.empty()) {
result = *collection.begin();
+ }
return (result);
}
// If operating in read-only mode, throw exception.
impl_->checkReadOnly();
+ boost::shared_ptr<MySqlHostWithOptionsExchange> host_ipv4_exchange(
+ new MySqlHostWithOptionsExchange(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
MySqlTransaction transaction(impl_->conn_);
// Create the MYSQL_BIND array for the host
- std::vector<MYSQL_BIND> bind = impl_->host_exchange_->createBindForSend(host);
+ std::vector<MYSQL_BIND> bind = host_ipv4_exchange->createBindForSend(host);
// ... and insert the host.
impl_->addStatement(MySqlHostDataSourceImpl::INSERT_HOST, bind);
MySqlHostDataSource::getAll(const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const {
+ boost::shared_ptr<MySqlHostIPv6Exchange> host_ipv46_exchange(
+ new MySqlHostIPv6Exchange(MySqlHostWithOptionsExchange::DHCP4_AND_DHCP6));
+
// Set up the WHERE clause value
MYSQL_BIND inbind[2];
memset(inbind, 0, sizeof(inbind));
ConstHostCollection result;
impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_DHCPID, inbind,
- impl_->host_ipv46_exchange_,
- result, false);
+ host_ipv46_exchange, result, false);
return (result);
}
ConstHostCollection
MySqlHostDataSource::getAll4(const SubnetID& subnet_id) const {
+ boost::shared_ptr<MySqlHostWithOptionsExchange> host_ipv4_exchange(
+ new MySqlHostWithOptionsExchange(MySqlHostWithOptionsExchange::DHCP4_ONLY));
+
// Set up the WHERE clause value
MYSQL_BIND inbind[1];
memset(inbind, 0, sizeof(inbind));
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 {
+ boost::shared_ptr<MySqlHostIPv6Exchange> host_ipv6_exchange(
+ new MySqlHostIPv6Exchange(MySqlHostWithOptionsExchange::DHCP6_ONLY));
+
// Set up the WHERE clause value
MYSQL_BIND inbind[1];
memset(inbind, 0, sizeof(inbind));
ConstHostCollection result;
impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_SUBID6,
- inbind, impl_->host_ipv6_exchange_,
- result, false);
+ inbind, host_ipv6_exchange, result, false);
return (result);
}
size_t& /*source_index*/,
uint64_t lower_host_id,
const HostPageSize& page_size) const {
+ boost::shared_ptr<MySqlHostWithOptionsExchange> host_ipv4_exchange(
+ new MySqlHostWithOptionsExchange(MySqlHostWithOptionsExchange::DHCP4_ONLY));
+
// Set up the WHERE clause value
MYSQL_BIND inbind[3];
memset(inbind, 0, sizeof(inbind));
ConstHostCollection result;
impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_SUBID4_PAGE,
- inbind, impl_->host_exchange_,
- result, false);
+ inbind, host_ipv4_exchange, result, false);
return (result);
}
size_t& /*source_index*/,
uint64_t lower_host_id,
const HostPageSize& page_size) const {
+ boost::shared_ptr<MySqlHostIPv6Exchange> host_ipv6_exchange(
+ new MySqlHostIPv6Exchange(MySqlHostWithOptionsExchange::DHCP6_ONLY));
+
// Set up the WHERE clause value
MYSQL_BIND inbind[3];
memset(inbind, 0, sizeof(inbind));
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 {
+ boost::shared_ptr<MySqlHostWithOptionsExchange> host_ipv4_exchange(
+ new MySqlHostWithOptionsExchange(MySqlHostWithOptionsExchange::DHCP4_ONLY));
// Set up the WHERE clause value
MYSQL_BIND inbind[1];
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);
}
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const {
+ boost::shared_ptr<MySqlHostWithOptionsExchange> host_ipv4_exchange(
+ new MySqlHostWithOptionsExchange(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");
}
+ boost::shared_ptr<MySqlHostWithOptionsExchange> host_ipv4_exchange(
+ new MySqlHostWithOptionsExchange(MySqlHostWithOptionsExchange::DHCP4_ONLY));
+
// Set up the WHERE clause value
MYSQL_BIND inbind[2];
uint32_t subnet = 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);
}
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const {
+ boost::shared_ptr<MySqlHostIPv6Exchange> host_ipv6_exchange(
+ new MySqlHostIPv6Exchange(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");
+ }
+
+ boost::shared_ptr<MySqlHostIPv6Exchange> host_ipv6_exchange(
+ new MySqlHostIPv6Exchange(MySqlHostWithOptionsExchange::DHCP6_ONLY));
// Set up the WHERE clause value
MYSQL_BIND inbind[2];
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;
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");
+ }
+
+ boost::shared_ptr<MySqlHostIPv6Exchange> host_ipv6_exchange(
+ new MySqlHostIPv6Exchange(MySqlHostWithOptionsExchange::DHCP6_ONLY));
+
// Set up the WHERE clause value
MYSQL_BIND inbind[2];
memset(inbind, 0, sizeof(inbind));
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;
MYSQL_SCHEMA_VERSION_MINOR);
std::pair<uint32_t, uint32_t> 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);
- }
-
- // Enable autocommit. To avoid a flush to disk on every commit, the global
- // parameter innodb_flush_log_at_trx_commit should be set to 2. This will
- // cause the changes to be written to the log, but flushed to disk in the
- // background every second. Setting the parameter to that value will speed
- // up the system, but at the risk of losing data if the system crashes.
- my_bool result = mysql_autocommit(conn_.mysql_, 1);
- if (result != 0) {
- isc_throw(DbOperationError, mysql_error(conn_.mysql_));
+ isc_throw(DbOpenError, "MySQL schema version mismatch: need version: "
+ << code_version.first << "." << code_version.second
+ << " found version: " << db_version.first << "."
+ << db_version.second);
}
// 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() {
bool
MySqlLeaseMgr::addLease(const Lease4Ptr& lease) {
+ boost::scoped_ptr<MySqlLease4Exchange> exchange4(new MySqlLease4Exchange());
+
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<MYSQL_BIND> bind = exchange4_->createBindForSend(lease);
+ std::vector<MYSQL_BIND> bind = exchange4->createBindForSend(lease);
// ... and drop to common code.
return (addLeaseCommon(INSERT_LEASE4, bind));
bool
MySqlLeaseMgr::addLease(const Lease6Ptr& lease) {
+ boost::scoped_ptr<MySqlLease6Exchange> exchange6(new MySqlLease6Exchange());
+
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<MYSQL_BIND> bind = exchange6_->createBindForSend(lease);
+ std::vector<MYSQL_BIND> bind = exchange6->createBindForSend(lease);
// ... and drop to common code.
return (addLeaseCommon(INSERT_LEASE6, bind));
}
}
+void MySqlLeaseMgr::getLeaseCollection(StatementIndex stindex, MYSQL_BIND* bind,
+ Lease4Collection& result) const {
+ boost::scoped_ptr<MySqlLease4Exchange> exchange4(new MySqlLease4Exchange());
+ getLeaseCollection(stindex, bind, exchange4, result);
+}
+
+void MySqlLeaseMgr::getLeaseCollection(StatementIndex stindex, MYSQL_BIND* bind,
+ Lease6Collection& result) const {
+ boost::scoped_ptr<MySqlLease6Exchange> exchange6(new MySqlLease6Exchange());
+ getLeaseCollection(stindex, bind, exchange6, result);
+}
+
void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* bind,
Lease4Ptr& result) const {
+ boost::scoped_ptr<MySqlLease4Exchange> exchange4(new MySqlLease4Exchange());
+
// 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()) {
void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* bind,
Lease6Ptr& result) const {
+ boost::scoped_ptr<MySqlLease6Exchange> exchange6(new MySqlLease6Exchange());
+
// 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()) {
void
MySqlLeaseMgr::updateLease4(const Lease4Ptr& lease) {
+ boost::scoped_ptr<MySqlLease4Exchange> exchange4(new MySqlLease4Exchange());
+
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<MYSQL_BIND> bind = exchange4_->createBindForSend(lease);
+ std::vector<MYSQL_BIND> bind = exchange4->createBindForSend(lease);
// Set up the WHERE clause and append it to the MYSQL_BIND array
MYSQL_BIND where;
void
MySqlLeaseMgr::updateLease6(const Lease6Ptr& lease) {
+ boost::scoped_ptr<MySqlLease6Exchange> exchange6(new MySqlLease6Exchange());
+
const StatementIndex stindex = UPDATE_LEASE6;
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
.arg(lease->type_);
// Create the MYSQL_BIND array for the data being updated
- std::vector<MYSQL_BIND> bind = exchange6_->createBindForSend(lease);
+ std::vector<MYSQL_BIND> bind = exchange6->createBindForSend(lease);
// Set up the WHERE clause value
MYSQL_BIND where;
/// @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
///
/// @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
///
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<MySqlLease4Exchange> exchange4_; ///< Exchange object
- boost::scoped_ptr<MySqlLease6Exchange> exchange6_; ///< Exchange object
-
/// @brief MySQL connection
db::MySqlConnection conn_;
};
GET_HOST_SUBID_ADDR, // Gets host by IPv4 SubnetID and IPv4 address
GET_HOST_PREFIX, // Gets host by IPv6 prefix
GET_HOST_SUBID6_ADDR, // Gets host by IPv6 SubnetID and IPv6 prefix
+ GET_HOST_SUBID4, // Gets hosts by IPv4 SubnetID
+ GET_HOST_SUBID6, // Gets hosts by IPv6 SubnetID
+ GET_HOST_SUBID4_PAGE, // Gets hosts by IPv4 SubnetID beginning by HID
+ GET_HOST_SUBID6_PAGE, // Gets hosts by IPv6 SubnetID beginning by HID
INSERT_HOST, // Insert new host to collection
INSERT_V6_RESRV, // Insert v6 reservation
INSERT_V4_HOST_OPTION, // Insert DHCPv4 option
DEL_HOST_ADDR4, // Delete v4 host (subnet-id, addr4)
DEL_HOST_SUBID4_ID, // Delete v4 host (subnet-id, ident.type, identifier)
DEL_HOST_SUBID6_ID, // Delete v6 host (subnet-id, ident.type, identifier)
- GET_HOST_SUBID4, // Gets hosts by IPv4 SubnetID
- GET_HOST_SUBID6, // Gets hosts by IPv6 SubnetID
- GET_HOST_SUBID4_PAGE, // Gets hosts by IPv4 SubnetID beginning by HID
- GET_HOST_SUBID6_PAGE, // Gets hosts by IPv6 SubnetID beginning by HID
NUM_STATEMENTS // Number of statements
};
/// has failed.
std::pair<uint32_t, uint32_t> getVersion() const;
- /// @brief Pointer to the object representing an exchange which
- /// can be used to retrieve hosts and DHCPv4 options.
- boost::shared_ptr<PgSqlHostWithOptionsExchange> 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<PgSqlHostIPv6Exchange> 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<PgSqlHostIPv6Exchange> host_ipv46_exchange_;
-
- /// @brief Pointer to an object representing an exchange which can
- /// be used to insert new IPv6 reservation.
- boost::shared_ptr<PgSqlIPv6ReservationExchange> 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<PgSqlOptionExchange> host_option_exchange_;
-
/// @brief PgSQL connection
PgSqlConnection conn_;
PgSqlHostDataSourceImpl::
PgSqlHostDataSourceImpl(const PgSqlConnection::ParameterMap& parameters)
- : host_exchange_(new PgSqlHostWithOptionsExchange(PgSqlHostWithOptionsExchange::DHCP4_ONLY)),
- host_ipv6_exchange_(new PgSqlHostIPv6Exchange(PgSqlHostWithOptionsExchange::DHCP6_ONLY)),
- host_ipv46_exchange_(new PgSqlHostIPv6Exchange(PgSqlHostWithOptionsExchange::
- DHCP4_AND_DHCP6)),
- host_ipv6_reservation_exchange_(new PgSqlIPv6ReservationExchange()),
- host_option_exchange_(new PgSqlOptionExchange()),
- conn_(parameters),
+ : conn_(parameters),
is_readonly_(false) {
// Open the database.
void
PgSqlHostDataSourceImpl::addResv(const IPv6Resrv& resv,
const HostID& id) {
+ boost::shared_ptr<PgSqlIPv6ReservationExchange> host_ipv6_reservation_exchange(
+ new PgSqlIPv6ReservationExchange());
+
PsqlBindArrayPtr bind_array;
- bind_array = host_ipv6_reservation_exchange_->createBindForSend(resv, id);
+ bind_array = host_ipv6_reservation_exchange->createBindForSend(resv, id);
+
addStatement(INSERT_V6_RESRV, bind_array);
}
const std::string& opt_space,
const Optional<SubnetID>&,
const HostID& id) {
+ boost::shared_ptr<PgSqlOptionExchange> host_option_exchange(new PgSqlOptionExchange());
+
PsqlBindArrayPtr bind_array;
- bind_array = host_option_exchange_->createBindForSend(opt_desc, opt_space,
- id);
+ bind_array = host_option_exchange->createBindForSend(opt_desc, opt_space, id);
+
addStatement(stindex, bind_array);
}
// Return single record if present, else clear the host.
ConstHostPtr result;
- if (!collection.empty())
+ if (!collection.empty()) {
result = *collection.begin();
+ }
return (result);
}
// If operating in read-only mode, throw exception.
impl_->checkReadOnly();
+ boost::shared_ptr<PgSqlHostWithOptionsExchange> host_ipv4_exchange(
+ new PgSqlHostWithOptionsExchange(PgSqlHostWithOptionsExchange::DHCP4_ONLY));
+
// Initiate PostgreSQL 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
PgSqlTransaction transaction(impl_->conn_);
// Create the PgSQL Bind array for the host
- PsqlBindArrayPtr bind_array = impl_->host_exchange_->createBindForSend(host);
+ PsqlBindArrayPtr bind_array = host_ipv4_exchange->createBindForSend(host);
// ... and insert the host.
uint32_t host_id = impl_->addStatement(PgSqlHostDataSourceImpl::INSERT_HOST,
PgSqlHostDataSource::getAll(const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const {
+ boost::shared_ptr<PgSqlHostIPv6Exchange> host_ipv46_exchange(
+ new PgSqlHostIPv6Exchange(PgSqlHostWithOptionsExchange::DHCP4_AND_DHCP6));
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
ConstHostCollection result;
impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_DHCPID,
- bind_array, impl_->host_ipv46_exchange_,
- result, false);
+ bind_array, host_ipv46_exchange, result, false);
return (result);
}
ConstHostCollection
PgSqlHostDataSource::getAll4(const SubnetID& subnet_id) const {
+ boost::shared_ptr<PgSqlHostWithOptionsExchange> host_ipv4_exchange(
+ new PgSqlHostWithOptionsExchange(PgSqlHostWithOptionsExchange::DHCP4_ONLY));
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
ConstHostCollection result;
impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID4,
- bind_array, impl_->host_exchange_,
- result, false);
+ bind_array, host_ipv4_exchange, result, false);
return (result);
}
ConstHostCollection
PgSqlHostDataSource::getAll6(const SubnetID& subnet_id) const {
+ boost::shared_ptr<PgSqlHostIPv6Exchange> host_ipv6_exchange(
+ new PgSqlHostIPv6Exchange(PgSqlHostWithOptionsExchange::DHCP6_ONLY));
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
ConstHostCollection result;
impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID6,
- bind_array, impl_->host_ipv6_exchange_,
- result, false);
+ bind_array, host_ipv6_exchange, result, false);
return (result);
}
size_t& /*source_index*/,
uint64_t lower_host_id,
const HostPageSize& page_size) const {
+ boost::shared_ptr<PgSqlHostWithOptionsExchange> host_ipv4_exchange(
+ new PgSqlHostWithOptionsExchange(PgSqlHostWithOptionsExchange::DHCP4_ONLY));
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
ConstHostCollection result;
impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID4_PAGE,
- bind_array, impl_->host_exchange_,
- result, false);
+ bind_array, host_ipv4_exchange, result, false);
return (result);
}
size_t& /*source_index*/,
uint64_t lower_host_id,
const HostPageSize& page_size) const {
+ boost::shared_ptr<PgSqlHostIPv6Exchange> host_ipv6_exchange(
+ new PgSqlHostIPv6Exchange(PgSqlHostWithOptionsExchange::DHCP6_ONLY));
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
ConstHostCollection result;
impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID6_PAGE,
- bind_array, impl_->host_ipv6_exchange_,
- result, false);
+ bind_array, host_ipv6_exchange, result, false);
return (result);
}
ConstHostCollection
PgSqlHostDataSource::getAll4(const asiolink::IOAddress& address) const {
+ boost::shared_ptr<PgSqlHostWithOptionsExchange> host_ipv4_exchange(
+ new PgSqlHostWithOptionsExchange(PgSqlHostWithOptionsExchange::DHCP4_ONLY));
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
ConstHostCollection result;
impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_ADDR, bind_array,
- impl_->host_exchange_, result, false);
+ host_ipv4_exchange, result, false);
return (result);
}
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const {
+ boost::shared_ptr<PgSqlHostWithOptionsExchange> host_ipv4_exchange(
+ new PgSqlHostWithOptionsExchange(PgSqlHostWithOptionsExchange::DHCP4_ONLY));
return (impl_->getHost(subnet_id, identifier_type, identifier_begin,
identifier_len,
PgSqlHostDataSourceImpl::GET_HOST_SUBID4_DHCPID,
- impl_->host_exchange_));
+ host_ipv4_exchange));
}
ConstHostPtr
PgSqlHostDataSource::get4(const SubnetID& subnet_id,
const asiolink::IOAddress& address) const {
if (!address.isV4()) {
- isc_throw(BadValue, "PgSqlHostDataSource::get4(id, address) - "
- " wrong address type, address supplied is an IPv6 address");
+ isc_throw(BadValue, "PgSqlHostDataSource::get4(id, address): "
+ "wrong address type, address supplied is an IPv6 address");
}
+ boost::shared_ptr<PgSqlHostWithOptionsExchange> host_ipv4_exchange(
+ new PgSqlHostWithOptionsExchange(PgSqlHostWithOptionsExchange::DHCP4_ONLY));
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
ConstHostCollection collection;
impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID_ADDR,
- bind_array, impl_->host_exchange_, collection,
- true);
+ bind_array, 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);
}
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const {
+ boost::shared_ptr<PgSqlHostIPv6Exchange> host_ipv6_exchange(
+ new PgSqlHostIPv6Exchange(PgSqlHostWithOptionsExchange::DHCP6_ONLY));
return (impl_->getHost(subnet_id, identifier_type, identifier_begin,
identifier_len, PgSqlHostDataSourceImpl::GET_HOST_SUBID6_DHCPID,
- impl_->host_ipv6_exchange_));
+ host_ipv6_exchange));
}
ConstHostPtr
PgSqlHostDataSource::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, "PgSqlHostDataSource::get6(prefix, prefix_len): "
+ "wrong address type, address supplied is an IPv4 address");
+ }
+
+ boost::shared_ptr<PgSqlHostIPv6Exchange> host_ipv6_exchange(
+ new PgSqlHostIPv6Exchange(PgSqlHostWithOptionsExchange::DHCP6_ONLY));
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
ConstHostCollection collection;
impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_PREFIX,
- bind_array, impl_->host_ipv6_exchange_,
- collection, true);
+ bind_array, host_ipv6_exchange, collection, true);
// Return single record if present, else clear the host.
ConstHostPtr result;
ConstHostPtr
PgSqlHostDataSource::get6(const SubnetID& subnet_id,
const asiolink::IOAddress& address) const {
- /// @todo: Check that prefix is v6 address, not v4.
+ if (!address.isV6()) {
+ isc_throw(BadValue, "PgSqlHostDataSource::get6(id, address): "
+ "wrong address type, address supplied is an IPv4 address");
+ }
+
+ boost::shared_ptr<PgSqlHostIPv6Exchange> host_ipv6_exchange(
+ new PgSqlHostIPv6Exchange(PgSqlHostWithOptionsExchange::DHCP6_ONLY));
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
ConstHostCollection collection;
impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID6_ADDR,
- bind_array, impl_->host_ipv6_exchange_,
- collection, true);
+ bind_array, host_ipv6_exchange, collection, true);
// Return single record if present, else clear the host.
ConstHostPtr result;
lease_ = lease;
try {
- addr_str_ = boost::lexical_cast<std::string>
- (lease->addr_.toUint32());
+ addr_str_ = boost::lexical_cast<std::string>(lease->addr_.toUint32());
bind_array.add(addr_str_);
if (lease->hwaddr_ && !lease->hwaddr_->hwaddr_.empty()) {
};
PgSqlLeaseMgr::PgSqlLeaseMgr(const DatabaseConnection::ParameterMap& parameters)
- : LeaseMgr(), exchange4_(new PgSqlLease4Exchange()),
- exchange6_(new PgSqlLease6Exchange()), conn_(parameters) {
+ : LeaseMgr(), conn_(parameters) {
conn_.openDatabase();
// Validate schema version first.
bool
PgSqlLeaseMgr::addLease(const Lease4Ptr& lease) {
+ boost::scoped_ptr<PgSqlLease4Exchange> exchange4(new PgSqlLease4Exchange());
+
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_ADD_ADDR4).arg(lease->addr_.toText());
PsqlBindArray bind_array;
- exchange4_->createBindForSend(lease, bind_array);
+ exchange4->createBindForSend(lease, bind_array);
return (addLeaseCommon(INSERT_LEASE4, bind_array));
}
bool
PgSqlLeaseMgr::addLease(const Lease6Ptr& lease) {
+ boost::scoped_ptr<PgSqlLease6Exchange> exchange6(new PgSqlLease6Exchange());
+
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_ADD_ADDR6).arg(lease->addr_.toText());
PsqlBindArray bind_array;
- exchange6_->createBindForSend(lease, bind_array);
+ exchange6->createBindForSend(lease, bind_array);
return (addLeaseCommon(INSERT_LEASE6, bind_array));
}
}
}
+void
+PgSqlLeaseMgr::getLeaseCollection(StatementIndex stindex, db::PsqlBindArray& bind_array,
+ Lease4Collection& result) const {
+ boost::scoped_ptr<PgSqlLease4Exchange> exchange4(new PgSqlLease4Exchange());
+
+ getLeaseCollection(stindex, bind_array, exchange4, result);
+}
+
+void
+PgSqlLeaseMgr::getLeaseCollection(StatementIndex stindex, db::PsqlBindArray& bind_array,
+ Lease6Collection& result) const {
+ boost::scoped_ptr<PgSqlLease6Exchange> exchange6(new PgSqlLease6Exchange());
+
+ getLeaseCollection(stindex, bind_array, exchange6, result);
+}
+
void
PgSqlLeaseMgr::getLease(StatementIndex stindex, PsqlBindArray& bind_array,
Lease4Ptr& result) const {
+ boost::scoped_ptr<PgSqlLease4Exchange> exchange4(new PgSqlLease4Exchange());
+
// 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_array, exchange4_, collection, true);
+ getLeaseCollection(stindex, bind_array, exchange4, collection, true);
// Return single record if present, else clear the lease.
if (collection.empty()) {
void
PgSqlLeaseMgr::getLease(StatementIndex stindex, PsqlBindArray& bind_array,
Lease6Ptr& result) const {
+ boost::scoped_ptr<PgSqlLease6Exchange> exchange6(new PgSqlLease6Exchange());
+
// 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_array, exchange6_, collection, true);
+ getLeaseCollection(stindex, bind_array, exchange6, collection, true);
// Return single record if present, else clear the lease.
if (collection.empty()) {
PsqlBindArray bind_array;
// LEASE ADDRESS
- std::string addr_str = boost::lexical_cast<std::string>
- (addr.toUint32());
+ std::string addr_str = boost::lexical_cast<std::string>(addr.toUint32());
bind_array.add(addr_str);
// Get the data
void
PgSqlLeaseMgr::updateLease4(const Lease4Ptr& lease) {
+ boost::scoped_ptr<PgSqlLease4Exchange> exchange4(new PgSqlLease4Exchange());
+
const StatementIndex stindex = UPDATE_LEASE4;
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
// Create the BIND array for the data being updated
PsqlBindArray bind_array;
- exchange4_->createBindForSend(lease, bind_array);
+ exchange4->createBindForSend(lease, bind_array);
// Set up the WHERE clause and append it to the SQL_BIND array
- std::string addr4_ = boost::lexical_cast<std::string>
- (lease->addr_.toUint32());
- bind_array.add(addr4_);
+ std::string addr_str = boost::lexical_cast<std::string>(lease->addr_.toUint32());
+ bind_array.add(addr_str);
// Drop to common update code
updateLeaseCommon(stindex, bind_array, lease);
void
PgSqlLeaseMgr::updateLease6(const Lease6Ptr& lease) {
+ boost::scoped_ptr<PgSqlLease6Exchange> exchange6(new PgSqlLease6Exchange());
+
const StatementIndex stindex = UPDATE_LEASE6;
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
// Create the BIND array for the data being updated
PsqlBindArray bind_array;
- exchange6_->createBindForSend(lease, bind_array);
+ exchange6->createBindForSend(lease, bind_array);
// Set up the WHERE clause and append it to the BIND array
std::string addr_str = lease->addr_.toText();
/// @throw isc::db::MultipleRecords Multiple records were retrieved
/// from the database where only one was expected.
void getLeaseCollection(StatementIndex stindex, db::PsqlBindArray& bind_array,
- Lease4Collection& result) const {
- getLeaseCollection(stindex, bind_array, exchange4_, result);
- }
+ Lease4Collection& result) const;
/// @brief Get Lease6 Collection
///
/// @throw isc::db::MultipleRecords Multiple records were retrieved
/// from the database where only one was expected.
void getLeaseCollection(StatementIndex stindex, db::PsqlBindArray& bind_array,
- Lease6Collection& result) const {
- getLeaseCollection(stindex, bind_array, exchange6_, result);
- }
+ Lease6Collection& result) const;
/// @brief Get Lease4 Common Code
///
uint64_t deleteExpiredReclaimedLeasesCommon(const uint32_t secs,
StatementIndex statement_index);
- /// 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<PgSqlLease4Exchange> exchange4_; ///< Exchange object
- boost::scoped_ptr<PgSqlLease6Exchange> exchange6_; ///< Exchange object
-
/// PostgreSQL connection handle
db::PgSqlConnection conn_;
};
if (status != mysql_) {
isc_throw(DbOpenError, mysql_error(mysql_));
}
+
+ // Enable autocommit. In case transaction is explicitly used, this
+ // setting will be overwritten for the transaction. However, there are
+ // cases when lack of autocommit could cause transactions to hang
+ // until commit or rollback is explicitly called. This already
+ // 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(mysql_, 1);
+ if (auto_commit != MLM_FALSE) {
+ isc_throw(DbOperationError, mysql_error(mysql_));
+ }
}
}
}
-void MySqlConnection::clearStatements() {
- statements_.clear();
- text_statements_.clear();
-}
-
/// @brief Destructor
MySqlConnection::~MySqlConnection() {
// Free up the prepared statements, ignoring errors. (What would we do
void prepareStatements(const TaggedStatement* start_statement,
const TaggedStatement* end_statement);
- /// @brief Clears prepared statements and text statements.
- void clearStatements();
-
/// @brief Open Database
///
/// Opens the database using the information supplied in the parameters
try {
// Open new connection.
conn_.openDatabase();
- my_bool result = mysql_autocommit(conn_.mysql_, 1);
- if (result != 0) {
- isc_throw(DbOperationError, "failed to set autocommit option "
- "for test MySQL connection");
- }
// Create mysql_connection_test table.
createTestTable();