BIND 10 trac3080, updated. f496ea9a139b6d48277bddc1d63cbab652f40b0e [3080] Many comments added for PostgreSQL backend
BIND 10 source code commits
bind10-changes at lists.isc.org
Fri Mar 14 18:45:08 UTC 2014
The branch, trac3080 has been updated
via f496ea9a139b6d48277bddc1d63cbab652f40b0e (commit)
from b9d939f4edea839b5fd06df6bc0833e34d3dd823 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit f496ea9a139b6d48277bddc1d63cbab652f40b0e
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Fri Mar 14 19:44:40 2014 +0100
[3080] Many comments added for PostgreSQL backend
-----------------------------------------------------------------------
Summary of changes:
src/lib/dhcpsrv/pgsql_lease_mgr.cc | 356 ++++++++++++++-----------
src/lib/dhcpsrv/pgsql_lease_mgr.h | 510 +++++++++++++++++++++++++++++++++---
2 files changed, 678 insertions(+), 188 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/dhcpsrv/pgsql_lease_mgr.cc b/src/lib/dhcpsrv/pgsql_lease_mgr.cc
index b4c65d5..2702236 100644
--- a/src/lib/dhcpsrv/pgsql_lease_mgr.cc
+++ b/src/lib/dhcpsrv/pgsql_lease_mgr.cc
@@ -33,127 +33,146 @@ using namespace isc::dhcp;
using namespace std;
namespace {
+
+// Maximum text representation of an IPv6 address
const size_t ADDRESS6_TEXT_MAX_LEN = 39;
+// Maximum number of parameters used in any signle query
const size_t MAX_PARAMETERS_IN_QUERY = 12;
+// Defines a single query
struct TaggedStatement {
+
+ /// Query index
PgSqlLeaseMgr::StatementIndex index;
+
+ /// Number of parameters for a given query
int nbparams;
+
+ /// @brief OID types
+ ///
+ /// Sspecify parameter types. See /usr/include/postgresql/catalog/pg_type.h.
+ /// For some reason that header does not export those parameters.
+ /// Those OIDs must match both input and output parameters.
const Oid types[MAX_PARAMETERS_IN_QUERY + 1];
+
+ /// Short name of the query.
const char* name;
+
+ /// Text represenation of the actual query.
const char* text;
};
TaggedStatement tagged_statements[] = {
{PgSqlLeaseMgr::DELETE_LEASE4, 1,
- { 20 },
- "delete_lease4",
- "DELETE FROM lease4 WHERE address = $1"},
+ { 20 },
+ "delete_lease4",
+ "DELETE FROM lease4 WHERE address = $1"},
{PgSqlLeaseMgr::DELETE_LEASE6, 1,
- { 1043 },
- "delete_lease6",
- "DELETE FROM lease6 WHERE address = $1"},
+ { 1043 },
+ "delete_lease6",
+ "DELETE FROM lease6 WHERE address = $1"},
{PgSqlLeaseMgr::GET_LEASE4_ADDR, 1,
- { 20 },
- "get_lease4_addr",
- "DECLARE get_lease4_addr CURSOR FOR "
- "SELECT address, hwaddr, client_id, "
- "valid_lifetime, extract(epoch from expire), subnet_id, fqdn_fwd, fqdn_rev, hostname "
- "FROM lease4 "
- "WHERE address = $1"},
+ { 20 },
+ "get_lease4_addr",
+ "DECLARE get_lease4_addr CURSOR FOR "
+ "SELECT address, hwaddr, client_id, "
+ "valid_lifetime, extract(epoch from expire), subnet_id, fqdn_fwd, fqdn_rev, hostname "
+ "FROM lease4 "
+ "WHERE address = $1"},
{PgSqlLeaseMgr::GET_LEASE4_CLIENTID, 1,
- { 17 },
- "get_lease4_clientid",
- "DECLARE get_lease4_clientid CURSOR FOR "
- "SELECT address, hwaddr, client_id, "
- "valid_lifetime, extract(epoch from expire), subnet_id, fqdn_fwd, fqdn_rev, hostname "
- "FROM lease4 "
- "WHERE client_id = $1"},
+ { 17 },
+ "get_lease4_clientid",
+ "DECLARE get_lease4_clientid CURSOR FOR "
+ "SELECT address, hwaddr, client_id, "
+ "valid_lifetime, extract(epoch from expire), subnet_id, fqdn_fwd, fqdn_rev, hostname "
+ "FROM lease4 "
+ "WHERE client_id = $1"},
{PgSqlLeaseMgr::GET_LEASE4_CLIENTID_SUBID, 2,
- { 17, 20 },
- "get_lease4_clientid_subid",
- "DECLARE get_lease4_clientid_subid CURSOR FOR "
- "SELECT address, hwaddr, client_id, "
- "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, fqdn_fwd, fqdn_rev, hostname "
- "FROM lease4 "
- "WHERE client_id = $1 AND subnet_id = $2"},
+ { 17, 20 },
+ "get_lease4_clientid_subid",
+ "DECLARE get_lease4_clientid_subid CURSOR FOR "
+ "SELECT address, hwaddr, client_id, "
+ "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, fqdn_fwd, fqdn_rev, hostname "
+ "FROM lease4 "
+ "WHERE client_id = $1 AND subnet_id = $2"},
{PgSqlLeaseMgr::GET_LEASE4_HWADDR, 1,
- { 17 },
- "get_lease4_hwaddr",
- "DECLARE get_lease4_hwaddr CURSOR FOR "
- "SELECT address, hwaddr, client_id, "
- "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, fqdn_fwd, fqdn_rev, hostname "
- "FROM lease4 "
- "WHERE hwaddr = $1"},
+ { 17 },
+ "get_lease4_hwaddr",
+ "DECLARE get_lease4_hwaddr CURSOR FOR "
+ "SELECT address, hwaddr, client_id, "
+ "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, fqdn_fwd, fqdn_rev, hostname "
+ "FROM lease4 "
+ "WHERE hwaddr = $1"},
{PgSqlLeaseMgr::GET_LEASE4_HWADDR_SUBID, 2,
- { 17, 20 },
- "get_lease4_hwaddr_subid",
- "DECLARE get_lease4_hwaddr_subid CURSOR FOR "
- "SELECT address, hwaddr, client_id, "
- "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, fqdn_fwd, fqdn_rev, hostname "
- "FROM lease4 "
- "WHERE hwaddr = $1 AND subnet_id = $2"},
+ { 17, 20 },
+ "get_lease4_hwaddr_subid",
+ "DECLARE get_lease4_hwaddr_subid CURSOR FOR "
+ "SELECT address, hwaddr, client_id, "
+ "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, fqdn_fwd, fqdn_rev, hostname "
+ "FROM lease4 "
+ "WHERE hwaddr = $1 AND subnet_id = $2"},
{PgSqlLeaseMgr::GET_LEASE6_ADDR, 2,
- { 1043, 21 },
- "get_lease6_addr",
- "DECLARE get_lease6_addr CURSOR FOR "
- "SELECT address, duid, valid_lifetime, "
- "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
- "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname "
- "FROM lease6 "
- "WHERE address = $1 AND lease_type = $2"},
+ { 1043, 21 },
+ "get_lease6_addr",
+ "DECLARE get_lease6_addr CURSOR FOR "
+ "SELECT address, duid, valid_lifetime, "
+ "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
+ "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname "
+ "FROM lease6 "
+ "WHERE address = $1 AND lease_type = $2"},
{PgSqlLeaseMgr::GET_LEASE6_DUID_IAID, 3,
- { 17, 20, 21 },
- "get_lease6_duid_iaid",
- "DECLARE get_lease6_duid_iaid CURSOR FOR "
- "SELECT address, duid, valid_lifetime, "
- "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
- "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname "
- "FROM lease6 "
- "WHERE duid = $1 AND iaid = $2 AND lease_type = $3"},
+ { 17, 20, 21 },
+ "get_lease6_duid_iaid",
+ "DECLARE get_lease6_duid_iaid CURSOR FOR "
+ "SELECT address, duid, valid_lifetime, "
+ "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
+ "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname "
+ "FROM lease6 "
+ "WHERE duid = $1 AND iaid = $2 AND lease_type = $3"},
{PgSqlLeaseMgr::GET_LEASE6_DUID_IAID_SUBID, 4,
- { 21, 17, 20, 20 },
- "get_lease6_duid_iaid_subid",
- "DECLARE get_lease6_duid_iaid_subid CURSOR FOR "
- "SELECT address, duid, valid_lifetime, "
- "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
- "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname "
- "FROM lease6 "
- "WHERE lease_type = $1 AND duid = $2 AND iaid = $3 AND subnet_id = $4"},
+ { 21, 17, 20, 20 },
+ "get_lease6_duid_iaid_subid",
+ "DECLARE get_lease6_duid_iaid_subid CURSOR FOR "
+ "SELECT address, duid, valid_lifetime, "
+ "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
+ "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname "
+ "FROM lease6 "
+ "WHERE lease_type = $1 AND duid = $2 AND iaid = $3 AND subnet_id = $4"},
{PgSqlLeaseMgr::GET_VERSION, 0,
- { 0 },
- "get_version",
- "DECLARE get_version CURSOR FOR "
- "SELECT version, minor FROM schema_version"},
+ { 0 },
+ "get_version",
+ "DECLARE get_version CURSOR FOR "
+ "SELECT version, minor FROM schema_version"},
{PgSqlLeaseMgr::INSERT_LEASE4, 9,
- { 20, 17, 17, 20, 1114, 20, 16, 16, 1043 },
- "insert_lease4",
- "INSERT INTO lease4(address, hwaddr, client_id, "
- "valid_lifetime, expire, subnet_id, fqdn_fwd, fqdn_rev, hostname) "
- "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)"},
+ { 20, 17, 17, 20, 1114, 20, 16, 16, 1043 },
+ "insert_lease4",
+ "INSERT INTO lease4(address, hwaddr, client_id, "
+ "valid_lifetime, expire, subnet_id, fqdn_fwd, fqdn_rev, hostname) "
+ "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)"},
{PgSqlLeaseMgr::INSERT_LEASE6, 12,
- { 1043, 17, 20, 1114, 20, 20, 21, 20, 21, 16, 16, 1043 },
- "insert_lease6",
- "INSERT INTO lease6(address, duid, valid_lifetime, "
- "expire, subnet_id, pref_lifetime, "
- "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname) "
- "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)"},
+ { 1043, 17, 20, 1114, 20, 20, 21, 20, 21, 16, 16, 1043 },
+ "insert_lease6",
+ "INSERT INTO lease6(address, duid, valid_lifetime, "
+ "expire, subnet_id, pref_lifetime, "
+ "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname) "
+ "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)"},
{PgSqlLeaseMgr::UPDATE_LEASE4, 10,
- { 20, 17, 17, 20, 1114, 20, 16, 16, 1043, 20 },
- "update_lease4",
- "UPDATE lease4 SET address = $1, hwaddr = $2, "
- "client_id = $3, valid_lifetime = $4, expire = $5, "
- "subnet_id = $6, fqdn_fwd = $7, fqdn_rev = $8, hostname = $9 "
- "WHERE address = $10"},
+ { 20, 17, 17, 20, 1114, 20, 16, 16, 1043, 20 },
+ "update_lease4",
+ "UPDATE lease4 SET address = $1, hwaddr = $2, "
+ "client_id = $3, valid_lifetime = $4, expire = $5, "
+ "subnet_id = $6, fqdn_fwd = $7, fqdn_rev = $8, hostname = $9 "
+ "WHERE address = $10"},
{PgSqlLeaseMgr::UPDATE_LEASE6, 13,
- { 1043, 17, 20, 1114, 20, 20, 21, 20, 21, 16, 16, 1043, 1043 },
- "update_lease6",
- "UPDATE lease6 SET address = $1, duid = $2, "
- "valid_lifetime = $3, expire = $4, subnet_id = $5, "
- "pref_lifetime = $6, lease_type = $7, iaid = $8, "
- "prefix_len = $9, fqdn_fwd = $10, fqdn_rev = $11, hostname = $12 "
- "WHERE address = $13"},
+ { 1043, 17, 20, 1114, 20, 20, 21, 20, 21, 16, 16, 1043, 1043 },
+ "update_lease6",
+ "UPDATE lease6 SET address = $1, duid = $2, "
+ "valid_lifetime = $3, expire = $4, subnet_id = $5, "
+ "pref_lifetime = $6, lease_type = $7, iaid = $8, "
+ "prefix_len = $9, fqdn_fwd = $10, fqdn_rev = $11, hostname = $12 "
+ "WHERE address = $13"},
+
// End of list sentinel
{PgSqlLeaseMgr::NUM_STATEMENTS, 0, { 0 }, NULL, NULL}
};
@@ -163,17 +182,25 @@ TaggedStatement tagged_statements[] = {
namespace isc {
namespace dhcp {
+/// @brief Auxiliary PostgreSQL exchange class
class PgSqlLeaseExchange {
protected:
- bindparams params;
+
+ /// Converts time_t structure to a text representation
+ /// @param expire timestamp to be converted
+ /// @param buffer text version will be written here
void
- convertToTimestamp(const time_t & expire_,
- char buffer_[20]) {
+ convertToTimestamp(const time_t& expire, char buffer[20]) {
struct tm tinfo;
- localtime_r(&expire_, &tinfo);
- strftime(buffer_, 20, "%Y-%m-%d %H:%M:%S", &tinfo);
+ localtime_r(&expire, &tinfo);
+ strftime(buffer, 20, "%Y-%m-%d %H:%M:%S", &tinfo);
}
+ /// Converts available text representations to bool
+ ///
+ /// Allowed values are "t" or "f". Any other will throw.
+ /// @param value text value to be converted
+ /// @throw BadValue if passed any value other than "t" or "f"
bool stringToBool(char* value) {
if (!strlen(value)) {
return (false);
@@ -188,11 +215,17 @@ protected:
" only accepted values are 't', 'f' or ''");
}
}
+
+ /// Compiled statement bind parameters
+ bindparams params;
};
+/// @brief Represents a single Lease4 exchange
class PgSqlLease4Exchange : public PgSqlLeaseExchange {
static const size_t LEASE_COLUMNS = 9;
public:
+
+ /// Default constructor
PgSqlLease4Exchange() : addr4_(0) {
memset(hwaddr_buffer_, 0, sizeof(hwaddr_buffer_));
memset(client_id_buffer_, 0, sizeof(client_id_buffer_));
@@ -234,7 +267,8 @@ public:
<< HWAddr::MAX_HWADDR_LEN);
}
- PgSqlParam pdest = { .value = string(lease_->hwaddr_.begin(), lease_->hwaddr_.end()),
+ PgSqlParam pdest = { .value = string(lease_->hwaddr_.begin(),
+ lease_->hwaddr_.end()),
.isbinary = 1,
.binarylen = static_cast<int>(lease_->hwaddr_.size()) };
params.push_back(pdest);
@@ -283,18 +317,16 @@ public:
Lease4Ptr
convertFromDatabase(PGresult *& r, int line) {
- const char * addr4_str = PQgetvalue(r, line, 0);
- unsigned char * hwaddr_str = PQunescapeBytea(
- (const unsigned char *)
- PQgetvalue(r, line, 1),
- & hwaddr_length_);
- unsigned char * client_id_str = PQunescapeBytea(
- (const unsigned char *)
- PQgetvalue(r, line, 2),
- & client_id_length_);
- const char * valid_lifetime_str = PQgetvalue(r, line, 3);
- const char * expire_str = PQgetvalue(r, line, 4);
- const char * subnet_id_str = PQgetvalue(r, line, 5);
+ const char* addr4_str = PQgetvalue(r, line, 0);
+ unsigned char* hwaddr_str = PQunescapeBytea((const unsigned char *)
+ PQgetvalue(r, line, 1),
+ & hwaddr_length_);
+ unsigned char* client_id_str = PQunescapeBytea((const unsigned char *)
+ PQgetvalue(r, line, 2),
+ & client_id_length_);
+ const char* valid_lifetime_str = PQgetvalue(r, line, 3);
+ const char* expire_str = PQgetvalue(r, line, 4);
+ const char* subnet_id_str = PQgetvalue(r, line, 5);
unsigned long valid_lifetime, expire, subnet_id;
istringstream tmp;
@@ -452,18 +484,17 @@ public:
Lease6Ptr
convertFromDatabase(PGresult * r, int line) {
- const char * addr6_str = PQgetvalue(r, line, 0);
- unsigned char * duid_str = PQunescapeBytea(
- (const unsigned char *)
- PQgetvalue(r, line, 1),
- & duid_length_);
- const char * valid_lifetime_str = PQgetvalue(r, line, 2);
- const char * expire_str = PQgetvalue(r, line, 3);
- const char * subnet_id_str = PQgetvalue(r, line, 4);
- const char * pref_lifetime_str = PQgetvalue(r, line, 5);
- const char * lease_type_str = PQgetvalue(r, line, 6);
- const char * iaid_str = PQgetvalue(r, line, 7);
- const char * prefixlen_str = PQgetvalue(r, line, 8);
+ const char* addr6_str = PQgetvalue(r, line, 0);
+ unsigned char* duid_str = PQunescapeBytea((const unsigned char *)
+ PQgetvalue(r, line, 1),
+ & duid_length_);
+ const char* valid_lifetime_str = PQgetvalue(r, line, 2);
+ const char* expire_str = PQgetvalue(r, line, 3);
+ const char* subnet_id_str = PQgetvalue(r, line, 4);
+ const char* pref_lifetime_str = PQgetvalue(r, line, 5);
+ const char* lease_type_str = PQgetvalue(r, line, 6);
+ const char* iaid_str = PQgetvalue(r, line, 7);
+ const char* prefixlen_str = PQgetvalue(r, line, 8);
unsigned int lease_type, prefixlen;
unsigned long valid_lifetime, expire, subnet_id, pref_lifetime, iaid;
@@ -559,7 +590,6 @@ public:
private:
string addr6_;
- // char addr6_buffer_[ADDRESS6_TEXT_MAX_LEN + 1];
string columns_[LEASE_COLUMNS];
time_t expire_;
vector<uint8_t> duid_;
@@ -585,10 +615,10 @@ PgSqlLeaseMgr::PgSqlLeaseMgr(const LeaseMgr::ParameterMap& parameters)
}
PgSqlLeaseMgr::~PgSqlLeaseMgr() {
- if(status) {
+ if (status) {
// Attempt to deallocate prepared queries set previously with DEALLOCATE query
// No internal libpq function for that, no errors checking as well
- PGresult * r;
+ PGresult* r = NULL;
for(int i = 0; tagged_statements[i].text != NULL; ++ i) {
string deallocate = "DEALLOCATE \"";
deallocate += tagged_statements[i].name;
@@ -694,19 +724,19 @@ PgSqlLeaseMgr::openDatabase() {
bool
PgSqlLeaseMgr::addLeaseCommon(StatementIndex stindex,
- bindparams & params) {
+ bindparams& params) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_ADD_ADDR4).arg(statements_[stindex].stmt_name);
- vector<const char *> params_;
- vector<int> lengths_;
- vector<int> formats_;
- convertToQuery(params, params_, lengths_, formats_);
+ vector<const char *> out_values;
+ vector<int> out_lengths;
+ vector<int> out_formats;
+ convertToQuery(params, out_values, out_lengths, out_formats);
PGresult * r = PQexecPrepared(status, statements_[stindex].stmt_name,
statements_[stindex].stmt_nbparams,
- ¶ms_[0], &lengths_[0], &formats_[0], 0);
+ &out_values[0], &out_lengths[0], &out_formats[0], 0);
int s = PQresultStatus(r);
if (s != PGRES_COMMAND_OK) {
@@ -755,10 +785,10 @@ void PgSqlLeaseMgr::getLeaseCollection(StatementIndex stindex,
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_GET_ADDR4).arg(statements_[stindex].stmt_name);
- vector<const char *> params_;
- vector<int> lengths_;
- vector<int> formats_;
- convertToQuery(params, params_, lengths_, formats_);
+ vector<const char *> out_values;
+ vector<int> out_lengths;
+ vector<int> out_formats;
+ convertToQuery(params, out_values, out_lengths, out_formats);
PGresult * r = PQexec(status, "SET AUTOCOMMIT TO OFF");
PQclear(r);
@@ -767,8 +797,8 @@ void PgSqlLeaseMgr::getLeaseCollection(StatementIndex stindex,
PQclear(r);
r = PQexecPrepared(status, statements_[stindex].stmt_name,
- statements_[stindex].stmt_nbparams,
- ¶ms_[0], &lengths_[0], &formats_[0], 0);
+ statements_[stindex].stmt_nbparams, &out_values[0],
+ &out_lengths[0], &out_formats[0], 0);
checkError(r, stindex, "unable to bind WHERE clause parameter");
PQclear(r);
@@ -878,8 +908,9 @@ PgSqlLeaseMgr::getLease4(const HWAddr& hwaddr) const {
if (!hwaddr.hwaddr_.empty()) {
uint8_t* data = const_cast<uint8_t *>(&hwaddr.hwaddr_[0]);
- PgSqlParam pdest = { .value = reinterpret_cast<char *>(data)
- , .isbinary = 1, .binarylen = static_cast<int>(hwaddr.hwaddr_.size()) };
+ PgSqlParam pdest = { .value = reinterpret_cast<char *>(data),
+ .isbinary = 1,
+ .binarylen = static_cast<int>(hwaddr.hwaddr_.size()) };
inparams.push_back(pdest);
} else {
inparams.push_back(PgSqlParam());
@@ -928,8 +959,9 @@ PgSqlLeaseMgr::getLease4(const ClientId& clientid) const {
bindparams inparams;
vector<uint8_t> client_data = clientid.getClientId();
- PgSqlParam pdest = { .value = reinterpret_cast<char *>(&client_data[0])
- , .isbinary = 1, .binarylen = static_cast<int>(clientid.getClientId().size()) };
+ PgSqlParam pdest = { .value = reinterpret_cast<char *>(&client_data[0]),
+ .isbinary = 1,
+ .binarylen = static_cast<int>(clientid.getClientId().size()) };
inparams.push_back(pdest);
// Get the data
@@ -950,8 +982,9 @@ PgSqlLeaseMgr::getLease4(const ClientId& clientid, SubnetID subnet_id) const {
ostringstream tmp;
vector<uint8_t> client_data = clientid.getClientId();
- PgSqlParam pdest = { .value = reinterpret_cast<char *>(&client_data[0])
- , .isbinary = 1, .binarylen = static_cast<int>(clientid.getClientId().size()) };
+ PgSqlParam pdest = { .value = reinterpret_cast<char *>(&client_data[0]),
+ .isbinary = 1,
+ .binarylen = static_cast<int>(clientid.getClientId().size()) };
inparams.push_back(pdest);
tmp << static_cast<unsigned long>(subnet_id);
@@ -1006,8 +1039,9 @@ PgSqlLeaseMgr::getLeases6(Lease::Type type, const DUID& duid, uint32_t iaid) con
bindparams inparams;
ostringstream tmp;
vector<uint8_t> duid_data = duid.getDuid();
- PgSqlParam pdest = { .value = reinterpret_cast<char *>(&duid_data[0])
- , .isbinary = 1, .binarylen = static_cast<int>(duid.getDuid().size()) };
+ PgSqlParam pdest = { .value = reinterpret_cast<char *>(&duid_data[0]),
+ .isbinary = 1,
+ .binarylen = static_cast<int>(duid.getDuid().size()) };
inparams.push_back(pdest);
/// @todo: use type
@@ -1198,6 +1232,36 @@ PgSqlLeaseMgr::getName() const {
return (name);
}
+void
+PgSqlLeaseMgr::checkError(PGresult* r, StatementIndex index,
+ const char* what) const {
+ int s = PQresultStatus(r);
+ if (s != PGRES_COMMAND_OK && s != PGRES_TUPLES_OK) {
+ PQclear(r);
+
+ isc_throw(DbOperationError, what << " for <" <<
+ statements_[index].stmt_name << ">, " <<
+ PQerrorMessage(status));
+ }
+}
+
+inline void
+PgSqlLeaseMgr::convertToQuery(const bindparams& params,
+ std::vector<const char *>& out_values,
+ std::vector<int>& out_lengths,
+ std::vector<int>& out_formats) const {
+ out_values.reserve(params.size());
+ out_lengths.reserve(params.size());
+ out_formats.reserve(params.size());
+
+ for(bindparams::const_iterator it = params.begin(); it != params.end();
+ ++it) {
+ out_values.push_back((* it).value.c_str());
+ out_lengths.push_back((* it).binarylen);
+ out_formats.push_back((* it).isbinary);
+ }
+}
+
string
PgSqlLeaseMgr::getDescription() const {
return (string("PostgreSQL Database"));
diff --git a/src/lib/dhcpsrv/pgsql_lease_mgr.h b/src/lib/dhcpsrv/pgsql_lease_mgr.h
index 2bda355..4043d52 100644
--- a/src/lib/dhcpsrv/pgsql_lease_mgr.h
+++ b/src/lib/dhcpsrv/pgsql_lease_mgr.h
@@ -25,60 +25,335 @@
namespace isc {
namespace dhcp {
+/// @brief An auxiliary structure for marshalling data for compiled statements
+///
+/// It represents a single field used in a query (e.g. one field used in WHERE
+/// or UPDATE clauses).
struct PgSqlParam {
- std::string value;
- int isbinary;
- int binarylen;
+ std::string value; ///< The actual value represented as text
+ bool isbinary; ///< Boolean flag that controls whether the data is binary
+ int binarylen; ///< Specified binary length
};
+/// @brief Defines all parameters for binding a compiled statement
typedef std::vector<PgSqlParam> bindparams;
+/// @brief Describes a single compiled statement
struct PgSqlStatementBind {
- const char * stmt_name;
- int stmt_nbparams;
+ const char* stmt_name; ///< Name of the compiled statement
+ int stmt_nbparams; ///< Number of statement parameters
};
+// Forward definitions (needed for shared_ptr definitions)
+// See pgsql_lease_mgr.cc file for actual class definitions
class PgSqlLease4Exchange;
class PgSqlLease6Exchange;
+/// Defines PostgreSQL backend version: 1.0
const uint32_t PG_CURRENT_VERSION = 1;
const uint32_t PG_CURRENT_MINOR = 0;
+/// @brief PostgreSQL Lease Manager
+///
+/// This class provides the \ref isc::dhcp::LeaseMgr interface to the PostgreSQL
+/// database. Use of this backend presupposes that a PostgreSQL database is
+/// available and that the Kea schema has been created within it.
class PgSqlLeaseMgr : public LeaseMgr {
public:
+
+ /// @brief Constructor
+ ///
+ /// Uses the following keywords in the parameters passed to it to
+ /// connect to the database:
+ /// - name - Name of the database to which to connect (mandatory)
+ /// - host - Host to which to connect (optional, defaults to "localhost")
+ /// - user - Username under which to connect (optional)
+ /// - password - Password for "user" on the database (optional)
+ ///
+ /// If the database is successfully opened, the version number in the
+ /// schema_version table will be checked against hard-coded value in
+ /// the implementation file.
+ ///
+ /// Finally, all the SQL commands are pre-compiled.
+ ///
+ /// @param parameters A data structure relating keywords and values
+ /// concerned with the database.
+ ///
+ /// @throw isc::dhcp::NoDatabaseName Mandatory database name not given
+ /// @throw isc::dhcp::DbOpenError Error opening the database
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
PgSqlLeaseMgr(const ParameterMap& parameters);
+
+ /// @brief Destructor (closes database)
virtual ~PgSqlLeaseMgr();
+
+ /// @brief Adds an IPv4 lease
+ ///
+ /// @param lease lease to be added
+ ///
+ /// @result true if the lease was added, false if not (because a lease
+ /// with the same address was already there).
+ ///
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual bool addLease(const Lease4Ptr& lease);
+
+ /// @brief Adds an IPv6 lease
+ ///
+ /// @param lease lease to be added
+ ///
+ /// @result true if the lease was added, false if not (because a lease
+ /// with the same address was already there).
+ ///
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual bool addLease(const Lease6Ptr& lease);
+ /// @brief Returns an IPv4 lease for specified IPv4 address
+ ///
+ /// This method return a lease that is associated with a given address.
+ /// For other query types (by hardware addr, by Client ID) there can be
+ /// several leases in different subnets (e.g. for mobile clients that
+ /// got address in different subnets). However, for a single address
+ /// there can be only one lease, so this method returns a pointer to
+ /// a single lease, not a container of leases.
+ ///
+ /// @param addr address of the searched lease
+ ///
+ /// @return smart pointer to the lease (or NULL if a lease is not found)
+ ///
+ /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
+ /// fit into the space allocated for the result. This indicates a
+ /// programming error.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress& addr) const;
+
+ /// @brief Returns existing IPv4 leases for specified hardware address.
+ ///
+ /// Although in the usual case there will be only one lease, for mobile
+ /// clients or clients with multiple static/fixed/reserved leases there
+ /// can be more than one. Thus return type is a container, not a single
+ /// pointer.
+ ///
+ /// @param hwaddr hardware address of the client
+ ///
+ /// @return lease collection
+ ///
+ /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
+ /// fit into the space allocated for the result. This indicates a
+ /// programming error.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease4Collection getLease4(const isc::dhcp::HWAddr& hwaddr) const;
+
+ /// @brief Returns existing IPv4 leases for specified hardware address
+ /// and a subnet
+ ///
+ /// There can be at most one lease for a given HW address in a single
+ /// pool, so this method with either return a single lease or NULL.
+ ///
+ /// @param hwaddr hardware address of the client
+ /// @param subnet_id identifier of the subnet that lease must belong to
+ ///
+ /// @return a pointer to the lease (or NULL if a lease is not found)
+ ///
+ /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
+ /// fit into the space allocated for the result. This indicates a
+ /// programming error.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease4Ptr getLease4(const isc::dhcp::HWAddr& hwaddr,
SubnetID subnet_id) const;
+
+ /// @brief Returns existing IPv4 leases for specified client-id
+ ///
+ /// Although in the usual case there will be only one lease, for mobile
+ /// clients or clients with multiple static/fixed/reserved leases there
+ /// can be more than one. Thus return type is a container, not a single
+ /// pointer.
+ ///
+ /// @param clientid client identifier
+ ///
+ /// @return lease collection
+ ///
+ /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
+ /// fit into the space allocated for the result. This indicates a
+ /// programming error.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease4Collection getLease4(const ClientId& clientid) const;
+
+ /// @brief Returns IPv4 lease for the specified client identifier, HW
+ /// address and subnet identifier.
+ ///
+ /// @param client_id A client identifier.
+ /// @param hwaddr Hardware address.
+ /// @param subnet_id A subnet identifier.
+ ///
+ /// @return A pointer to the lease or NULL if the lease is not found.
+ /// @throw isc::NotImplemented On every call as this function is currently
+ /// not implemented for the MySQL backend.
virtual Lease4Ptr getLease4(const ClientId& client_id, const HWAddr& hwaddr,
SubnetID subnet_id) const;
+
+
+ /// @brief Returns existing IPv4 lease for specified client-id
+ ///
+ /// There can be at most one lease for a given HW address in a single
+ /// pool, so this method with either return a single lease or NULL.
+ ///
+ /// @param clientid client identifier
+ /// @param subnet_id identifier of the subnet that lease must belong to
+ ///
+ /// @return a pointer to the lease (or NULL if a lease is not found)
+ ///
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease4Ptr getLease4(const ClientId& clientid,
SubnetID subnet_id) const;
+ /// @brief Returns existing IPv6 lease for a given IPv6 address.
+ ///
+ /// For a given address, we assume that there will be only one lease.
+ /// The assumption here is that there will not be site or link-local
+ /// addresses used, so there is no way of having address duplication.
+ ///
+ /// @param type specifies lease type: (NA, TA or PD)
+ /// @param addr address of the searched lease
+ ///
+ /// @return smart pointer to the lease (or NULL if a lease is not found)
+ ///
+ /// @throw isc::BadValue record retrieved from database had an invalid
+ /// lease type field.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease6Ptr getLease6(Lease::Type type,
const isc::asiolink::IOAddress& addr) const;
+
+ /// @brief Returns existing IPv6 leases for a given DUID+IA combination
+ ///
+ /// Although in the usual case there will be only one lease, for mobile
+ /// clients or clients with multiple static/fixed/reserved leases there
+ /// can be more than one. Thus return type is a container, not a single
+ /// pointer.
+ ///
+ /// @param type specifies lease type: (NA, TA or PD)
+ /// @param duid client DUID
+ /// @param iaid IA identifier
+ ///
+ /// @return smart pointer to the lease (or NULL if a lease is not found)
+ ///
+ /// @throw isc::BadValue record retrieved from database had an invalid
+ /// lease type field.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease6Collection getLeases6(Lease::Type type, const DUID& duid,
uint32_t iaid) const;
+
+ /// @brief Returns existing IPv6 lease for a given DUID+IA combination
+ ///
+ /// @param type specifies lease type: (NA, TA or PD)
+ /// @param duid client DUID
+ /// @param iaid IA identifier
+ /// @param subnet_id subnet id of the subnet the lease belongs to
+ ///
+ /// @return lease collection (may be empty if no lease is found)
+ ///
+ /// @throw isc::BadValue record retrieved from database had an invalid
+ /// lease type field.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease6Collection getLeases6(Lease::Type type, const DUID& duid,
uint32_t iaid, SubnetID subnet_id) const;
+ /// @brief Updates IPv4 lease.
+ ///
+ /// Updates the record of the lease in the database (as identified by the
+ /// address) with the data in the passed lease object.
+ ///
+ /// @param lease4 The lease to be updated.
+ ///
+ /// @throw isc::dhcp::NoSuchLease Attempt to update a lease that did not
+ /// exist.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual void updateLease4(const Lease4Ptr& lease4);
+
+ /// @brief Updates IPv6 lease.
+ ///
+ /// Updates the record of the lease in the database (as identified by the
+ /// address) with the data in the passed lease object.
+ ///
+ /// @param lease6 The lease to be updated.
+ ///
+ /// @throw isc::dhcp::NoSuchLease Attempt to update a lease that did not
+ /// exist.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual void updateLease6(const Lease6Ptr& lease6);
+
+ /// @brief Deletes a lease.
+ ///
+ /// @param addr Address of the lease to be deleted. This can be an IPv4
+ /// address or an IPv6 address.
+ ///
+ /// @return true if deletion was successful, false if no such lease exists
+ ///
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual bool deleteLease(const isc::asiolink::IOAddress& addr);
+
+ /// @brief Return backend type
+ ///
+ /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
+ ///
+ /// @return Type of the backend.
virtual std::string getType() const {
return (std::string("postgresql"));
}
+
+ /// @brief Returns name of the database.
+ ///
+ /// @return database name
virtual std::string getName() const;
+
+ /// @brief Returns description of the backend.
+ ///
+ /// This description may be multiline text that describes the backend.
+ ///
+ /// @return Description of the backend.
virtual std::string getDescription() const;
+
+ /// @brief Returns backend version.
+ ///
+ /// @return Version number as a pair of unsigned integers. "first" is the
+ /// major version number, "second" the minor number.
+ ///
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual std::pair<uint32_t, uint32_t> getVersion() const;
+
+ /// @brief Commit Transactions
+ ///
+ /// Commits all pending database operations. On databases that don't
+ /// support transactions, this is a no-op.
+ ///
+ /// @throw DbOperationError Iif the commit failed.
virtual void commit();
+
+ /// @brief Rollback Transactions
+ ///
+ /// Rolls back all pending database operations. On databases that don't
+ /// support transactions, this is a no-op.
+ ///
+ /// @throw DbOperationError If the rollback failed.
virtual void rollback();
+
+ /// @brief Statement Tags
+ ///
+ /// The contents of the enum are indexes into the list of compiled SQL statements
enum StatementIndex {
DELETE_LEASE4, // Delete from lease4 by address
DELETE_LEASE6, // Delete from lease6 by address
@@ -97,61 +372,212 @@ public:
UPDATE_LEASE6, // Update a Lease6 entry
NUM_STATEMENTS // Number of statements
};
+
private:
+
+ /// @brief Prepare statements
+ ///
+ /// Creates the prepared statements for all of the SQL statements used
+ /// by the PostgreSQL backend.
+ ///
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
+ /// @throw isc::InvalidParameter 'index' is not valid for the vector. This
+ /// represents an internal error within the code.
void prepareStatements();
+
+ /// @brief Open Database
+ ///
+ /// Opens the database using the information supplied in the parameters
+ /// passed to the constructor.
+ ///
+ /// @throw NoDatabaseName Mandatory database name not given
+ /// @throw DbOpenError Error opening the database
void openDatabase();
- bool addLeaseCommon(StatementIndex stindex, bindparams & params);
+
+ /// @brief Add Lease Common Code
+ ///
+ /// This method performs the common actions for both flavours (V4 and V6)
+ /// of the addLease method. It binds the contents of the lease object to
+ /// the prepared statement and adds it to the database.
+ ///
+ /// @param stindex Index of statemnent being executed
+ /// @param bind MYSQL_BIND array that has been created for the type
+ /// of lease in question.
+ ///
+ /// @return true if the lease was added, false if it was not added because
+ /// a lease with that address already exists in the database.
+ ///
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
+ bool addLeaseCommon(StatementIndex stindex, bindparams& params);
+
+ /// @brief Get Lease Collection Common Code
+ ///
+ /// This method performs the common actions for obtaining multiple leases
+ /// from the database.
+ ///
+ /// @param stindex Index of statement being executed
+ /// @param params PostgreSQL parameters for the query
+ /// @param exchange Exchange object to use
+ /// @param result Returned collection of Leases Note that any leases in
+ /// the collection when this method is called are not erased: the
+ /// new data is appended to the end.
+ /// @param single If true, only a single data item is to be retrieved.
+ /// If more than one is present, a MultipleRecords exception will
+ /// be thrown.
+ ///
+ /// @throw isc::dhcp::BadValue Data retrieved from the database was invalid.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
+ /// @throw isc::dhcp::MultipleRecords Multiple records were retrieved
+ /// from the database where only one was expected.
template <typename Exchange, typename LeaseCollection>
- void getLeaseCollection(StatementIndex stindex, bindparams & params,
+ void getLeaseCollection(StatementIndex stindex, bindparams& params,
Exchange& exchange, LeaseCollection& result,
bool single = false) const;
- void getLeaseCollection(StatementIndex stindex, bindparams & params,
+
+ /// @brief Gets Lease4 Collection
+ ///
+ /// Gets a collection of Lease4 objects. This is just an interface to
+ /// the get lease collection common code.
+ ///
+ /// @param stindex Index of statement being executed
+ /// @param params PostgreSQL parameters for the query
+ /// @param lease LeaseCollection object returned. Note that any leases in
+ /// the collection when this method is called are not erased: the
+ /// new data is appended to the end.
+ ///
+ /// @throw isc::dhcp::BadValue Data retrieved from the database was invalid.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
+ /// @throw isc::dhcp::MultipleRecords Multiple records were retrieved
+ /// from the database where only one was expected.
+ void getLeaseCollection(StatementIndex stindex, bindparams& params,
Lease4Collection& result) const {
getLeaseCollection(stindex, params, exchange4_, result);
}
- void getLeaseCollection(StatementIndex stindex, bindparams & params,
+
+ /// @brief Get Lease6 Collection
+ ///
+ /// Gets a collection of Lease6 objects. This is just an interface to
+ /// the get lease collection common code.
+ ///
+ /// @param stindex Index of statement being executed
+ /// @param params PostgreSQL parameters for the query
+ /// @param lease LeaseCollection object returned. Note that any existing
+ /// data in the collection is erased first.
+ ///
+ /// @throw isc::dhcp::BadValue Data retrieved from the database was invalid.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
+ /// @throw isc::dhcp::MultipleRecords Multiple records were retrieved
+ /// from the database where only one was expected.
+ void getLeaseCollection(StatementIndex stindex, bindparams& params,
Lease6Collection& result) const {
getLeaseCollection(stindex, params, exchange6_, result);
}
- inline void checkError(PGresult * r, StatementIndex index,
- const char* what) const {
- int s = PQresultStatus(r);
- if (s != PGRES_COMMAND_OK && s != PGRES_TUPLES_OK) {
- PQclear(r);
-
- isc_throw(DbOperationError, what << " for <" <<
- statements_[index].stmt_name << ">, " <<
- PQerrorMessage(status));
- }
- }
- inline void convertToQuery(bindparams & params,
- std::vector<const char *>& params_,
- std::vector<int>& lengths_,
- std::vector<int>& formats_) const {
- params_.reserve(params.size());
- lengths_.reserve(params.size());
- formats_.reserve(params.size());
-
- for(bindparams::const_iterator it = params.begin(); it != params.end();
- ++ it) {
- params_.push_back((* it).value.c_str());
- lengths_.push_back((* it).binarylen);
- formats_.push_back((* it).isbinary);
- }
- }
- void getLease(StatementIndex stindex, bindparams & params,
+
+ /// @brief Checks result of the r object
+ ///
+ /// Checks status of the operation passed as first argument and throws
+ /// DbOperationError with details if it is non-success.
+ ///
+ /// @param r result of the last PostgreSQL operation
+ /// @param index will be used to print out compiled statement name
+ /// @param what operation that cause the error
+ ///
+ /// @throw isc::dhcp::DbOperationError Detailed PostgreSQL failure
+ inline void checkError(PGresult* r, StatementIndex index, const char* what) const;
+
+ /// @brief Converts query parameters to format accepted by PostgreSQL
+ ///
+ /// Converts parameters stored in params into 3 vectors: out_params,
+ /// out_lengths and out_formats.
+ /// @param params input parameters
+ /// @param out_values [out] values of specified parameters
+ /// @param out_lengths [out] lengths of specified values
+ /// @param out_formats [out] specifies format (text (0) or binary (1))
+ inline void convertToQuery(const bindparams& params,
+ std::vector<const char *>& out_values,
+ std::vector<int>& out_lengths,
+ std::vector<int>& out_formats) const;
+
+ /// @brief Get Lease4 Common Code
+ ///
+ /// This method performs the common actions for the various getLease4()
+ /// methods. It acts as an interface to the getLeaseCollection() method,
+ /// but retrieveing only a single lease.
+ ///
+ /// @param stindex Index of statement being executed
+ /// @param bindparams PostgreSQL array for input parameters
+ /// @param lease Lease4 object returned
+ void getLease(StatementIndex stindex, bindparams& params,
Lease4Ptr& result) const;
- void getLease(StatementIndex stindex, bindparams & params,
+
+ /// @brief Get Lease6 Common Code
+ ///
+ /// This method performs the common actions for the various getLease4()
+ /// methods. It acts as an interface to the getLeaseCollection() method,
+ /// but retrieveing only a single lease.
+ ///
+ /// @param stindex Index of statement being executed
+ /// @param bindparams PostgreSQL array for input parameters
+ /// @param lease Lease6 object returned
+ void getLease(StatementIndex stindex, bindparams& params,
Lease6Ptr& result) const;
+
+
+ /// @brief Update lease common code
+ ///
+ /// Holds the common code for updating a lease. It binds the parameters
+ /// to the prepared statement, executes it, then checks how many rows
+ /// were affected.
+ ///
+ /// @param stindex Index of prepared statement to be executed
+ /// @param bindparams Array of PostgreSQL objects representing the parameters.
+ /// (Note that the number is determined by the number of parameters
+ /// in the statement.)
+ /// @param lease Pointer to the lease object whose record is being updated.
+ ///
+ /// @throw NoSuchLease Could not update a lease because no lease matches
+ /// the address given.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
template <typename LeasePtr>
- void updateLeaseCommon(StatementIndex stindex, bindparams & params,
+ void updateLeaseCommon(StatementIndex stindex, bindparams& params,
const LeasePtr& lease);
- bool deleteLeaseCommon(StatementIndex stindex, bindparams & params);
- boost::scoped_ptr<PgSqlLease4Exchange> exchange4_;
- boost::scoped_ptr<PgSqlLease6Exchange> exchange6_;
+ /// @brief Delete lease common code
+ ///
+ /// Holds the common code for deleting a lease. It binds the parameters
+ /// to the prepared statement, executes the statement and checks to
+ /// see how many rows were deleted.
+ ///
+ /// @param stindex Index of prepared statement to be executed
+ /// @param bindparams Array of PostgreSQL objects representing the parameters.
+ /// (Note that the number is determined by the number of parameters
+ /// in the statement.)
+ ///
+ /// @return true if one or more rows were deleted, false if none were
+ /// deleted.
+ ///
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
+ bool deleteLeaseCommon(StatementIndex stindex, bindparams& params);
+
+ /// 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
+
+ /// A vector of compiled SQL statements
std::vector<PgSqlStatementBind> statements_;
- PGconn * status;
+
+ /// PostgreSQL connection handle
+ PGconn* status;
};
}; // end of isc::dhcp namespace
More information about the bind10-changes
mailing list