26 #include <boost/algorithm/string/split.hpp>
27 #include <boost/algorithm/string/classification.hpp>
28 #include <boost/array.hpp>
29 #include <boost/pointer_cast.hpp>
30 #include <boost/static_assert.hpp>
33 #include <mysqld_error.h>
53 const uint8_t MAX_IDENTIFIER_TYPE =
static_cast<uint8_t
>(Host::LAST_IDENTIFIER_TYPE);
83 class MySqlHostExchange {
87 static const size_t HOST_COLUMNS = 14;
97 MySqlHostExchange(
const size_t additional_columns_num = 0)
98 : columns_num_(HOST_COLUMNS + additional_columns_num),
99 bind_(columns_num_), columns_(columns_num_),
100 error_(columns_num_,
MLM_FALSE), host_id_(0),
101 dhcp_identifier_length_(0), dhcp_identifier_type_(0),
102 dhcp4_subnet_id_(SUBNET_ID_UNUSED),
103 dhcp6_subnet_id_(SUBNET_ID_UNUSED), ipv4_address_(0),
104 hostname_length_(0), dhcp4_client_classes_length_(0),
105 dhcp6_client_classes_length_(0),
106 user_context_length_(0),
107 dhcp4_next_server_(0),
108 dhcp4_server_hostname_length_(0),
109 dhcp4_boot_file_name_length_(0),
123 memset(dhcp_identifier_buffer_, 0,
sizeof(dhcp_identifier_buffer_));
124 memset(hostname_, 0,
sizeof(hostname_));
125 memset(dhcp4_client_classes_, 0,
sizeof(dhcp4_client_classes_));
126 memset(dhcp6_client_classes_, 0,
sizeof(dhcp6_client_classes_));
127 memset(user_context_, 0,
sizeof(user_context_));
128 memset(dhcp4_server_hostname_, 0,
sizeof(dhcp4_server_hostname_));
129 memset(dhcp4_boot_file_name_, 0,
sizeof(dhcp4_boot_file_name_));
130 memset(auth_key_, 0,
sizeof(auth_key_));
135 columns_[0] =
"host_id";
136 columns_[1] =
"dhcp_identifier";
137 columns_[2] =
"dhcp_identifier_type";
138 columns_[3] =
"dhcp4_subnet_id";
139 columns_[4] =
"dhcp6_subnet_id";
140 columns_[5] =
"ipv4_address";
141 columns_[6] =
"hostname";
142 columns_[7] =
"dhcp4_client_classes";
143 columns_[8] =
"dhcp6_client_classes";
144 columns_[9] =
"user_context";
145 columns_[10] =
"dhcp4_next_server";
146 columns_[11] =
"dhcp4_server_hostname";
147 columns_[12] =
"dhcp4_boot_file_name";
148 columns_[13] =
"auth_key";
150 BOOST_STATIC_ASSERT(13 < HOST_COLUMNS);
154 virtual ~MySqlHostExchange() {
171 size_t findAvailColumn()
const {
172 std::vector<std::string>::const_iterator empty_column =
173 std::find(columns_.begin(), columns_.end(), std::string());
174 return (std::distance(columns_.begin(), empty_column));
180 uint64_t getHostId()
const {
194 static void setErrorIndicators(std::vector<MYSQL_BIND>& bind,
195 std::vector<my_bools>&
error) {
196 for (
size_t i = 0; i < error.size(); ++i) {
198 bind[i].error =
reinterpret_cast<my_bool*
>(&error[i]);
215 static std::string getColumnsInError(std::vector<my_bools>& error,
216 const std::vector<std::string>& names) {
217 std::string result =
"";
220 for (
size_t i = 0; i < names.size(); ++i) {
222 if (!result.empty()) {
229 if (result.empty()) {
248 std::vector<MYSQL_BIND> createBindForSend(
const HostPtr& host,
const bool unique_ip) {
256 memset(&bind_[0], 0,
sizeof(MYSQL_BIND) * bind_.size());
265 bind_[0].buffer_type = MYSQL_TYPE_LONG;
266 bind_[0].buffer =
reinterpret_cast<char*
>(&host_id_);
270 dhcp_identifier_length_ = host->getIdentifier().size();
271 memcpy(static_cast<void*>(dhcp_identifier_buffer_),
272 &(host->getIdentifier())[0],
273 host->getIdentifier().size());
275 bind_[1].buffer_type = MYSQL_TYPE_BLOB;
276 bind_[1].buffer = dhcp_identifier_buffer_;
277 bind_[1].buffer_length = dhcp_identifier_length_;
278 bind_[1].length = &dhcp_identifier_length_;
281 dhcp_identifier_type_ =
static_cast<uint8_t
>(host->getIdentifierType());
282 bind_[2].buffer_type = MYSQL_TYPE_TINY;
283 bind_[2].buffer =
reinterpret_cast<char*
>(&dhcp_identifier_type_);
289 dhcp4_subnet_id_ = host->getIPv4SubnetID();
290 dhcp4_subnet_id_null_ = host->getIPv4SubnetID() == SUBNET_ID_UNUSED ?
MLM_TRUE :
MLM_FALSE;
291 bind_[3].buffer_type = MYSQL_TYPE_LONG;
292 bind_[3].buffer =
reinterpret_cast<char*
>(&dhcp4_subnet_id_);
294 bind_[3].is_null = &dhcp4_subnet_id_null_;
299 dhcp6_subnet_id_ = host->getIPv6SubnetID();
300 dhcp6_subnet_id_null_ = host->getIPv6SubnetID() == SUBNET_ID_UNUSED ?
MLM_TRUE :
MLM_FALSE;
301 bind_[4].buffer_type = MYSQL_TYPE_LONG;
302 bind_[4].buffer =
reinterpret_cast<char*
>(&dhcp6_subnet_id_);
304 bind_[4].is_null = &dhcp6_subnet_id_null_;
309 ipv4_address_ = host->getIPv4Reservation().toUint32();
311 bind_[5].buffer_type = MYSQL_TYPE_LONG;
312 bind_[5].buffer =
reinterpret_cast<char*
>(&ipv4_address_);
314 bind_[5].is_null = &ipv4_address_null_;
317 strncpy(hostname_, host->getHostname().c_str(), HOSTNAME_MAX_LEN - 1);
318 hostname_length_ = host->getHostname().length();
319 bind_[6].buffer_type = MYSQL_TYPE_STRING;
320 bind_[6].buffer =
reinterpret_cast<char*
>(hostname_);
321 bind_[6].buffer_length = hostname_length_;
324 bind_[7].buffer_type = MYSQL_TYPE_STRING;
326 string classes4_txt = host->getClientClasses4().toText(
",");
328 bind_[7].buffer = dhcp4_client_classes_;
329 bind_[7].buffer_length = classes4_txt.length();
332 bind_[8].buffer_type = MYSQL_TYPE_STRING;
334 string classes6_txt = host->getClientClasses6().toText(
",");
336 bind_[8].buffer = dhcp6_client_classes_;
337 bind_[8].buffer_length = classes6_txt.length();
342 bind_[9].buffer_type = MYSQL_TYPE_STRING;
343 string ctx_txt = ctx->str();
345 bind_[9].buffer = user_context_;
346 bind_[9].buffer_length = ctx_txt.length();
348 bind_[9].buffer_type = MYSQL_TYPE_NULL;
354 dhcp4_next_server_ = host->getNextServer().toUint32();
355 bind_[10].buffer_type = MYSQL_TYPE_LONG;
356 bind_[10].buffer =
reinterpret_cast<char*
>(&dhcp4_next_server_);
362 bind_[11].buffer_type = MYSQL_TYPE_STRING;
363 std::string server_hostname = host->getServerHostname();
364 strncpy(dhcp4_server_hostname_, server_hostname.c_str(),
366 bind_[11].buffer = dhcp4_server_hostname_;
367 bind_[11].buffer_length = server_hostname.length();
370 bind_[12].buffer_type = MYSQL_TYPE_STRING;
371 std::string boot_file_name = host->getBootFileName();
372 strncpy(dhcp4_boot_file_name_, boot_file_name.c_str(),
374 bind_[12].buffer = dhcp4_boot_file_name_;
375 bind_[12].buffer_length = boot_file_name.length();
378 bind_[13].buffer_type = MYSQL_TYPE_STRING;
379 std::string auth_key = host->getKey().toText();
382 bind_[13].buffer = auth_key_;
383 bind_[13].buffer_length = auth_key.length();
385 }
catch (
const std::exception& ex) {
387 "Could not create bind array from Host: "
388 << host->getHostname() <<
", reason: " << ex.
what());
392 std::vector<MYSQL_BIND> vec(bind_.begin(), bind_.begin() + HOST_COLUMNS);
398 vec.push_back(bind_[5]);
399 vec.push_back(bind_[3]);
411 virtual std::vector<MYSQL_BIND> createBindForReceive() {
418 memset(&bind_[0], 0,
sizeof(MYSQL_BIND) * bind_.size());
421 bind_[0].buffer_type = MYSQL_TYPE_LONG;
422 bind_[0].buffer =
reinterpret_cast<char*
>(&host_id_);
426 dhcp_identifier_length_ =
sizeof(dhcp_identifier_buffer_);
427 bind_[1].buffer_type = MYSQL_TYPE_BLOB;
428 bind_[1].buffer =
reinterpret_cast<char*
>(dhcp_identifier_buffer_);
429 bind_[1].buffer_length = dhcp_identifier_length_;
430 bind_[1].length = &dhcp_identifier_length_;
433 bind_[2].buffer_type = MYSQL_TYPE_TINY;
434 bind_[2].buffer =
reinterpret_cast<char*
>(&dhcp_identifier_type_);
439 bind_[3].buffer_type = MYSQL_TYPE_LONG;
440 bind_[3].buffer =
reinterpret_cast<char*
>(&dhcp4_subnet_id_);
442 bind_[3].is_null = &dhcp4_subnet_id_null_;
446 bind_[4].buffer_type = MYSQL_TYPE_LONG;
447 bind_[4].buffer =
reinterpret_cast<char*
>(&dhcp6_subnet_id_);
449 bind_[4].is_null = &dhcp6_subnet_id_null_;
453 bind_[5].buffer_type = MYSQL_TYPE_LONG;
454 bind_[5].buffer =
reinterpret_cast<char*
>(&ipv4_address_);
456 bind_[5].is_null = &ipv4_address_null_;
460 hostname_length_ =
sizeof(hostname_);
461 bind_[6].buffer_type = MYSQL_TYPE_STRING;
462 bind_[6].buffer =
reinterpret_cast<char*
>(hostname_);
463 bind_[6].buffer_length = hostname_length_;
464 bind_[6].length = &hostname_length_;
465 bind_[6].is_null = &hostname_null_;
469 dhcp4_client_classes_length_ =
sizeof(dhcp4_client_classes_);
470 bind_[7].buffer_type = MYSQL_TYPE_STRING;
471 bind_[7].buffer =
reinterpret_cast<char*
>(dhcp4_client_classes_);
472 bind_[7].buffer_length = dhcp4_client_classes_length_;
473 bind_[7].length = &dhcp4_client_classes_length_;
474 bind_[7].is_null = &dhcp4_client_classes_null_;
478 dhcp6_client_classes_length_ =
sizeof(dhcp6_client_classes_);
479 bind_[8].buffer_type = MYSQL_TYPE_STRING;
480 bind_[8].buffer =
reinterpret_cast<char*
>(dhcp6_client_classes_);
481 bind_[8].buffer_length = dhcp6_client_classes_length_;
482 bind_[8].length = &dhcp6_client_classes_length_;
483 bind_[8].is_null = &dhcp6_client_classes_null_;
487 user_context_length_ =
sizeof(user_context_);
488 bind_[9].buffer_type = MYSQL_TYPE_STRING;
489 bind_[9].buffer =
reinterpret_cast<char*
>(user_context_);
490 bind_[9].buffer_length = user_context_length_;
491 bind_[9].length = &user_context_length_;
492 bind_[9].is_null = &user_context_null_;
496 bind_[10].buffer_type = MYSQL_TYPE_LONG;
497 bind_[10].buffer =
reinterpret_cast<char*
>(&dhcp4_next_server_);
499 bind_[10].is_null = &dhcp4_next_server_null_;
503 dhcp4_server_hostname_length_ =
sizeof(dhcp4_server_hostname_);
504 bind_[11].buffer_type = MYSQL_TYPE_STRING;
505 bind_[11].buffer =
reinterpret_cast<char*
>(dhcp4_server_hostname_);
506 bind_[11].buffer_length = dhcp4_server_hostname_length_;
507 bind_[11].length = &dhcp4_server_hostname_length_;
508 bind_[11].is_null = &dhcp4_server_hostname_null_;
512 dhcp4_boot_file_name_length_ =
sizeof(dhcp4_boot_file_name_);
513 bind_[12].buffer_type = MYSQL_TYPE_STRING;
514 bind_[12].buffer =
reinterpret_cast<char*
>(dhcp4_boot_file_name_);
515 bind_[12].buffer_length = dhcp4_boot_file_name_length_;
516 bind_[12].length = &dhcp4_boot_file_name_length_;
517 bind_[12].is_null = &dhcp4_boot_file_name_null_;
521 auth_key_length_ =
sizeof(auth_key_);
522 bind_[13].buffer_type = MYSQL_TYPE_STRING;
523 bind_[13].buffer =
reinterpret_cast<char*
>(auth_key_);
524 bind_[13].buffer_length = auth_key_length_;
525 bind_[13].length = &auth_key_length_;
526 bind_[13].is_null = &auth_key_null_;
529 setErrorIndicators(bind_, error_);
546 if (dhcp_identifier_type_ > MAX_IDENTIFIER_TYPE) {
548 << static_cast<int>(dhcp_identifier_type_));
557 SubnetID ipv4_subnet_id(SUBNET_ID_UNUSED);
558 if (dhcp4_subnet_id_null_ ==
MLM_FALSE) {
559 ipv4_subnet_id =
static_cast<SubnetID>(dhcp4_subnet_id_);
564 SubnetID ipv6_subnet_id(SUBNET_ID_UNUSED);
565 if (dhcp6_subnet_id_null_ ==
MLM_FALSE) {
566 ipv6_subnet_id =
static_cast<SubnetID>(dhcp6_subnet_id_);
573 ipv4_reservation = asiolink::IOAddress(ipv4_address_);
578 std::string hostname;
580 hostname = std::string(hostname_, hostname_length_);
584 std::string dhcp4_client_classes;
585 if (dhcp4_client_classes_null_ ==
MLM_FALSE) {
586 dhcp4_client_classes = std::string(dhcp4_client_classes_,
587 dhcp4_client_classes_length_);
591 std::string dhcp6_client_classes;
592 if (dhcp6_client_classes_null_ ==
MLM_FALSE) {
593 dhcp6_client_classes = std::string(dhcp6_client_classes_,
594 dhcp6_client_classes_length_);
598 std::string user_context;
600 user_context_[user_context_length_] =
'\0';
601 user_context.assign(user_context_);
606 if (dhcp4_next_server_null_ ==
MLM_FALSE) {
607 next_server = asiolink::IOAddress(dhcp4_next_server_);
611 std::string dhcp4_server_hostname;
612 if (dhcp4_server_hostname_null_ ==
MLM_FALSE) {
613 dhcp4_server_hostname = std::string(dhcp4_server_hostname_,
614 dhcp4_server_hostname_length_);
618 std::string dhcp4_boot_file_name;
619 if (dhcp4_boot_file_name_null_ ==
MLM_FALSE) {
620 dhcp4_boot_file_name = std::string(dhcp4_boot_file_name_,
621 dhcp4_boot_file_name_length_);
625 std::string auth_key;
627 auth_key = std::string(auth_key_, auth_key_length_);
631 HostPtr h(
new Host(dhcp_identifier_buffer_, dhcp_identifier_length_,
632 type, ipv4_subnet_id, ipv6_subnet_id, ipv4_reservation,
633 hostname, dhcp4_client_classes, dhcp6_client_classes,
634 next_server, dhcp4_server_hostname,
635 dhcp4_boot_file_name,
AuthKey(auth_key)));
636 h->setHostId(host_id_);
639 if (!user_context.empty()) {
642 if (!ctx || (ctx->getType() != Element::map)) {
644 <<
"' is not a JSON map");
649 <<
"' is invalid JSON: " << ex.
what());
674 if (hosts.empty() || (hosts.back()->getHostId() != getHostId())) {
677 host = retrieveHost();
678 hosts.push_back(host);
692 std::string getErrorColumns() {
693 return (getColumnsInError(error_, columns_));
702 std::vector<MYSQL_BIND> bind_;
705 std::vector<std::string> columns_;
708 std::vector<my_bools> error_;
721 uint8_t dhcp_identifier_buffer_[DUID::MAX_DUID_LEN];
724 unsigned long dhcp_identifier_length_;
728 uint8_t dhcp_identifier_type_;
731 uint32_t dhcp4_subnet_id_;
734 uint32_t dhcp6_subnet_id_;
737 uint32_t ipv4_address_;
740 char hostname_[HOSTNAME_MAX_LEN];
743 unsigned long hostname_length_;
750 unsigned long dhcp4_client_classes_length_;
757 unsigned long dhcp6_client_classes_length_;
763 unsigned long user_context_length_;
766 uint32_t dhcp4_next_server_;
772 unsigned long dhcp4_server_hostname_length_;
778 unsigned long dhcp4_boot_file_name_length_;
784 unsigned long auth_key_length_;
803 my_bool dhcp4_client_classes_null_;
807 my_bool dhcp6_client_classes_null_;
813 my_bool dhcp4_next_server_null_;
816 my_bool dhcp4_server_hostname_null_;
819 my_bool dhcp4_boot_file_name_null_;
836 class MySqlHostWithOptionsExchange :
public MySqlHostExchange {
840 static const size_t OPTION_COLUMNS = 7;
856 class OptionProcessor {
866 const size_t start_column)
867 : universe_(universe), start_column_(start_column), option_id_(0),
868 code_(0), value_length_(0), formatted_value_length_(0),
869 space_length_(0), persistent_(false), user_context_length_(0),
873 option_id_index_(start_column), code_index_(start_column_ + 1),
874 value_index_(start_column_ + 2),
875 formatted_value_index_(start_column_ + 3),
876 space_index_(start_column_ + 4),
877 persistent_index_(start_column_ + 5),
878 user_context_index_(start_column_ + 6),
879 most_recent_option_id_(0) {
881 memset(value_, 0,
sizeof(value_));
882 memset(formatted_value_, 0,
sizeof(formatted_value_));
883 memset(space_, 0,
sizeof(space_));
884 memset(user_context_, 0,
sizeof(user_context_));
888 uint64_t getOptionId()
const {
913 if ((option_id_null_ ==
MLM_TRUE) ||
914 (most_recent_option_id_ >= option_id_)) {
920 most_recent_option_id_ = option_id_;
927 space_[space_length_] =
'\0';
928 space.assign(space_);
933 space = (universe_ == Option::V4 ?
938 std::string formatted_value;
939 if (formatted_value_null_ ==
MLM_FALSE) {
940 formatted_value_[formatted_value_length_] =
'\0';
941 formatted_value.assign(formatted_value_);
945 std::string user_context;
947 user_context_[user_context_length_] =
'\0';
948 user_context.assign(user_context_);
964 uint32_t vendor_id = LibDHCP::optionSpaceToVendorId(space);
966 def = LibDHCP::getVendorOptionDef(universe_, vendor_id,
code_);
973 def = LibDHCP::getRuntimeOptionDef(space,
code_);
981 option.reset(
new Option(universe_,
code_, buf.begin(),
988 if (formatted_value.empty()) {
990 option = def->optionFactory(universe_,
code_, buf.begin(),
995 std::vector<std::string> split_vec;
996 boost::split(split_vec, formatted_value, boost::is_any_of(
","));
997 option = def->optionFactory(universe_,
code_, split_vec);
1004 if (!user_context.empty()) {
1007 if (!ctx || (ctx->getType() != Element::map)) {
1009 <<
"' is no a JSON map");
1011 desc.setContext(ctx);
1014 <<
"' is invalid JSON: " << ex.
what());
1018 cfg->add(desc, space);
1025 void setColumnNames(std::vector<std::string>& columns) {
1026 columns[option_id_index_] =
"option_id";
1027 columns[code_index_] =
"code";
1028 columns[value_index_] =
"value";
1029 columns[formatted_value_index_] =
"formatted_value";
1030 columns[space_index_] =
"space";
1031 columns[persistent_index_] =
"persistent";
1032 columns[user_context_index_] =
"user_context";
1041 void setBindFields(std::vector<MYSQL_BIND>& bind) {
1045 most_recent_option_id_ = 0;
1049 persistent_ =
false;
1057 memset(value_, 0,
sizeof(value_));
1058 memset(formatted_value_, 0,
sizeof(formatted_value_));
1059 memset(space_, 0,
sizeof(space_));
1060 memset(user_context_, 0,
sizeof(user_context_));
1063 bind[option_id_index_].buffer_type = MYSQL_TYPE_LONG;
1064 bind[option_id_index_].buffer =
reinterpret_cast<char*
>(&option_id_);
1065 bind[option_id_index_].is_unsigned =
MLM_TRUE;
1066 bind[option_id_index_].is_null = &option_id_null_;
1069 bind[code_index_].buffer_type = MYSQL_TYPE_SHORT;
1070 bind[code_index_].buffer =
reinterpret_cast<char*
>(&
code_);
1071 bind[code_index_].is_unsigned =
MLM_TRUE;
1072 bind[code_index_].is_null = &code_null_;
1075 value_length_ =
sizeof(value_);
1076 bind[value_index_].buffer_type = MYSQL_TYPE_BLOB;
1077 bind[value_index_].buffer =
reinterpret_cast<char*
>(value_);
1078 bind[value_index_].buffer_length = value_length_;
1079 bind[value_index_].length = &value_length_;
1080 bind[value_index_].is_null = &value_null_;
1083 formatted_value_length_ =
sizeof(formatted_value_);
1084 bind[formatted_value_index_].buffer_type = MYSQL_TYPE_STRING;
1085 bind[formatted_value_index_].buffer =
reinterpret_cast<char*
>(formatted_value_);
1086 bind[formatted_value_index_].buffer_length = formatted_value_length_;
1087 bind[formatted_value_index_].length = &formatted_value_length_;
1088 bind[formatted_value_index_].is_null = &formatted_value_null_;
1091 space_length_ =
sizeof(space_);
1092 bind[space_index_].buffer_type = MYSQL_TYPE_STRING;
1093 bind[space_index_].buffer =
reinterpret_cast<char*
>(space_);
1094 bind[space_index_].buffer_length = space_length_;
1095 bind[space_index_].length = &space_length_;
1096 bind[space_index_].is_null = &space_null_;
1099 bind[persistent_index_].buffer_type = MYSQL_TYPE_TINY;
1100 bind[persistent_index_].buffer =
reinterpret_cast<char*
>(&persistent_);
1101 bind[persistent_index_].is_unsigned =
MLM_TRUE;
1104 user_context_length_ =
sizeof(user_context_);
1105 bind[user_context_index_].buffer_type = MYSQL_TYPE_STRING;
1106 bind[user_context_index_].buffer =
reinterpret_cast<char*
>(user_context_);
1107 bind[user_context_index_].buffer_length = user_context_length_;
1108 bind[user_context_index_].length = &user_context_length_;
1109 bind[user_context_index_].is_null = &user_context_null_;
1118 size_t start_column_;
1121 uint32_t option_id_;
1130 unsigned long value_length_;
1136 unsigned long formatted_value_length_;
1142 unsigned long space_length_;
1152 unsigned long user_context_length_;
1168 my_bool formatted_value_null_;
1179 size_t option_id_index_;
1186 size_t value_index_;
1189 size_t formatted_value_index_;
1192 size_t space_index_;
1195 size_t persistent_index_;
1199 size_t user_context_index_;
1202 uint32_t most_recent_option_id_;
1206 typedef boost::shared_ptr<OptionProcessor> OptionProcessorPtr;
1216 enum FetchedOptions {
1230 MySqlHostWithOptionsExchange(
const FetchedOptions& fetched_options,
1231 const size_t additional_columns_num = 0)
1232 : MySqlHostExchange(getRequiredColumnsNum(fetched_options)
1233 + additional_columns_num),
1234 opt_proc4_(), opt_proc6_() {
1237 if ((fetched_options == DHCP4_ONLY) ||
1238 (fetched_options == DHCP4_AND_DHCP6)) {
1239 opt_proc4_.reset(
new OptionProcessor(Option::V4,
1240 findAvailColumn()));
1241 opt_proc4_->setColumnNames(columns_);
1245 if ((fetched_options == DHCP6_ONLY) ||
1246 (fetched_options == DHCP4_AND_DHCP6)) {
1247 opt_proc6_.reset(
new OptionProcessor(Option::V6,
1248 findAvailColumn()));
1249 opt_proc6_->setColumnNames(columns_);
1264 if (!hosts.empty()) {
1273 most_recent_host = boost::const_pointer_cast<
Host>(hosts.back());
1279 if (!most_recent_host || (most_recent_host->getHostId() < getHostId())) {
1280 HostPtr host = retrieveHost();
1281 hosts.push_back(host);
1282 most_recent_host = host;
1288 opt_proc4_->retrieveOption(cfg);
1294 opt_proc6_->retrieveOption(cfg);
1301 virtual std::vector<MYSQL_BIND> createBindForReceive() {
1303 static_cast<void>(MySqlHostExchange::createBindForReceive());
1307 opt_proc4_->setBindFields(bind_);
1312 opt_proc6_->setBindFields(bind_);
1316 setErrorIndicators(bind_, error_);
1334 static size_t getRequiredColumnsNum(
const FetchedOptions& fetched_options) {
1335 return (fetched_options == DHCP4_AND_DHCP6 ? 2 * OPTION_COLUMNS :
1342 OptionProcessorPtr opt_proc4_;
1347 OptionProcessorPtr opt_proc6_;
1362 class MySqlHostIPv6Exchange :
public MySqlHostWithOptionsExchange {
1366 static const size_t RESERVATION_COLUMNS = 5;
1374 MySqlHostIPv6Exchange(
const FetchedOptions& fetched_options)
1375 : MySqlHostWithOptionsExchange(fetched_options, RESERVATION_COLUMNS),
1377 reserv_type_(0), reserv_type_null_(
MLM_FALSE),
1378 ipv6_address_buffer_len_(0), prefix_len_(0), iaid_(0),
1379 reservation_id_index_(findAvailColumn()),
1380 address_index_(reservation_id_index_ + 1),
1381 prefix_len_index_(reservation_id_index_ + 2),
1382 type_index_(reservation_id_index_ + 3),
1383 iaid_index_(reservation_id_index_ + 4),
1384 most_recent_reservation_id_(0) {
1386 memset(ipv6_address_buffer_, 0,
sizeof(ipv6_address_buffer_));
1389 columns_[reservation_id_index_] =
"reservation_id";
1390 columns_[address_index_] =
"address";
1391 columns_[prefix_len_index_] =
"prefix_len";
1392 columns_[type_index_] =
"type";
1393 columns_[iaid_index_] =
"dhcp6_iaid";
1399 uint32_t getReservationId()
const {
1401 return (reservation_id_);
1416 switch (reserv_type_) {
1418 type = IPv6Resrv::TYPE_NA;
1422 type = IPv6Resrv::TYPE_PD;
1427 "invalid IPv6 reservation type returned: "
1428 << static_cast<int>(reserv_type_)
1429 <<
". Only 0 or 2 are allowed.");
1432 ipv6_address_buffer_[ipv6_address_buffer_len_] =
'\0';
1433 std::string address = ipv6_address_buffer_;
1460 MySqlHostWithOptionsExchange::processFetchedData(hosts);
1462 if (getReservationId() == 0) {
1466 if (hosts.empty()) {
1468 " IPv6 reservation");
1470 HostPtr host = boost::const_pointer_cast<
Host>(hosts.back());
1474 if (getReservationId() > most_recent_reservation_id_) {
1475 most_recent_reservation_id_ = getReservationId();
1477 if (most_recent_reservation_id_ > 0) {
1478 host->addReservation(retrieveReservation());
1491 virtual std::vector<MYSQL_BIND> createBindForReceive() {
1494 most_recent_reservation_id_ = 0;
1497 static_cast<void>(MySqlHostWithOptionsExchange::createBindForReceive());
1500 bind_[reservation_id_index_].buffer_type = MYSQL_TYPE_LONG;
1501 bind_[reservation_id_index_].buffer =
reinterpret_cast<char*
>(&reservation_id_);
1502 bind_[reservation_id_index_].is_unsigned =
MLM_TRUE;
1505 ipv6_address_buffer_len_ =
sizeof(ipv6_address_buffer_) - 1;
1506 bind_[address_index_].buffer_type = MYSQL_TYPE_STRING;
1507 bind_[address_index_].buffer = ipv6_address_buffer_;
1508 bind_[address_index_].buffer_length = ipv6_address_buffer_len_;
1509 bind_[address_index_].length = &ipv6_address_buffer_len_;
1512 bind_[prefix_len_index_].buffer_type = MYSQL_TYPE_TINY;
1513 bind_[prefix_len_index_].buffer =
reinterpret_cast<char*
>(&prefix_len_);
1514 bind_[prefix_len_index_].is_unsigned =
MLM_TRUE;
1518 bind_[type_index_].buffer_type = MYSQL_TYPE_TINY;
1519 bind_[type_index_].buffer =
reinterpret_cast<char*
>(&reserv_type_);
1520 bind_[type_index_].is_unsigned =
MLM_TRUE;
1521 bind_[type_index_].is_null = &reserv_type_null_;
1524 bind_[iaid_index_].buffer_type = MYSQL_TYPE_LONG;
1525 bind_[iaid_index_].buffer =
reinterpret_cast<char*
>(&iaid_);
1526 bind_[iaid_index_].is_unsigned =
MLM_TRUE;
1529 setErrorIndicators(bind_, error_);
1537 uint32_t reservation_id_;
1540 uint8_t reserv_type_;
1549 char ipv6_address_buffer_[ADDRESS6_TEXT_MAX_LEN + 1];
1552 unsigned long ipv6_address_buffer_len_;
1555 uint8_t prefix_len_;
1562 size_t reservation_id_index_;
1566 size_t address_index_;
1569 size_t prefix_len_index_;
1580 uint32_t most_recent_reservation_id_;
1593 class MySqlIPv6ReservationExchange {
1597 static const size_t RESRV_COLUMNS = 6;
1604 MySqlIPv6ReservationExchange()
1605 : host_id_(0), address_(
"::"), address_len_(0), prefix_len_(0), type_(0),
1609 std::fill(&error_[0], &error_[RESRV_COLUMNS],
MLM_FALSE);
1612 columns_[0] =
"host_id";
1613 columns_[1] =
"address";
1614 columns_[2] =
"prefix_len";
1615 columns_[3] =
"type";
1616 columns_[4] =
"dhcp6_iaid";
1617 BOOST_STATIC_ASSERT(4 < RESRV_COLUMNS);
1634 std::vector<MYSQL_BIND> createBindForSend(
const IPv6Resrv& resv,
1636 const bool unique_ip) {
1647 memset(bind_, 0,
sizeof(bind_));
1654 address_len_ = address_.length();
1655 bind_[0].buffer_type = MYSQL_TYPE_BLOB;
1656 bind_[0].buffer =
reinterpret_cast<char*
>
1657 (
const_cast<char*
>(address_.c_str()));
1658 bind_[0].buffer_length = address_len_;
1659 bind_[0].length = &address_len_;
1663 bind_[1].buffer_type = MYSQL_TYPE_TINY;
1664 bind_[1].buffer =
reinterpret_cast<char*
>(&prefix_len_);
1669 type_ = resv.
getType() == IPv6Resrv::TYPE_NA ? 0 : 2;
1670 bind_[2].buffer_type = MYSQL_TYPE_TINY;
1671 bind_[2].buffer =
reinterpret_cast<char*
>(&type_);
1677 bind_[3].buffer_type = MYSQL_TYPE_LONG;
1678 bind_[3].buffer =
reinterpret_cast<char*
>(&iaid_);
1682 bind_[4].buffer_type = MYSQL_TYPE_LONG;
1683 bind_[4].buffer =
reinterpret_cast<char*
>(&host_id_);
1686 }
catch (
const std::exception& ex) {
1688 "Could not create bind array from IPv6 Reservation: "
1689 << resv_.toText() <<
", reason: " << ex.
what());
1695 std::vector<MYSQL_BIND> vec(&bind_[0], &bind_[RESRV_COLUMNS-1]);
1701 vec.push_back(bind_[0]);
1702 vec.push_back(bind_[1]);
1714 std::string address_;
1717 unsigned long address_len_;
1720 uint8_t prefix_len_;
1732 MYSQL_BIND bind_[RESRV_COLUMNS];
1735 std::string columns_[RESRV_COLUMNS];
1739 my_bool error_[RESRV_COLUMNS];
1745 class MySqlOptionExchange {
1749 static const size_t OPTION_COLUMNS = 10;
1754 MySqlOptionExchange()
1755 : type_(0), value_len_(0), formatted_value_len_(0), space_(),
1756 space_len_(0), persistent_(false), user_context_(),
1757 user_context_len_(0), client_class_(), client_class_len_(0),
1758 subnet_id_(SUBNET_ID_UNUSED), host_id_(0), option_() {
1760 BOOST_STATIC_ASSERT(9 < OPTION_COLUMNS);
1766 std::vector<MYSQL_BIND> createBindForSend(
const OptionDescriptor& opt_desc,
1767 const std::string& opt_space,
1775 memset(bind_, 0,
sizeof(bind_));
1781 bind_[0].buffer_type = MYSQL_TYPE_NULL;
1784 type_ = option_->getType();
1785 bind_[1].buffer_type = MYSQL_TYPE_SHORT;
1786 bind_[1].buffer =
reinterpret_cast<char*
>(&type_);
1797 const char* buf_ptr =
static_cast<const char*
>(buf.getData());
1798 value_.assign(buf_ptr + opt_desc.
option_->getHeaderLen(),
1799 buf_ptr + buf.getLength());
1800 value_len_ = value_.size();
1801 bind_[2].buffer_type = MYSQL_TYPE_BLOB;
1802 bind_[2].buffer = &value_[0];
1803 bind_[2].buffer_length = value_len_;
1804 bind_[2].length = &value_len_;
1810 bind_[2].buffer_type = MYSQL_TYPE_NULL;
1816 bind_[3].buffer_type = MYSQL_TYPE_STRING;
1818 bind_[3].buffer_length = formatted_value_len_;
1819 bind_[3].length = &formatted_value_len_;
1822 bind_[3].buffer_type = MYSQL_TYPE_NULL;
1827 space_len_ = space_.size();
1828 bind_[4].buffer_type = MYSQL_TYPE_STRING;
1829 bind_[4].buffer =
const_cast<char*
>(space_.c_str());
1830 bind_[4].buffer_length = space_len_;
1831 bind_[4].length = &space_len_;
1835 bind_[5].buffer_type = MYSQL_TYPE_TINY;
1836 bind_[5].buffer =
reinterpret_cast<char*
>(&persistent_);
1842 user_context_ = ctx->str();
1843 user_context_len_ = user_context_.size();
1844 bind_[6].buffer_type = MYSQL_TYPE_STRING;
1845 bind_[6].buffer =
const_cast<char*
>(user_context_.c_str());
1846 bind_[6].buffer_length = user_context_len_;
1847 bind_[6].length = &user_context_len_;
1849 bind_[6].buffer_type = MYSQL_TYPE_NULL;
1853 client_class_len_ = client_class_.size();
1854 bind_[7].buffer_type = MYSQL_TYPE_STRING;
1855 bind_[7].buffer =
const_cast<char*
>(client_class_.c_str());
1856 bind_[7].buffer_length = client_class_len_;
1857 bind_[7].length = &client_class_len_;
1861 subnet_id_ = subnet_id;
1862 bind_[8].buffer_type = MYSQL_TYPE_LONG;
1863 bind_[8].buffer =
reinterpret_cast<char*
>(subnet_id_);
1867 bind_[8].buffer_type = MYSQL_TYPE_NULL;
1872 bind_[9].buffer_type = MYSQL_TYPE_LONG;
1873 bind_[9].buffer =
reinterpret_cast<char*
>(&host_id_);
1876 }
catch (
const std::exception& ex) {
1878 "Could not create bind array for inserting DHCP "
1879 "option: " << option_->toText() <<
", reason: "
1883 return (std::vector<MYSQL_BIND>(&bind_[0], &bind_[OPTION_COLUMNS]));
1892 std::vector<uint8_t> value_;
1895 unsigned long value_len_;
1898 unsigned long formatted_value_len_;
1904 unsigned long space_len_;
1911 std::string user_context_;
1914 unsigned long user_context_len_;
1917 std::string client_class_;
1920 unsigned long client_class_len_;
1923 uint32_t subnet_id_;
1932 MYSQL_BIND bind_[OPTION_COLUMNS];
2118 std::pair<uint32_t, uint32_t> getVersion()
const;
2130 std::vector<MYSQL_BIND>& bind);
2165 const std::string& opt_space,
2179 const uint64_t host_id);
2195 const char* what)
const;
2218 boost::shared_ptr<MySqlHostExchange> exchange,
2242 const uint8_t* identifier_begin,
2243 const size_t identifier_len,
2245 boost::shared_ptr<MySqlHostExchange> exchange)
const;
2279 typedef boost::array<TaggedStatement, MySqlHostDataSourceImpl::NUM_STATEMENTS>
2280 TaggedStatementArray;
2284 TaggedStatementArray tagged_statements = { {
2289 {MySqlHostDataSourceImpl::GET_HOST_DHCPID,
2290 "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
2291 "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, "
2292 "h.hostname, h.dhcp4_client_classes, h.dhcp6_client_classes, "
2294 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2295 "h.dhcp4_boot_file_name, h.auth_key, "
2296 "o4.option_id, o4.code, o4.value, o4.formatted_value, o4.space, "
2297 "o4.persistent, o4.user_context, "
2298 "o6.option_id, o6.code, o6.value, o6.formatted_value, o6.space, "
2299 "o6.persistent, o6.user_context, "
2300 "r.reservation_id, r.address, r.prefix_len, r.type, "
2303 "LEFT JOIN dhcp4_options AS o4 "
2304 "ON h.host_id = o4.host_id "
2305 "LEFT JOIN dhcp6_options AS o6 "
2306 "ON h.host_id = o6.host_id "
2307 "LEFT JOIN ipv6_reservations AS r "
2308 "ON h.host_id = r.host_id "
2309 "WHERE dhcp_identifier = ? AND dhcp_identifier_type = ? "
2310 "ORDER BY h.host_id, o4.option_id, o6.option_id, r.reservation_id"},
2315 {MySqlHostDataSourceImpl::GET_HOST_ADDR,
2316 "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
2317 "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2318 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2319 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2320 "h.dhcp4_boot_file_name, h.auth_key, "
2321 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2322 "o.persistent, o.user_context "
2324 "LEFT JOIN dhcp4_options AS o "
2325 "ON h.host_id = o.host_id "
2326 "WHERE ipv4_address = ? "
2327 "ORDER BY h.host_id, o.option_id"},
2332 {MySqlHostDataSourceImpl::GET_HOST_SUBID4_DHCPID,
2333 "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
2334 "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2335 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2336 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2337 "h.dhcp4_boot_file_name, h.auth_key, "
2338 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2339 "o.persistent, o.user_context "
2341 "LEFT JOIN dhcp4_options AS o "
2342 "ON h.host_id = o.host_id "
2343 "WHERE h.dhcp4_subnet_id = ? AND h.dhcp_identifier_type = ? "
2344 "AND h.dhcp_identifier = ? "
2345 "ORDER BY h.host_id, o.option_id"},
2350 {MySqlHostDataSourceImpl::GET_HOST_SUBID6_DHCPID,
2351 "SELECT h.host_id, h.dhcp_identifier, "
2352 "h.dhcp_identifier_type, h.dhcp4_subnet_id, "
2353 "h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2354 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2355 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2356 "h.dhcp4_boot_file_name, h.auth_key, "
2357 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2358 "o.persistent, o.user_context, "
2359 "r.reservation_id, r.address, r.prefix_len, r.type, "
2362 "LEFT JOIN dhcp6_options AS o "
2363 "ON h.host_id = o.host_id "
2364 "LEFT JOIN ipv6_reservations AS r "
2365 "ON h.host_id = r.host_id "
2366 "WHERE h.dhcp6_subnet_id = ? AND h.dhcp_identifier_type = ? "
2367 "AND h.dhcp_identifier = ? "
2368 "ORDER BY h.host_id, o.option_id, r.reservation_id"},
2374 {MySqlHostDataSourceImpl::GET_HOST_SUBID_ADDR,
2375 "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
2376 "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2377 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2378 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2379 "h.dhcp4_boot_file_name, h.auth_key, "
2380 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2381 "o.persistent, o.user_context "
2383 "LEFT JOIN dhcp4_options AS o "
2384 "ON h.host_id = o.host_id "
2385 "WHERE h.dhcp4_subnet_id = ? AND h.ipv4_address = ? "
2386 "ORDER BY h.host_id, o.option_id"},
2394 {MySqlHostDataSourceImpl::GET_HOST_PREFIX,
2395 "SELECT h.host_id, h.dhcp_identifier, "
2396 "h.dhcp_identifier_type, h.dhcp4_subnet_id, "
2397 "h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2398 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2399 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2400 "h.dhcp4_boot_file_name, h.auth_key, "
2401 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2402 "o.persistent, o.user_context,"
2403 "r.reservation_id, r.address, r.prefix_len, r.type, "
2406 "LEFT JOIN dhcp6_options AS o "
2407 "ON h.host_id = o.host_id "
2408 "LEFT JOIN ipv6_reservations AS r "
2409 "ON h.host_id = r.host_id "
2410 "WHERE h.host_id = "
2411 "( SELECT host_id FROM ipv6_reservations "
2412 "WHERE address = ? AND prefix_len = ? ) "
2413 "ORDER BY h.host_id, o.option_id, r.reservation_id"},
2421 {MySqlHostDataSourceImpl::GET_HOST_SUBID6_ADDR,
2422 "SELECT h.host_id, h.dhcp_identifier, "
2423 "h.dhcp_identifier_type, h.dhcp4_subnet_id, "
2424 "h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2425 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2426 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2427 "h.dhcp4_boot_file_name, h.auth_key, "
2428 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2429 "o.persistent, o.user_context, "
2430 "r.reservation_id, r.address, r.prefix_len, r.type, "
2433 "LEFT JOIN dhcp6_options AS o "
2434 "ON h.host_id = o.host_id "
2435 "LEFT JOIN ipv6_reservations AS r "
2436 "ON h.host_id = r.host_id "
2437 "WHERE h.dhcp6_subnet_id = ? AND r.address = ? "
2438 "ORDER BY h.host_id, o.option_id, r.reservation_id"},
2443 {MySqlHostDataSourceImpl::GET_HOST_SUBID4,
2444 "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
2445 "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2446 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2447 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2448 "h.dhcp4_boot_file_name, h.auth_key, "
2449 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2450 "o.persistent, o.user_context "
2452 "LEFT JOIN dhcp4_options AS o "
2453 "ON h.host_id = o.host_id "
2454 "WHERE h.dhcp4_subnet_id = ? "
2455 "ORDER BY h.host_id, o.option_id"},
2461 {MySqlHostDataSourceImpl::GET_HOST_SUBID6,
2462 "SELECT h.host_id, h.dhcp_identifier, "
2463 "h.dhcp_identifier_type, h.dhcp4_subnet_id, "
2464 "h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2465 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2466 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2467 "h.dhcp4_boot_file_name, h.auth_key, "
2468 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2469 "o.persistent, o.user_context, "
2470 "r.reservation_id, r.address, r.prefix_len, r.type, "
2473 "LEFT JOIN dhcp6_options AS o "
2474 "ON h.host_id = o.host_id "
2475 "LEFT JOIN ipv6_reservations AS r "
2476 "ON h.host_id = r.host_id "
2477 "WHERE h.dhcp6_subnet_id = ? "
2478 "ORDER BY h.host_id, o.option_id, r.reservation_id"},
2484 {MySqlHostDataSourceImpl::GET_HOST_HOSTNAME,
2485 "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
2486 "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, "
2487 "h.hostname, h.dhcp4_client_classes, h.dhcp6_client_classes, "
2489 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2490 "h.dhcp4_boot_file_name, h.auth_key, "
2491 "o4.option_id, o4.code, o4.value, o4.formatted_value, o4.space, "
2492 "o4.persistent, o4.user_context, "
2493 "o6.option_id, o6.code, o6.value, o6.formatted_value, o6.space, "
2494 "o6.persistent, o6.user_context, "
2495 "r.reservation_id, r.address, r.prefix_len, r.type, "
2498 "LEFT JOIN dhcp4_options AS o4 "
2499 "ON h.host_id = o4.host_id "
2500 "LEFT JOIN dhcp6_options AS o6 "
2501 "ON h.host_id = o6.host_id "
2502 "LEFT JOIN ipv6_reservations AS r "
2503 "ON h.host_id = r.host_id "
2504 "WHERE h.hostname = ? "
2505 "ORDER BY h.host_id, o4.option_id, o6.option_id, r.reservation_id"},
2510 {MySqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID4,
2511 "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
2512 "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2513 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2514 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2515 "h.dhcp4_boot_file_name, h.auth_key, "
2516 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2517 "o.persistent, o.user_context "
2519 "LEFT JOIN dhcp4_options AS o "
2520 "ON h.host_id = o.host_id "
2521 "WHERE h.hostname = ? AND h.dhcp4_subnet_id = ? "
2522 "ORDER BY h.host_id, o.option_id"},
2527 {MySqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID6,
2528 "SELECT h.host_id, h.dhcp_identifier, "
2529 "h.dhcp_identifier_type, h.dhcp4_subnet_id, "
2530 "h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2531 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2532 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2533 "h.dhcp4_boot_file_name, h.auth_key, "
2534 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2535 "o.persistent, o.user_context, "
2536 "r.reservation_id, r.address, r.prefix_len, r.type, "
2539 "LEFT JOIN dhcp6_options AS o "
2540 "ON h.host_id = o.host_id "
2541 "LEFT JOIN ipv6_reservations AS r "
2542 "ON h.host_id = r.host_id "
2543 "WHERE h.hostname = ? AND h.dhcp6_subnet_id = ? "
2544 "ORDER BY h.host_id, o.option_id, r.reservation_id"},
2551 {MySqlHostDataSourceImpl::GET_HOST_SUBID4_PAGE,
2552 "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
2553 "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2554 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2555 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2556 "h.dhcp4_boot_file_name, h.auth_key, "
2557 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2558 "o.persistent, o.user_context "
2559 "FROM ( SELECT * FROM hosts AS h "
2560 "WHERE h.dhcp4_subnet_id = ? AND h.host_id > ? "
2561 "ORDER BY h.host_id "
2563 "LEFT JOIN dhcp4_options AS o "
2564 "ON h.host_id = o.host_id "
2565 "ORDER BY h.host_id, o.option_id"},
2572 {MySqlHostDataSourceImpl::GET_HOST_SUBID6_PAGE,
2573 "SELECT h.host_id, h.dhcp_identifier, "
2574 "h.dhcp_identifier_type, h.dhcp4_subnet_id, "
2575 "h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2576 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2577 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2578 "h.dhcp4_boot_file_name, h.auth_key, "
2579 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2580 "o.persistent, o.user_context, "
2581 "r.reservation_id, r.address, r.prefix_len, r.type, "
2583 "FROM ( SELECT * FROM hosts AS h "
2584 "WHERE h.dhcp6_subnet_id = ? AND h.host_id > ? "
2585 "ORDER BY h.host_id "
2587 "LEFT JOIN dhcp6_options AS o "
2588 "ON h.host_id = o.host_id "
2589 "LEFT JOIN ipv6_reservations AS r "
2590 "ON h.host_id = r.host_id "
2591 "ORDER BY h.host_id, o.option_id, r.reservation_id"},
2598 {MySqlHostDataSourceImpl::GET_HOST_PAGE4,
2599 "SELECT h.host_id, h.dhcp_identifier, h.dhcp_identifier_type, "
2600 "h.dhcp4_subnet_id, h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2601 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2602 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2603 "h.dhcp4_boot_file_name, h.auth_key, "
2604 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2605 "o.persistent, o.user_context "
2606 "FROM ( SELECT * FROM hosts AS h "
2607 "WHERE h.host_id > ? "
2608 "ORDER BY h.host_id "
2610 "LEFT JOIN dhcp4_options AS o "
2611 "ON h.host_id = o.host_id "
2612 "ORDER BY h.host_id, o.option_id"},
2619 {MySqlHostDataSourceImpl::GET_HOST_PAGE6,
2620 "SELECT h.host_id, h.dhcp_identifier, "
2621 "h.dhcp_identifier_type, h.dhcp4_subnet_id, "
2622 "h.dhcp6_subnet_id, h.ipv4_address, h.hostname, "
2623 "h.dhcp4_client_classes, h.dhcp6_client_classes, h.user_context, "
2624 "h.dhcp4_next_server, h.dhcp4_server_hostname, "
2625 "h.dhcp4_boot_file_name, h.auth_key, "
2626 "o.option_id, o.code, o.value, o.formatted_value, o.space, "
2627 "o.persistent, o.user_context, "
2628 "r.reservation_id, r.address, r.prefix_len, r.type, "
2630 "FROM ( SELECT * FROM hosts AS h "
2631 "WHERE h.host_id > ? "
2632 "ORDER BY h.host_id "
2634 "LEFT JOIN dhcp6_options AS o "
2635 "ON h.host_id = o.host_id "
2636 "LEFT JOIN ipv6_reservations AS r "
2637 "ON h.host_id = r.host_id "
2638 "ORDER BY h.host_id, o.option_id, r.reservation_id"},
2642 {MySqlHostDataSourceImpl::INSERT_HOST_NON_UNIQUE_IP,
2643 "INSERT INTO hosts(host_id, dhcp_identifier, dhcp_identifier_type, "
2644 "dhcp4_subnet_id, dhcp6_subnet_id, ipv4_address, hostname, "
2645 "dhcp4_client_classes, dhcp6_client_classes, "
2646 "user_context, dhcp4_next_server, "
2647 "dhcp4_server_hostname, dhcp4_boot_file_name, auth_key) "
2648 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"},
2661 {MySqlHostDataSourceImpl::INSERT_HOST_UNIQUE_IP,
2662 "INSERT INTO hosts(host_id, dhcp_identifier, dhcp_identifier_type, "
2663 "dhcp4_subnet_id, dhcp6_subnet_id, ipv4_address, hostname, "
2664 "dhcp4_client_classes, dhcp6_client_classes, "
2665 "user_context, dhcp4_next_server, "
2666 "dhcp4_server_hostname, dhcp4_boot_file_name, auth_key) "
2667 "SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? FROM DUAL "
2668 "WHERE NOT EXISTS ("
2669 "SELECT 1 FROM hosts "
2670 "WHERE ipv4_address = ? AND dhcp4_subnet_id = ? "
2676 {MySqlHostDataSourceImpl::INSERT_V6_RESRV_NON_UNIQUE,
2677 "INSERT INTO ipv6_reservations(address, prefix_len, type, "
2678 "dhcp6_iaid, host_id) "
2679 "VALUES (?, ?, ?, ?, ?)"},
2683 {MySqlHostDataSourceImpl::INSERT_V6_RESRV_UNIQUE,
2684 "INSERT INTO ipv6_reservations(address, prefix_len, type, "
2685 "dhcp6_iaid, host_id) "
2686 "SELECT ?, ?, ?, ?, ? FROM DUAL "
2687 "WHERE NOT EXISTS ("
2688 "SELECT 1 FROM ipv6_reservations "
2689 "WHERE address = ? AND prefix_len = ? "
2695 {MySqlHostDataSourceImpl::INSERT_V4_HOST_OPTION,
2696 "INSERT INTO dhcp4_options(option_id, code, value, formatted_value, space, "
2697 "persistent, user_context, dhcp_client_class, dhcp4_subnet_id, host_id, scope_id) "
2698 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 3)"},
2702 {MySqlHostDataSourceImpl::INSERT_V6_HOST_OPTION,
2703 "INSERT INTO dhcp6_options(option_id, code, value, formatted_value, space, "
2704 "persistent, user_context, dhcp_client_class, dhcp6_subnet_id, host_id, scope_id) "
2705 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 3)"},
2708 {MySqlHostDataSourceImpl::DEL_HOST_ADDR4,
2709 "DELETE FROM hosts WHERE dhcp4_subnet_id = ? AND ipv4_address = ?"},
2712 {MySqlHostDataSourceImpl::DEL_HOST_ADDR6,
2713 "DELETE h FROM hosts AS h "
2714 "INNER JOIN ipv6_reservations AS r "
2715 "ON h.host_id = r.host_id "
2716 "WHERE h.dhcp6_subnet_id = ? AND r.address = ?"},
2719 {MySqlHostDataSourceImpl::DEL_HOST_SUBID4_ID,
2720 "DELETE FROM hosts WHERE dhcp4_subnet_id = ? AND dhcp_identifier_type=? "
2721 "AND dhcp_identifier = ?"},
2724 {MySqlHostDataSourceImpl::DEL_HOST_SUBID6_ID,
2725 "DELETE FROM hosts WHERE dhcp6_subnet_id = ? AND dhcp_identifier_type=? "
2726 "AND dhcp_identifier = ?"}
2737 : conn_(parameters, io_service_accessor, db_reconnect_callback),
2738 is_readonly_(true) {
2746 if (MultiThreadingMgr::instance().getMode()) {
2750 lock_guard<mutex> lock(mgr_.
pool_->mutex_);
2751 if (!mgr_.
pool_->pool_.empty()) {
2753 mgr_.
pool_->pool_.pop_back();
2761 if (mgr_.
pool_->pool_.empty()) {
2769 if (MultiThreadingMgr::instance().getMode()) {
2771 lock_guard<mutex> lock(mgr_.pool_->mutex_);
2772 mgr_.pool_->pool_.push_back(ctx_);
2773 if (ctx_->conn_.isUnusable()) {
2774 mgr_.unusable_ =
true;
2776 }
else if (ctx_->conn_.isUnusable()) {
2777 mgr_.unusable_ =
true;
2782 : parameters_(parameters), ip_reservations_unique_(true), unusable_(false),
2787 timer_name_ += boost::lexical_cast<std::string>(
reinterpret_cast<uint64_t
>(
this));
2793 std::pair<uint32_t, uint32_t> db_version =
getVersion();
2794 if (code_version != db_version) {
2796 "MySQL schema version mismatch: need version: "
2797 << code_version.first <<
"." << code_version.second
2798 <<
" found version: " << db_version.first <<
"."
2799 << db_version.second);
2816 ctx->conn_.openDatabase();
2821 ctx->conn_.prepareStatements(tagged_statements.begin(),
2826 ctx->is_readonly_ = ctx->conn_.configuredReadOnly();
2830 if (!ctx->is_readonly_) {
2833 tagged_statements.end());
2840 ctx->host_ipv4_exchange_.reset(
new MySqlHostWithOptionsExchange(MySqlHostWithOptionsExchange::DHCP4_ONLY));
2841 ctx->host_ipv6_exchange_.reset(
new MySqlHostIPv6Exchange(MySqlHostWithOptionsExchange::DHCP6_ONLY));
2842 ctx->host_ipv46_exchange_.reset(
new MySqlHostIPv6Exchange(MySqlHostWithOptionsExchange::DHCP4_AND_DHCP6));
2843 ctx->host_ipv6_reservation_exchange_.reset(
new MySqlIPv6ReservationExchange());
2844 ctx->host_option_exchange_.reset(
new MySqlOptionExchange());
2864 bool reopened =
false;
2866 const std::string timer_name = db_reconnect_ctl->timerName();
2871 std::list<std::string> host_db_access_list = cfg_db->getHostDbAccessStringList();
2872 for (std::string& hds : host_db_access_list) {
2879 }
catch (
const std::exception& ex) {
2895 if (!db_reconnect_ctl->checkRetries()) {
2898 .arg(db_reconnect_ctl->maxRetries());
2911 .arg(db_reconnect_ctl->maxRetries() - db_reconnect_ctl->retriesLeft() + 1)
2912 .arg(db_reconnect_ctl->maxRetries())
2913 .arg(db_reconnect_ctl->retryInterval());
2919 db_reconnect_ctl->retryInterval(),
2928 std::pair<uint32_t, uint32_t>
2939 std::vector<MYSQL_BIND>& bind) {
2941 int status = mysql_stmt_bind_param(ctx->conn_.statements_[stindex], &bind[0]);
2942 checkError(ctx, status, stindex,
"unable to bind parameters");
2949 if (mysql_errno(ctx->conn_.mysql_) == ER_DUP_ENTRY) {
2952 checkError(ctx, status, stindex,
"unable to execute");
2960 my_ulonglong numrows = mysql_stmt_affected_rows(ctx->conn_.statements_[stindex]);
2971 int status = mysql_stmt_bind_param(ctx->conn_.statements_[stindex], &bind[0]);
2972 checkError(ctx, status, stindex,
"unable to bind parameters");
2978 checkError(ctx, status, stindex,
"unable to execute");
2982 my_ulonglong numrows = mysql_stmt_affected_rows(ctx->conn_.statements_[stindex]);
2984 return (numrows != 0);
2991 std::vector<MYSQL_BIND> bind = ctx->host_ipv6_reservation_exchange_->
3001 const std::string& opt_space,
3004 std::vector<MYSQL_BIND> bind = ctx->host_option_exchange_->createBindForSend(opt_desc, opt_space, subnet_id,
id);
3013 const uint64_t host_id) {
3016 std::list<std::string> option_spaces = options_cfg->getOptionSpaceNames();
3017 std::list<std::string> vendor_spaces = options_cfg->getVendorIdsSpaceNames();
3018 option_spaces.insert(option_spaces.end(), vendor_spaces.begin(),
3019 vendor_spaces.end());
3023 for (
auto space = option_spaces.begin(); space != option_spaces.end(); ++space) {
3025 if (options && !options->empty()) {
3026 for (
auto opt = options->begin(); opt != options->end(); ++opt) {
3037 const char* what)
const {
3038 ctx->conn_.checkError(status, index, what);
3045 boost::shared_ptr<MySqlHostExchange> exchange,
3047 bool single)
const {
3050 int status = mysql_stmt_bind_param(ctx->conn_.statements_[stindex], bind);
3051 checkError(ctx, status, stindex,
"unable to bind WHERE clause parameter");
3055 std::vector<MYSQL_BIND> outbind = exchange->createBindForReceive();
3056 status = mysql_stmt_bind_result(ctx->conn_.statements_[stindex], &outbind[0]);
3057 checkError(ctx, status, stindex,
"unable to bind SELECT clause parameters");
3061 checkError(ctx, status, stindex,
"unable to execute");
3065 status = mysql_stmt_store_result(ctx->conn_.statements_[stindex]);
3066 checkError(ctx, status, stindex,
"unable to set up for storing all results");
3073 while ((status = mysql_stmt_fetch(ctx->conn_.statements_[stindex])) ==
3076 exchange->processFetchedData(result);
3081 ctx->conn_.text_statements_[stindex] <<
">");
3084 if (single && (result.size() > 1)) {
3086 "database where only one was expected for query "
3087 << ctx->conn_.text_statements_[stindex]);
3095 checkError(ctx, status, stindex,
"unable to fetch results");
3097 }
else if (status == MYSQL_DATA_TRUNCATED) {
3100 <<
" returned truncated data: columns affected are "
3101 << exchange->getErrorColumns());
3109 const uint8_t* identifier_begin,
3110 const size_t identifier_len,
3112 boost::shared_ptr<MySqlHostExchange> exchange)
const {
3115 MYSQL_BIND inbind[3];
3116 memset(inbind, 0,
sizeof(inbind));
3118 uint32_t subnet_buffer =
static_cast<uint32_t
>(subnet_id);
3119 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3120 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet_buffer);
3124 std::vector<char> identifier_vec(identifier_begin,
3125 identifier_begin + identifier_len);
3126 unsigned long length = identifier_vec.size();
3127 inbind[2].buffer_type = MYSQL_TYPE_BLOB;
3128 inbind[2].buffer = &identifier_vec[0];
3129 inbind[2].buffer_length = length;
3130 inbind[2].length = &length;
3133 char identifier_type_copy =
static_cast<char>(identifier_type);
3134 inbind[1].buffer_type = MYSQL_TYPE_TINY;
3135 inbind[1].buffer =
reinterpret_cast<char*
>(&identifier_type_copy);
3143 if (!collection.empty()) {
3144 result = *collection.begin();
3152 if (ctx->is_readonly_) {
3154 " operate in read only mode");
3167 return impl_->parameters_;
3177 impl_->checkReadOnly(ctx);
3189 bool unique_ip = impl_->ip_reservations_unique_ && !host->getIPv4Reservation().isV4Zero()
3190 && host->getIPv4SubnetID() != SUBNET_ID_UNUSED;
3193 std::vector<MYSQL_BIND> bind = ctx->host_ipv4_exchange_->createBindForSend(host, unique_ip);
3200 uint64_t host_id = mysql_insert_id(ctx->conn_.mysql_);
3206 cfg_option4, host_id);
3213 cfg_option6, host_id);
3218 if (std::distance(v6resv.first, v6resv.second) > 0) {
3221 impl_->addResv(ctx, resv->second, host_id);
3237 impl_->checkReadOnly(ctx);
3240 MYSQL_BIND inbind[2];
3242 uint32_t subnet = subnet_id;
3243 memset(inbind, 0,
sizeof(inbind));
3244 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3245 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet);
3251 inbind[1].buffer_type = MYSQL_TYPE_LONG;
3252 inbind[1].buffer =
reinterpret_cast<char*
>(&addr4);
3259 std::string addr_str = addr.
toText();
3260 unsigned long addr_len = addr_str.size();
3261 inbind[1].buffer_type = MYSQL_TYPE_BLOB;
3262 inbind[1].buffer =
reinterpret_cast<char*
>
3263 (
const_cast<char*
>(addr_str.c_str()));
3264 inbind[1].length = &addr_len;
3265 inbind[1].buffer_length = addr_len;
3273 const uint8_t* identifier_begin,
3274 const size_t identifier_len) {
3280 impl_->checkReadOnly(ctx);
3283 MYSQL_BIND inbind[3];
3286 memset(inbind, 0,
sizeof(inbind));
3287 uint32_t subnet =
static_cast<uint32_t
>(subnet_id);
3288 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3289 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet);
3293 char identifier_type_copy =
static_cast<char>(identifier_type);
3294 inbind[1].buffer_type = MYSQL_TYPE_TINY;
3295 inbind[1].buffer =
reinterpret_cast<char*
>(&identifier_type_copy);
3299 std::vector<char> identifier_vec(identifier_begin,
3300 identifier_begin + identifier_len);
3301 unsigned long length = identifier_vec.size();
3302 inbind[2].buffer_type = MYSQL_TYPE_BLOB;
3303 inbind[2].buffer = &identifier_vec[0];
3304 inbind[2].buffer_length = length;
3305 inbind[2].length = &length;
3314 const uint8_t* identifier_begin,
3315 const size_t identifier_len) {
3321 impl_->checkReadOnly(ctx);
3324 MYSQL_BIND inbind[3];
3327 memset(inbind, 0,
sizeof(inbind));
3328 uint32_t subnet =
static_cast<uint32_t
>(subnet_id);
3329 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3330 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet);
3334 char identifier_type_copy =
static_cast<char>(identifier_type);
3335 inbind[1].buffer_type = MYSQL_TYPE_TINY;
3336 inbind[1].buffer =
reinterpret_cast<char*
>(&identifier_type_copy);
3340 std::vector<char> identifier_vec(identifier_begin,
3341 identifier_begin + identifier_len);
3342 unsigned long length = identifier_vec.size();
3343 inbind[2].buffer_type = MYSQL_TYPE_BLOB;
3344 inbind[2].buffer = &identifier_vec[0];
3345 inbind[2].buffer_length = length;
3346 inbind[2].length = &length;
3354 const uint8_t* identifier_begin,
3355 const size_t identifier_len)
const {
3361 MYSQL_BIND inbind[2];
3362 memset(inbind, 0,
sizeof(inbind));
3365 char identifier_type_copy =
static_cast<char>(identifier_type);
3366 inbind[1].buffer = &identifier_type_copy;
3367 inbind[1].buffer_type = MYSQL_TYPE_TINY;
3371 std::vector<char> identifier_vec(identifier_begin,
3372 identifier_begin + identifier_len);
3373 unsigned long int length = identifier_vec.size();
3374 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
3375 inbind[0].buffer = &identifier_vec[0];
3376 inbind[0].buffer_length = length;
3377 inbind[0].length = &length;
3381 ctx->host_ipv46_exchange_, result,
false);
3393 MYSQL_BIND inbind[1];
3394 memset(inbind, 0,
sizeof(inbind));
3395 uint32_t subnet = subnet_id;
3396 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3397 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet);
3402 ctx->host_ipv4_exchange_, result,
false);
3414 MYSQL_BIND inbind[1];
3415 memset(inbind, 0,
sizeof(inbind));
3416 uint32_t subnet = subnet_id;
3417 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3418 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet);
3423 ctx->host_ipv6_exchange_, result,
false);
3435 MYSQL_BIND inbind[1];
3436 memset(inbind, 0,
sizeof(inbind));
3439 char hostname_[HOSTNAME_MAX_LEN];
3440 strncpy(hostname_, hostname.c_str(), HOSTNAME_MAX_LEN - 1);
3441 unsigned long length = hostname.length();
3442 inbind[0].buffer_type = MYSQL_TYPE_STRING;
3443 inbind[0].buffer =
reinterpret_cast<char*
>(hostname_);
3444 inbind[0].buffer_length = length;
3445 inbind[0].length = &length;
3449 ctx->host_ipv46_exchange_, result,
false);
3462 MYSQL_BIND inbind[2];
3463 memset(inbind, 0,
sizeof(inbind));
3466 char hostname_[HOSTNAME_MAX_LEN];
3467 strncpy(hostname_, hostname.c_str(), HOSTNAME_MAX_LEN - 1);
3468 unsigned long length = hostname.length();
3469 inbind[0].buffer_type = MYSQL_TYPE_STRING;
3470 inbind[0].buffer =
reinterpret_cast<char*
>(hostname_);
3471 inbind[0].buffer_length = length;
3472 inbind[0].length = &length;
3475 uint32_t subnet = subnet_id;
3476 inbind[1].buffer_type = MYSQL_TYPE_LONG;
3477 inbind[1].buffer =
reinterpret_cast<char*
>(&subnet);
3482 ctx->host_ipv4_exchange_, result,
false);
3495 MYSQL_BIND inbind[2];
3496 memset(inbind, 0,
sizeof(inbind));
3499 char hostname_[HOSTNAME_MAX_LEN];
3500 strncpy(hostname_, hostname.c_str(), HOSTNAME_MAX_LEN - 1);
3501 unsigned long length = hostname.length();
3502 inbind[0].buffer_type = MYSQL_TYPE_STRING;
3503 inbind[0].buffer =
reinterpret_cast<char*
>(hostname_);
3504 inbind[0].buffer_length = length;
3505 inbind[0].length = &length;
3508 uint32_t subnet = subnet_id;
3509 inbind[1].buffer_type = MYSQL_TYPE_LONG;
3510 inbind[1].buffer =
reinterpret_cast<char*
>(&subnet);
3515 ctx->host_ipv6_exchange_, result,
false);
3523 uint64_t lower_host_id,
3530 MYSQL_BIND inbind[3];
3531 memset(inbind, 0,
sizeof(inbind));
3534 uint32_t subnet = subnet_id;
3535 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3536 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet);
3540 uint32_t host_id = lower_host_id;
3541 inbind[1].buffer_type = MYSQL_TYPE_LONG;
3542 inbind[1].buffer =
reinterpret_cast<char*
>(&host_id);
3546 uint32_t page_size_data = page_size.
page_size_;
3547 inbind[2].buffer_type = MYSQL_TYPE_LONG;
3548 inbind[2].buffer =
reinterpret_cast<char*
>(&page_size_data);
3553 ctx->host_ipv4_exchange_, result,
false);
3561 uint64_t lower_host_id,
3568 MYSQL_BIND inbind[3];
3569 memset(inbind, 0,
sizeof(inbind));
3572 uint32_t subnet = subnet_id;
3573 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3574 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet);
3578 uint32_t host_id = lower_host_id;
3579 inbind[1].buffer_type = MYSQL_TYPE_LONG;
3580 inbind[1].buffer =
reinterpret_cast<char*
>(&host_id);
3584 uint32_t page_size_data = page_size.
page_size_;
3585 inbind[2].buffer_type = MYSQL_TYPE_LONG;
3586 inbind[2].buffer =
reinterpret_cast<char*
>(&page_size_data);
3591 ctx->host_ipv6_exchange_, result,
false);
3598 uint64_t lower_host_id,
3605 MYSQL_BIND inbind[2];
3606 memset(inbind, 0,
sizeof(inbind));
3609 uint32_t host_id = lower_host_id;
3610 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3611 inbind[0].buffer =
reinterpret_cast<char*
>(&host_id);
3615 uint32_t page_size_data = page_size.
page_size_;
3616 inbind[1].buffer_type = MYSQL_TYPE_LONG;
3617 inbind[1].buffer =
reinterpret_cast<char*
>(&page_size_data);
3622 ctx->host_ipv4_exchange_, result,
false);
3629 uint64_t lower_host_id,
3636 MYSQL_BIND inbind[2];
3637 memset(inbind, 0,
sizeof(inbind));
3640 uint32_t host_id = lower_host_id;
3641 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3642 inbind[0].buffer =
reinterpret_cast<char*
>(&host_id);
3646 uint32_t page_size_data = page_size.
page_size_;
3647 inbind[1].buffer_type = MYSQL_TYPE_LONG;
3648 inbind[1].buffer =
reinterpret_cast<char*
>(&page_size_data);
3653 ctx->host_ipv6_exchange_, result,
false);
3665 MYSQL_BIND inbind[1];
3666 memset(inbind, 0,
sizeof(inbind));
3668 uint32_t addr4 = address.
toUint32();
3669 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3670 inbind[0].buffer =
reinterpret_cast<char*
>(&addr4);
3675 ctx->host_ipv4_exchange_, result,
false);
3683 const uint8_t* identifier_begin,
3684 const size_t identifier_len)
const {
3689 return (impl_->getHost(ctx, subnet_id, identifier_type, identifier_begin, identifier_len,
3691 ctx->host_ipv4_exchange_));
3697 if (!address.
isV4()) {
3699 "wrong address type, address supplied is an IPv6 address");
3707 MYSQL_BIND inbind[2];
3708 uint32_t subnet = subnet_id;
3709 memset(inbind, 0,
sizeof(inbind));
3710 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3711 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet);
3714 uint32_t addr4 = address.
toUint32();
3715 inbind[1].buffer_type = MYSQL_TYPE_LONG;
3716 inbind[1].buffer =
reinterpret_cast<char*
>(&addr4);
3721 ctx->host_ipv4_exchange_, collection,
true);
3725 if (!collection.empty()) {
3726 result = *collection.begin();
3735 if (!address.
isV4()) {
3737 "wrong address type, address supplied is an IPv6 address");
3745 MYSQL_BIND inbind[2];
3746 uint32_t subnet = subnet_id;
3747 memset(inbind, 0,
sizeof(inbind));
3748 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3749 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet);
3752 uint32_t addr4 = address.
toUint32();
3753 inbind[1].buffer_type = MYSQL_TYPE_LONG;
3754 inbind[1].buffer =
reinterpret_cast<char*
>(&addr4);
3759 ctx->host_ipv4_exchange_, collection,
false);
3760 return (collection);
3766 const uint8_t* identifier_begin,
3767 const size_t identifier_len)
const {
3772 return (impl_->getHost(ctx, subnet_id, identifier_type, identifier_begin, identifier_len,
3774 ctx->host_ipv6_exchange_));
3779 const uint8_t prefix_len)
const {
3780 if (!prefix.
isV6()) {
3782 "wrong address type, address supplied is an IPv4 address");
3790 MYSQL_BIND inbind[2];
3791 memset(inbind, 0,
sizeof(inbind));
3793 std::string addr6 = prefix.
toText();
3794 unsigned long addr6_length = addr6.size();
3796 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
3797 inbind[0].buffer =
reinterpret_cast<char*
>
3798 (
const_cast<char*
>(addr6.c_str()));
3799 inbind[0].length = &addr6_length;
3800 inbind[0].buffer_length = addr6_length;
3802 uint8_t tmp = prefix_len;
3803 inbind[1].buffer_type = MYSQL_TYPE_TINY;
3804 inbind[1].buffer =
reinterpret_cast<char*
>(&tmp);
3809 ctx->host_ipv6_exchange_, collection,
true);
3813 if (!collection.empty()) {
3814 result = *collection.begin();
3823 if (!address.
isV6()) {
3825 "wrong address type, address supplied is an IPv4 address");
3833 MYSQL_BIND inbind[2];
3834 memset(inbind, 0,
sizeof(inbind));
3836 uint32_t subnet_buffer =
static_cast<uint32_t
>(subnet_id);
3837 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3838 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet_buffer);
3841 std::string addr6 = address.
toText();
3842 unsigned long addr6_length = addr6.size();
3844 inbind[1].buffer_type = MYSQL_TYPE_BLOB;
3845 inbind[1].buffer =
reinterpret_cast<char*
>
3846 (
const_cast<char*
>(addr6.c_str()));
3847 inbind[1].length = &addr6_length;
3848 inbind[1].buffer_length = addr6_length;
3852 ctx->host_ipv6_exchange_, collection,
true);
3856 if (!collection.empty()) {
3857 result = *collection.begin();
3866 if (!address.
isV6()) {
3868 "wrong address type, address supplied is an IPv4 address");
3876 MYSQL_BIND inbind[2];
3877 memset(inbind, 0,
sizeof(inbind));
3879 uint32_t subnet_buffer =
static_cast<uint32_t
>(subnet_id);
3880 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3881 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet_buffer);
3884 std::string addr6 = address.
toText();
3885 unsigned long addr6_length = addr6.size();
3887 inbind[1].buffer_type = MYSQL_TYPE_BLOB;
3888 inbind[1].buffer =
reinterpret_cast<char*
>
3889 (
const_cast<char*
>(addr6.c_str()));
3890 inbind[1].length = &addr6_length;
3891 inbind[1].buffer_length = addr6_length;
3895 ctx->host_ipv6_exchange_, collection,
false);
3896 return (collection);
3903 std::string name =
"";
3909 name = ctx->conn_.getParameter(
"name");
3918 return (std::string(
"Host data source that stores host information"
3919 "in MySQL database"));
3922 std::pair<uint32_t, uint32_t>
3924 return(impl_->getVersion());
3934 impl_->checkReadOnly(ctx);
3935 ctx->conn_.commit();
3945 impl_->checkReadOnly(ctx);
3946 ctx->conn_.rollback();
3951 impl_->ip_reservations_unique_ = unique;
3957 return (impl_->unusable_);
MySqlHostContextPtr createContext() const
Create a new context.
RAII class creating a critical section.
bool my_bool
my_bool type in MySQL 8.x.
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
uint32_t toUint32() const
Converts IPv4 address to uint32_t.
static bool dbReconnect(ReconnectCtlPtr db_reconnect_ctl)
Attempts to reconnect the server to the host DB backend manager.
const size_t OPTION_FORMATTED_VALUE_MAX_LEN
Maximum length of option value specified in textual format.
boost::shared_ptr< MySqlHostContextPool > MySqlHostContextPoolPtr
Type of pointers to context pools.
Wraps value holding size of the page with host reservations.
boost::shared_ptr< CfgOption > CfgOptionPtr
Non-const pointer.
Fetch and Release MySQL Results.
const size_t USER_CONTEXT_MAX_LEN
Maximum length of user context.
bool delStatement(MySqlHostContextPtr &ctx, StatementIndex stindex, MYSQL_BIND *bind)
Executes statements that delete records.
MySqlHostDataSourceImpl(const DatabaseConnection::ParameterMap ¶meters)
Constructor.
const size_t CLIENT_CLASSES_MAX_LEN
Maximum length of classes stored in a dhcp4/6_client_classes columns.
virtual void rollback()
Rollback Transactions.
std::vector< MySqlHostContextPtr > pool_
The vector of available contexts.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
virtual bool del4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len)
Attempts to delete a host by (subnet4-id, identifier type, identifier)
A standard Data module exception that is thrown if a parse error is encountered when constructing an ...
const size_t BOOT_FILE_NAME_MAX_LEN
Maximum length of the boot file name.
virtual bool setIPReservationsUnique(const bool unique)
Controls whether IP reservations are unique or non-unique.
boost::shared_ptr< Host > HostPtr
Pointer to the Host object.
static std::pair< uint32_t, uint32_t > getVersion(const ParameterMap ¶meters)
Get the schema version.
void commit()
Commits transaction.
const asiolink::IOAddress & getPrefix() const
Returns prefix for the reservation.
const isc::log::MessageID DHCPSRV_MYSQL_HOST_DB_GET_VERSION
boost::shared_ptr< const CfgOption > ConstCfgOptionPtr
Const pointer.
virtual ConstHostCollection getAllbyHostname(const std::string &hostname) const
Return all hosts with a hostname.
virtual ConstHostCollection getAll6(const SubnetID &subnet_id) const
Return all hosts in a DHCPv6 subnet.
static CfgMgr & instance()
returns a single instance of Configuration Manager
const size_t page_size_
Holds page size.
virtual bool del6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len)
Attempts to delete a host by (subnet6-id, identifier type, identifier)
static isc::asiolink::IOServicePtr & getIOService()
Returns pointer to the IO service.
boost::shared_ptr< Option > OptionPtr
const uint32_t MYSQL_SCHEMA_VERSION_MAJOR
Universe
defines option universe DHCPv4 or DHCPv6
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
virtual bool isUnusable()
Flag which indicates if the host manager has at least one unusable connection.
void addStatement(MySqlHostContextPtr &ctx, MySqlHostDataSourceImpl::StatementIndex stindex, std::vector< MYSQL_BIND > &bind)
Executes statements which inserts a row into one of the tables.
const isc::log::MessageID DHCPSRV_MYSQL_HOST_DB_RECONNECT_ATTEMPT_SCHEDULE
const uint32_t MYSQL_SCHEMA_VERSION_MINOR
std::string timer_name_
Timer name used to register database reconnect timer.
static ParameterMap parse(const std::string &dbaccess)
Parse database access string.
void addResv(MySqlHostContextPtr &ctx, const IPv6Resrv &resv, const HostID &id)
Inserts IPv6 Reservation into ipv6_reservation table.
bool unusable_
Indicates if there is at least one connection that can no longer be used for normal operations...
IPv6 reservation for a host.
const size_t OPTION_SPACE_MAX_LEN
Maximum length of option space name.
MySqlConnection conn_
MySQL connection.
bool isV4() const
Convenience function to check for an IPv4 address.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Exception thrown on failure to open database.
const size_t SERVER_HOSTNAME_MAX_LEN
Maximum length of the server hostname.
int MysqlExecuteStatement(MYSQL_STMT *stmt)
Execute a prepared statement.
Multiple lease records found where one expected.
DatabaseConnection::ParameterMap parameters_
The parameters.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
std::string formatted_value_
Option value in textual (CSV) format.
const my_bool MLM_FALSE
MySQL false value.
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
boost::shared_ptr< MySqlHostIPv6Exchange > host_ipv46_exchange_
Pointer to an object representing an exchange which can be used to retrieve hosts, DHCPv4 and DHCPv6 options, and IPv6 reservations using a single query.
std::pair< uint32_t, uint32_t > getVersion() const
Returns backend version.
static bool delBackend(const std::string &db_type)
Delete an alternate host backend (aka host data source).
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
boost::shared_ptr< CfgDbAccess > CfgDbAccessPtr
A pointer to the CfgDbAccess.
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
boost::shared_ptr< MySqlHostWithOptionsExchange > host_ipv4_exchange_
The exchange objects are used for transfer of data to/from the database.
~MySqlHostDataSourceImpl()
Destructor.
bool persistent_
Persistence flag.
A generic exception that is thrown when an unexpected error condition occurs.
const isc::log::MessageID DHCPSRV_MYSQL_HOST_DB_RECONNECT_ATTEMPT_FAILED
virtual void commit()
Commit Transactions.
virtual ~MySqlHostDataSource()
Virtual destructor.
static const IOAddress & IPV4_ZERO_ADDRESS()
Returns an address set to all zeros.
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
data::ConstElementPtr getContext() const
Returns const pointer to the user context.
void addOptions(MySqlHostContextPtr &ctx, const StatementIndex &stindex, const ConstCfgOptionPtr &options_cfg, const uint64_t host_id)
Inserts multiple options into the database.
Represents a device with IPv4 and/or IPv6 reservations.
virtual ConstHostCollection getAllbyHostname4(const std::string &hostname, const SubnetID &subnet_id) const
Return all hosts with a hostname in a DHCPv4 subnet.
Type
Type of the reservation.
IPv6ResrvCollection::const_iterator IPv6ResrvIterator
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
const isc::log::MessageID DHCPSRV_MYSQL_HOST_DB_READONLY
OptionPtr option_
Option instance.
const int MLM_MYSQL_FETCH_SUCCESS
check for bool size
virtual std::pair< uint32_t, uint32_t > getVersion() const
Returns backend version.
StatementIndex
Statement Tags.
static bool invokeDbFailedCallback(const ReconnectCtlPtr &db_reconnect_ctl)
Invokes the connection's restore failed connectivity callback.
Defines the logger used by the top-level component of kea-dhcp-ddns.
virtual ConstHostCollection getPage6(const SubnetID &subnet_id, size_t &source_index, uint64_t lower_host_id, const HostPageSize &page_size) const
Returns range of hosts in a DHCPv6 subnet.
std::function< bool(ReconnectCtlPtr db_reconnect_ctl)> DbCallback
Defines a callback prototype for propagating events upward.
MySqlHostContextPtr ctx_
The context.
boost::shared_ptr< MySqlOptionExchange > host_option_exchange_
Pointer to an object representing an exchange which can be used to insert DHCPv4 or DHCPv6 option int...
bool ip_reservations_unique_
Holds the setting whether the IP reservations must be unique or may be non-unique.
const isc::log::MessageID DHCPSRV_MYSQL_HOST_DB_RECONNECT_FAILED
MySqlHostContextPoolPtr pool_
The pool of contexts.
virtual ConstHostCollection getPage4(const SubnetID &subnet_id, size_t &source_index, uint64_t lower_host_id, const HostPageSize &page_size) const
Returns range of hosts in a DHCPv4 subnet.
static bool invokeDbRecoveredCallback(const ReconnectCtlPtr &db_reconnect_ctl)
Invokes the connection's restored connectivity callback.
virtual ConstHostCollection getAllbyHostname6(const std::string &hostname, const SubnetID &subnet_id) const
Return all hosts with a hostname in a DHCPv6 subnet.
virtual ConstHostPtr get6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Returns a host connected to the IPv6 subnet.
virtual ConstHostCollection getAll(const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Return all hosts connected to any subnet for which reservations have been made using a specified iden...
Implementation of the MySqlHostDataSource.
MySqlHostContextAlloc(MySqlHostDataSourceImpl &mgr)
Constructor.
void addOption(MySqlHostContextPtr &ctx, const MySqlHostDataSourceImpl::StatementIndex &stindex, const OptionDescriptor &opt_desc, const std::string &opt_space, const Optional< SubnetID > &subnet_id, const HostID &host_id)
Inserts a single DHCP option into the database.
const int MLM_MYSQL_FETCH_FAILURE
MySQL fetch failure code.
A wrapper interface for the ASIO library.
Type getType() const
Returns reservation type.
static bool invokeDbLostCallback(const ReconnectCtlPtr &db_reconnect_ctl)
Invokes the connection's lost connectivity callback.
#define DHCP6_OPTION_SPACE
void checkReadOnly(MySqlHostContextPtr &ctx) const
Throws exception if database is read only.
RAII object representing MySQL transaction.
#define DHCP4_OPTION_SPACE
global std option spaces
static void addBackend(const std::string &access)
Add an alternate host backend (aka host data source).
boost::shared_ptr< OptionContainer > OptionContainerPtr
Pointer to the OptionContainer object.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
std::string toText() const
Convert the address to a string.
bool is_readonly_
Indicates if the database is opened in read only mode.
boost::shared_ptr< MySqlHostContext > MySqlHostContextPtr
Type of pointers to contexts.
~MySqlHostContextAlloc()
Destructor.
Attempt to modify data in read-only database.
boost::shared_ptr< MySqlHostIPv6Exchange > host_ipv6_exchange_
Pointer to an object representing an exchange which can be used to retrieve hosts, DHCPv6 options and IPv6 reservations.
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
boost::shared_ptr< MySqlIPv6ReservationExchange > host_ipv6_reservation_exchange_
Pointer to an object representing an exchange which can be used to insert new IPv6 reservation...
bool isV6() const
Convenience function to check for an IPv6 address.
void checkError(MySqlHostContextPtr &ctx, const int status, const StatementIndex index, const char *what) const
Check Error and Throw Exception.
void getHostCollection(MySqlHostContextPtr &ctx, StatementIndex stindex, MYSQL_BIND *bind, boost::shared_ptr< MySqlHostExchange > exchange, ConstHostCollection &result, bool single) const
Creates collection of Host objects with associated information such as IPv6 reservations and/or DHCP ...
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
IdentifierType
Type of the host identifier.
std::function< isc::asiolink::IOServicePtr()> IOServiceAccessor
Function which returns the IOService that can be used to recover the connection.
const size_t TEXT_AUTH_KEY_LEN
Maximum length of authentication keys (coded in hexadecimal).
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
uint8_t getPrefixLen() const
Returns prefix length.
virtual std::string getDescription() const
Returns description of the backend.
static const TimerMgrPtr & instance()
Returns pointer to the sole instance of the TimerMgr.
The IOAddress class represents an IP addresses (version agnostic)
virtual std::string getName() const
Returns backend name.
ConstHostPtr getHost(MySqlHostContextPtr &ctx, const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, StatementIndex stindex, boost::shared_ptr< MySqlHostExchange > exchange) const
Retrieves a host by subnet and client's unique identifier.
boost::shared_ptr< ReconnectCtl > ReconnectCtlPtr
Pointer to an instance of ReconnectCtl.
static const StatementIndex WRITE_STMTS_BEGIN
Index of first statement performing write to the database.
const size_t OPTION_VALUE_MAX_LEN
Maximum length of option value.
uint64_t HostID
HostID (used only when storing in MySQL, PostgreSQL or Cassandra)
virtual ConstHostCollection getAll4(const SubnetID &subnet_id) const
Return all hosts in a DHCPv4 subnet.
A template representing an optional value.
std::mutex mutex_
The mutex to protect pool access.
virtual bool del(const SubnetID &subnet_id, const asiolink::IOAddress &addr)
Attempts to delete hosts by (subnet-id, address)
Exception thrown on failure to execute a database function.
const my_bool MLM_TRUE
MySQL true value.
MySqlHostDataSource(const db::DatabaseConnection::ParameterMap ¶meters)
Constructor.
virtual isc::db::DatabaseConnection::ParameterMap getParameters() const
Return backend parameters.
boost::shared_ptr< IOServiceAccessor > IOServiceAccessorPtr
Pointer to an instance of IOServiceAccessor.
Database duplicate entry error.
virtual void add(const HostPtr &host)
Adds a new host to the collection.
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Common MySQL Connector Pool.
virtual ConstHostPtr get4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Returns a host connected to the IPv4 subnet.