/// in the Client FQDN %Option (see RFC4702 and RFC4704).
const size_t HOSTNAME_MAX_LEN = 255;
-/// @brief Maximum length of dhcp identifier field
-///
-const size_t DHCP_IDENTIFIER_MAX_LEN = 128;
TaggedStatement tagged_statements[] = {
- {MySqlHostDataSource::INSERT_HOST,
- "INSERT INTO hosts(host_id, dhcp_identifier, dhcp_identifier_type, "
- "dhcp4_subnet_id, dhcp6_subnet_id, ipv4_address, "
- "hostname, dhcp4_client_classes, dhcp6_client_classes) "
- "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"},
- {MySqlHostDataSource::GET_HOST_HWADDR_DUID,
- "SELECT host_id, dhcp_identifier, dhcp_identifier_type, dhcp4_subnet_id, "
- "dhcp6_subnet_id, ipv4_address, hostname, dhcp4_client_classes, dhcp6_client_classes "
- "FROM hosts "
- "WHERE dhcp_identifier = ?"},
- {MySqlHostDataSource::GET_HOST_ADDR,
- "SELECT host_id, dhcp_identifier, dhcp_identifier_type, dhcp4_subnet_id, "
- "dhcp6_subnet_id, ipv4_address, hostname, dhcp4_client_classes, dhcp6_client_classes "
- "FROM hosts "
- "WHERE ipv4_address = ?"},
- {MySqlHostDataSource::GET_HOST_SUBID4_DHCPID,
- "SELECT host_id, dhcp_identifier, dhcp_identifier_type, dhcp4_subnet_id, "
- "dhcp6_subnet_id, ipv4_address, hostname, dhcp4_client_classes, dhcp6_client_classes "
- "FROM hosts "
- "WHERE dhcp4_subnet_id = ? AND dhcp_identifier = ?"},
- {MySqlHostDataSource::GET_HOST_SUBID6_DHCPID,
- "SELECT host_id, dhcp_identifier, dhcp_identifier_type, dhcp4_subnet_id, "
- "dhcp6_subnet_id, ipv4_address, hostname, dhcp4_client_classes, dhcp6_client_classes "
- "FROM hosts "
- "WHERE dhcp6_subnet_id = ? AND dhcp_identifier = ?"},
- {MySqlHostDataSource::GET_HOST_SUBID_ADDR,
- "SELECT host_id, dhcp_identifier, dhcp_identifier_type, dhcp4_subnet_id, "
- "dhcp6_subnet_id, ipv4_address, hostname, dhcp4_client_classes, dhcp6_client_classes "
- "FROM hosts "
- "WHERE dhcp4_subnet_id = ? AND ipv4_address = ?"},
- {MySqlHostDataSource::GET_HOST_PREFIX,
- "SELECT h.host_id, dhcp_identifier, dhcp_identifier_type, dhcp4_subnet_id, "
- "dhcp6_subnet_id, ipv4_address, hostname, dhcp4_client_classes, dhcp6_client_classes "
- "FROM hosts h "
- "LEFT JOIN ipv6_reservations r ON h.host_id = r.host_id "
- "WHERE r.prefix_len = ? AND r.address = ?"},
+ {MySqlHostDataSource::INSERT_HOST,
+ "INSERT INTO hosts(host_id, dhcp_identifier, dhcp_identifier_type, "
+ "dhcp4_subnet_id, dhcp6_subnet_id, ipv4_address, hostname, "
+ "dhcp4_client_classes, dhcp6_client_classes) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"},
+ {MySqlHostDataSource::GET_HOST_HWADDR_DUID,
+ "SELECT host_id, dhcp_identifier, dhcp_identifier_type, "
+ "dhcp4_subnet_id, dhcp6_subnet_id, ipv4_address, hostname, "
+ "dhcp4_client_classes, dhcp6_client_classes "
+ "FROM hosts "
+ "WHERE dhcp_identifier = ? AND dhcp_identifier_type = ?"},
+ {MySqlHostDataSource::GET_HOST_ADDR,
+ "SELECT host_id, dhcp_identifier, dhcp_identifier_type, "
+ "dhcp4_subnet_id, dhcp6_subnet_id, ipv4_address, hostname, "
+ "dhcp4_client_classes, dhcp6_client_classes "
+ "FROM hosts "
+ "WHERE ipv4_address = ?"},
+ {MySqlHostDataSource::GET_HOST_SUBID4_DHCPID,
+ "SELECT host_id, dhcp_identifier, dhcp_identifier_type, "
+ "dhcp4_subnet_id, dhcp6_subnet_id, ipv4_address, hostname, "
+ "dhcp4_client_classes, dhcp6_client_classes "
+ "FROM hosts "
+ "WHERE dhcp4_subnet_id = ? AND dhcp_identifier = ?"},
+ {MySqlHostDataSource::GET_HOST_SUBID6_DHCPID,
+ "SELECT host_id, dhcp_identifier, dhcp_identifier_type, "
+ "dhcp4_subnet_id, dhcp6_subnet_id, ipv4_address, hostname, "
+ "dhcp4_client_classes, dhcp6_client_classes "
+ "FROM hosts "
+ "WHERE dhcp6_subnet_id = ? AND dhcp_identifier = ?"},
+ {MySqlHostDataSource::GET_HOST_SUBID_ADDR,
+ "SELECT host_id, dhcp_identifier, dhcp_identifier_type, "
+ "dhcp4_subnet_id, dhcp6_subnet_id, ipv4_address, hostname, "
+ "dhcp4_client_classes, dhcp6_client_classes "
+ "FROM hosts "
+ "WHERE dhcp4_subnet_id = ? AND ipv4_address = ?"},
+ {MySqlHostDataSource::GET_HOST_PREFIX,
+ "SELECT h.host_id, dhcp_identifier, dhcp_identifier_type, "
+ "dhcp4_subnet_id, dhcp6_subnet_id, ipv4_address, hostname, "
+ "dhcp4_client_classes, dhcp6_client_classes "
+ "FROM hosts h, ipv6_reservations r "
+ "WHERE h.host_id = r.host_id AND r.prefix_len = ? "
+ " AND r.address = ?"},
{MySqlHostDataSource::GET_VERSION,
- "SELECT version, minor FROM schema_version"},
+ "SELECT version, minor FROM schema_version"},
{MySqlHostDataSource::NUM_STATEMENTS, NULL}
};
/// The initialization of the variables here is only to satisfy cppcheck -
/// all variables are initialized/set in the methods before they are used.
MySqlHostReservationExchange() : host_id_(0), dhcp_identifier_length_(0),
- dhcp_identifier_type_(0), dhcp4_subnet_id_(0),
- dhcp6_subnet_id_(0), ipv4_address_(0),
- hostname_length_(0), dhcp4_client_classes_length_(0),
- dhcp6_client_classes_length_(0), dhcp4_subnet_id_null_(MLM_FALSE),
- dhcp6_subnet_id_null_(MLM_FALSE), ipv4_address_null_(MLM_FALSE),
- hostname_null_(MLM_FALSE), dhcp4_client_classes_null_(MLM_FALSE),
- dhcp6_client_classes_null_(MLM_FALSE){
+ dhcp_identifier_type_(0), dhcp4_subnet_id_(0), dhcp6_subnet_id_(0),
+ ipv4_address_(0), hostname_length_(0), dhcp4_client_classes_length_(0),
+ dhcp6_client_classes_length_(0), dhcp4_subnet_id_null_(MLM_FALSE),
+ dhcp6_subnet_id_null_(MLM_FALSE), ipv4_address_null_(MLM_FALSE),
+ hostname_null_(MLM_FALSE), dhcp4_client_classes_null_(MLM_FALSE),
+ dhcp6_client_classes_null_(MLM_FALSE){
memset(dhcp_identifier_buffer_, 0, sizeof(dhcp_identifier_buffer_));
memset(hostname_, 0, sizeof(hostname_));
/// @brief Set error indicators
///
- /// Sets the error indicator for each of the MYSQL_BIND elements. It points
+ /// Sets the error indicator for each of the MYSQL_BIND elements. It points
/// the "error" field within an element of the input array to the
/// corresponding element of the passed error array.
///
/// Fills in the MYSQL_BIND array for sending data in the Host object to
/// the database.
///
- /// @param host Host object to be added to the database. None of the
- /// fields in the host reservation are modified - the host data is only read.
+ /// @param host Host object to be added to the database.
+ /// None of the fields in the host reservation are modified -
+ /// the host data is only read.
///
/// @return Vector of MySQL BIND objects representing the data to be added.
std::vector<MYSQL_BIND> createBindForSend(const HostPtr& host) {
try {
// host_id : INT UNSIGNED NOT NULL
- // The host_id is auto_incremented by MySQL database,
- // so we need to pass the NULL value
+ // The host_id is auto_incremented by MySQL database,
+ // so we need to pass the NULL value
host_id_ = static_cast<uint32_t>(NULL);
bind_[0].buffer_type = MYSQL_TYPE_LONG;
bind_[0].buffer = reinterpret_cast<char*>(&host_id_);
bind_[0].is_unsigned = MLM_TRUE;
- // bind_[0].is_null = &MLM_TRUE; //compile problems here!
+ //bind_[0].is_null = &MLM_FALSE; // commented out for performance
+ // reasons, see memset() above
// dhcp_identifier : VARBINARY(128) NOT NULL
// Check which of the identifiers is used and set values accordingly
if (host_->getDuid()) {
dhcp_identifier_length_ = host_->getDuid()->getDuid().size();
- bind_[1].buffer_type = MYSQL_TYPE_BLOB;
- bind_[1].buffer = reinterpret_cast<char*>(host_->getDuid()->getDuid()[0]);
- bind_[1].buffer_length = dhcp_identifier_length_;
- bind_[1].length = &dhcp_identifier_length_;
- // bind_[1].is_null = &MLM_FALSE; // commented out for performance
- // reasons, see memset() above
+ bind_[1].buffer_type = MYSQL_TYPE_BLOB;
+ bind_[1].buffer = reinterpret_cast<char*>
+ (host_->getDuid()->getDuid()[0]);
+ bind_[1].buffer_length = dhcp_identifier_length_;
+ bind_[1].length = &dhcp_identifier_length_;
+ // bind_[1].is_null = &MLM_FALSE; // commented out for performance
+ // reasons, see memset() above
} else if (host_->getHWAddress()){
- dhcp_identifier_length_ = host_->getHWAddress()->hwaddr_.size();
- bind_[1].buffer_type = MYSQL_TYPE_BLOB;
- bind_[1].buffer = reinterpret_cast<char*>(&(host_->getHWAddress()->hwaddr_[0]));
- bind_[1].buffer_length = dhcp_identifier_length_;
- bind_[1].length = &dhcp_identifier_length_;
- // bind_[1].is_null = &MLM_FALSE; // commented out for performance
- // reasons, see memset() above
+ dhcp_identifier_length_ = host_->getHWAddress()->hwaddr_.size();
+ bind_[1].buffer_type = MYSQL_TYPE_BLOB;
+ bind_[1].buffer = reinterpret_cast<char*>
+ (&(host_->getHWAddress()->hwaddr_[0]));
+ bind_[1].buffer_length = dhcp_identifier_length_;
+ bind_[1].length = &dhcp_identifier_length_;
+ // bind_[1].is_null = &MLM_FALSE; // commented out for performance
+ // reasons, see memset() above
}
// dhcp_identifier_type : TINYINT NOT NULL
// Check which of the identifier types is used and set values accordingly
if (host_->getHWAddress()) {
- bind_[2].buffer_type = MYSQL_TYPE_TINY;
- bind_[2].buffer = reinterpret_cast<char*>(0); // 0 = IDENT_HWADDR
- bind_[2].is_unsigned = MLM_TRUE;
- // bind_[2].is_null = &MLM_FALSE; // commented out for performance
- // reasons, see memset() above
+ bind_[2].buffer_type = MYSQL_TYPE_TINY;
+ bind_[2].buffer = reinterpret_cast<char*>(0);// 0 = IDENT_HWADDR
+ bind_[2].is_unsigned = MLM_TRUE;
+ // bind_[2].is_null = &MLM_FALSE; // commented out for performance
+ // reasons, see memset() above
} else if (host_->getDuid()) {
- bind_[2].buffer_type = MYSQL_TYPE_TINY;
- bind_[2].buffer = reinterpret_cast<char*>(1); // 1 = IDENT_DUID
- bind_[2].is_unsigned = MLM_TRUE;
- // bind_[2].is_null = &MLM_FALSE; // commented out for performance
- // reasons, see memset() above
+ bind_[2].buffer_type = MYSQL_TYPE_TINY;
+ bind_[2].buffer = reinterpret_cast<char*>(1);// 1 = IDENT_DUID
+ bind_[2].is_unsigned = MLM_TRUE;
+ // bind_[2].is_null = &MLM_FALSE; // commented out for performance
+ // reasons, see memset() above
}
// dhcp4_subnet_id : INT UNSIGNED NULL
/// @return Host Pointer to a Lease6 object holding the relevant data.
HostPtr getHostData(){
- // Set the dhcp identifier type in a variable of the appropriate data type, which
- // has been initialized with an arbitrary (but valid) value.
+ // Set the dhcp identifier type in a variable of the appropriate data type,
+ // which has been initialized with an arbitrary (but valid) value.
Host::IdentifierType type = Host::IDENT_HWADDR;
switch (dhcp_identifier_type_) {
break;
default:
- isc_throw(BadValue, "invalid dhcp identifier type returned (" <<
- static_cast<int>(dhcp_identifier_type_) << ") for host with "
- << "identifier " << reinterpret_cast<char*>(dhcp_identifier_[0]) << ". Only 0 or 1 are allowed.");
+ isc_throw(BadValue, "invalid dhcp identifier type returned: "
+ << static_cast<int>(dhcp_identifier_type_)
+ << ". Only 0 or 1 are allowed.");
}
// Set subnets ID's if they are given, if not, leave an empty object
- SubnetID ipv4_subnet_id = static_cast<SubnetID>(NULL); // This is probably wrong way to do it...
+ SubnetID ipv4_subnet_id(0);
if (dhcp4_subnet_id_null_ == MLM_FALSE)
- ipv4_subnet_id = static_cast<SubnetID>(dhcp4_subnet_id_);
+ ipv4_subnet_id = static_cast<SubnetID>(dhcp4_subnet_id_);
- SubnetID ipv6_subnet_id = static_cast<SubnetID>(NULL);
+ SubnetID ipv6_subnet_id(0);
if (dhcp6_subnet_id_null_ == MLM_FALSE)
ipv6_subnet_id = static_cast<SubnetID>(dhcp6_subnet_id_);
if (hostname_null_ == MLM_FALSE)
hostname = std::string (hostname_, hostname_ + hostname_length_);
- // Not sure if this is necessary yet, since Host constructor takes strings, not ClientClasses objects
+ // Not sure if this is necessary yet, since Host constructor takes strings,
+ // not ClientClasses objects
// Set client classes if they were given, if not, set empty client classes
ClientClasses dhcp4_client_classes;
if (dhcp4_client_classes_null_ == MLM_FALSE)
dhcp6_client_classes.insert(dhcp6_client_classes_);
// Returning Host object with set fields
- return (HostPtr(new Host(dhcp_identifier_buffer_,
- dhcp_identifier_length_,
- type,
- ipv4_subnet_id,
- ipv6_subnet_id,
- ipv4_reservation,
- hostname,
- dhcp4_client_classes_,
- dhcp6_client_classes_)));
+ return (HostPtr(
+ new Host(dhcp_identifier_buffer_, dhcp_identifier_length_,
+ type, ipv4_subnet_id, ipv6_subnet_id, ipv4_reservation,
+ hostname, dhcp4_client_classes_, dhcp6_client_classes_)));
}
/// @brief Return columns in error
}
private:
- //std::string addr6_; //< String form of address
- //char addr6_buffer_[ADDRESS6_TEXT_MAX_LEN + 1]; // array form of V6 address
- uint32_t host_id_; // Unique identifier of the host
- std::vector<uint8_t> dhcp_identifier_; // DHCP identifier, can be HW address (0) or DUID (1)
- uint8_t dhcp_identifier_buffer_[DHCP_IDENTIFIER_MAX_LEN]; // Buffer form of dhcp identifier
- size_t dhcp_identifier_length_; // Length of the dhcp identifier
- uint8_t dhcp_identifier_type_; // Type of the dhcp_identifier (HW address or DUID)
- uint32_t dhcp4_subnet_id_; // Subnet identifier for the DHCPv4 client.
- uint32_t dhcp6_subnet_id_; // Subnet identifier for the DHCPv6 client.
- uint32_t ipv4_address_; // Reserved IPv4 address.
- IPv6ResrvCollection ipv6_reservations_; // Collection of IPv6 reservations for the host.
- char hostname_[HOSTNAME_MAX_LEN];// Name reserved for the host.
- unsigned long hostname_length_; // hostname length
- char dhcp4_client_classes_[CLIENT_CLASSES_MAX_LEN]; // Collection of classes associated with a DHCPv4 client.
- unsigned long dhcp4_client_classes_length_;// dhcp4_client_classes length
- char dhcp6_client_classes_[CLIENT_CLASSES_MAX_LEN]; // Collection of classes associated with a DHCPv6 client.
- unsigned long dhcp6_client_classes_length_;// dhcp6_client_classes length
- HWAddrPtr hw_address_; // Pointer to the hardware address associated with the reservations for the host.
- DuidPtr duid_; // Pointer to the DUID associated with the reservations for the host.
+ uint32_t host_id_; /// Host unique identifier
+ std::vector<uint8_t> dhcp_identifier_; /// HW address (0) / DUID (1)
+ uint8_t dhcp_identifier_buffer_[DUID::MAX_DUID_LEN];
+ /// Buffer for dhcp identifier
+ size_t dhcp_identifier_length_; /// Length of dhcp identifier
+ uint8_t dhcp_identifier_type_; /// Type of dhcp_identifier
+ uint32_t dhcp4_subnet_id_; /// Subnet DHCPv4 identifier
+ uint32_t dhcp6_subnet_id_; /// Subnet DHCPv6 identifier
+ uint32_t ipv4_address_; /// Reserved IPv4 address.
+ IPv6ResrvCollection ipv6_reservations_; /// IPv6 reservations collection
+ char hostname_[HOSTNAME_MAX_LEN]; /// Name reserved for the host
+ unsigned long hostname_length_; /// hostname length
+ char dhcp4_client_classes_[CLIENT_CLASSES_MAX_LEN];
+ /// DHCPv4 client classes
+ unsigned long dhcp4_client_classes_length_; /// dhcp4_client_classes length
+ char dhcp6_client_classes_[CLIENT_CLASSES_MAX_LEN];
+ /// DHCPv6 client classes
+ unsigned long dhcp6_client_classes_length_; /// dhcp6_client_classes length
+ HWAddrPtr hw_address_; /// Pointer to hardware address
+ DuidPtr duid_; /// Pointer to DUID
// NULL flags for subnets id, ipv4 address, hostname and client classes
- my_bool dhcp4_subnet_id_null_;
- my_bool dhcp6_subnet_id_null_;
- my_bool ipv4_address_null_;
- my_bool hostname_null_;
- my_bool dhcp4_client_classes_null_;
- my_bool dhcp6_client_classes_null_;
-
- MYSQL_BIND bind_[HOST_COLUMNS];
- std::string columns_[HOST_COLUMNS]; // Column names
- my_bool error_[HOST_COLUMNS]; // Error array
- HostPtr host_; // Pointer to Host object
+ my_bool dhcp4_subnet_id_null_;
+ my_bool dhcp6_subnet_id_null_;
+ my_bool ipv4_address_null_;
+ my_bool hostname_null_;
+ my_bool dhcp4_client_classes_null_;
+ my_bool dhcp6_client_classes_null_;
+
+ MYSQL_BIND bind_[HOST_COLUMNS];
+ std::string columns_[HOST_COLUMNS]; /// Column names
+ my_bool error_[HOST_COLUMNS]; /// Error array
+ HostPtr host_; // Pointer to Host object
};
// MySqlHostDataSource Constructor and Destructor
MySqlHostDataSource::MySqlHostDataSource(
- const MySqlConnection::ParameterMap& parameters) :
- MySqlConnection(parameters) {
-
- // Open the database.
- openDatabase();
-
- // Enable autocommit. To avoid a flush to disk on every commit, the global
- // parameter innodb_flush_log_at_trx_commit should be set to 2. This will
- // cause the changes to be written to the log, but flushed to disk in the
- // background every second. Setting the parameter to that value will speed
- // up the system, but at the risk of losing data if the system crashes.
- my_bool result = mysql_autocommit(mysql_, 1);
- if (result != 0) {
- isc_throw(DbOperationError, mysql_error(mysql_));
- }
+ const MySqlConnection::ParameterMap& parameters) : conn_(parameters) {
+
+ // Open the database.
+ conn_.openDatabase();
+
+ // Enable autocommit. To avoid a flush to disk on every commit, the global
+ // parameter innodb_flush_log_at_trx_commit should be set to 2. This will
+ // cause the changes to be written to the log, but flushed to disk in the
+ // background every second. Setting the parameter to that value will speed
+ // up the system, but at the risk of losing data if the system crashes.
+ my_bool result = mysql_autocommit(conn_.mysql_, 1);
+ if (result != 0) {
+ isc_throw(DbOperationError, mysql_error(conn_.mysql_));
+ }
- // Prepare all statements likely to be used.
- prepareStatements(tagged_statements, MySqlHostDataSource::NUM_STATEMENTS);
+ // Prepare all statements likely to be used.
+ conn_.prepareStatements(tagged_statements,
+ MySqlHostDataSource::NUM_STATEMENTS);
- // Create the exchange objects for use in exchanging data between the
- // program and the database.
- hostExchange_.reset(new MySqlHostReservationExchange());
+ // Create the exchange objects for use in exchanging data between the
+ // program and the database.
+ hostExchange_.reset(new MySqlHostReservationExchange());
}
MySqlHostDataSource::~MySqlHostDataSource() {
- // Free up the prepared statements, ignoring errors. (What would we do
- // about them? We're destroying this object and are not really concerned
- // with errors on a database connection that is about to go away.)
- for (int i = 0; i < statements_.size(); ++i) {
- if (statements_[i] != NULL) {
- (void) mysql_stmt_close(statements_[i]);
- statements_[i] = NULL;
- }
- }
+ // Free up the prepared statements, ignoring errors. (What would we do
+ // about them? We're destroying this object and are not really concerned
+ // with errors on a database connection that is about to go away.)
+ for (int i = 0; i < conn_.statements_.size(); ++i) {
+ if (conn_.statements_[i] != NULL) {
+ (void) mysql_stmt_close(conn_.statements_[i]);
+ conn_.statements_[i] = NULL;
+ }
+ }
- // There is no need to close the database in this destructor: it is
- // closed in the destructor of the mysql_ member variable.
+ // There is no need to close the database in this destructor: it is
+ // closed in the destructor of the mysql_ member variable.
}
-// Time conversion methods.
-//
-// Note that the MySQL TIMESTAMP data type (used for "expire") converts data
-// from the current timezone to UTC for storage, and from UTC to the current
-// timezone for retrieval.
-//
-// This causes no problems providing that:
-// a) cltt is given in local time
-// b) We let the system take care of timezone conversion when converting
-// from a time read from the database into a local time.
-
void
MySqlHostDataSource::add(const HostPtr& host) {
// Create the MYSQL_BIND array for the host
std::vector<MYSQL_BIND> bind = hostExchange_->createBindForSend(host);
// ... and drop to add code.
- if (!addHost(INSERT_HOST, bind)) {
- // Throw an failure exception here
- }
+ addHost(INSERT_HOST, bind);
}
-bool
+void
MySqlHostDataSource::addHost(StatementIndex stindex,
std::vector<MYSQL_BIND>& bind) {
// Bind the parameters to the statement
- int status = mysql_stmt_bind_param(statements_[stindex], &bind[0]);
+ int status = mysql_stmt_bind_param(conn_.statements_[stindex],
+ &bind[0]);
checkError(status, stindex, "unable to bind parameters");
// Execute the statement
- status = mysql_stmt_execute(statements_[stindex]);
+ status = mysql_stmt_execute(conn_.statements_[stindex]);
if (status != 0) {
-
- // Failure: check for the special case of duplicate entry. If this is
- // the case, we return false to indicate that the row was not added.
- // Otherwise we throw an exception.
- if (mysql_errno(mysql_) == ER_DUP_ENTRY) {
- return (false);
- }
- checkError(status, stindex, "unable to execute");
+ // Failure: check for the special case of duplicate entry.
+ if (mysql_errno(conn_.mysql_) == ER_DUP_ENTRY) {
+ isc_throw(DuplicateEntry, "Database duplicate entry error");
+ }
+ checkError(status, stindex, "unable to execute");
}
-
- // Insert succeeded
- return (true);
}
void
MySqlHostDataSource::getHostCollection(StatementIndex stindex, MYSQL_BIND* bind,
- boost::shared_ptr<MySqlHostReservationExchange> exchange,
- ConstHostCollection& result, bool single) const {
+ boost::shared_ptr<MySqlHostReservationExchange> exchange,
+ ConstHostCollection& result, bool single) const {
// Bind the selection parameters to the statement
- int status = mysql_stmt_bind_param(statements_[stindex], bind);
+ int status = mysql_stmt_bind_param(conn_.statements_[stindex], bind);
checkError(status, stindex, "unable to bind WHERE clause parameter");
// Set up the MYSQL_BIND array for the data being returned and bind it to
// the statement.
std::vector<MYSQL_BIND> outbind = exchange->createBindForReceive();
- status = mysql_stmt_bind_result(statements_[stindex], &outbind[0]);
+ status = mysql_stmt_bind_result(conn_.statements_[stindex], &outbind[0]);
checkError(status, stindex, "unable to bind SELECT clause parameters");
// Execute the statement
- status = mysql_stmt_execute(statements_[stindex]);
+ status = mysql_stmt_execute(conn_.statements_[stindex]);
checkError(status, stindex, "unable to execute");
// Ensure that all the lease information is retrieved in one go to avoid
// overhead of going back and forth between client and server.
- status = mysql_stmt_store_result(statements_[stindex]);
+ status = mysql_stmt_store_result(conn_.statements_[stindex]);
checkError(status, stindex, "unable to set up for storing all results");
// Set up the fetch "release" object to release resources associated
// with the call to mysql_stmt_fetch when this method exits, then
// retrieve the data.
- MySqlFreeResult fetch_release(statements_[stindex]);
+ MySqlFreeResult fetch_release(conn_.statements_[stindex]);
int count = 0;
- while ((status = mysql_stmt_fetch(statements_[stindex])) == 0) {
+ while ((status = mysql_stmt_fetch(conn_.statements_[stindex])) == 0) {
try {
result.push_back(exchange->getHostData());
} catch (const isc::BadValue& ex) {
// Rethrow the exception with a bit more data.
isc_throw(BadValue, ex.what() << ". Statement is <" <<
- text_statements_[stindex] << ">");
+ conn_.text_statements_[stindex] << ">");
}
if (single && (++count > 1)) {
isc_throw(MultipleRecords, "multiple records were found in the "
"database where only one was expected for query "
- << text_statements_[stindex]);
+ << conn_.text_statements_[stindex]);
}
}
checkError(status, stindex, "unable to fetch results");
} else if (status == MYSQL_DATA_TRUNCATED) {
// Data truncated - throw an exception indicating what was at fault
- isc_throw(DataTruncated, text_statements_[stindex]
+ isc_throw(DataTruncated, conn_.text_statements_[stindex]
<< " returned truncated data: columns affected are "
<< exchange->getErrorColumns());
}
MYSQL_BIND inbind[2];
memset(inbind, 0, sizeof(inbind));
- // DUID
- const vector<uint8_t>& duid_vector = duid->getDuid();
- unsigned long duid_length = duid_vector.size();
- inbind[0].buffer_type = MYSQL_TYPE_BLOB;
- inbind[0].buffer =
- reinterpret_cast<char*>(const_cast<uint8_t*>(&duid_vector[0]));
- inbind[0].buffer_length = duid_length;
- inbind[0].length = &duid_length;
-
- // HW Address
- const vector<uint8_t>& hwaddr_vector = hwaddr->hwaddr_;
- unsigned long hwaddr_length = hwaddr_vector.size();
- inbind[1].buffer_type = MYSQL_TYPE_BLOB;
- inbind[1].buffer =
- reinterpret_cast<char*>(const_cast<uint8_t*>(&hwaddr_vector[0]));
- inbind[1].buffer_length = hwaddr_length;
- inbind[1].length = &hwaddr_length;
+ if (duid){
+ // DUID
+ // set proper dhcp_identifier_type
+ inbind[1].buffer = reinterpret_cast<char*>(1);
+
+ const vector<uint8_t>& duid_vector = duid->getDuid();
+ unsigned long duid_length = duid_vector.size();
+ inbind[0].buffer_type = MYSQL_TYPE_BLOB;
+ inbind[0].buffer = reinterpret_cast<char*>
+ (const_cast<uint8_t*>(&duid_vector[0]));
+ inbind[0].buffer_length = duid_length;
+ inbind[0].length = &duid_length;
+ } else if (hwaddr) {
+ // HW Address
+ // set proper dhcp_identifier_type
+ inbind[1].buffer = reinterpret_cast<char*>(0);
+
+ const vector<uint8_t>& hwaddr_vector = hwaddr->hwaddr_;
+ unsigned long hwaddr_length = hwaddr_vector.size();
+ inbind[0].buffer_type = MYSQL_TYPE_BLOB;
+ inbind[0].buffer = reinterpret_cast<char*>
+ (const_cast<uint8_t*>(&hwaddr_vector[0]));
+ inbind[0].buffer_length = hwaddr_length;
+ inbind[0].length = &hwaddr_length;
+ }
+
+ // dhcp_identifier_type
+ inbind[1].buffer_type = MYSQL_TYPE_TINY;
+ inbind[1].is_unsigned = MLM_TRUE;
ConstHostCollection result;
- getHostCollection(GET_HOST_HWADDR_DUID, inbind, hostExchange_, result, false);
+ getHostCollection(GET_HOST_HWADDR_DUID, inbind, hostExchange_,
+ result, false);
return (result);
}
const vector<uint8_t>& hwaddr_vector = hwaddr->hwaddr_;
unsigned long hwaddr_length = hwaddr_vector.size();
inbind[1].buffer_type = MYSQL_TYPE_BLOB;
- inbind[1].buffer =
- reinterpret_cast<char*>(const_cast<uint8_t*>(&hwaddr_vector[0]));
+ inbind[1].buffer = reinterpret_cast<char*>
+ (const_cast<uint8_t*>(&hwaddr_vector[0]));
inbind[1].buffer_length = hwaddr_length;
inbind[1].length = &hwaddr_length;
} else if (duid) {
const vector<uint8_t>& duid_vector = duid->getDuid();
unsigned long duid_length = duid_vector.size();
inbind[1].buffer_type = MYSQL_TYPE_BLOB;
- inbind[1].buffer =
- reinterpret_cast<char*>(const_cast<uint8_t*>(&duid_vector[0]));
+ inbind[1].buffer = reinterpret_cast<char*>
+ (const_cast<uint8_t*>(&duid_vector[0]));
inbind[1].buffer_length = duid_length;
inbind[1].length = &duid_length;
}
// if none of the identifiers was given, this field should remain null
ConstHostCollection collection;
- getHostCollection(GET_HOST_SUBID4_DHCPID, inbind, hostExchange_, collection,
- true);
+ getHostCollection(GET_HOST_SUBID4_DHCPID, inbind, hostExchange_,
+ collection, true);
// Return single record if present, else clear the host.
ConstHostPtr result;
- if (collection.empty()) {
- result.reset();
- } else {
- result = *collection.begin();
- }
+ if (!collection.empty())
+ result = *collection.begin();
return (result);
}
inbind[1].is_unsigned = MLM_TRUE;
ConstHostCollection collection;
- getHostCollection(GET_HOST_SUBID_ADDR, inbind, hostExchange_, collection,
- true);
+ getHostCollection(GET_HOST_SUBID_ADDR, inbind, hostExchange_,
+ collection, true);
// Return single record if present, else clear the host.
ConstHostPtr result;
- if (collection.empty()) {
- result.reset();
- } else {
- result = *collection.begin();
- }
+ if (!collection.empty())
+ result = *collection.begin();
return (result);
}
const vector<uint8_t>& hwaddr_vector = hwaddr->hwaddr_;
unsigned long hwaddr_length = hwaddr_vector.size();
inbind[1].buffer_type = MYSQL_TYPE_BLOB;
- inbind[1].buffer =
- reinterpret_cast<char*>(const_cast<uint8_t*>(&hwaddr_vector[0]));
+ inbind[1].buffer = reinterpret_cast<char*>
+ (const_cast<uint8_t*>(&hwaddr_vector[0]));
inbind[1].buffer_length = hwaddr_length;
inbind[1].length = &hwaddr_length;
} else if (duid) {
const vector<uint8_t>& duid_vector = duid->getDuid();
unsigned long duid_length = duid_vector.size();
inbind[1].buffer_type = MYSQL_TYPE_BLOB;
- inbind[1].buffer =
- reinterpret_cast<char*>(const_cast<uint8_t*>(&duid_vector[0]));
+ inbind[1].buffer = reinterpret_cast<char*>
+ (const_cast<uint8_t*>(&duid_vector[0]));
inbind[1].buffer_length = duid_length;
inbind[1].length = &duid_length;
}
// if none of the identifiers was given, this field should remain null
ConstHostCollection collection;
- getHostCollection(GET_HOST_SUBID6_DHCPID, inbind, hostExchange_, collection,
- true);
+ getHostCollection(GET_HOST_SUBID6_DHCPID, inbind, hostExchange_,
+ collection, true);
// Return single record if present, else clear the host.
ConstHostPtr result;
- if (collection.empty()) {
- result.reset();
- } else {
- result = *collection.begin();
- }
+ if (!collection.empty())
+ result = *collection.begin();
return (result);
}
inbind[1].is_unsigned = MLM_TRUE;
ConstHostCollection collection;
- getHostCollection(GET_HOST_PREFIX, inbind, hostExchange_, collection, true);
+ getHostCollection(GET_HOST_PREFIX, inbind, hostExchange_,
+ collection, true);
// Return single record if present, else clear the host.
ConstHostPtr result;
- if (collection.empty()) {
- result.reset();
- } else {
- result = *collection.begin();
- }
+ if (!collection.empty())
+ result = *collection.begin();
return (result);
}
inbind[1].is_unsigned = MLM_TRUE;
ConstHostCollection collection;
- getHostCollection(GET_HOST_SUBID_ADDR, inbind, hostExchange_, collection,
- true);
+ getHostCollection(GET_HOST_SUBID_ADDR, inbind, hostExchange_,
+ collection, true);
// Return single record if present, else clear the host.
ConstHostPtr result;
- if (collection.empty()) {
- result.reset();
- } else {
- result = *collection.begin();
- }
+ if (!collection.empty())
+ result = *collection.begin();
return (result);
}
std::string MySqlHostDataSource::getName() const {
std::string name = "";
try {
- name = getParameter("name");
+ name = conn_.getParameter("name");
} catch (...) {
// Return an empty name
}
}
std::string MySqlHostDataSource::getDescription() const {
- return (std::string("MySQL Database"));
+ return (std::string("Host data source that stores host information"
+ "in MySQL database"));
}
std::pair<uint32_t, uint32_t> MySqlHostDataSource::getVersion() const {
uint32_t minor; // Minor version number
// Execute the prepared statement
- int status = mysql_stmt_execute(statements_[stindex]);
+ int status = mysql_stmt_execute(conn_.statements_[stindex]);
if (status != 0) {
- isc_throw(DbOperationError,
- "unable to execute <" << text_statements_[stindex] << "> - reason: " << mysql_error(mysql_));
+ isc_throw(DbOperationError, "unable to execute <"
+ << conn_.text_statements_[stindex]
+ << "> - reason: " << mysql_error(conn_.mysql_));
}
// Bind the output of the statement to the appropriate variables.
bind[1].buffer = &minor;
bind[1].buffer_length = sizeof(minor);
- status = mysql_stmt_bind_result(statements_[stindex], bind);
+ status = mysql_stmt_bind_result(conn_.statements_[stindex], bind);
if (status != 0) {
- isc_throw(DbOperationError,
- "unable to bind result set: " << mysql_error(mysql_));
+ isc_throw(DbOperationError, "unable to bind result set: "
+ << mysql_error(conn_.mysql_));
}
// Fetch the data and set up the "release" object to release associated
// resources when this method exits then retrieve the data.
- MySqlFreeResult fetch_release(statements_[stindex]);
- status = mysql_stmt_fetch(statements_[stindex]);
+ MySqlFreeResult fetch_release(conn_.statements_[stindex]);
+ status = mysql_stmt_fetch(conn_.statements_[stindex]);
if (status != 0) {
- isc_throw(DbOperationError,
- "unable to obtain result set: " << mysql_error(mysql_));
+ isc_throw(DbOperationError, "unable to obtain result set: "
+ << mysql_error(conn_.mysql_));
}
return (std::make_pair(major, minor));
}
-void MySqlHostDataSource::commit() {
- LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_COMMIT);
- if (mysql_commit(mysql_) != 0) {
- isc_throw(DbOperationError, "commit failed: " << mysql_error(mysql_));
- }
-}
-
-void MySqlHostDataSource::rollback() {
- LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_ROLLBACK);
- if (mysql_rollback(mysql_) != 0) {
- isc_throw(DbOperationError, "rollback failed: " << mysql_error(mysql_));
- }
-}
-
}; // end of isc::dhcp namespace
}; // end of isc namespace
#include <boost/utility.hpp>
#include <mysql.h>
-
namespace isc {
namespace dhcp {
-// Define the current database schema values
-
-const uint32_t CURRENT_VERSION_VERSION = 3;
-const uint32_t CURRENT_VERSION_MINOR = 0;
-
-
// Forward declaration of the Host exchange objects. These classes are defined
// in the .cc file.
class MySqlHostReservationExchange;
+/// @brief MySQL Host Data Source
+///
+/// This class provides the \ref isc::dhcp::BaseHostDataSource interface to the MySQL
+/// database. Use of this backend presupposes that a MySQL database is
+/// available and that the Kea schema has been created within it.
-class MySqlHostDataSource : public BaseHostDataSource, public MySqlConnection {
+class MySqlHostDataSource: public BaseHostDataSource {
public:
/// @brief Constructor
/// @throw isc::dhcp::DbOpenError Error opening the database
/// @throw isc::dhcp::DbOperationError An operation on the open database has
/// failed.
- MySqlHostDataSource(const ParameterMap& parameters);
+ MySqlHostDataSource(const DatabaseConnection::ParameterMap& parameters);
/// @brief Destructor (closes database)
virtual ~MySqlHostDataSource();
getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid = DuidPtr()) const;
/// @brief Returns a collection of hosts using the specified IPv4 address.
- ///
- /// This method may return multiple @c Host objects if they are connected
- /// to different subnets.
- ///
- /// @param address IPv4 address for which the @c Host object is searched.
- ///
- /// @return Collection of const @c Host objects.
- virtual ConstHostCollection
- getAll4(const asiolink::IOAddress& address) const;
-
- /// @brief Returns a host connected to the IPv4 subnet.
- ///
- /// Implementations of this method should guard against the case when
- /// mutliple instances of the @c Host are present, e.g. when two
- /// @c Host objects are found, one for the DUID, another one for the
- /// HW address. In such case, an implementation of this method
- /// should throw an exception.
- ///
- /// @param subnet_id Subnet identifier.
- /// @param hwaddr HW address of the client or NULL if no HW address
- /// available.
- /// @param duid client id or NULL if not available.
- ///
- /// @return Const @c Host object using a specified HW address or DUID.
- virtual ConstHostPtr
- get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
- const DuidPtr& duid = DuidPtr()) const;
-
- /// @brief Returns a host connected to the IPv4 subnet and having
- /// a reservation for a specified IPv4 address.
- ///
- /// One of the use cases for this method is to detect collisions between
- /// dynamically allocated addresses and reserved addresses. When the new
- /// address is assigned to a client, the allocation mechanism should check
- /// if this address is not reserved for some other host and do not allocate
- /// this address if reservation is present.
- ///
- /// Implementations of this method should guard against invalid addresses,
- /// such as IPv6 address.
- ///
- /// @param subnet_id Subnet identifier.
- /// @param address reserved IPv4 address.
- ///
- /// @return Const @c Host object using a specified IPv4 address.
- virtual ConstHostPtr
- get4(const SubnetID& subnet_id, const asiolink::IOAddress& address) const;
-
- /// @brief Returns a host connected to the IPv6 subnet.
- ///
- /// Implementations of this method should guard against the case when
- /// mutliple instances of the @c Host are present, e.g. when two
- /// @c Host objects are found, one for the DUID, another one for the
- /// HW address. In such case, an implementation of this method
- /// should throw an exception.
- ///
- /// @param subnet_id Subnet identifier.
- /// @param hwaddr HW address of the client or NULL if no HW address
- /// available.
- /// @param duid DUID or NULL if not available.
- ///
- /// @return Const @c Host object using a specified HW address or DUID.
- virtual ConstHostPtr
- get6(const SubnetID& subnet_id, const DuidPtr& duid,
- const HWAddrPtr& hwaddr = HWAddrPtr()) const;
-
- /// @brief Returns a host using the specified IPv6 prefix.
- ///
- /// @param prefix IPv6 prefix for which the @c Host object is searched.
- /// @param prefix_len IPv6 prefix length.
- ///
- /// @return Const @c Host object using a specified HW address or DUID.
- virtual ConstHostPtr
- get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const;
-
- /// @brief Returns a host from specific subnet and reserved address.
- ///
- /// @param subnet_id subnet identfier.
- /// @param address specified address.
- ///
- /// @return Const @c host object that has a reservation for specified address.
- virtual ConstHostPtr
- get6(const SubnetID& subnet_id, const asiolink::IOAddress& address) const;
+ ///
+ /// This method may return multiple @c Host objects if they are connected
+ /// to different subnets.
+ ///
+ /// @param address IPv4 address for which the @c Host object is searched.
+ ///
+ /// @return Collection of const @c Host objects.
+ virtual ConstHostCollection
+ getAll4(const asiolink::IOAddress& address) const;
+
+ /// @brief Returns a host connected to the IPv4 subnet.
+ ///
+ /// Implementations of this method should guard against the case when
+ /// mutliple instances of the @c Host are present, e.g. when two
+ /// @c Host objects are found, one for the DUID, another one for the
+ /// HW address. In such case, an implementation of this method
+ /// should throw an MultipleRecords exception.
+ ///
+ /// @param subnet_id Subnet identifier.
+ /// @param hwaddr HW address of the client or NULL if no HW address
+ /// available.
+ /// @param duid client id or NULL if not available.
+ ///
+ /// @return Const @c Host object using a specified HW address or DUID.
+ virtual ConstHostPtr
+ get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
+ const DuidPtr& duid = DuidPtr()) const;
+
+ /// @brief Returns a host connected to the IPv4 subnet and having
+ /// a reservation for a specified IPv4 address.
+ ///
+ /// One of the use cases for this method is to detect collisions between
+ /// dynamically allocated addresses and reserved addresses. When the new
+ /// address is assigned to a client, the allocation mechanism should check
+ /// if this address is not reserved for some other host and do not allocate
+ /// this address if reservation is present.
+ ///
+ /// Implementations of this method should guard against invalid addresses,
+ /// such as IPv6 address.
+ ///
+ /// @param subnet_id Subnet identifier.
+ /// @param address reserved IPv4 address.
+ ///
+ /// @return Const @c Host object using a specified IPv4 address.
+ virtual ConstHostPtr
+ get4(const SubnetID& subnet_id, const asiolink::IOAddress& address) const;
+
+ /// @brief Returns a host connected to the IPv6 subnet.
+ ///
+ /// Implementations of this method should guard against the case when
+ /// mutliple instances of the @c Host are present, e.g. when two
+ /// @c Host objects are found, one for the DUID, another one for the
+ /// HW address. In such case, an implementation of this method
+ /// should throw an MultipleRecords exception.
+ ///
+ /// @param subnet_id Subnet identifier.
+ /// @param hwaddr HW address of the client or NULL if no HW address
+ /// available.
+ /// @param duid DUID or NULL if not available.
+ ///
+ /// @return Const @c Host object using a specified HW address or DUID.
+ virtual ConstHostPtr
+ get6(const SubnetID& subnet_id, const DuidPtr& duid,
+ const HWAddrPtr& hwaddr = HWAddrPtr()) const;
+
+ /// @brief Returns a host using the specified IPv6 prefix.
+ ///
+ /// @param prefix IPv6 prefix for which the @c Host object is searched.
+ /// @param prefix_len IPv6 prefix length.
+ ///
+ /// @return Const @c Host object using a specified HW address or DUID.
+ virtual ConstHostPtr
+ get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const;
+
+ /// @brief Returns a host from specific subnet and reserved address.
+ ///
+ /// @param subnet_id subnet identfier.
+ /// @param address specified address.
+ ///
+ /// @return Const @c host object that has a reservation for specified address.
+ virtual ConstHostPtr
+ get6(const SubnetID& subnet_id, const asiolink::IOAddress& address) const;
/// @brief Adds a new host to the collection.
///
/// The implementations of this method should guard against duplicate
/// reservations for the same host, where possible. For example, when the
/// reservation for the same HW address and subnet id is added twice, the
- /// implementation should throw an exception. Note, that usually it is
- /// impossible to guard against adding duplicated host, where one instance
- /// is identified by HW address, another one by DUID.
+ /// addHost method should throw an DuplicateEntry exception. Note, that
+ /// usually it is impossible to guard against adding duplicated host, where
+ /// one instance is identified by HW address, another one by DUID.
///
/// @param host Pointer to the new @c Host object being added.
virtual void add(const HostPtr& host);
/// @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("mysql"));
- }
-
- /// @brief Returns backend name.
- ///
- /// Each backend have specific name, e.g. "mysql" or "sqlite".
- ///
- /// @return Name of the backend.
- 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 If 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();
+ ///
+ /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
+ ///
+ /// @return Type of the backend.
+ virtual std::string getType() const {
+ return (std::string("mysql"));
+ }
+
+ /// @brief Returns backend name.
+ ///
+ /// Each backend have specific name, e.g. "mysql" or "sqlite".
+ ///
+ /// @return Name of the backend.
+ 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 stored in the database, 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;
+
+ MySqlConnection* getDatabaseConnection() {
+ return &conn_;
+ }
/// @brief Statement Tags
///
/// The contents of the enum are indexes into the list of SQL statements
- enum StatementIndex {
- INSERT_HOST, // Insert new host to collection
- GET_HOST_HWADDR_DUID, // Get hosts identified by DUID and/or HW address
- GET_HOST_ADDR, // Get hosts with specified IPv4 address
- GET_HOST_SUBID4_DHCPID, // Get host with specified IPv4 SubnetID and HW address and/or DUID
- GET_HOST_SUBID6_DHCPID, // Get host with specified IPv6 SubnetID and HW address and/or DUID
- GET_HOST_SUBID_ADDR, // Get host with specified IPv4 SubnetID and IPv4 address
- GET_HOST_PREFIX, // Get host with specified IPv6 prefix
- GET_VERSION, // Obtain version number
- NUM_STATEMENTS // Number of statements
- };
+ enum StatementIndex {
+ INSERT_HOST, // Insert new host to collection
+ GET_HOST_HWADDR_DUID, // Gets hosts by DUID and/or HW address
+ GET_HOST_ADDR, // Gets hosts by IPv4 address
+ GET_HOST_SUBID4_DHCPID, // Gets host by IPv4 SubnetID, HW address/DUID
+ GET_HOST_SUBID6_DHCPID, // Gets host by IPv6 SubnetID, HW address/DUID
+ GET_HOST_SUBID_ADDR, // Gets host by IPv4 SubnetID and IPv4 address
+ GET_HOST_PREFIX, // Gets host by IPv6 prefix
+ GET_VERSION, // Obtain version number
+ NUM_STATEMENTS // Number of statements
+ };
private:
- /// @brief Add Host Code
- ///
- /// This method performs adding a host operation.
- /// It binds the contents of the host 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 host
- ///
- /// @return true if the host was added, false if it was not.
- bool addHost(StatementIndex stindex, std::vector<MYSQL_BIND>& bind);
-
- /// @brief Get Host Collection Code
- ///
- /// This method obtains multiple hosts from the database.
- ///
- /// @param stindex Index of statement being executed
- /// @param bind MYSQL_BIND array for input parameters
- /// @param exchange Exchange object to use
- /// @param result ConstHostCollection object returned. Note that any hosts 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.
- void getHostCollection(StatementIndex stindex, MYSQL_BIND* bind,
- boost::shared_ptr<MySqlHostReservationExchange> exchange,
- ConstHostCollection& result, bool single = false) const;
-
- /// @brief Check Error and Throw Exception
- ///
- /// Virtually all MySQL functions return a status which, if non-zero,
- /// indicates an error. This inline function conceals a lot of error
- /// checking/exception-throwing code.
- ///
- /// @param status Status code: non-zero implies an error
- /// @param index Index of statement that caused the error
- /// @param what High-level description of the error
- ///
- /// @throw isc::dhcp::DbOperationError An operation on the open database has
- /// failed.
- inline void checkError(int status, StatementIndex index,
- const char* what) const {
- if (status != 0) {
- isc_throw(DbOperationError,
- what << " for <" << text_statements_[index] << ">, reason: "
- << mysql_error(mysql_) << " (error code " << mysql_errno(mysql_) << ")");
- }
- }
+ /// @brief Add Host Code
+ ///
+ /// This method performs adding a host operation.
+ /// It binds the contents of the host 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 host
+ ///
+ /// @htrow isc::dhcp::DuplicateEntry Database throws duplicate entry error
+ void addHost(StatementIndex stindex, std::vector<MYSQL_BIND>& bind);
+
+ /// @brief Get Host Collection Code
+ ///
+ /// This method obtains multiple hosts from the database.
+ ///
+ /// @param stindex Index of statement being executed
+ /// @param bind MYSQL_BIND array for input parameters
+ /// @param exchange Exchange object to use
+ /// @param result ConstHostCollection object returned. Note that any hosts
+ /// 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.
+ void getHostCollection(StatementIndex stindex, MYSQL_BIND* bind,
+ boost::shared_ptr<MySqlHostReservationExchange> exchange,
+ ConstHostCollection& result, bool single = false) const;
+ /// @brief Check Error and Throw Exception
+ ///
+ /// Virtually all MySQL functions return a status which, if non-zero,
+ /// indicates an error. This inline function conceals a lot of error
+ /// checking/exception-throwing code.
+ ///
+ /// @param status Status code: non-zero implies an error
+ /// @param index Index of statement that caused the error
+ /// @param what High-level description of the error
+ ///
+ /// @throw isc::dhcp::DbOperationError An operation on the open database
+ /// has failed.
+ inline void checkError(int status, StatementIndex index,
+ const char* what) const {
+ if (status != 0) {
+ isc_throw(DbOperationError, what << " for <"
+ << conn_.text_statements_[index] << ">, reason: "
+ << mysql_error(conn_.mysql_) << " (error code "
+ << mysql_errno(conn_.mysql_) << ")");
+ }
+ }
// Members
/// 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::shared_ptr<MySqlHostReservationExchange> hostExchange_; ///< Exchange object
+
+ /// @brief MySQL Host Reservation Exchange object
+ boost::shared_ptr<MySqlHostReservationExchange> hostExchange_;
+
+ /// @brief MySQL connection
+ MySqlConnection conn_;
};