Browse Source

[3080] Many comments added for PostgreSQL backend

Tomek Mrugalski 11 years ago
parent
commit
f496ea9a13
2 changed files with 678 additions and 188 deletions
  1. 210 146
      src/lib/dhcpsrv/pgsql_lease_mgr.cc
  2. 468 42
      src/lib/dhcpsrv/pgsql_lease_mgr.h

+ 210 - 146
src/lib/dhcpsrv/pgsql_lease_mgr.cc

@@ -33,127 +33,146 @@ using namespace isc::dhcp;
 using namespace std;
 using namespace std;
 
 
 namespace {
 namespace {
+
+// Maximum text representation of an IPv6 address
 const size_t ADDRESS6_TEXT_MAX_LEN = 39;
 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;
 const size_t MAX_PARAMETERS_IN_QUERY = 12;
 
 
+// Defines a single query
 struct TaggedStatement {
 struct TaggedStatement {
+
+    /// Query index
     PgSqlLeaseMgr::StatementIndex index;
     PgSqlLeaseMgr::StatementIndex index;
+
+    /// Number of parameters for a given query
     int nbparams;
     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];
     const Oid types[MAX_PARAMETERS_IN_QUERY + 1];
+
+    /// Short name of the query.
     const char* name;
     const char* name;
+
+    /// Text represenation of the actual query.
     const char* text;
     const char* text;
 };
 };
 
 
 TaggedStatement tagged_statements[] = {
 TaggedStatement tagged_statements[] = {
     {PgSqlLeaseMgr::DELETE_LEASE4, 1,
     {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,
     {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,
     {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,
     {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,
     {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,
     {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,
     {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,
     {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,
     {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,
     {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,
     {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,
     {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,
     {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,
     {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,
     {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
     // End of list sentinel
     {PgSqlLeaseMgr::NUM_STATEMENTS, 0,  { 0 }, NULL, NULL}
     {PgSqlLeaseMgr::NUM_STATEMENTS, 0,  { 0 }, NULL, NULL}
 };
 };
@@ -163,17 +182,25 @@ TaggedStatement tagged_statements[] = {
 namespace isc {
 namespace isc {
 namespace dhcp {
 namespace dhcp {
 
 
+/// @brief Auxiliary PostgreSQL exchange class
 class PgSqlLeaseExchange {
 class PgSqlLeaseExchange {
 protected:
 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
     void
-    convertToTimestamp(const time_t & expire_,
-                       char buffer_[20]) {
+    convertToTimestamp(const time_t& expire, char buffer[20]) {
         struct tm tinfo;
         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) {
     bool stringToBool(char* value) {
         if (!strlen(value)) {
         if (!strlen(value)) {
             return (false);
             return (false);
@@ -188,11 +215,17 @@ protected:
                       " only accepted values are 't', 'f' or ''");
                       " only accepted values are 't', 'f' or ''");
         }
         }
     }
     }
+
+    /// Compiled statement bind parameters
+    bindparams params;
 };
 };
 
 
+/// @brief Represents a single Lease4 exchange
 class PgSqlLease4Exchange : public PgSqlLeaseExchange {
 class PgSqlLease4Exchange : public PgSqlLeaseExchange {
     static const size_t LEASE_COLUMNS = 9;
     static const size_t LEASE_COLUMNS = 9;
 public:
 public:
+
+    /// Default constructor
     PgSqlLease4Exchange() : addr4_(0) {
     PgSqlLease4Exchange() : addr4_(0) {
         memset(hwaddr_buffer_, 0, sizeof(hwaddr_buffer_));
         memset(hwaddr_buffer_, 0, sizeof(hwaddr_buffer_));
         memset(client_id_buffer_, 0, sizeof(client_id_buffer_));
         memset(client_id_buffer_, 0, sizeof(client_id_buffer_));
@@ -234,7 +267,8 @@ public:
                           << HWAddr::MAX_HWADDR_LEN);
                           << 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,
                                  .isbinary = 1,
                                  .binarylen = static_cast<int>(lease_->hwaddr_.size()) };
                                  .binarylen = static_cast<int>(lease_->hwaddr_.size()) };
             params.push_back(pdest);
             params.push_back(pdest);
@@ -283,18 +317,16 @@ public:
 
 
     Lease4Ptr
     Lease4Ptr
     convertFromDatabase(PGresult *& r, int line) {
     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;
         unsigned long valid_lifetime, expire, subnet_id;
 
 
         istringstream tmp;
         istringstream tmp;
@@ -452,18 +484,17 @@ public:
 
 
     Lease6Ptr
     Lease6Ptr
     convertFromDatabase(PGresult * r, int line) {
     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 int lease_type, prefixlen;
         unsigned long valid_lifetime, expire, subnet_id, pref_lifetime, iaid;
         unsigned long valid_lifetime, expire, subnet_id, pref_lifetime, iaid;
 
 
@@ -559,7 +590,6 @@ public:
 
 
 private:
 private:
     string     addr6_;
     string     addr6_;
-    //  char            addr6_buffer_[ADDRESS6_TEXT_MAX_LEN + 1];
     string     columns_[LEASE_COLUMNS];
     string     columns_[LEASE_COLUMNS];
     time_t          expire_;
     time_t          expire_;
     vector<uint8_t> duid_;
     vector<uint8_t> duid_;
@@ -585,10 +615,10 @@ PgSqlLeaseMgr::PgSqlLeaseMgr(const LeaseMgr::ParameterMap& parameters)
 }
 }
 
 
 PgSqlLeaseMgr::~PgSqlLeaseMgr() {
 PgSqlLeaseMgr::~PgSqlLeaseMgr() {
-    if(status) {
+    if (status) {
         // Attempt to deallocate prepared queries set previously with DEALLOCATE query
         // Attempt to deallocate prepared queries set previously with DEALLOCATE query
         // No internal libpq function for that, no errors checking as well
         // 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) {
         for(int i = 0; tagged_statements[i].text != NULL; ++ i) {
             string deallocate = "DEALLOCATE \"";
             string deallocate = "DEALLOCATE \"";
             deallocate += tagged_statements[i].name;
             deallocate += tagged_statements[i].name;
@@ -694,19 +724,19 @@ PgSqlLeaseMgr::openDatabase() {
 
 
 bool
 bool
 PgSqlLeaseMgr::addLeaseCommon(StatementIndex stindex,
 PgSqlLeaseMgr::addLeaseCommon(StatementIndex stindex,
-                              bindparams & params) {
+                              bindparams& params) {
 
 
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
               DHCPSRV_PGSQL_ADD_ADDR4).arg(statements_[stindex].stmt_name);
               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,
     PGresult * r = PQexecPrepared(status, statements_[stindex].stmt_name,
                                   statements_[stindex].stmt_nbparams,
                                   statements_[stindex].stmt_nbparams,
-                                  &params_[0], &lengths_[0], &formats_[0], 0);
+                                  &out_values[0], &out_lengths[0], &out_formats[0], 0);
 
 
     int s = PQresultStatus(r);
     int s = PQresultStatus(r);
     if (s != PGRES_COMMAND_OK) {
     if (s != PGRES_COMMAND_OK) {
@@ -755,10 +785,10 @@ void PgSqlLeaseMgr::getLeaseCollection(StatementIndex stindex,
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
               DHCPSRV_PGSQL_GET_ADDR4).arg(statements_[stindex].stmt_name);
               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");
     PGresult * r = PQexec(status, "SET AUTOCOMMIT TO OFF");
     PQclear(r);
     PQclear(r);
@@ -767,8 +797,8 @@ void PgSqlLeaseMgr::getLeaseCollection(StatementIndex stindex,
     PQclear(r);
     PQclear(r);
 
 
     r = PQexecPrepared(status, statements_[stindex].stmt_name,
     r = PQexecPrepared(status, statements_[stindex].stmt_name,
-                                  statements_[stindex].stmt_nbparams,
-                                  &params_[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");
     checkError(r, stindex, "unable to bind WHERE clause parameter");
     PQclear(r);
     PQclear(r);
@@ -878,8 +908,9 @@ PgSqlLeaseMgr::getLease4(const HWAddr& hwaddr) const {
 
 
     if (!hwaddr.hwaddr_.empty()) {
     if (!hwaddr.hwaddr_.empty()) {
         uint8_t* data = const_cast<uint8_t *>(&hwaddr.hwaddr_[0]);
         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);
         inparams.push_back(pdest);
     } else {
     } else {
         inparams.push_back(PgSqlParam());
         inparams.push_back(PgSqlParam());
@@ -928,8 +959,9 @@ PgSqlLeaseMgr::getLease4(const ClientId& clientid) const {
     bindparams inparams;
     bindparams inparams;
 
 
     vector<uint8_t> client_data = clientid.getClientId();
     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);
     inparams.push_back(pdest);
 
 
     // Get the data
     // Get the data
@@ -950,8 +982,9 @@ PgSqlLeaseMgr::getLease4(const ClientId& clientid, SubnetID subnet_id) const {
     ostringstream tmp;
     ostringstream tmp;
 
 
     vector<uint8_t> client_data = clientid.getClientId();
     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);
     inparams.push_back(pdest);
 
 
     tmp << static_cast<unsigned long>(subnet_id);
     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;
     bindparams inparams;
     ostringstream tmp;
     ostringstream tmp;
     vector<uint8_t> duid_data = duid.getDuid();
     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);
     inparams.push_back(pdest);
 
 
     /// @todo: use type
     /// @todo: use type
@@ -1198,6 +1232,36 @@ PgSqlLeaseMgr::getName() const {
     return (name);
     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
 string
 PgSqlLeaseMgr::getDescription() const {
 PgSqlLeaseMgr::getDescription() const {
     return (string("PostgreSQL Database"));
     return (string("PostgreSQL Database"));

+ 468 - 42
src/lib/dhcpsrv/pgsql_lease_mgr.h

@@ -25,60 +25,335 @@
 namespace isc {
 namespace isc {
 namespace dhcp {
 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 {
 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;
 typedef std::vector<PgSqlParam> bindparams;
 
 
+/// @brief Describes a single compiled statement
 struct PgSqlStatementBind {
 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 PgSqlLease4Exchange;
 class PgSqlLease6Exchange;
 class PgSqlLease6Exchange;
 
 
+/// Defines PostgreSQL backend version: 1.0
 const uint32_t PG_CURRENT_VERSION = 1;
 const uint32_t PG_CURRENT_VERSION = 1;
 const uint32_t PG_CURRENT_MINOR = 0;
 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 {
 class PgSqlLeaseMgr : public LeaseMgr {
 public:
 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);
     PgSqlLeaseMgr(const ParameterMap& parameters);
+
+    /// @brief Destructor (closes database)
     virtual ~PgSqlLeaseMgr();
     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);
     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);
     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;
     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;
     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,
     virtual Lease4Ptr getLease4(const isc::dhcp::HWAddr& hwaddr,
                                 SubnetID subnet_id) const;
                                 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;
     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,
     virtual Lease4Ptr getLease4(const ClientId& client_id, const HWAddr& hwaddr,
                                 SubnetID subnet_id) const;
                                 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,
     virtual Lease4Ptr getLease4(const ClientId& clientid,
                                 SubnetID subnet_id) const;
                                 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,
     virtual Lease6Ptr getLease6(Lease::Type type,
                                 const isc::asiolink::IOAddress& addr) const;
                                 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,
     virtual Lease6Collection getLeases6(Lease::Type type, const DUID& duid,
                                        uint32_t iaid) const;
                                        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,
     virtual Lease6Collection getLeases6(Lease::Type type, const DUID& duid,
                                         uint32_t iaid, SubnetID subnet_id) const;
                                         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);
     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);
     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);
     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 {
     virtual std::string getType() const {
         return (std::string("postgresql"));
         return (std::string("postgresql"));
     }
     }
+
+    /// @brief Returns name of the database.
+    ///
+    /// @return database name
     virtual std::string getName() const;
     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;
     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;
     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();
     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();
     virtual void rollback();
+
+    /// @brief Statement Tags
+    ///
+    /// The contents of the enum are indexes into the list of compiled SQL statements
     enum StatementIndex {
     enum StatementIndex {
         DELETE_LEASE4,              // Delete from lease4 by address
         DELETE_LEASE4,              // Delete from lease4 by address
         DELETE_LEASE6,              // Delete from lease6 by address
         DELETE_LEASE6,              // Delete from lease6 by address
@@ -97,61 +372,212 @@ public:
         UPDATE_LEASE6,              // Update a Lease6 entry
         UPDATE_LEASE6,              // Update a Lease6 entry
         NUM_STATEMENTS              // Number of statements
         NUM_STATEMENTS              // Number of statements
     };
     };
+
 private:
 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();
     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();
     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>
     template <typename Exchange, typename LeaseCollection>
-    void getLeaseCollection(StatementIndex stindex, bindparams & params,
+    void getLeaseCollection(StatementIndex stindex, bindparams& params,
                             Exchange& exchange, LeaseCollection& result,
                             Exchange& exchange, LeaseCollection& result,
                             bool single = false) const;
                             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 {
                             Lease4Collection& result) const {
         getLeaseCollection(stindex, params, exchange4_, result);
         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 {
                             Lease6Collection& result) const {
         getLeaseCollection(stindex, params, exchange6_, result);
         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;
                   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;
                   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>
     template <typename LeasePtr>
-    void updateLeaseCommon(StatementIndex stindex, bindparams & params,
+    void updateLeaseCommon(StatementIndex stindex, bindparams& params,
                            const LeasePtr& lease);
                            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_;
     std::vector<PgSqlStatementBind> statements_;
-    PGconn * status;
+
+    /// PostgreSQL connection handle
+    PGconn* status;
 };
 };
 
 
 }; // end of isc::dhcp namespace
 }; // end of isc::dhcp namespace