#include <dhcpsrv/dhcpsrv_log.h>
#include <dhcpsrv/pgsql_host_data_source.h>
#include <util/buffer.h>
+#include <util/multi_threading_mgr.h>
#include <util/optional.h>
#include <boost/algorithm/string/split.hpp>
#include <boost/static_assert.hpp>
#include <stdint.h>
+
+#include <mutex>
#include <string>
using namespace isc;
/// bound values extracted from host
///
/// @throw DbOperationError if bind_array cannot be populated.
- PsqlBindArrayPtr
- createBindForSend(const HostPtr& host) {
+ PsqlBindArrayPtr createBindForSend(const HostPtr& host) {
if (!host) {
isc_throw(BadValue, "createBindForSend:: host object is NULL");
}
/// a second time.
///
/// @return HostPtr to the newly created Host object
+ ///
/// @throw DbOperationError if the host cannot be created.
HostPtr retrieveHost(const PgSqlResult& r, int row,
const HostID& peeked_host_id = 0) {
///
/// @return pointer to newly constructed bind_array containing the
/// bound values extracted from host
- PsqlBindArrayPtr
- createBindForSend(const OptionDescriptor& opt_desc,
- const std::string& opt_space,
- const HostID& host_id) {
+ PsqlBindArrayPtr createBindForSend(const OptionDescriptor& opt_desc,
+ const std::string& opt_space,
+ const HostID& host_id) {
// Hold pointer to the option to make sure it remains valid until
// we complete a query.
option_ = opt_desc.option_;
OptionPtr option_;
};
-} // end of anonymous namespace
+} // namespace
namespace isc {
namespace dhcp {
+/// @brief PostgreSQL Host Context
+///
+/// This class stores the thread context for the manager pool.
+class PgSqlHostContext {
+public:
+
+ /// @brief Constructor
+ ///
+ /// @param parameters See PgSqlHostMgr constructor.
+ PgSqlHostContext(const DatabaseConnection::ParameterMap& parameters);
+
+ /// 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".)
+
+ /// @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 PostgreSQL connection
+ PgSqlConnection conn_;
+
+ /// @brief Indicates if the database is opened in read only mode.
+ bool is_readonly_;
+};
+
+/// @brief PostgreSQL Host Context Pool
+///
+/// This class provides a pool of contexts.
+class PgSqlHostContextPool {
+public:
+
+ /// @brief The vector of available contexts.
+ std::vector<PgSqlHostContextPtr> pool_;
+
+ /// @brief The mutex to protect pool access.
+ std::mutex mutex_;
+};
+
+/// @brief Type of pointers to context pools.
+typedef boost::shared_ptr<PgSqlHostContextPool> PgSqlHostContextPoolPtr;
+
/// @brief Implementation of the @ref PgSqlHostDataSource.
class PgSqlHostDataSourceImpl {
public:
/// @brief Destructor.
~PgSqlHostDataSourceImpl();
+ /// @brief Create a new context.
+ ///
+ /// The database is opened with all the SQL commands pre-compiled.
+ ///
+ /// @return A new (never null) context.
+ ///
+ /// @throw isc::dhcp::NoDatabaseName Mandatory database name not given.
+ /// @throw isc::db::DbOperationError An operation on the open database has
+ /// failed.
+ PgSqlHostContextPtr createContext() const;
+
/// @brief Executes statements which insert a row into one of the tables.
///
+ /// @param ctx Context
/// @param stindex Index of a statement being executed.
/// @param bind Vector of PgsqlBindArray objects to be used for the query
/// @param return_last_id flag indicating whether or not the insert
/// the value in the result set in the first col of the first row.
///
/// @throw isc::db::DuplicateEntry Database throws duplicate entry error
- uint64_t addStatement(PgSqlHostDataSourceImpl::StatementIndex stindex,
+ uint64_t addStatement(PgSqlHostContextPtr& ctx,
+ PgSqlHostDataSourceImpl::StatementIndex stindex,
PsqlBindArrayPtr& bind,
const bool return_last_id = false);
/// @brief Executes statements that delete records.
///
+ /// @param ctx Context
/// @param stindex Index of a statement being executed.
/// @param bind pointer to PsqlBindArray objects to be used for the query
+ ///
/// @return true if any records were deleted, false otherwise
- bool delStatement(PgSqlHostDataSourceImpl::StatementIndex stindex,
+ bool delStatement(PgSqlHostContextPtr& ctx,
+ PgSqlHostDataSourceImpl::StatementIndex stindex,
PsqlBindArrayPtr& bind);
/// @brief Inserts IPv6 Reservation into ipv6_reservation table.
///
+ /// @param ctx Context
/// @param resv IPv6 Reservation to be added
/// @param id ID of a host owning this reservation
- void addResv(const IPv6Resrv& resv, const HostID& id);
+ void addResv(PgSqlHostContextPtr& ctx,
+ const IPv6Resrv& resv,
+ const HostID& id);
/// @brief Inserts a single DHCP option into the database.
///
+ /// @param ctx Context
/// @param stindex Index of a statement being executed.
/// @param opt_desc Option descriptor holding information about an option
/// to be inserted into the database.
/// @param opt_space Option space name.
/// @param subnet_id Subnet identifier.
/// @param host_id Host identifier.
- void addOption(const PgSqlHostDataSourceImpl::StatementIndex& stindex,
+ void addOption(PgSqlHostContextPtr& ctx,
+ const PgSqlHostDataSourceImpl::StatementIndex& stindex,
const OptionDescriptor& opt_desc,
const std::string& opt_space,
const Optional<SubnetID>& subnet_id,
/// @brief Inserts multiple options into the database.
///
+ /// @param ctx Context
/// @param stindex Index of a statement being executed.
/// @param options_cfg An object holding a collection of options to be
/// inserted into the database.
/// @param host_id Host identifier retrieved using getColumnValue
/// in addStatement method
- void addOptions(const StatementIndex& stindex,
+ void addOptions(PgSqlHostContextPtr& ctx,
+ const StatementIndex& stindex,
const ConstCfgOptionPtr& options_cfg,
const uint64_t host_id);
/// Whether IPv6 reservations and/or options are assigned to the
/// @ref Host objects depends on the type of the exchange object.
///
+ /// @param ctx Context
/// @param stindex Statement index.
/// @param bind Pointer to an array of PgSQL bindings.
/// @param exchange Pointer to the exchange object used for the
/// @param [out] result Reference to the collection of hosts returned.
/// @param single A boolean value indicating if a single host is
/// expected to be returned, or multiple hosts.
- void getHostCollection(StatementIndex stindex, PsqlBindArrayPtr bind,
+ void getHostCollection(PgSqlHostContextPtr& ctx,
+ StatementIndex stindex, PsqlBindArrayPtr bind,
boost::shared_ptr<PgSqlHostExchange> exchange,
ConstHostCollection& result, bool single) const;
/// This method is used by both PgSqlHostDataSource::get4 and
/// PgSqlHostDataSource::get6 methods.
///
+ /// @param ctx Context
/// @param subnet_id Subnet identifier.
/// @param identifier_type Identifier type.
/// @param identifier_begin Pointer to a beginning of a buffer containing
///
/// @return Pointer to const instance of Host or null pointer if
/// no host found.
- ConstHostPtr getHost(const SubnetID& subnet_id,
+ ConstHostPtr getHost(PgSqlHostContextPtr& ctx,
+ const SubnetID& subnet_id,
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len,
/// database. If the backend is operating in read-only mode this
/// method will throw exception.
///
+ /// @param ctx Context
+ ///
/// @throw DbReadOnly if backend is operating in read only mode.
- void checkReadOnly() const;
+ void checkReadOnly(PgSqlHostContextPtr& ctx) const;
/// @brief Returns PostgreSQL schema version of the open database
///
/// 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 The parameters
PgSqlConnection::ParameterMap parameters_;
- /// @brief PgSQL connection
- PgSqlConnection conn_;
-
- /// @brief Indicates if the database is opened in read only mode.
- bool is_readonly_;
+ /// @brief The pool of contexts
+ PgSqlHostContextPoolPtr pool_;
};
namespace {
// results in multiple rows being returned for the same host. The hosts are
// retrieved by subnet id.
{1,
- { OID_INT8 }, "get_host_subid4",
+ { OID_INT8 },
+ "get_host_subid4",
"SELECT h.host_id, h.dhcp_identifier, 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, "
// are usually many hosts in a subnet. The amount of returned data may
// be huge.
{1,
- { OID_INT8 }, "get_host_subid6",
+ { OID_INT8 },
+ "get_host_subid6",
"SELECT h.host_id, h.dhcp_identifier, "
" h.dhcp_identifier_type, h.dhcp4_subnet_id, "
" h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
// Using fixed scope_id = 3, which associates an option with host.
{7,
{ OID_INT2, OID_BYTEA, OID_TEXT,
- OID_VARCHAR, OID_BOOL, OID_TEXT, OID_INT8},
+ OID_VARCHAR, OID_BOOL, OID_TEXT, OID_INT8 },
"insert_v4_host_option",
"INSERT INTO dhcp4_options(code, value, formatted_value, space, "
" persistent, user_context, host_id, scope_id) "
// Using fixed scope_id = 3, which associates an option with host.
{7,
{ OID_INT2, OID_BYTEA, OID_TEXT,
- OID_VARCHAR, OID_BOOL, OID_TEXT, OID_INT8},
+ OID_VARCHAR, OID_BOOL, OID_TEXT, OID_INT8 },
"insert_v6_host_option",
"INSERT INTO dhcp6_options(code, value, formatted_value, space, "
" persistent, user_context, host_id, scope_id) "
}
};
-}; // end anonymous namespace
+} // namespace
+
+// PgSqlHostContext Constructor
-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()),
- parameters_(parameters),
- conn_(parameters),
- is_readonly_(false) {
+PgSqlHostContext::PgSqlHostContext(const DatabaseConnection::ParameterMap& parameters)
+ : conn_(parameters), is_readonly_(true) {
+}
+
+// PgSqlHostContextAlloc Constructor and Destructor
+
+PgSqlHostDataSource::PgSqlHostContextAlloc::PgSqlHostContextAlloc(
+ const PgSqlHostDataSourceImpl& mgr) : ctx_(), mgr_(mgr) {
+
+ if (MultiThreadingMgr::instance().getMode()) {
+ {
+ lock_guard<mutex> lock(mgr_.pool_->mutex_);
+ if (!mgr_.pool_->pool_.empty()) {
+ ctx_ = mgr_.pool_->pool_.back();
+ mgr_.pool_->pool_.pop_back();
+ }
+ }
+ if (!ctx_) {
+ ctx_ = mgr_.createContext();
+ }
+ } else {
+ if (mgr_.pool_->pool_.empty()) {
+ isc_throw(Unexpected, "No available PostgreSQL lease context?!");
+ }
+ ctx_ = mgr_.pool_->pool_.back();
+ }
+}
+
+PgSqlHostDataSource::PgSqlHostContextAlloc::~PgSqlHostContextAlloc() {
+ if (MultiThreadingMgr::instance().getMode()) {
+ lock_guard<mutex> lock(mgr_.pool_->mutex_);
+ mgr_.pool_->pool_.push_back(ctx_);
+ }
+}
+
+PgSqlHostDataSourceImpl::PgSqlHostDataSourceImpl(const PgSqlConnection::ParameterMap& parameters)
+ : parameters_(parameters) {
// Validate the schema version first.
std::pair<uint32_t, uint32_t> code_version(PG_SCHEMA_VERSION_MAJOR,
isc_throw(DbOpenError,
"PostgreSQL schema version mismatch: need version: "
<< code_version.first << "." << code_version.second
- << " found version: " << db_version.first << "."
+ << " found version: " << db_version.first << "."
<< db_version.second);
}
+ // Create an initial context.
+ pool_.reset(new PgSqlHostContextPool());
+ pool_->pool_.push_back(createContext());
+}
+
+// Create context.
+
+PgSqlHostContextPtr
+PgSqlHostDataSourceImpl::createContext() const {
+ PgSqlHostContextPtr ctx(new PgSqlHostContext(parameters_));
+
// Open the database.
- conn_.openDatabase();
+ ctx->conn_.openDatabase();
// Now prepare the SQL statements.
- conn_.prepareStatements(tagged_statements.begin(),
- tagged_statements.begin() + WRITE_STMTS_BEGIN);
+ ctx->conn_.prepareStatements(tagged_statements.begin(),
+ tagged_statements.begin() + WRITE_STMTS_BEGIN);
// Check if the backend is explicitly configured to operate with
// read only access to the database.
- is_readonly_ = conn_.configuredReadOnly();
+ ctx->is_readonly_ = ctx->conn_.configuredReadOnly();
// If we are using read-write mode for the database we also prepare
// statements for INSERTS etc.
- if (!is_readonly_) {
- conn_.prepareStatements(tagged_statements.begin() + WRITE_STMTS_BEGIN,
- tagged_statements.end());
+ if (!ctx->is_readonly_) {
+ ctx->conn_.prepareStatements(tagged_statements.begin() + WRITE_STMTS_BEGIN,
+ tagged_statements.end());
} else {
LOG_INFO(dhcpsrv_logger, DHCPSRV_PGSQL_HOST_DB_READONLY);
}
+
+ ctx->host_exchange_.reset(new PgSqlHostWithOptionsExchange(PgSqlHostWithOptionsExchange::DHCP4_ONLY));
+ ctx->host_ipv6_exchange_.reset(new PgSqlHostIPv6Exchange(PgSqlHostWithOptionsExchange::DHCP6_ONLY));
+ ctx->host_ipv46_exchange_.reset(new PgSqlHostIPv6Exchange(PgSqlHostWithOptionsExchange::DHCP4_AND_DHCP6));
+ ctx->host_ipv6_reservation_exchange_.reset(new PgSqlIPv6ReservationExchange());
+ ctx->host_option_exchange_.reset(new PgSqlOptionExchange());
+
+ return (ctx);
}
PgSqlHostDataSourceImpl::~PgSqlHostDataSourceImpl() {
}
uint64_t
-PgSqlHostDataSourceImpl::addStatement(StatementIndex stindex,
+PgSqlHostDataSourceImpl::addStatement(PgSqlHostContextPtr& ctx,
+ StatementIndex stindex,
PsqlBindArrayPtr& bind_array,
const bool return_last_id) {
uint64_t last_id = 0;
- PgSqlResult r(PQexecPrepared(conn_, tagged_statements[stindex].name,
+ PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
tagged_statements[stindex].nbparams,
&bind_array->values_[0],
&bind_array->lengths_[0],
if (s != PGRES_COMMAND_OK) {
// Failure: check for the special case of duplicate entry.
- if (conn_.compareError(r, PgSqlConnection::DUPLICATE_KEY)) {
+ if (ctx->conn_.compareError(r, PgSqlConnection::DUPLICATE_KEY)) {
isc_throw(DuplicateEntry, "Database duplicate entry error");
}
// Connection determines if the error is fatal or not, and
// throws the appropriate exception
- conn_.checkStatementError(r, tagged_statements[stindex]);
+ ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
}
if (return_last_id) {
}
bool
-PgSqlHostDataSourceImpl::delStatement(StatementIndex stindex,
+PgSqlHostDataSourceImpl::delStatement(PgSqlHostContextPtr& ctx,
+ StatementIndex stindex,
PsqlBindArrayPtr& bind_array) {
- PgSqlResult r(PQexecPrepared(conn_, tagged_statements[stindex].name,
+ PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
tagged_statements[stindex].nbparams,
&bind_array->values_[0],
&bind_array->lengths_[0],
if (s != PGRES_COMMAND_OK) {
// Connection determines if the error is fatal or not, and
// throws the appropriate exception
- conn_.checkStatementError(r, tagged_statements[stindex]);
+ ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
}
// Now check how many rows (hosts) were deleted. This should be either
}
void
-PgSqlHostDataSourceImpl::addResv(const IPv6Resrv& resv,
+PgSqlHostDataSourceImpl::addResv(PgSqlHostContextPtr& ctx,
+ const IPv6Resrv& resv,
const HostID& id) {
- PsqlBindArrayPtr bind_array;
- bind_array = host_ipv6_reservation_exchange_->createBindForSend(resv, id);
- addStatement(INSERT_V6_RESRV, bind_array);
+ PsqlBindArrayPtr bind_array = ctx->host_ipv6_reservation_exchange_->createBindForSend(resv, id);
+
+ addStatement(ctx, INSERT_V6_RESRV, bind_array);
}
void
-PgSqlHostDataSourceImpl::addOption(const StatementIndex& stindex,
+PgSqlHostDataSourceImpl::addOption(PgSqlHostContextPtr& ctx,
+ const StatementIndex& stindex,
const OptionDescriptor& opt_desc,
const std::string& opt_space,
const Optional<SubnetID>&,
const HostID& id) {
- PsqlBindArrayPtr bind_array;
- bind_array = host_option_exchange_->createBindForSend(opt_desc, opt_space,
- id);
- addStatement(stindex, bind_array);
+ PsqlBindArrayPtr bind_array = ctx->host_option_exchange_->createBindForSend(opt_desc, opt_space, id);
+
+ addStatement(ctx, stindex, bind_array);
}
void
-PgSqlHostDataSourceImpl::addOptions(const StatementIndex& stindex,
+PgSqlHostDataSourceImpl::addOptions(PgSqlHostContextPtr& ctx,
+ const StatementIndex& stindex,
const ConstCfgOptionPtr& options_cfg,
const uint64_t host_id) {
// Get option space names and vendor space names and combine them within a
// For each option space retrieve all options and insert them into the
// database.
- for (std::list<std::string>::const_iterator space = option_spaces.begin();
- space != option_spaces.end(); ++space) {
+ for (auto space = option_spaces.begin(); space != option_spaces.end(); ++space) {
OptionContainerPtr options = options_cfg->getAll(*space);
if (options && !options->empty()) {
- for (OptionContainer::const_iterator opt = options->begin();
- opt != options->end(); ++opt) {
- addOption(stindex, *opt, *space, Optional<SubnetID>(),
- host_id);
+ for (auto opt = options->begin(); opt != options->end(); ++opt) {
+ addOption(ctx, stindex, *opt, *space, Optional<SubnetID>(), host_id);
}
}
}
}
void
-PgSqlHostDataSourceImpl::
-getHostCollection(StatementIndex stindex, PsqlBindArrayPtr bind_array,
- boost::shared_ptr<PgSqlHostExchange> exchange,
- ConstHostCollection& result, bool single) const {
+PgSqlHostDataSourceImpl::getHostCollection(PgSqlHostContextPtr& ctx,
+ StatementIndex stindex,
+ PsqlBindArrayPtr bind_array,
+ boost::shared_ptr<PgSqlHostExchange> exchange,
+ ConstHostCollection& result,
+ bool single) const {
exchange->clear();
- PgSqlResult r(PQexecPrepared(conn_, tagged_statements[stindex].name,
+ PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
tagged_statements[stindex].nbparams,
&bind_array->values_[0],
&bind_array->lengths_[0],
&bind_array->formats_[0], 0));
- conn_.checkStatementError(r, tagged_statements[stindex]);
+ ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
int rows = r.getRows();
- for(int row = 0; row < rows; ++row) {
+ for (int row = 0; row < rows; ++row) {
exchange->processRowData(result, r, row);
if (single && result.size() > 1) {
}
ConstHostPtr
-PgSqlHostDataSourceImpl::
-getHost(const SubnetID& subnet_id,
- const Host::IdentifierType& identifier_type,
- const uint8_t* identifier_begin,
- const size_t identifier_len,
- StatementIndex stindex,
- boost::shared_ptr<PgSqlHostExchange> exchange) const {
+PgSqlHostDataSourceImpl::getHost(PgSqlHostContextPtr& ctx,
+ const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin,
+ const size_t identifier_len,
+ StatementIndex stindex,
+ boost::shared_ptr<PgSqlHostExchange> exchange) const {
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
bind_array->add(identifier_begin, identifier_len);
ConstHostCollection collection;
- getHostCollection(stindex, bind_array, exchange, collection, true);
+ getHostCollection(ctx, stindex, bind_array, 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);
}
-std::pair<uint32_t, uint32_t> PgSqlHostDataSourceImpl::getVersion() const {
+std::pair<uint32_t, uint32_t>
+PgSqlHostDataSourceImpl::getVersion() const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_HOST_DB_GET_VERSION);
return (PgSqlConnection::getVersion(parameters_));
}
void
-PgSqlHostDataSourceImpl::checkReadOnly() const {
- if (is_readonly_) {
+PgSqlHostDataSourceImpl::checkReadOnly(PgSqlHostContextPtr& ctx) const {
+ if (ctx->is_readonly_) {
isc_throw(ReadOnlyDb, "PostgreSQL host database backend is configured"
" to operate in read only mode");
}
/*********** PgSqlHostDataSource *********************/
-PgSqlHostDataSource::
-PgSqlHostDataSource(const PgSqlConnection::ParameterMap& parameters)
+PgSqlHostDataSource::PgSqlHostDataSource(const PgSqlConnection::ParameterMap& parameters)
: impl_(new PgSqlHostDataSourceImpl(parameters)) {
}
PgSqlHostDataSource::~PgSqlHostDataSource() {
- delete impl_;
}
void
PgSqlHostDataSource::add(const HostPtr& host) {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
// If operating in read-only mode, throw exception.
- impl_->checkReadOnly();
+ impl_->checkReadOnly(ctx);
// 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
// the PgSqlTransaction class.
- PgSqlTransaction transaction(impl_->conn_);
+ PgSqlTransaction transaction(ctx->conn_);
// Create the PgSQL Bind array for the host
- PsqlBindArrayPtr bind_array = impl_->host_exchange_->createBindForSend(host);
+ PsqlBindArrayPtr bind_array = ctx->host_exchange_->createBindForSend(host);
// ... and insert the host.
- uint32_t host_id = impl_->addStatement(PgSqlHostDataSourceImpl::INSERT_HOST,
+ uint32_t host_id = impl_->addStatement(ctx, PgSqlHostDataSourceImpl::INSERT_HOST,
bind_array, true);
// Insert DHCPv4 options.
ConstCfgOptionPtr cfg_option4 = host->getCfgOption4();
if (cfg_option4) {
- impl_->addOptions(PgSqlHostDataSourceImpl::INSERT_V4_HOST_OPTION,
+ impl_->addOptions(ctx, PgSqlHostDataSourceImpl::INSERT_V4_HOST_OPTION,
cfg_option4, host_id);
}
// Insert DHCPv6 options.
ConstCfgOptionPtr cfg_option6 = host->getCfgOption6();
if (cfg_option6) {
- impl_->addOptions(PgSqlHostDataSourceImpl::INSERT_V6_HOST_OPTION,
+ impl_->addOptions(ctx, PgSqlHostDataSourceImpl::INSERT_V6_HOST_OPTION,
cfg_option6, host_id);
}
if (std::distance(v6resv.first, v6resv.second) > 0) {
for (IPv6ResrvIterator resv = v6resv.first; resv != v6resv.second;
++resv) {
- impl_->addResv(resv->second, host_id);
+ impl_->addResv(ctx, resv->second, host_id);
}
}
bool
PgSqlHostDataSource::del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
// If operating in read-only mode, throw exception.
- impl_->checkReadOnly();
+ impl_->checkReadOnly(ctx);
if (addr.isV4()) {
PsqlBindArrayPtr bind_array(new PsqlBindArray());
bind_array->add(subnet_id);
bind_array->add(addr);
- return (impl_->delStatement(PgSqlHostDataSourceImpl::DEL_HOST_ADDR4,
+ return (impl_->delStatement(ctx, PgSqlHostDataSourceImpl::DEL_HOST_ADDR4,
bind_array));
}
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
+ // If operating in read-only mode, throw exception.
+ impl_->checkReadOnly(ctx);
PsqlBindArrayPtr bind_array(new PsqlBindArray());
// identifier
bind_array->add(identifier_begin, identifier_len);
- return (impl_->delStatement(PgSqlHostDataSourceImpl::DEL_HOST_SUBID4_ID,
+ return (impl_->delStatement(ctx, PgSqlHostDataSourceImpl::DEL_HOST_SUBID4_ID,
bind_array));
}
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
+ // If operating in read-only mode, throw exception.
+ impl_->checkReadOnly(ctx);
+
PsqlBindArrayPtr bind_array(new PsqlBindArray());
// Subnet-id
// identifier
bind_array->add(identifier_begin, identifier_len);
- return (impl_->delStatement(PgSqlHostDataSourceImpl::DEL_HOST_SUBID6_ID,
+ return (impl_->delStatement(ctx, PgSqlHostDataSourceImpl::DEL_HOST_SUBID6_ID,
bind_array));
}
PgSqlHostDataSource::getAll(const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
bind_array->add(static_cast<uint8_t>(identifier_type));
ConstHostCollection result;
- impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_DHCPID,
- bind_array, impl_->host_ipv46_exchange_,
- result, false);
+ impl_->getHostCollection(ctx, PgSqlHostDataSourceImpl::GET_HOST_DHCPID,
+ bind_array, ctx->host_ipv46_exchange_, result, false);
+
return (result);
}
ConstHostCollection
PgSqlHostDataSource::getAll4(const SubnetID& subnet_id) const {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
bind_array->add(subnet_id);
ConstHostCollection result;
- impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID4,
- bind_array, impl_->host_exchange_,
- result, false);
+ impl_->getHostCollection(ctx, PgSqlHostDataSourceImpl::GET_HOST_SUBID4,
+ bind_array, ctx->host_exchange_, result, false);
return (result);
}
ConstHostCollection
PgSqlHostDataSource::getAll6(const SubnetID& subnet_id) const {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
bind_array->add(subnet_id);
ConstHostCollection result;
- impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID6,
- bind_array, impl_->host_ipv6_exchange_,
- result, false);
+ impl_->getHostCollection(ctx, PgSqlHostDataSourceImpl::GET_HOST_SUBID6,
+ bind_array, ctx->host_ipv6_exchange_, result, false);
return (result);
}
ConstHostCollection
PgSqlHostDataSource::getAllbyHostname(const std::string& hostname) const {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
bind_array->add(hostname);
ConstHostCollection result;
- impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_HOSTNAME,
- bind_array, impl_->host_ipv46_exchange_,
- result, false);
+ impl_->getHostCollection(ctx, PgSqlHostDataSourceImpl::GET_HOST_HOSTNAME,
+ bind_array, ctx->host_ipv46_exchange_, result, false);
+
return (result);
}
ConstHostCollection
PgSqlHostDataSource::getAllbyHostname4(const std::string& hostname,
const SubnetID& subnet_id) const {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
bind_array->add(subnet_id);
ConstHostCollection result;
- impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID4,
- bind_array, impl_->host_exchange_,
- result, false);
+ impl_->getHostCollection(ctx, PgSqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID4,
+ bind_array, ctx->host_exchange_, result, false);
return (result);
}
ConstHostCollection
PgSqlHostDataSource::getAllbyHostname6(const std::string& hostname,
const SubnetID& subnet_id) const {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
bind_array->add(subnet_id);
ConstHostCollection result;
- impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID6,
- bind_array, impl_->host_ipv6_exchange_,
- result, false);
+ impl_->getHostCollection(ctx, PgSqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID6,
+ bind_array, ctx->host_ipv6_exchange_, result, false);
return (result);
}
size_t& /*source_index*/,
uint64_t lower_host_id,
const HostPageSize& page_size) const {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
bind_array->add(page_size_data);
ConstHostCollection result;
- impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID4_PAGE,
- bind_array, impl_->host_exchange_,
- result, false);
+ impl_->getHostCollection(ctx, PgSqlHostDataSourceImpl::GET_HOST_SUBID4_PAGE,
+ bind_array, ctx->host_exchange_, result, false);
return (result);
}
size_t& /*source_index*/,
uint64_t lower_host_id,
const HostPageSize& page_size) const {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
bind_array->add(page_size_data);
ConstHostCollection result;
- impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID6_PAGE,
- bind_array, impl_->host_ipv6_exchange_,
- result, false);
+ impl_->getHostCollection(ctx, PgSqlHostDataSourceImpl::GET_HOST_SUBID6_PAGE,
+ bind_array, ctx->host_ipv6_exchange_, result, false);
return (result);
}
ConstHostCollection
PgSqlHostDataSource::getAll4(const asiolink::IOAddress& address) const {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
bind_array->add(address);
ConstHostCollection result;
- impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_ADDR, bind_array,
- impl_->host_exchange_, result, false);
+ impl_->getHostCollection(ctx, PgSqlHostDataSourceImpl::GET_HOST_ADDR,
+ bind_array, ctx->host_exchange_, result, false);
return (result);
}
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
- return (impl_->getHost(subnet_id, identifier_type, identifier_begin,
- identifier_len,
+ return (impl_->getHost(ctx, subnet_id, identifier_type, identifier_begin, identifier_len,
PgSqlHostDataSourceImpl::GET_HOST_SUBID4_DHCPID,
- impl_->host_exchange_));
+ ctx->host_exchange_));
}
ConstHostPtr
PgSqlHostDataSource::get4(const SubnetID& subnet_id,
const asiolink::IOAddress& address) const {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
if (!address.isV4()) {
isc_throw(BadValue, "PgSqlHostDataSource::get4(id, address) - "
" wrong address type, address supplied is an IPv6 address");
bind_array->add(address);
ConstHostCollection collection;
- impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID_ADDR,
- bind_array, impl_->host_exchange_, collection,
- true);
+ impl_->getHostCollection(ctx, PgSqlHostDataSourceImpl::GET_HOST_SUBID_ADDR,
+ bind_array, ctx->host_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 {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
- return (impl_->getHost(subnet_id, identifier_type, identifier_begin,
- identifier_len, PgSqlHostDataSourceImpl::GET_HOST_SUBID6_DHCPID,
- impl_->host_ipv6_exchange_));
+ return (impl_->getHost(ctx, subnet_id, identifier_type, identifier_begin, identifier_len,
+ PgSqlHostDataSourceImpl::GET_HOST_SUBID6_DHCPID,
+ ctx->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");
+ }
+
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
bind_array->add(prefix_len);
ConstHostCollection collection;
- impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_PREFIX,
- bind_array, impl_->host_ipv6_exchange_,
- collection, true);
+ impl_->getHostCollection(ctx, PgSqlHostDataSourceImpl::GET_HOST_PREFIX,
+ bind_array, ctx->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");
+ }
+
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
// Set up the WHERE clause value
PsqlBindArrayPtr bind_array(new PsqlBindArray());
bind_array->add(address);
ConstHostCollection collection;
- impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID6_ADDR,
- bind_array, impl_->host_ipv6_exchange_,
- collection, true);
+ impl_->getHostCollection(ctx, PgSqlHostDataSourceImpl::GET_HOST_SUBID6_ADDR,
+ bind_array, ctx->host_ipv6_exchange_, collection, true);
// Return single record if present, else clear the host.
ConstHostPtr result;
// Miscellaneous database methods.
-std::string PgSqlHostDataSource::getName() const {
+std::string
+PgSqlHostDataSource::getName() const {
std::string name = "";
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
try {
- name = impl_->conn_.getParameter("name");
+ name = ctx->conn_.getParameter("name");
} catch (...) {
// Return an empty name
}
return (name);
}
-std::string PgSqlHostDataSource::getDescription() const {
+std::string
+PgSqlHostDataSource::getDescription() const {
return (std::string("Host data source that stores host information"
"in PostgreSQL database"));
}
-std::pair<uint32_t, uint32_t> PgSqlHostDataSource::getVersion() const {
+std::pair<uint32_t, uint32_t>
+PgSqlHostDataSource::getVersion() const {
return(impl_->getVersion());
}
void
PgSqlHostDataSource::commit() {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
// If operating in read-only mode, throw exception.
- impl_->checkReadOnly();
- impl_->conn_.commit();
+ impl_->checkReadOnly(ctx);
+ ctx->conn_.commit();
}
void
PgSqlHostDataSource::rollback() {
+ // Get a context
+ PgSqlHostContextAlloc get_context(*impl_);
+ PgSqlHostContextPtr ctx = get_context.ctx_;
+
// If operating in read-only mode, throw exception.
- impl_->checkReadOnly();
- impl_->conn_.rollback();
+ impl_->checkReadOnly(ctx);
+ ctx->conn_.rollback();
}
-}; // end of isc::dhcp namespace
-}; // end of isc namespace
+} // namespace dhcp
+} // namespace isc
/// Forward declaration to the implementation of the @ref PgSqlHostDataSource.
class PgSqlHostDataSourceImpl;
+/// @brief Type of pointers to PgSqlHostDataSourceImpl.
+typedef boost::shared_ptr<PgSqlHostDataSourceImpl> PgSqlHostDataSourceImplPtr;
+
+/// Forward declaration for the thread context for the manager pool.
+class PgSqlHostContext;
+
+/// @brief Type of pointers to contexts.
+typedef boost::shared_ptr<PgSqlHostContext> PgSqlHostContextPtr;
+
/// @brief PostgreSQL Host Data Source
///
/// This class implements the @ref isc::dhcp::BaseHostDataSource interface to
/// - IDENT_CIRCUIT_ID
/// - IDENT_CLIENT_ID
///
-class PgSqlHostDataSource: public BaseHostDataSource {
+class PgSqlHostDataSource : public BaseHostDataSource {
public:
/// @brief Constructor
/// @param addr specified address.
/// @return true if deletion was successful, false if the host was not there.
/// @throw various exceptions in case of errors
- virtual bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr);
+ virtual bool del(const SubnetID& subnet_id,
+ const asiolink::IOAddress& addr);
/// @brief Attempts to delete a host by (subnet4-id, identifier type, identifier)
///
/// @throw various exceptions in case of errors
virtual bool del4(const SubnetID& subnet_id,
const Host::IdentifierType& identifier_type,
- const uint8_t* identifier_begin, const size_t identifier_len);
+ const uint8_t* identifier_begin,
+ const size_t identifier_len);
/// @brief Attempts to delete a host by (subnet6-id, identifier type, identifier)
///
/// @throw various exceptions in case of errors
virtual bool del6(const SubnetID& subnet_id,
const Host::IdentifierType& identifier_type,
- const uint8_t* identifier_begin, const size_t identifier_len);
+ const uint8_t* identifier_begin,
+ const size_t identifier_len);
/// @brief Return all hosts connected to any subnet for which reservations
/// have been made using a specified identifier.
/// @param identifier_len Identifier length.
///
/// @return Collection of const @c Host objects.
- virtual ConstHostCollection
- getAll(const Host::IdentifierType& identifier_type,
- const uint8_t* identifier_begin, const size_t identifier_len) const;
+ virtual ConstHostCollection getAll(const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin,
+ const size_t identifier_len) const;
/// @brief Return all hosts in a DHCPv4 subnet.
///
/// @param subnet_id subnet identifier to filter by
///
/// @return Collection of const @ref Host objects.
- virtual ConstHostCollection
- getAll4(const SubnetID& subnet_id) const;
+ virtual ConstHostCollection getAll4(const SubnetID& subnet_id) const;
/// @brief Return all hosts in a DHCPv6 subnet.
///
/// @param subnet_id subnet identifier to filter by
///
/// @return Collection of const @ref Host objects.
- virtual ConstHostCollection
- getAll6(const SubnetID& subnet_id) const;
+ virtual ConstHostCollection getAll6(const SubnetID& subnet_id) const;
/// @brief Return all hosts with a hostname.
///
/// @param hostname The lower case hostname.
///
/// @return Collection of const @c Host objects.
- virtual ConstHostCollection
- getAllbyHostname(const std::string& hostname) const;
+ virtual ConstHostCollection getAllbyHostname(const std::string& hostname) const;
/// @brief Return all hosts with a hostname in a DHCPv4 subnet.
///
/// @param subnet_id Subnet identifier.
///
/// @return Collection of const @c Host objects.
- virtual ConstHostCollection
- getAllbyHostname4(const std::string& hostname, const SubnetID& subnet_id) const;
+ virtual ConstHostCollection getAllbyHostname4(const std::string& hostname,
+ const SubnetID& subnet_id) const;
/// @brief Return all hosts with a hostname in a DHCPv6 subnet.
///
/// @param subnet_id Subnet identifier.
///
/// @return Collection of const @c Host objects.
- virtual ConstHostCollection
- getAllbyHostname6(const std::string& hostname, const SubnetID& subnet_id) const;
+ virtual ConstHostCollection getAllbyHostname6(const std::string& hostname,
+ const SubnetID& subnet_id) const;
/// @brief Returns range of hosts in a DHCPv4 subnet.
///
/// @param page_size maximum size of the page returned.
///
/// @return Collection of const @c Host objects (may be empty).
- virtual ConstHostCollection
- getPage4(const SubnetID& subnet_id,
- size_t& source_index,
- uint64_t lower_host_id,
- const HostPageSize& page_size) const;
+ virtual ConstHostCollection getPage4(const SubnetID& subnet_id,
+ size_t& source_index,
+ uint64_t lower_host_id,
+ const HostPageSize& page_size) const;
/// @brief Returns range of hosts in a DHCPv6 subnet.
///
/// @param page_size maximum size of the page returned.
///
/// @return Collection of const @c Host objects (may be empty).
- virtual ConstHostCollection
- getPage6(const SubnetID& subnet_id,
- size_t& source_index,
- uint64_t lower_host_id,
- const HostPageSize& page_size) const;
+ virtual ConstHostCollection getPage6(const SubnetID& subnet_id,
+ size_t& source_index,
+ uint64_t lower_host_id,
+ const HostPageSize& page_size) const;
/// @brief Returns a collection of hosts using the specified IPv4 address.
///
/// @param address IPv4 address for which the @c Host object is searched.
///
/// @return Collection of const @c Host objects.
- virtual ConstHostCollection
- getAll4(const asiolink::IOAddress& address) const;
+ virtual ConstHostCollection getAll4(const asiolink::IOAddress& address) const;
/// @brief Returns a host connected to the IPv4 subnet.
///
///
/// @return Const @c Host object for which reservation has been made using
/// the specified identifier.
- virtual ConstHostPtr
- get4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
- const uint8_t* identifier_begin, const size_t identifier_len) const;
+ virtual ConstHostPtr get4(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin,
+ const size_t identifier_len) const;
/// @brief Returns a host connected to the IPv4 subnet and having
/// a reservation for a specified IPv4 address.
///
/// @return Const @c Host object using a specified IPv4 address.
/// @throw BadValue is given an IPv6 address
- virtual ConstHostPtr
- get4(const SubnetID& subnet_id, const asiolink::IOAddress& address) const;
+ virtual ConstHostPtr get4(const SubnetID& subnet_id,
+ const asiolink::IOAddress& address) const;
/// @brief Returns a host connected to the IPv6 subnet.
///
///
/// @return Const @c Host object for which reservation has been made using
/// the specified identifier.
- virtual ConstHostPtr
- get6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
- const uint8_t* identifier_begin, const size_t identifier_len) const;
+ virtual ConstHostPtr get6(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin,
+ const size_t identifier_len) const;
/// @brief Returns a host using the specified IPv6 prefix.
///
/// @param prefix_len IPv6 prefix length.
///
/// @return Const @c Host object using a specified IPv6 prefix.
- virtual ConstHostPtr
- get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const;
+ virtual ConstHostPtr get6(const asiolink::IOAddress& prefix,
+ const uint8_t prefix_len) const;
/// @brief Returns a host connected to the IPv6 subnet and having
/// a reservation for a specified IPv6 address or prefix.
/// @param address reserved IPv6 address/prefix.
///
/// @return Const @c Host object using a specified IPv6 address/prefix.
- virtual ConstHostPtr
- get6(const SubnetID& subnet_id, const asiolink::IOAddress& address) const;
+ virtual ConstHostPtr get6(const SubnetID& subnet_id,
+ const asiolink::IOAddress& address) const;
/// @brief Return backend type
///
/// Rolls back all pending database operations.
virtual void rollback();
+ /// @brief Context RAII Allocator.
+ class PgSqlHostContextAlloc {
+ public:
+
+ /// @brief Constructor
+ ///
+ /// This constructor takes a context of the pool if one is available
+ /// or creates a new one.
+ ///
+ /// @param mgr A parent instance
+ PgSqlHostContextAlloc(const PgSqlHostDataSourceImpl& mgr);
+
+ /// @brief Destructor
+ ///
+ /// This destructor puts back the context in the pool.
+ ~PgSqlHostContextAlloc();
+
+ /// @brief The context
+ PgSqlHostContextPtr ctx_;
+
+ private:
+ /// @brief The manager
+ const PgSqlHostDataSourceImpl& mgr_;
+ };
+
private:
/// @brief Pointer to the implementation of the @ref PgSqlHostDataSource.
- PgSqlHostDataSourceImpl* impl_;
+ PgSqlHostDataSourceImplPtr impl_;
};
}