16 #include <boost/array.hpp>
17 #include <boost/static_assert.hpp>
18 #include <mysqld_error.h>
82 const size_t HOSTNAME_MAX_LEN = 255;
88 const size_t ADDRESS6_TEXT_MAX_LEN = 39;
91 const size_t USER_CONTEXT_MAX_LEN = 8192;
93 boost::array<TaggedStatement, MySqlLeaseMgr::NUM_STATEMENTS>
95 {MySqlLeaseMgr::DELETE_LEASE4,
96 "DELETE FROM lease4 WHERE address = ?"},
97 {MySqlLeaseMgr::DELETE_LEASE4_STATE_EXPIRED,
99 "WHERE state = ? AND expire < ?"},
100 {MySqlLeaseMgr::DELETE_LEASE6,
101 "DELETE FROM lease6 WHERE address = ?"},
102 {MySqlLeaseMgr::DELETE_LEASE6_STATE_EXPIRED,
103 "DELETE FROM lease6 "
104 "WHERE state = ? AND expire < ?"},
105 {MySqlLeaseMgr::GET_LEASE4,
106 "SELECT address, hwaddr, client_id, "
107 "valid_lifetime, expire, subnet_id, "
108 "fqdn_fwd, fqdn_rev, hostname, "
109 "state, user_context "
111 {MySqlLeaseMgr::GET_LEASE4_ADDR,
112 "SELECT address, hwaddr, client_id, "
113 "valid_lifetime, expire, subnet_id, "
114 "fqdn_fwd, fqdn_rev, hostname, "
115 "state, user_context "
117 "WHERE address = ?"},
118 {MySqlLeaseMgr::GET_LEASE4_CLIENTID,
119 "SELECT address, hwaddr, client_id, "
120 "valid_lifetime, expire, subnet_id, "
121 "fqdn_fwd, fqdn_rev, hostname, "
122 "state, user_context "
124 "WHERE client_id = ?"},
125 {MySqlLeaseMgr::GET_LEASE4_CLIENTID_SUBID,
126 "SELECT address, hwaddr, client_id, "
127 "valid_lifetime, expire, subnet_id, "
128 "fqdn_fwd, fqdn_rev, hostname, "
129 "state, user_context "
131 "WHERE client_id = ? AND subnet_id = ?"},
132 {MySqlLeaseMgr::GET_LEASE4_HWADDR,
133 "SELECT address, hwaddr, client_id, "
134 "valid_lifetime, expire, subnet_id, "
135 "fqdn_fwd, fqdn_rev, hostname, "
136 "state, user_context "
139 {MySqlLeaseMgr::GET_LEASE4_HWADDR_SUBID,
140 "SELECT address, hwaddr, client_id, "
141 "valid_lifetime, expire, subnet_id, "
142 "fqdn_fwd, fqdn_rev, hostname, "
143 "state, user_context "
145 "WHERE hwaddr = ? AND subnet_id = ?"},
146 {MySqlLeaseMgr::GET_LEASE4_PAGE,
147 "SELECT address, hwaddr, client_id, "
148 "valid_lifetime, expire, subnet_id, "
149 "fqdn_fwd, fqdn_rev, hostname, "
150 "state, user_context "
155 {MySqlLeaseMgr::GET_LEASE4_SUBID,
156 "SELECT address, hwaddr, client_id, "
157 "valid_lifetime, expire, subnet_id, "
158 "fqdn_fwd, fqdn_rev, hostname, "
159 "state, user_context "
161 "WHERE subnet_id = ?"},
162 {MySqlLeaseMgr::GET_LEASE4_EXPIRE,
163 "SELECT address, hwaddr, client_id, "
164 "valid_lifetime, expire, subnet_id, "
165 "fqdn_fwd, fqdn_rev, hostname, "
166 "state, user_context "
168 "WHERE state != ? AND expire < ? "
169 "ORDER BY expire ASC "
171 {MySqlLeaseMgr::GET_LEASE6,
172 "SELECT address, duid, valid_lifetime, "
173 "expire, subnet_id, pref_lifetime, "
174 "lease_type, iaid, prefix_len, "
175 "fqdn_fwd, fqdn_rev, hostname, "
176 "hwaddr, hwtype, hwaddr_source, "
177 "state, user_context "
179 {MySqlLeaseMgr::GET_LEASE6_ADDR,
180 "SELECT address, duid, valid_lifetime, "
181 "expire, subnet_id, pref_lifetime, "
182 "lease_type, iaid, prefix_len, "
183 "fqdn_fwd, fqdn_rev, hostname, "
184 "hwaddr, hwtype, hwaddr_source, "
185 "state, user_context "
187 "WHERE address = ? AND lease_type = ?"},
188 {MySqlLeaseMgr::GET_LEASE6_DUID_IAID,
189 "SELECT address, duid, valid_lifetime, "
190 "expire, subnet_id, pref_lifetime, "
191 "lease_type, iaid, prefix_len, "
192 "fqdn_fwd, fqdn_rev, hostname, "
193 "hwaddr, hwtype, hwaddr_source, "
194 "state, user_context "
196 "WHERE duid = ? AND iaid = ? AND lease_type = ?"},
197 {MySqlLeaseMgr::GET_LEASE6_DUID_IAID_SUBID,
198 "SELECT address, duid, valid_lifetime, "
199 "expire, subnet_id, pref_lifetime, "
200 "lease_type, iaid, prefix_len, "
201 "fqdn_fwd, fqdn_rev, hostname, "
202 "hwaddr, hwtype, hwaddr_source, "
203 "state, user_context "
205 "WHERE duid = ? AND iaid = ? AND subnet_id = ? "
206 "AND lease_type = ?"},
207 {MySqlLeaseMgr::GET_LEASE6_PAGE,
208 "SELECT address, duid, valid_lifetime, "
209 "expire, subnet_id, pref_lifetime, "
210 "lease_type, iaid, prefix_len, "
211 "fqdn_fwd, fqdn_rev, hostname, "
212 "hwaddr, hwtype, hwaddr_source, "
213 "state, user_context "
218 {MySqlLeaseMgr::GET_LEASE6_SUBID,
219 "SELECT address, duid, valid_lifetime, "
220 "expire, subnet_id, pref_lifetime, "
221 "lease_type, iaid, prefix_len, "
222 "fqdn_fwd, fqdn_rev, hostname, "
223 "hwaddr, hwtype, hwaddr_source, "
224 "state, user_context "
226 "WHERE subnet_id = ?"},
227 {MySqlLeaseMgr::GET_LEASE6_DUID,
228 "SELECT address, duid, valid_lifetime, "
229 "expire, subnet_id, pref_lifetime, "
230 "lease_type, iaid, prefix_len, "
231 "fqdn_fwd, fqdn_rev, hostname, "
232 "hwaddr, hwtype, hwaddr_source, "
233 "state, user_context "
236 {MySqlLeaseMgr::GET_LEASE6_EXPIRE,
237 "SELECT address, duid, valid_lifetime, "
238 "expire, subnet_id, pref_lifetime, "
239 "lease_type, iaid, prefix_len, "
240 "fqdn_fwd, fqdn_rev, hostname, "
241 "hwaddr, hwtype, hwaddr_source, "
242 "state, user_context "
244 "WHERE state != ? AND expire < ? "
245 "ORDER BY expire ASC "
247 {MySqlLeaseMgr::INSERT_LEASE4,
248 "INSERT INTO lease4(address, hwaddr, client_id, "
249 "valid_lifetime, expire, subnet_id, "
250 "fqdn_fwd, fqdn_rev, hostname, "
251 "state, user_context) "
252 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"},
253 {MySqlLeaseMgr::INSERT_LEASE6,
254 "INSERT INTO lease6(address, duid, valid_lifetime, "
255 "expire, subnet_id, pref_lifetime, "
256 "lease_type, iaid, prefix_len, "
257 "fqdn_fwd, fqdn_rev, hostname, "
258 "hwaddr, hwtype, hwaddr_source, "
259 "state, user_context) "
260 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"},
261 {MySqlLeaseMgr::UPDATE_LEASE4,
262 "UPDATE lease4 SET address = ?, hwaddr = ?, "
263 "client_id = ?, valid_lifetime = ?, expire = ?, "
264 "subnet_id = ?, fqdn_fwd = ?, fqdn_rev = ?, "
266 "state = ?, user_context = ? "
267 "WHERE address = ?"},
268 {MySqlLeaseMgr::UPDATE_LEASE6,
269 "UPDATE lease6 SET address = ?, duid = ?, "
270 "valid_lifetime = ?, expire = ?, subnet_id = ?, "
271 "pref_lifetime = ?, lease_type = ?, iaid = ?, "
272 "prefix_len = ?, fqdn_fwd = ?, fqdn_rev = ?, "
273 "hostname = ?, hwaddr = ?, hwtype = ?, hwaddr_source = ?, "
274 "state = ?, user_context = ? "
275 "WHERE address = ?"},
276 {MySqlLeaseMgr::ALL_LEASE4_STATS,
277 "SELECT subnet_id, state, leases as state_count"
278 " FROM lease4_stat ORDER BY subnet_id, state"},
280 {MySqlLeaseMgr::SUBNET_LEASE4_STATS,
281 "SELECT subnet_id, state, leases as state_count"
283 " WHERE subnet_id = ? "
286 {MySqlLeaseMgr::SUBNET_RANGE_LEASE4_STATS,
287 "SELECT subnet_id, state, leases as state_count"
289 " WHERE subnet_id >= ? and subnet_id <= ? "
290 " ORDER BY subnet_id, state"},
292 {MySqlLeaseMgr::ALL_LEASE6_STATS,
293 "SELECT subnet_id, lease_type, state, leases as state_count"
294 " FROM lease6_stat ORDER BY subnet_id, lease_type, state" },
296 {MySqlLeaseMgr::SUBNET_LEASE6_STATS,
297 "SELECT subnet_id, lease_type, state, leases as state_count"
299 " WHERE subnet_id = ? "
300 " ORDER BY lease_type, state" },
302 {MySqlLeaseMgr::SUBNET_RANGE_LEASE6_STATS,
303 "SELECT subnet_id, lease_type, state, leases as state_count"
305 " WHERE subnet_id >= ? and subnet_id <= ? "
306 " ORDER BY subnet_id, lease_type, state" }
337 for (
size_t i = 0; i < count; ++i) {
339 bind[i].error =
reinterpret_cast<char*
>(&error[i]);
358 std::string result =
"";
361 for (
size_t i = 0; i < count; ++i) {
363 if (!result.empty()) {
370 if (result.empty()) {
393 static const size_t LEASE_COLUMNS = 11;
401 client_id_length_(0), client_id_null_(
MLM_FALSE),
402 subnet_id_(0), valid_lifetime_(0),
403 fqdn_fwd_(false), fqdn_rev_(false), hostname_length_(0),
404 state_(0), user_context_length_(0),
406 memset(hwaddr_buffer_, 0,
sizeof(hwaddr_buffer_));
407 memset(client_id_buffer_, 0,
sizeof(client_id_buffer_));
408 memset(hostname_buffer_, 0,
sizeof(hostname_buffer_));
409 memset(user_context_, 0,
sizeof(user_context_));
410 std::fill(&error_[0], &error_[LEASE_COLUMNS],
MLM_FALSE);
413 columns_[0] =
"address";
414 columns_[1] =
"hwaddr";
415 columns_[2] =
"client_id";
416 columns_[3] =
"valid_lifetime";
417 columns_[4] =
"expire";
418 columns_[5] =
"subnet_id";
419 columns_[6] =
"fqdn_fwd";
420 columns_[7] =
"fqdn_rev";
421 columns_[8] =
"hostname";
422 columns_[9] =
"state";
423 columns_[10] =
"user_context";
424 BOOST_STATIC_ASSERT(10 < LEASE_COLUMNS);
446 memset(bind_, 0,
sizeof(bind_));
455 addr4_ = lease_->addr_.toUint32();
456 bind_[0].buffer_type = MYSQL_TYPE_LONG;
457 bind_[0].buffer =
reinterpret_cast<char*
>(&addr4_);
465 hwaddr_ = hwaddr->hwaddr_;
466 hwaddr_length_ = hwaddr->hwaddr_.size();
473 if (hwaddr_.empty()) {
477 bind_[1].buffer_type = MYSQL_TYPE_BLOB;
478 bind_[1].buffer =
reinterpret_cast<char*
>(&(hwaddr_[0]));
479 bind_[1].buffer_length = hwaddr_length_;
480 bind_[1].length = &hwaddr_length_;
482 bind_[1].buffer_type = MYSQL_TYPE_NULL;
489 bind_[1].buffer = NULL;
490 bind_[1].is_null = &hwaddr_null_;
494 if (lease_->client_id_) {
495 client_id_ = lease_->client_id_->getClientId();
496 client_id_length_ = client_id_.size();
503 if (client_id_.empty()) {
504 client_id_.resize(1);
507 bind_[2].buffer_type = MYSQL_TYPE_BLOB;
508 bind_[2].buffer =
reinterpret_cast<char*
>(&client_id_[0]);
509 bind_[2].buffer_length = client_id_length_;
510 bind_[2].length = &client_id_length_;
514 bind_[2].buffer_type = MYSQL_TYPE_NULL;
521 bind_[2].buffer = NULL;
522 bind_[2].is_null = &client_id_null_;
526 bind_[3].buffer_type = MYSQL_TYPE_LONG;
527 bind_[3].buffer =
reinterpret_cast<char*
>(&lease_->valid_lft_);
538 MySqlConnection::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
540 bind_[4].buffer_type = MYSQL_TYPE_TIMESTAMP;
541 bind_[4].buffer =
reinterpret_cast<char*
>(&expire_);
542 bind_[4].buffer_length =
sizeof(expire_);
548 bind_[5].buffer_type = MYSQL_TYPE_LONG;
549 bind_[5].buffer =
reinterpret_cast<char*
>(&lease_->subnet_id_);
555 bind_[6].buffer_type = MYSQL_TYPE_TINY;
556 bind_[6].buffer =
reinterpret_cast<char*
>(&lease_->fqdn_fwd_);
562 bind_[7].buffer_type = MYSQL_TYPE_TINY;
563 bind_[7].buffer =
reinterpret_cast<char*
>(&lease_->fqdn_rev_);
572 bind_[8].buffer_type = MYSQL_TYPE_STRING;
573 bind_[8].buffer =
const_cast<char*
>(lease_->hostname_.c_str());
574 bind_[8].buffer_length = lease_->hostname_.length();
579 bind_[9].buffer_type = MYSQL_TYPE_LONG;
580 bind_[9].buffer =
reinterpret_cast<char*
>(&lease_->state_);
588 bind_[10].buffer_type = MYSQL_TYPE_STRING;
589 string ctx_txt = ctx->str();
590 strncpy(user_context_, ctx_txt.c_str(), USER_CONTEXT_MAX_LEN - 1);
591 bind_[10].buffer = user_context_;
592 bind_[10].buffer_length = ctx_txt.length();
596 bind_[10].buffer_type = MYSQL_TYPE_NULL;
600 setErrorIndicators(bind_, error_, LEASE_COLUMNS);
603 BOOST_STATIC_ASSERT(10 < LEASE_COLUMNS);
605 }
catch (
const std::exception& ex) {
607 "Could not create bind array from Lease4: "
608 << lease_->addr_.toText() <<
", reason: " << ex.
what());
613 return (std::vector<MYSQL_BIND>(&bind_[0], &bind_[LEASE_COLUMNS]));
629 memset(bind_, 0,
sizeof(bind_));
632 bind_[0].buffer_type = MYSQL_TYPE_LONG;
633 bind_[0].buffer =
reinterpret_cast<char*
>(&addr4_);
639 hwaddr_length_ =
sizeof(hwaddr_buffer_);
640 bind_[1].buffer_type = MYSQL_TYPE_BLOB;
641 bind_[1].buffer =
reinterpret_cast<char*
>(hwaddr_buffer_);
642 bind_[1].buffer_length = hwaddr_length_;
643 bind_[1].length = &hwaddr_length_;
648 client_id_length_ =
sizeof(client_id_buffer_);
649 bind_[2].buffer_type = MYSQL_TYPE_BLOB;
650 bind_[2].buffer =
reinterpret_cast<char*
>(client_id_buffer_);
651 bind_[2].buffer_length = client_id_length_;
652 bind_[2].length = &client_id_length_;
653 bind_[2].is_null = &client_id_null_;
658 bind_[3].buffer_type = MYSQL_TYPE_LONG;
659 bind_[3].buffer =
reinterpret_cast<char*
>(&valid_lifetime_);
665 bind_[4].buffer_type = MYSQL_TYPE_TIMESTAMP;
666 bind_[4].buffer =
reinterpret_cast<char*
>(&expire_);
667 bind_[4].buffer_length =
sizeof(expire_);
672 bind_[5].buffer_type = MYSQL_TYPE_LONG;
673 bind_[5].buffer =
reinterpret_cast<char*
>(&subnet_id_);
679 bind_[6].buffer_type = MYSQL_TYPE_TINY;
680 bind_[6].buffer =
reinterpret_cast<char*
>(&fqdn_fwd_);
686 bind_[7].buffer_type = MYSQL_TYPE_TINY;
687 bind_[7].buffer =
reinterpret_cast<char*
>(&fqdn_rev_);
696 hostname_length_ =
sizeof(hostname_buffer_);
697 bind_[8].buffer_type = MYSQL_TYPE_STRING;
698 bind_[8].buffer =
reinterpret_cast<char*
>(hostname_buffer_);
699 bind_[8].buffer_length = hostname_length_;
700 bind_[8].length = &hostname_length_;
705 bind_[9].buffer_type = MYSQL_TYPE_LONG;
706 bind_[9].buffer =
reinterpret_cast<char*
>(&state_);
713 user_context_length_ =
sizeof(user_context_);
714 bind_[10].buffer_type = MYSQL_TYPE_STRING;
715 bind_[10].buffer =
reinterpret_cast<char*
>(user_context_);
716 bind_[10].buffer_length = user_context_length_;
717 bind_[10].length= &user_context_length_;
718 bind_[10].is_null = &user_context_null_;
721 setErrorIndicators(bind_, error_, LEASE_COLUMNS);
724 BOOST_STATIC_ASSERT(10 < LEASE_COLUMNS);
728 return(std::vector<MYSQL_BIND>(&bind_[0], &bind_[LEASE_COLUMNS]));
743 MySqlConnection::convertFromDatabaseTime(expire_, valid_lifetime_, cltt);
747 client_id_length_ = 0;
752 std::string hostname(hostname_buffer_,
753 hostname_buffer_ + hostname_length_);
762 std::string user_context;
764 user_context_[user_context_length_] =
'\0';
765 user_context.assign(user_context_);
770 if (!user_context.empty()) {
771 ctx = Element::fromJSON(user_context);
772 if (!ctx || (ctx->getType() != Element::map)) {
774 <<
"' is not a JSON map");
780 client_id_buffer_, client_id_length_,
781 valid_lifetime_, 0, 0, cltt, subnet_id_,
782 fqdn_fwd_, fqdn_rev_, hostname));
785 lease->state_ = state_;
788 lease->setContext(ctx);
805 return (getColumnsInError(error_, columns_, LEASE_COLUMNS));
814 MYSQL_BIND bind_[LEASE_COLUMNS];
815 std::string columns_[LEASE_COLUMNS];
816 my_bool error_[LEASE_COLUMNS];
817 std::vector<uint8_t> hwaddr_;
818 uint8_t hwaddr_buffer_[HWAddr::MAX_HWADDR_LEN];
819 unsigned long hwaddr_length_;
820 my_bool hwaddr_null_;
821 std::vector<uint8_t> client_id_;
822 uint8_t client_id_buffer_[ClientId::MAX_CLIENT_ID_LEN];
823 unsigned long client_id_length_;
824 my_bool client_id_null_;
828 uint32_t valid_lifetime_;
831 char hostname_buffer_[HOSTNAME_MAX_LEN];
832 unsigned long hostname_length_;
834 char user_context_[USER_CONTEXT_MAX_LEN];
835 unsigned long user_context_length_;
836 my_bool user_context_null_;
854 static const size_t LEASE_COLUMNS = 17;
862 iaid_(0), lease_type_(0), prefixlen_(0),
863 pref_lifetime_(0), subnet_id_(0), valid_lifetime_(0),
864 fqdn_fwd_(false), fqdn_rev_(false),
865 hostname_length_(0), hwaddr_length_(0),
866 hwaddr_null_(
MLM_FALSE), hwtype_(0), hwaddr_source_(0),
867 state_(0), user_context_length_(0),
869 memset(addr6_buffer_, 0,
sizeof(addr6_buffer_));
870 memset(duid_buffer_, 0,
sizeof(duid_buffer_));
871 memset(hostname_buffer_, 0,
sizeof(hostname_buffer_));
872 memset(hwaddr_buffer_, 0,
sizeof(hwaddr_buffer_));
873 memset(user_context_, 0,
sizeof(user_context_));
874 std::fill(&error_[0], &error_[LEASE_COLUMNS],
MLM_FALSE);
877 columns_[0] =
"address";
878 columns_[1] =
"duid";
879 columns_[2] =
"valid_lifetime";
880 columns_[3] =
"expire";
881 columns_[4] =
"subnet_id";
882 columns_[5] =
"pref_lifetime";
883 columns_[6] =
"lease_type";
884 columns_[7] =
"iaid";
885 columns_[8] =
"prefix_len";
886 columns_[9] =
"fqdn_fwd";
887 columns_[10] =
"fqdn_rev";
888 columns_[11] =
"hostname";
889 columns_[12] =
"hwaddr";
890 columns_[13] =
"hwtype";
891 columns_[14] =
"hwaddr_source";
892 columns_[15] =
"state";
893 columns_[16] =
"user_context";
894 BOOST_STATIC_ASSERT(16 < LEASE_COLUMNS);
915 memset(bind_, 0,
sizeof(bind_));
919 addr6_ = lease_->addr_.toText();
920 addr6_length_ = addr6_.size();
936 bind_[0].buffer_type = MYSQL_TYPE_STRING;
937 bind_[0].buffer =
const_cast<char*
>(addr6_.c_str());
938 bind_[0].buffer_length = addr6_length_;
939 bind_[0].length = &addr6_length_;
944 if (!lease_->duid_) {
946 <<
" is missing mandatory client-id.");
948 duid_ = lease_->duid_->getDuid();
949 duid_length_ = duid_.size();
951 bind_[1].buffer_type = MYSQL_TYPE_BLOB;
952 bind_[1].buffer =
reinterpret_cast<char*
>(&(duid_[0]));
953 bind_[1].buffer_length = duid_length_;
954 bind_[1].length = &duid_length_;
959 bind_[2].buffer_type = MYSQL_TYPE_LONG;
960 bind_[2].buffer =
reinterpret_cast<char*
>(&lease_->valid_lft_);
971 MySqlConnection::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
973 bind_[3].buffer_type = MYSQL_TYPE_TIMESTAMP;
974 bind_[3].buffer =
reinterpret_cast<char*
>(&expire_);
975 bind_[3].buffer_length =
sizeof(expire_);
981 bind_[4].buffer_type = MYSQL_TYPE_LONG;
982 bind_[4].buffer =
reinterpret_cast<char*
>(&lease_->subnet_id_);
989 bind_[5].buffer_type = MYSQL_TYPE_LONG;
990 bind_[5].buffer =
reinterpret_cast<char*
>(&lease_->preferred_lft_);
997 lease_type_ = lease_->type_;
998 bind_[6].buffer_type = MYSQL_TYPE_TINY;
999 bind_[6].buffer =
reinterpret_cast<char*
>(&lease_type_);
1006 bind_[7].buffer_type = MYSQL_TYPE_LONG;
1007 bind_[7].buffer =
reinterpret_cast<char*
>(&lease_->iaid_);
1014 bind_[8].buffer_type = MYSQL_TYPE_TINY;
1015 bind_[8].buffer =
reinterpret_cast<char*
>(&lease_->prefixlen_);
1021 bind_[9].buffer_type = MYSQL_TYPE_TINY;
1022 bind_[9].buffer =
reinterpret_cast<char*
>(&lease_->fqdn_fwd_);
1028 bind_[10].buffer_type = MYSQL_TYPE_TINY;
1029 bind_[10].buffer =
reinterpret_cast<char*
>(&lease_->fqdn_rev_);
1035 bind_[11].buffer_type = MYSQL_TYPE_STRING;
1036 bind_[11].buffer =
const_cast<char*
>(lease_->hostname_.c_str());
1037 bind_[11].buffer_length = lease_->hostname_.length();
1044 hwaddr_ = hwaddr->hwaddr_;
1045 hwaddr_length_ = hwaddr->hwaddr_.size();
1052 if (hwaddr_.empty()) {
1056 bind_[12].buffer_type = MYSQL_TYPE_BLOB;
1057 bind_[12].buffer =
reinterpret_cast<char*
>(&(hwaddr_[0]));
1058 bind_[12].buffer_length = hwaddr_length_;
1059 bind_[12].length = &hwaddr_length_;
1061 bind_[12].buffer_type = MYSQL_TYPE_NULL;
1068 bind_[12].buffer = NULL;
1069 bind_[12].is_null = &hwaddr_null_;
1074 hwtype_ = lease->hwaddr_->htype_;
1075 bind_[13].buffer_type = MYSQL_TYPE_SHORT;
1076 bind_[13].buffer =
reinterpret_cast<char*
>(&hwtype_);
1080 bind_[13].buffer_type = MYSQL_TYPE_NULL;
1087 bind_[13].buffer = NULL;
1088 bind_[13].is_null = &hwaddr_null_;
1093 hwaddr_source_ = lease->hwaddr_->source_;
1094 bind_[14].buffer_type = MYSQL_TYPE_LONG;
1095 bind_[14].buffer =
reinterpret_cast<char*
>(&hwaddr_source_);
1099 bind_[14].buffer_type = MYSQL_TYPE_NULL;
1106 bind_[14].buffer = NULL;
1107 bind_[14].is_null = &hwaddr_null_;
1111 bind_[15].buffer_type = MYSQL_TYPE_LONG;
1112 bind_[15].buffer =
reinterpret_cast<char*
>(&lease_->state_);
1120 bind_[16].buffer_type = MYSQL_TYPE_STRING;
1121 string ctx_txt = ctx->str();
1122 strncpy(user_context_, ctx_txt.c_str(), USER_CONTEXT_MAX_LEN - 1);
1123 bind_[16].buffer = user_context_;
1124 bind_[16].buffer_length = ctx_txt.length();
1128 bind_[16].buffer_type = MYSQL_TYPE_NULL;
1132 setErrorIndicators(bind_, error_, LEASE_COLUMNS);
1135 BOOST_STATIC_ASSERT(16 < LEASE_COLUMNS);
1137 }
catch (
const std::exception& ex) {
1139 "Could not create bind array from Lease6: "
1140 << lease_->addr_.toText() <<
", reason: " << ex.
what());
1145 return (std::vector<MYSQL_BIND>(&bind_[0], &bind_[LEASE_COLUMNS]));
1163 memset(bind_, 0,
sizeof(bind_));
1169 addr6_length_ =
sizeof(addr6_buffer_) - 1;
1170 bind_[0].buffer_type = MYSQL_TYPE_STRING;
1171 bind_[0].buffer = addr6_buffer_;
1172 bind_[0].buffer_length = addr6_length_;
1173 bind_[0].length = &addr6_length_;
1178 duid_length_ =
sizeof(duid_buffer_);
1179 bind_[1].buffer_type = MYSQL_TYPE_BLOB;
1180 bind_[1].buffer =
reinterpret_cast<char*
>(duid_buffer_);
1181 bind_[1].buffer_length = duid_length_;
1182 bind_[1].length = &duid_length_;
1187 bind_[2].buffer_type = MYSQL_TYPE_LONG;
1188 bind_[2].buffer =
reinterpret_cast<char*
>(&valid_lifetime_);
1194 bind_[3].buffer_type = MYSQL_TYPE_TIMESTAMP;
1195 bind_[3].buffer =
reinterpret_cast<char*
>(&expire_);
1196 bind_[3].buffer_length =
sizeof(expire_);
1201 bind_[4].buffer_type = MYSQL_TYPE_LONG;
1202 bind_[4].buffer =
reinterpret_cast<char*
>(&subnet_id_);
1208 bind_[5].buffer_type = MYSQL_TYPE_LONG;
1209 bind_[5].buffer =
reinterpret_cast<char*
>(&pref_lifetime_);
1215 bind_[6].buffer_type = MYSQL_TYPE_TINY;
1216 bind_[6].buffer =
reinterpret_cast<char*
>(&lease_type_);
1222 bind_[7].buffer_type = MYSQL_TYPE_LONG;
1223 bind_[7].buffer =
reinterpret_cast<char*
>(&iaid_);
1229 bind_[8].buffer_type = MYSQL_TYPE_TINY;
1230 bind_[8].buffer =
reinterpret_cast<char*
>(&prefixlen_);
1236 bind_[9].buffer_type = MYSQL_TYPE_TINY;
1237 bind_[9].buffer =
reinterpret_cast<char*
>(&fqdn_fwd_);
1243 bind_[10].buffer_type = MYSQL_TYPE_TINY;
1244 bind_[10].buffer =
reinterpret_cast<char*
>(&fqdn_rev_);
1250 hostname_length_ =
sizeof(hostname_buffer_);
1251 bind_[11].buffer_type = MYSQL_TYPE_STRING;
1252 bind_[11].buffer =
reinterpret_cast<char*
>(hostname_buffer_);
1253 bind_[11].buffer_length = hostname_length_;
1254 bind_[11].length = &hostname_length_;
1260 hwaddr_length_ =
sizeof(hwaddr_buffer_);
1261 bind_[12].buffer_type = MYSQL_TYPE_BLOB;
1262 bind_[12].buffer =
reinterpret_cast<char*
>(hwaddr_buffer_);
1263 bind_[12].buffer_length = hwaddr_length_;
1264 bind_[12].length = &hwaddr_length_;
1265 bind_[12].is_null = &hwaddr_null_;
1268 bind_[13].buffer_type = MYSQL_TYPE_SHORT;
1269 bind_[13].buffer =
reinterpret_cast<char*
>(&hwtype_);
1273 bind_[14].buffer_type = MYSQL_TYPE_LONG;
1274 bind_[14].buffer =
reinterpret_cast<char*
>(&hwaddr_source_);
1278 bind_[15].buffer_type = MYSQL_TYPE_LONG;
1279 bind_[15].buffer =
reinterpret_cast<char*
>(&state_);
1286 user_context_length_ =
sizeof(user_context_);
1287 bind_[16].buffer_type = MYSQL_TYPE_STRING;
1288 bind_[16].buffer =
reinterpret_cast<char*
>(user_context_);
1289 bind_[16].buffer_length = user_context_length_;
1290 bind_[16].length= &user_context_length_;
1291 bind_[16].is_null = &user_context_null_;
1294 setErrorIndicators(bind_, error_, LEASE_COLUMNS);
1297 BOOST_STATIC_ASSERT(16 < LEASE_COLUMNS);
1301 return(std::vector<MYSQL_BIND>(&bind_[0], &bind_[LEASE_COLUMNS]));
1318 addr6_buffer_[addr6_length_] =
'\0';
1319 std::string address = addr6_buffer_;
1325 switch (lease_type_) {
1326 case Lease::TYPE_NA:
1327 type = Lease::TYPE_NA;
1330 case Lease::TYPE_TA:
1331 type = Lease::TYPE_TA;
1334 case Lease::TYPE_PD:
1335 type = Lease::TYPE_PD;
1340 static_cast<int>(lease_type_) <<
") for lease with "
1341 <<
"address " << address <<
". Only 0, 1, or 2 are "
1346 DuidPtr duid_ptr(
new DUID(duid_buffer_, duid_length_));
1350 std::string hostname(hostname_buffer_,
1351 hostname_buffer_ + hostname_length_);
1356 hwaddr.reset(
new HWAddr(hwaddr_buffer_, hwaddr_length_, hwtype_));
1357 hwaddr->source_ = hwaddr_source_;
1361 std::string user_context;
1363 user_context_[user_context_length_] =
'\0';
1364 user_context.assign(user_context_);
1369 if (!user_context.empty()) {
1370 ctx = Element::fromJSON(user_context);
1371 if (!ctx || (ctx->getType() != Element::map)) {
1373 <<
"' is not a JSON map");
1380 pref_lifetime_, valid_lifetime_, 0, 0,
1381 subnet_id_, fqdn_fwd_, fqdn_rev_,
1382 hostname, hwaddr, prefixlen_));
1384 MySqlConnection::convertFromDatabaseTime(expire_, valid_lifetime_, cltt);
1385 result->cltt_ = cltt;
1388 result->state_ = state_;
1391 result->setContext(ctx);
1408 return (getColumnsInError(error_, columns_, LEASE_COLUMNS));
1416 char addr6_buffer_[ADDRESS6_TEXT_MAX_LEN + 1];
1417 unsigned long addr6_length_;
1419 MYSQL_BIND bind_[LEASE_COLUMNS];
1420 std::string columns_[LEASE_COLUMNS];
1421 std::vector<uint8_t> duid_;
1422 uint8_t duid_buffer_[DUID::MAX_DUID_LEN];
1423 unsigned long duid_length_;
1424 my_bool error_[LEASE_COLUMNS];
1428 uint8_t lease_type_;
1430 uint32_t pref_lifetime_;
1431 uint32_t subnet_id_;
1432 uint32_t valid_lifetime_;
1435 char hostname_buffer_[HOSTNAME_MAX_LEN];
1436 unsigned long hostname_length_;
1437 uint8_t hwaddr_buffer_[HWAddr::MAX_HWADDR_LEN];
1438 std::vector<uint8_t> hwaddr_;
1439 unsigned long hwaddr_length_;
1440 my_bool hwaddr_null_;
1442 uint32_t hwaddr_source_;
1444 char user_context_[USER_CONTEXT_MAX_LEN];
1445 unsigned long user_context_length_;
1446 my_bool user_context_null_;
1467 const bool fetch_type)
1468 : conn_(conn), statement_index_(statement_index), statement_(NULL),
1469 fetch_type_(fetch_type),
1472 bind_(fetch_type_ ? 4 : 3),
1473 subnet_id_(0), lease_type_(0), lease_state_(0), state_count_(0) {
1474 validateStatement();
1487 const bool fetch_type,
const SubnetID& subnet_id)
1488 :
LeaseStatsQuery(subnet_id), conn_(conn), statement_index_(statement_index),
1489 statement_(NULL), fetch_type_(fetch_type),
1492 bind_(fetch_type_ ? 4 : 3),
1493 subnet_id_(0), lease_type_(0), lease_state_(0), state_count_(0) {
1494 validateStatement();
1510 const bool fetch_type,
const SubnetID& first_subnet_id,
1513 statement_index_(statement_index), statement_(NULL), fetch_type_(fetch_type),
1516 bind_(fetch_type_ ? 4 : 3),
1517 subnet_id_(0), lease_type_(0), lease_state_(0), state_count_(0) {
1518 validateStatement();
1523 (void) mysql_stmt_free_result(statement_);
1535 if (getSelectMode() != ALL_SUBNETS) {
1536 MYSQL_BIND inbind[2];
1537 memset(inbind, 0,
sizeof(inbind));
1540 inbind[0].buffer_type = MYSQL_TYPE_LONG;
1541 inbind[0].buffer =
reinterpret_cast<char*
>(&first_subnet_id_);
1545 if (getSelectMode() == SUBNET_RANGE) {
1546 inbind[1].buffer_type = MYSQL_TYPE_LONG;
1547 inbind[1].buffer =
reinterpret_cast<char*
>(&last_subnet_id_);
1552 int status = mysql_stmt_bind_param(statement_, &inbind[0]);
1553 conn_.checkError(status, statement_index_,
"unable to bind parameters");
1558 bind_[col].buffer_type = MYSQL_TYPE_LONG;
1559 bind_[col].buffer =
reinterpret_cast<char*
>(&subnet_id_);
1566 bind_[col].buffer_type = MYSQL_TYPE_LONG;
1567 bind_[col].buffer =
reinterpret_cast<char*
>(&lease_type_);
1571 fetch_type_ = Lease::TYPE_NA;
1575 bind_[col].buffer_type = MYSQL_TYPE_LONG;
1576 bind_[col].buffer =
reinterpret_cast<char*
>(&lease_state_);
1581 bind_[col].buffer_type = MYSQL_TYPE_LONGLONG;
1582 bind_[col].buffer =
reinterpret_cast<char*
>(&state_count_);
1587 int status = mysql_stmt_bind_result(statement_, &bind_[0]);
1588 conn_.checkError(status, statement_index_,
"outbound binding failed");
1591 status = mysql_stmt_execute(statement_);
1592 conn_.checkError(status, statement_index_,
"unable to execute");
1596 status = mysql_stmt_store_result(statement_);
1597 conn_.checkError(status, statement_index_,
"results storage failed");
1612 bool have_row =
false;
1613 int status = mysql_stmt_fetch(statement_);
1620 }
else if (status != MYSQL_NO_DATA) {
1621 conn_.checkError(status, statement_index_,
"getNextRow failed");
1631 void validateStatement() {
1632 if (statement_index_ >= MySqlLeaseMgr::NUM_STATEMENTS) {
1634 " - invalid statement index" << statement_index_);
1637 statement_ = conn_.statements_[statement_index_];
1644 size_t statement_index_;
1647 MYSQL_STMT *statement_;
1653 std::vector<MYSQL_BIND> bind_;
1656 uint32_t subnet_id_;
1658 uint32_t lease_type_;
1660 uint32_t lease_state_;
1662 int64_t state_count_;
1667 MySqlLeaseMgr::MySqlLeaseMgr(
const MySqlConnection::ParameterMap& parameters)
1668 : conn_(parameters) {
1676 std::pair<uint32_t, uint32_t> db_version =
getVersion();
1677 if (code_version != db_version) {
1679 "MySQL schema version mismatch: need version: "
1680 << code_version.first <<
"." << code_version.second
1681 <<
" found version: " << db_version.first <<
"."
1682 << db_version.second);
1690 my_bool result = mysql_autocommit(conn_.
mysql_, 1);
1711 std::stringstream tmp;
1714 tmp <<
", library " << mysql_get_client_info();
1723 MySqlLeaseMgr::addLeaseCommon(StatementIndex stindex,
1724 std::vector<MYSQL_BIND>& bind) {
1727 int status = mysql_stmt_bind_param(conn_.
statements_[stindex], &bind[0]);
1728 checkError(status, stindex,
"unable to bind parameters");
1731 status = mysql_stmt_execute(conn_.
statements_[stindex]);
1737 if (mysql_errno(conn_.
mysql_) == ER_DUP_ENTRY) {
1740 checkError(status, stindex,
"unable to execute");
1750 DHCPSRV_MYSQL_ADD_ADDR4).arg(lease->addr_.toText());
1753 std::vector<MYSQL_BIND> bind = exchange4_->createBindForSend(lease);
1762 DHCPSRV_MYSQL_ADD_ADDR6).arg(lease->addr_.toText())
1766 std::vector<MYSQL_BIND> bind = exchange6_->createBindForSend(lease);
1797 template <
typename Exchange,
typename LeaseCollection>
1798 void MySqlLeaseMgr::getLeaseCollection(StatementIndex stindex,
1801 LeaseCollection& result,
1802 bool single)
const {
1808 status = mysql_stmt_bind_param(conn_.
statements_[stindex], bind);
1809 checkError(status, stindex,
"unable to bind WHERE clause parameter");
1814 std::vector<MYSQL_BIND> outbind = exchange->createBindForReceive();
1815 status = mysql_stmt_bind_result(conn_.
statements_[stindex], &outbind[0]);
1816 checkError(status, stindex,
"unable to bind SELECT clause parameters");
1819 status = mysql_stmt_execute(conn_.
statements_[stindex]);
1820 checkError(status, stindex,
"unable to execute");
1824 status = mysql_stmt_store_result(conn_.
statements_[stindex]);
1825 checkError(status, stindex,
"unable to set up for storing all results");
1832 while ((status = mysql_stmt_fetch(conn_.
statements_[stindex])) == 0) {
1834 result.push_back(exchange->getLeaseData());
1842 if (single && (++count > 1)) {
1844 "database where only one was expected for query "
1852 checkError(status, stindex,
"unable to fetch results");
1853 }
else if (status == MYSQL_DATA_TRUNCATED) {
1856 <<
" returned truncated data: columns affected are "
1857 << exchange->getErrorColumns());
1861 void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* bind,
1869 getLeaseCollection(stindex, bind, exchange4_, collection,
true);
1872 if (collection.empty()) {
1875 result = *collection.begin();
1879 void MySqlLeaseMgr::getLease(StatementIndex stindex, MYSQL_BIND* bind,
1887 getLeaseCollection(stindex, bind, exchange6_, collection,
true);
1890 if (collection.empty()) {
1893 result = *collection.begin();
1903 DHCPSRV_MYSQL_GET_ADDR4).arg(addr.
toText());
1906 MYSQL_BIND inbind[1];
1907 memset(inbind, 0,
sizeof(inbind));
1910 inbind[0].buffer_type = MYSQL_TYPE_LONG;
1911 inbind[0].buffer =
reinterpret_cast<char*
>(&addr4);
1924 DHCPSRV_MYSQL_GET_HWADDR).arg(hwaddr.
toText());
1927 MYSQL_BIND inbind[1];
1928 memset(inbind, 0,
sizeof(inbind));
1930 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
1932 unsigned long hwaddr_length = hwaddr.
hwaddr_.size();
1936 uint8_t single_byte_data = 0;
1943 uint8_t* data = !hwaddr.
hwaddr_.empty() ?
const_cast<uint8_t*
>(&hwaddr.
hwaddr_[0])
1944 : &single_byte_data;
1946 inbind[0].buffer =
reinterpret_cast<char*
>(data);
1947 inbind[0].buffer_length = hwaddr_length;
1948 inbind[0].length = &hwaddr_length;
1960 DHCPSRV_MYSQL_GET_SUBID_HWADDR)
1961 .arg(subnet_id).arg(hwaddr.
toText());
1964 MYSQL_BIND inbind[2];
1965 memset(inbind, 0,
sizeof(inbind));
1967 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
1969 unsigned long hwaddr_length = hwaddr.
hwaddr_.size();
1973 std::vector<uint8_t> single_byte_vec(1);
1980 uint8_t* data = !hwaddr.
hwaddr_.empty() ?
const_cast<uint8_t*
>(&hwaddr.
hwaddr_[0])
1981 : &single_byte_vec[0];
1983 inbind[0].buffer =
reinterpret_cast<char*
>(data);
1984 inbind[0].buffer_length = hwaddr_length;
1985 inbind[0].length = &hwaddr_length;
1987 inbind[1].buffer_type = MYSQL_TYPE_LONG;
1988 inbind[1].buffer =
reinterpret_cast<char*
>(&subnet_id);
2001 DHCPSRV_MYSQL_GET_CLIENTID).arg(clientid.
toText());
2004 MYSQL_BIND inbind[1];
2005 memset(inbind, 0,
sizeof(inbind));
2007 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
2009 std::vector<uint8_t> client_data = clientid.
getClientId();
2010 unsigned long client_data_length = client_data.size();
2014 if (client_data.empty()) {
2015 client_data.resize(1);
2018 inbind[0].buffer =
reinterpret_cast<char*
>(&client_data[0]);
2019 inbind[0].buffer_length = client_data_length;
2020 inbind[0].length = &client_data_length;
2036 " called, but it is not implemented");
2042 DHCPSRV_MYSQL_GET_SUBID_CLIENTID)
2043 .arg(subnet_id).arg(clientid.
toText());
2046 MYSQL_BIND inbind[2];
2047 memset(inbind, 0,
sizeof(inbind));
2049 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
2051 std::vector<uint8_t> client_data = clientid.
getClientId();
2052 unsigned long client_data_length = client_data.size();
2056 if (client_data.empty()) {
2057 client_data.resize(1);
2060 inbind[0].buffer =
reinterpret_cast<char*
>(&client_data[0]);
2061 inbind[0].buffer_length = client_data_length;
2062 inbind[0].length = &client_data_length;
2064 inbind[1].buffer_type = MYSQL_TYPE_LONG;
2065 inbind[1].buffer =
reinterpret_cast<char*
>(&subnet_id);
2081 MYSQL_BIND inbind[1];
2082 memset(inbind, 0,
sizeof(inbind));
2085 inbind[0].buffer_type = MYSQL_TYPE_LONG;
2086 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet_id);
2110 if (!lower_bound_address.
isV4()) {
2112 "retrieving leases from the lease database, got "
2113 << lower_bound_address);
2118 .arg(lower_bound_address.
toText());
2121 MYSQL_BIND inbind[2];
2122 memset(inbind, 0,
sizeof(inbind));
2125 uint32_t lb_address_data = lower_bound_address.
toUint32();
2126 inbind[0].buffer_type = MYSQL_TYPE_LONG;
2127 inbind[0].buffer =
reinterpret_cast<char*
>(&lb_address_data);
2131 size_t* ps =
const_cast<size_t*
>(&page_size.
page_size_);
2132 inbind[1].buffer_type = MYSQL_TYPE_LONG;
2133 inbind[1].buffer =
reinterpret_cast<char*
>(ps);
2147 DHCPSRV_MYSQL_GET_ADDR6).arg(addr.
toText())
2151 MYSQL_BIND inbind[2];
2152 memset(inbind, 0,
sizeof(inbind));
2154 std::string addr6 = addr.
toText();
2155 unsigned long addr6_length = addr6.size();
2159 inbind[0].buffer_type = MYSQL_TYPE_STRING;
2160 inbind[0].buffer =
const_cast<char*
>(addr6.c_str());
2161 inbind[0].buffer_length = addr6_length;
2162 inbind[0].length = &addr6_length;
2165 inbind[1].buffer_type = MYSQL_TYPE_TINY;
2166 inbind[1].buffer =
reinterpret_cast<char*
>(&lease_type);
2177 const DUID& duid, uint32_t iaid)
const {
2179 DHCPSRV_MYSQL_GET_IAID_DUID).arg(iaid).arg(duid.
toText())
2183 MYSQL_BIND inbind[3];
2184 memset(inbind, 0,
sizeof(inbind));
2198 const vector<uint8_t>& duid_vector = duid.
getDuid();
2199 unsigned long duid_length = duid_vector.size();
2206 uint8_t single_byte_data = 0;
2207 uint8_t* data = !duid_vector.empty() ?
const_cast<uint8_t*
>(&duid_vector[0])
2208 : &single_byte_data;
2210 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
2211 inbind[0].buffer =
reinterpret_cast<char*
>(data);
2212 inbind[0].buffer_length = duid_length;
2213 inbind[0].length = &duid_length;
2216 inbind[1].buffer_type = MYSQL_TYPE_LONG;
2217 inbind[1].buffer =
reinterpret_cast<char*
>(&iaid);
2221 inbind[2].buffer_type = MYSQL_TYPE_TINY;
2222 inbind[2].buffer =
reinterpret_cast<char*
>(&lease_type);
2234 const DUID& duid, uint32_t iaid,
2237 DHCPSRV_MYSQL_GET_IAID_SUBID_DUID)
2238 .arg(iaid).arg(subnet_id).arg(duid.
toText())
2242 MYSQL_BIND inbind[4];
2243 memset(inbind, 0,
sizeof(inbind));
2247 const vector<uint8_t>& duid_vector = duid.
getDuid();
2248 unsigned long duid_length = duid_vector.size();
2249 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
2250 inbind[0].buffer =
reinterpret_cast<char*
>(
2251 const_cast<uint8_t*
>(&duid_vector[0]));
2252 inbind[0].buffer_length = duid_length;
2253 inbind[0].length = &duid_length;
2256 inbind[1].buffer_type = MYSQL_TYPE_LONG;
2257 inbind[1].buffer =
reinterpret_cast<char*
>(&iaid);
2261 inbind[2].buffer_type = MYSQL_TYPE_LONG;
2262 inbind[2].buffer =
reinterpret_cast<char*
>(&subnet_id);
2266 inbind[3].buffer_type = MYSQL_TYPE_TINY;
2267 inbind[3].buffer =
reinterpret_cast<char*
>(&lease_type);
2283 MYSQL_BIND inbind[1];
2284 memset(inbind, 0,
sizeof(inbind));
2287 inbind[0].buffer_type = MYSQL_TYPE_LONG;
2288 inbind[0].buffer =
reinterpret_cast<char*
>(&subnet_id);
2314 MYSQL_BIND inbind[1];
2315 memset(inbind, 0,
sizeof(inbind));
2317 const vector<uint8_t>& duid_vector = duid.
getDuid();
2318 unsigned long duid_length = duid_vector.size();
2320 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
2321 inbind[0].buffer =
reinterpret_cast<char*
>(
2322 const_cast<uint8_t*
>(&duid_vector[0]));
2323 inbind[0].buffer_length = duid_length;
2324 inbind[0].length = &duid_length;
2337 if (!lower_bound_address.
isV6()) {
2339 "retrieving leases from the lease database, got "
2340 << lower_bound_address);
2345 .arg(lower_bound_address.
toText());
2348 MYSQL_BIND inbind[2];
2349 memset(inbind, 0,
sizeof(inbind));
2354 std::string lb_address_data =
"0";
2355 if (!lower_bound_address.
isV6Zero()) {
2356 lb_address_data = lower_bound_address.
toText();
2360 unsigned long lb_address_data_size = lb_address_data.size();
2361 inbind[0].buffer_type = MYSQL_TYPE_STRING;
2362 inbind[0].buffer =
const_cast<char*
>(lb_address_data.c_str());
2363 inbind[0].buffer_length = lb_address_data_size;
2364 inbind[0].length = &lb_address_data_size;
2367 size_t* ps =
const_cast<size_t*
>(&page_size.
page_size_);
2368 inbind[1].buffer_type = MYSQL_TYPE_LONG;
2369 inbind[1].buffer =
reinterpret_cast<char*
>(ps);
2381 const size_t max_leases)
const {
2389 const size_t max_leases)
const {
2395 template<
typename LeaseCollection>
2397 MySqlLeaseMgr::getExpiredLeasesCommon(LeaseCollection& expired_leases,
2398 const size_t max_leases,
2399 StatementIndex statement_index)
const {
2401 MYSQL_BIND inbind[3];
2402 memset(inbind, 0,
sizeof(inbind));
2406 inbind[0].buffer_type = MYSQL_TYPE_LONG;
2407 inbind[0].buffer =
reinterpret_cast<char*
>(&state);
2411 MYSQL_TIME expire_time;
2413 inbind[1].buffer_type = MYSQL_TYPE_TIMESTAMP;
2414 inbind[1].buffer =
reinterpret_cast<char*
>(&expire_time);
2415 inbind[1].buffer_length =
sizeof(expire_time);
2419 uint32_t limit = max_leases > 0 ?
static_cast<uint32_t
>(max_leases) :
2420 std::numeric_limits<uint32_t>::max();
2421 inbind[2].buffer_type = MYSQL_TYPE_LONG;
2422 inbind[2].buffer =
reinterpret_cast<char*
>(&limit);
2426 getLeaseCollection(statement_index, inbind, expired_leases);
2433 template <
typename LeasePtr>
2435 MySqlLeaseMgr::updateLeaseCommon(StatementIndex stindex, MYSQL_BIND* bind,
2439 int status = mysql_stmt_bind_param(conn_.
statements_[stindex], bind);
2440 checkError(status, stindex,
"unable to bind parameters");
2443 status = mysql_stmt_execute(conn_.
statements_[stindex]);
2444 checkError(status, stindex,
"unable to execute");
2448 int affected_rows = mysql_stmt_affected_rows(conn_.
statements_[stindex]);
2449 if (affected_rows == 0) {
2451 lease->addr_ <<
" as it does not exist");
2452 }
else if (affected_rows > 1) {
2456 "that had the address " << lease->addr_);
2465 DHCPSRV_MYSQL_UPDATE_ADDR4).arg(lease->addr_.toText());
2468 std::vector<MYSQL_BIND> bind = exchange4_->createBindForSend(lease);
2472 memset(&where, 0,
sizeof(where));
2474 uint32_t addr4 = lease->addr_.toUint32();
2475 where.buffer_type = MYSQL_TYPE_LONG;
2476 where.buffer =
reinterpret_cast<char*
>(&addr4);
2478 bind.push_back(where);
2481 updateLeaseCommon(stindex, &bind[0], lease);
2489 DHCPSRV_MYSQL_UPDATE_ADDR6).arg(lease->addr_.toText())
2493 std::vector<MYSQL_BIND> bind = exchange6_->createBindForSend(lease);
2497 memset(&where, 0,
sizeof(where));
2499 std::string addr6 = lease->addr_.toText();
2500 unsigned long addr6_length = addr6.size();
2504 where.buffer_type = MYSQL_TYPE_STRING;
2505 where.buffer =
const_cast<char*
>(addr6.c_str());
2506 where.buffer_length = addr6_length;
2507 where.length = &addr6_length;
2508 bind.push_back(where);
2511 updateLeaseCommon(stindex, &bind[0], lease);
2520 MySqlLeaseMgr::deleteLeaseCommon(StatementIndex stindex, MYSQL_BIND* bind) {
2523 int status = mysql_stmt_bind_param(conn_.
statements_[stindex], bind);
2524 checkError(status, stindex,
"unable to bind WHERE clause parameter");
2527 status = mysql_stmt_execute(conn_.
statements_[stindex]);
2528 checkError(status, stindex,
"unable to execute");
2532 return (
static_cast<uint64_t
>(mysql_stmt_affected_rows(conn_.
statements_[stindex])));
2538 DHCPSRV_MYSQL_DELETE_ADDR).arg(addr.
toText());
2541 MYSQL_BIND inbind[1];
2542 memset(inbind, 0,
sizeof(inbind));
2547 inbind[0].buffer_type = MYSQL_TYPE_LONG;
2548 inbind[0].buffer =
reinterpret_cast<char*
>(&addr4);
2554 std::string addr6 = addr.
toText();
2555 unsigned long addr6_length = addr6.size();
2559 inbind[0].buffer_type = MYSQL_TYPE_STRING;
2560 inbind[0].buffer =
const_cast<char*
>(addr6.c_str());
2561 inbind[0].buffer_length = addr6_length;
2562 inbind[0].length = &addr6_length;
2571 DHCPSRV_MYSQL_DELETE_EXPIRED_RECLAIMED4)
2579 DHCPSRV_MYSQL_DELETE_EXPIRED_RECLAIMED6)
2585 MySqlLeaseMgr::deleteExpiredReclaimedLeasesCommon(
const uint32_t secs,
2586 StatementIndex statement_index) {
2588 MYSQL_BIND inbind[2];
2589 memset(inbind, 0,
sizeof(inbind));
2593 inbind[0].buffer_type = MYSQL_TYPE_LONG;
2594 inbind[0].buffer =
reinterpret_cast<char*
>(&state);
2598 MYSQL_TIME expire_time;
2600 inbind[1].buffer_type = MYSQL_TYPE_TIMESTAMP;
2601 inbind[1].buffer =
reinterpret_cast<char*
>(&expire_time);
2602 inbind[1].buffer_length =
sizeof(expire_time);
2605 uint64_t deleted_leases = deleteLeaseCommon(statement_index, inbind);
2607 DHCPSRV_MYSQL_DELETED_EXPIRED_RECLAIMED)
2608 .arg(deleted_leases);
2610 return (deleted_leases);
2638 first_subnet_id, last_subnet_id));
2668 first_subnet_id, last_subnet_id));
2687 std::string name =
"";
2698 return (std::string(
"MySQL Database"));
2701 std::pair<uint32_t, uint32_t>
2704 DHCPSRV_MYSQL_GET_VERSION);
2707 MYSQL_STMT *stmt = mysql_stmt_init(conn_.
mysql_);
2710 "statement structure, reason: " << mysql_error(conn_.
mysql_));
2714 const char* version_sql =
"SELECT version, minor FROM schema_version";
2715 int status = mysql_stmt_prepare(stmt, version_sql, strlen(version_sql));
2718 << version_sql <<
">, reason: " << mysql_error(conn_.
mysql_));
2722 if (mysql_stmt_execute(stmt) != 0) {
2724 << version_sql <<
">, reason: " << mysql_errno(conn_.
mysql_));
2729 memset(bind, 0,
sizeof(bind));
2732 bind[0].buffer_type = MYSQL_TYPE_LONG;
2733 bind[0].is_unsigned = 1;
2734 bind[0].buffer = &major;
2735 bind[0].buffer_length =
sizeof(major);
2738 bind[1].buffer_type = MYSQL_TYPE_LONG;
2739 bind[1].is_unsigned = 1;
2740 bind[1].buffer = &minor;
2741 bind[1].buffer_length =
sizeof(minor);
2743 if (mysql_stmt_bind_result(stmt, bind)) {
2745 << version_sql <<
">, reason: " << mysql_errno(conn_.
mysql_));
2749 if (mysql_stmt_fetch(stmt)) {
2750 mysql_stmt_close(stmt);
2752 << version_sql <<
">, reason: " << mysql_errno(conn_.
mysql_));
2756 mysql_stmt_close(stmt);
2758 return (std::make_pair(major, minor));
2764 if (mysql_commit(conn_.
mysql_) != 0) {
2772 if (mysql_rollback(conn_.
mysql_) != 0) {
2778 MySqlLeaseMgr::checkError(
int status, StatementIndex index,
2779 const char* what)
const {