Kea 2.7.1
mysql_lease_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
10#include <dhcp/duid.h>
11#include <dhcp/hwaddr.h>
13#include <dhcpsrv/cfgmgr.h>
14#include <dhcpsrv/dhcpsrv_log.h>
17#include <dhcpsrv/timer_mgr.h>
20
21#include <boost/array.hpp>
22#include <boost/make_shared.hpp>
23#include <boost/static_assert.hpp>
24#include <mysqld_error.h>
25
26#include <ctime>
27#include <iostream>
28#include <iomanip>
29#include <limits>
30#include <sstream>
31#include <string>
32#include <vector>
33
34using namespace isc;
35using namespace isc::asiolink;
36using namespace isc::db;
37using namespace isc::dhcp;
38using namespace isc::data;
39using namespace isc::util;
40using namespace std;
41
83
84namespace {
85
87const size_t LIMITS_TEXT_MAX_LEN = 512;
88
89boost::array<TaggedStatement, MySqlLeaseMgr::NUM_STATEMENTS>
90tagged_statements = { {
92 "DELETE FROM lease4 WHERE address = ? AND expire = ?"},
94 "DELETE FROM lease4 "
95 "WHERE state = ? AND expire < ?"},
97 "DELETE FROM lease6 WHERE address = ? AND expire = ?"},
99 "DELETE FROM lease6 "
100 "WHERE state = ? AND expire < ?"},
102 "SELECT address, hwaddr, client_id, "
103 "valid_lifetime, expire, subnet_id, "
104 "fqdn_fwd, fqdn_rev, hostname, "
105 "state, user_context, relay_id, remote_id, pool_id "
106 "FROM lease4"},
108 "SELECT address, hwaddr, client_id, "
109 "valid_lifetime, expire, subnet_id, "
110 "fqdn_fwd, fqdn_rev, hostname, "
111 "state, user_context, relay_id, remote_id, pool_id "
112 "FROM lease4 "
113 "WHERE address = ?"},
115 "SELECT address, hwaddr, client_id, "
116 "valid_lifetime, expire, subnet_id, "
117 "fqdn_fwd, fqdn_rev, hostname, "
118 "state, user_context, relay_id, remote_id, pool_id "
119 "FROM lease4 "
120 "WHERE client_id = ?"},
122 "SELECT address, hwaddr, client_id, "
123 "valid_lifetime, expire, subnet_id, "
124 "fqdn_fwd, fqdn_rev, hostname, "
125 "state, user_context, relay_id, remote_id, pool_id "
126 "FROM lease4 "
127 "WHERE client_id = ? AND subnet_id = ?"},
129 "SELECT address, hwaddr, client_id, "
130 "valid_lifetime, expire, subnet_id, "
131 "fqdn_fwd, fqdn_rev, hostname, "
132 "state, user_context, relay_id, remote_id, pool_id "
133 "FROM lease4 "
134 "WHERE hwaddr = ?"},
136 "SELECT address, hwaddr, client_id, "
137 "valid_lifetime, expire, subnet_id, "
138 "fqdn_fwd, fqdn_rev, hostname, "
139 "state, user_context, relay_id, remote_id, pool_id "
140 "FROM lease4 "
141 "WHERE hwaddr = ? AND subnet_id = ?"},
143 "SELECT address, hwaddr, client_id, "
144 "valid_lifetime, expire, subnet_id, "
145 "fqdn_fwd, fqdn_rev, hostname, "
146 "state, user_context, relay_id, remote_id, pool_id "
147 "FROM lease4 "
148 "WHERE address > ? "
149 "ORDER BY address "
150 "LIMIT ?"},
152 "SELECT address, hwaddr, client_id, "
153 "valid_lifetime, expire, subnet_id, "
154 "fqdn_fwd, fqdn_rev, hostname, "
155 "state, user_context, relay_id, remote_id, pool_id "
156 "FROM lease4 "
157 "WHERE address > ? AND user_context IS NOT NULL "
158 "ORDER BY address "
159 "LIMIT ?"},
161 "SELECT address, hwaddr, client_id, "
162 "valid_lifetime, expire, subnet_id, "
163 "fqdn_fwd, fqdn_rev, hostname, "
164 "state, user_context, relay_id, remote_id, pool_id "
165 "FROM lease4 "
166 "WHERE subnet_id = ?"},
168 "SELECT address, hwaddr, client_id, "
169 "valid_lifetime, expire, subnet_id, "
170 "fqdn_fwd, fqdn_rev, hostname, "
171 "state, user_context, relay_id, remote_id, pool_id "
172 "FROM lease4 "
173 "WHERE hostname = ?"},
175 "SELECT address, hwaddr, client_id, "
176 "valid_lifetime, expire, subnet_id, "
177 "fqdn_fwd, fqdn_rev, hostname, "
178 "state, user_context, relay_id, remote_id, pool_id "
179 "FROM lease4 "
180 "WHERE state != ? "
181 "AND valid_lifetime != 4294967295 "
182 "AND expire < ? "
183 "ORDER BY expire ASC "
184 "LIMIT ?"},
186 "SELECT address, hwaddr, client_id, "
187 "valid_lifetime, expire, subnet_id, "
188 "fqdn_fwd, fqdn_rev, hostname, "
189 "state, user_context, relay_id, remote_id, pool_id "
190 "FROM lease4 "
191 "WHERE relay_id = ? and address > ? "
192 "ORDER BY address "
193 "LIMIT ?"},
195 "SELECT address, hwaddr, client_id, "
196 "valid_lifetime, expire, subnet_id, "
197 "fqdn_fwd, fqdn_rev, hostname, "
198 "state, user_context, relay_id, remote_id, pool_id "
199 "FROM lease4 "
200 "WHERE relay_id = ? and address > ? "
201 " and UNIX_TIMESTAMP(expire) - IF"
202 "(valid_lifetime = 4294967295, 0, valid_lifetime)"
203 " >= ? "
204 "ORDER BY address "
205 "LIMIT ?"},
207 "SELECT address, hwaddr, client_id, "
208 "valid_lifetime, expire, subnet_id, "
209 "fqdn_fwd, fqdn_rev, hostname, "
210 "state, user_context, relay_id, remote_id, pool_id "
211 "FROM lease4 "
212 "WHERE relay_id = ? and address > ? "
213 " and UNIX_TIMESTAMP(expire) - IF"
214 "(valid_lifetime = 4294967295, 0, valid_lifetime)"
215 " >= ? "
216 " and UNIX_TIMESTAMP(expire) - IF"
217 "(valid_lifetime = 4294967295, 0, valid_lifetime)"
218 " <= ? "
219 "ORDER BY address "
220 "LIMIT ?"},
222 "SELECT address, hwaddr, client_id, "
223 "valid_lifetime, expire, subnet_id, "
224 "fqdn_fwd, fqdn_rev, hostname, "
225 "state, user_context, relay_id, remote_id, pool_id "
226 "FROM lease4 "
227 "WHERE relay_id = ? and address > ? "
228 " and UNIX_TIMESTAMP(expire) - IF"
229 "(valid_lifetime = 4294967295, 0, valid_lifetime)"
230 " <= ? "
231 "ORDER BY address "
232 "LIMIT ?"},
234 "SELECT address, hwaddr, client_id, "
235 "valid_lifetime, expire, subnet_id, "
236 "fqdn_fwd, fqdn_rev, hostname, "
237 "state, user_context, relay_id, remote_id, pool_id "
238 "FROM lease4 "
239 "WHERE remote_id = ? and address > ? "
240 "ORDER BY address "
241 "LIMIT ?"},
243 "SELECT address, hwaddr, client_id, "
244 "valid_lifetime, expire, subnet_id, "
245 "fqdn_fwd, fqdn_rev, hostname, "
246 "state, user_context, relay_id, remote_id, pool_id "
247 "FROM lease4 "
248 "WHERE remote_id = ? and address > ? "
249 " and UNIX_TIMESTAMP(expire) - IF"
250 "(valid_lifetime = 4294967295, 0, valid_lifetime)"
251 " >= ? "
252 "ORDER BY address "
253 "LIMIT ?"},
255 "SELECT address, hwaddr, client_id, "
256 "valid_lifetime, expire, subnet_id, "
257 "fqdn_fwd, fqdn_rev, hostname, "
258 "state, user_context, relay_id, remote_id, pool_id "
259 "FROM lease4 "
260 "WHERE remote_id = ? and address > ? "
261 " and UNIX_TIMESTAMP(expire) - IF"
262 "(valid_lifetime = 4294967295, 0, valid_lifetime)"
263 " >= ? "
264 " and UNIX_TIMESTAMP(expire) - IF"
265 "(valid_lifetime = 4294967295, 0, valid_lifetime)"
266 " <= ? "
267 "ORDER BY address "
268 "LIMIT ?"},
270 "SELECT address, hwaddr, client_id, "
271 "valid_lifetime, expire, subnet_id, "
272 "fqdn_fwd, fqdn_rev, hostname, "
273 "state, user_context, relay_id, remote_id, pool_id "
274 "FROM lease4 "
275 "WHERE remote_id = ? and address > ? "
276 " and UNIX_TIMESTAMP(expire) - IF"
277 "(valid_lifetime = 4294967295, 0, valid_lifetime)"
278 " <= ? "
279 "ORDER BY address "
280 "LIMIT ?"},
282 "SELECT address, duid, valid_lifetime, "
283 "expire, subnet_id, pref_lifetime, "
284 "lease_type, iaid, prefix_len, "
285 "fqdn_fwd, fqdn_rev, hostname, "
286 "hwaddr, hwtype, hwaddr_source, "
287 "state, user_context, pool_id "
288 "FROM lease6"},
290 "SELECT address, duid, valid_lifetime, "
291 "expire, subnet_id, pref_lifetime, "
292 "lease_type, iaid, prefix_len, "
293 "fqdn_fwd, fqdn_rev, hostname, "
294 "hwaddr, hwtype, hwaddr_source, "
295 "state, user_context, pool_id "
296 "FROM lease6 "
297 "WHERE address = ? AND lease_type = ?"},
299 "SELECT address, duid, valid_lifetime, "
300 "expire, subnet_id, pref_lifetime, "
301 "lease_type, iaid, prefix_len, "
302 "fqdn_fwd, fqdn_rev, hostname, "
303 "hwaddr, hwtype, hwaddr_source, "
304 "state, user_context, pool_id "
305 "FROM lease6 "
306 "WHERE duid = ? AND iaid = ? AND lease_type = ?"},
308 "SELECT address, duid, valid_lifetime, "
309 "expire, subnet_id, pref_lifetime, "
310 "lease_type, iaid, prefix_len, "
311 "fqdn_fwd, fqdn_rev, hostname, "
312 "hwaddr, hwtype, hwaddr_source, "
313 "state, user_context, pool_id "
314 "FROM lease6 "
315 "WHERE duid = ? AND iaid = ? AND subnet_id = ? "
316 "AND lease_type = ?"},
318 "SELECT address, duid, valid_lifetime, "
319 "expire, subnet_id, pref_lifetime, "
320 "lease_type, iaid, prefix_len, "
321 "fqdn_fwd, fqdn_rev, hostname, "
322 "hwaddr, hwtype, hwaddr_source, "
323 "state, user_context, pool_id "
324 "FROM lease6 "
325 "WHERE address > ? "
326 "ORDER BY address "
327 "LIMIT ?"},
329 "SELECT address, duid, valid_lifetime, "
330 "expire, subnet_id, pref_lifetime, "
331 "lease_type, iaid, prefix_len, "
332 "fqdn_fwd, fqdn_rev, hostname, "
333 "hwaddr, hwtype, hwaddr_source, "
334 "state, user_context, pool_id "
335 "FROM lease6 "
336 "WHERE address > ? AND user_context IS NOT NULL "
337 "ORDER BY address "
338 "LIMIT ?"},
340 "SELECT address, duid, valid_lifetime, "
341 "expire, subnet_id, pref_lifetime, "
342 "lease_type, iaid, prefix_len, "
343 "fqdn_fwd, fqdn_rev, hostname, "
344 "hwaddr, hwtype, hwaddr_source, "
345 "state, user_context, pool_id "
346 "FROM lease6 "
347 "WHERE subnet_id = ?"},
349 "SELECT address, duid, valid_lifetime, "
350 "expire, subnet_id, pref_lifetime, "
351 "lease_type, iaid, prefix_len, "
352 "fqdn_fwd, fqdn_rev, hostname, "
353 "hwaddr, hwtype, hwaddr_source, "
354 "state, user_context, pool_id "
355 "FROM lease6 "
356 "WHERE subnet_id = ? AND address > ? "
357 "ORDER BY address "
358 "LIMIT ?"},
360 "SELECT address, duid, valid_lifetime, "
361 "expire, subnet_id, pref_lifetime, "
362 "lease_type, iaid, prefix_len, "
363 "fqdn_fwd, fqdn_rev, hostname, "
364 "hwaddr, hwtype, hwaddr_source, "
365 "state, user_context, pool_id "
366 "FROM lease6 "
367 "WHERE duid = ?"},
369 "SELECT address, duid, valid_lifetime, "
370 "expire, subnet_id, pref_lifetime, "
371 "lease_type, iaid, prefix_len, "
372 "fqdn_fwd, fqdn_rev, hostname, "
373 "hwaddr, hwtype, hwaddr_source, "
374 "state, user_context, pool_id "
375 "FROM lease6 "
376 "WHERE hostname = ?"},
378 "SELECT address, duid, valid_lifetime, "
379 "expire, subnet_id, pref_lifetime, "
380 "lease_type, iaid, prefix_len, "
381 "fqdn_fwd, fqdn_rev, hostname, "
382 "hwaddr, hwtype, hwaddr_source, "
383 "state, user_context, pool_id "
384 "FROM lease6 "
385 "WHERE state != ? "
386 "AND valid_lifetime != 4294967295 "
387 "AND expire < ? "
388 "ORDER BY expire ASC "
389 "LIMIT ?"},
391 "INSERT INTO lease4(address, hwaddr, client_id, "
392 "valid_lifetime, expire, subnet_id, "
393 "fqdn_fwd, fqdn_rev, hostname, "
394 "state, user_context, relay_id, remote_id, pool_id) "
395 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"},
397 "INSERT INTO lease6(address, duid, valid_lifetime, "
398 "expire, subnet_id, pref_lifetime, "
399 "lease_type, iaid, prefix_len, "
400 "fqdn_fwd, fqdn_rev, hostname, "
401 "hwaddr, hwtype, hwaddr_source, "
402 "state, user_context, pool_id) "
403 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"},
405 "UPDATE lease4 SET address = ?, hwaddr = ?, "
406 "client_id = ?, valid_lifetime = ?, expire = ?, "
407 "subnet_id = ?, fqdn_fwd = ?, fqdn_rev = ?, "
408 "hostname = ?, "
409 "state = ?, user_context = ?, "
410 "relay_id = ?, remote_id = ?, pool_id = ? "
411 "WHERE address = ? AND expire = ?"},
413 "UPDATE lease6 SET address = ?, duid = ?, "
414 "valid_lifetime = ?, expire = ?, subnet_id = ?, "
415 "pref_lifetime = ?, lease_type = ?, iaid = ?, "
416 "prefix_len = ?, fqdn_fwd = ?, fqdn_rev = ?, "
417 "hostname = ?, hwaddr = ?, hwtype = ?, hwaddr_source = ?, "
418 "state = ?, user_context = ?, pool_id = ? "
419 "WHERE address = ? AND expire = ?"},
421 "SELECT subnet_id, state, leases as state_count "
422 "FROM lease4_stat ORDER BY subnet_id, state"},
424 "SELECT subnet_id, state, leases as state_count "
425 "FROM lease4_stat "
426 "WHERE subnet_id = ? "
427 "ORDER BY state"},
429 "SELECT subnet_id, state, leases as state_count "
430 "FROM lease4_stat "
431 "WHERE subnet_id >= ? and subnet_id <= ? "
432 "ORDER BY subnet_id, state"},
434 "SELECT subnet_id, pool_id, state, leases as state_count "
435 "FROM lease4_pool_stat ORDER BY subnet_id, pool_id, state"},
437 "SELECT subnet_id, lease_type, state, leases as state_count "
438 "FROM lease6_stat ORDER BY subnet_id, lease_type, state"},
440 "SELECT subnet_id, lease_type, state, leases as state_count "
441 "FROM lease6_stat "
442 "WHERE subnet_id = ? "
443 "ORDER BY lease_type, state"},
445 "SELECT subnet_id, lease_type, state, leases as state_count "
446 "FROM lease6_stat "
447 "WHERE subnet_id >= ? and subnet_id <= ? "
448 "ORDER BY subnet_id, lease_type, state"},
450 "SELECT subnet_id, pool_id, lease_type, state, leases as state_count "
451 "FROM lease6_pool_stat ORDER BY subnet_id, pool_id, lease_type, state"},
453 "SELECT checkLease4Limits(?)"},
455 "SELECT checkLease6Limits(?)"},
457 "SELECT isJsonSupported()"},
459 "SELECT leases "
460 "FROM lease4_stat_by_client_class "
461 "WHERE client_class = ?"},
463 "SELECT leases "
464 "FROM lease6_stat_by_client_class "
465 "WHERE client_class = ? AND lease_type = ?"},
467 "DELETE FROM lease6_relay_id"},
469 "DELETE FROM lease6_remote_id"},
471 "DELETE FROM lease6_relay_id WHERE lease_addr = ?"},
473 "DELETE FROM lease6_remote_id WHERE lease_addr = ?"},
475 "INSERT INTO lease6_relay_id(relay_id, lease_addr) "
476 "VALUES (?, ?)"},
478 "INSERT INTO lease6_remote_id(remote_id, lease_addr) "
479 "VALUES (?, ?)"},
481 "SELECT l.address, l.duid, l.valid_lifetime, "
482 "l.expire, l.subnet_id, l.pref_lifetime, "
483 "l.lease_type, l.iaid, l.prefix_len, "
484 "l.fqdn_fwd, l.fqdn_rev, l.hostname, "
485 "l.hwaddr, l.hwtype, l.hwaddr_source, "
486 "l.state, l.user_context, l.pool_id "
487 "FROM lease6 AS l "
488 "INNER JOIN lease6_relay_id AS r "
489 " ON l.address = r.lease_addr "
490 " WHERE r.relay_id = ? AND r.lease_addr > ? "
491 "GROUP BY l.address "
492 "ORDER BY l.address "
493 "LIMIT ?"},
495 "SELECT l.address, l.duid, l.valid_lifetime, "
496 "l.expire, l.subnet_id, l.pref_lifetime, "
497 "l.lease_type, l.iaid, l.prefix_len, "
498 "l.fqdn_fwd, l.fqdn_rev, l.hostname, "
499 "l.hwaddr, l.hwtype, l.hwaddr_source, "
500 "l.state, l.user_context, l.pool_id "
501 "FROM lease6 AS l "
502 "INNER JOIN lease6_remote_id AS r "
503 " ON l.address = r.lease_addr "
504 " WHERE r.remote_id = ? AND r.lease_addr > ? "
505 "GROUP BY l.address "
506 "ORDER BY l.address "
507 "LIMIT ?"},
509 "SELECT COUNT(*) FROM lease6_relay_id"},
511 "SELECT COUNT(*) FROM lease6_remote_id"},
512} }; // tagged_statements
513
514} // namespace
515
516namespace isc {
517namespace dhcp {
518
525
527public:
528
540 static void setErrorIndicators(MYSQL_BIND* bind, my_bool* error,
541 size_t count) {
542 for (size_t i = 0; i < count; ++i) {
543 error[i] = MLM_FALSE;
544 bind[i].error = &error[i];
545 }
546 }
547
561 static std::string getColumnsInError(my_bool* error, std::string* names,
562 size_t count) {
563 std::string result = "";
564
565 // Accumulate list of column names
566 for (size_t i = 0; i < count; ++i) {
567 if (error[i] == MLM_TRUE) {
568 if (!result.empty()) {
569 result += ", ";
570 }
571 result += names[i];
572 }
573 }
574
575 if (result.empty()) {
576 result = "(None)";
577 }
578
579 return (result);
580 }
581};
582
595
600
601 static const size_t ADDRESS_COL = 0;
602 static const size_t HWADDR_COL = 1;
603 static const size_t CLIENT_ID_COL = 2;
604 static const size_t VALID_LIFETIME_COL = 3;
605 static const size_t EXPIRE_COL = 4;
606 static const size_t SUBNET_ID_COL = 5;
607 static const size_t FQDN_FWD_COL = 6;
608 static const size_t FQDN_REV_COL = 7;
609 static const size_t HOSTNAME_COL = 8;
610 static const size_t STATE_COL = 9;
611 static const size_t USER_CONTEXT_COL = 10;
612 static const size_t RELAY_ID_COL = 11;
613 static const size_t REMOTE_ID_COL = 12;
614 static const size_t POOL_ID_COL = 13;
616
617 static const size_t LEASE_COLUMNS = 14;
618
619public:
620
625 MySqlLease4Exchange() : addr4_(0), hwaddr_length_(0), hwaddr_null_(MLM_FALSE),
626 client_id_length_(0), client_id_null_(MLM_FALSE),
627 subnet_id_(0), pool_id_(0), valid_lifetime_(0),
628 fqdn_fwd_(false), fqdn_rev_(false), hostname_length_(0),
629 state_(0), user_context_length_(0),
630 user_context_null_(MLM_FALSE), relay_id_length_(0),
631 relay_id_null_(MLM_FALSE), remote_id_length_(0),
632 remote_id_null_(MLM_FALSE) {
633 memset(hwaddr_buffer_, 0, sizeof(hwaddr_buffer_));
634 memset(client_id_buffer_, 0, sizeof(client_id_buffer_));
635 memset(hostname_buffer_, 0, sizeof(hostname_buffer_));
636 memset(user_context_, 0, sizeof(user_context_));
637 memset(relay_id_buffer_, 0, sizeof(relay_id_buffer_));
638 memset(remote_id_buffer_, 0, sizeof(remote_id_buffer_));
639 std::fill(&error_[0], &error_[LEASE_COLUMNS], MLM_FALSE);
640
641 // Set the column names (for error messages)
642 columns_[ADDRESS_COL] = "address";
643 columns_[HWADDR_COL] = "hwaddr";
644 columns_[CLIENT_ID_COL] = "client_id";
645 columns_[VALID_LIFETIME_COL] = "valid_lifetime";
646 columns_[EXPIRE_COL] = "expire";
647 columns_[SUBNET_ID_COL] = "subnet_id";
648 columns_[FQDN_FWD_COL] = "fqdn_fwd";
649 columns_[FQDN_REV_COL] = "fqdn_rev";
650 columns_[HOSTNAME_COL] = "hostname";
651 columns_[STATE_COL] = "state";
652 columns_[USER_CONTEXT_COL] = "user_context";
653 columns_[RELAY_ID_COL] = "relay_id";
654 columns_[REMOTE_ID_COL] = "remote_id";
655 columns_[POOL_ID_COL] = "pool_id";
656 BOOST_STATIC_ASSERT(13 < LEASE_COLUMNS);
657 }
658
668 std::vector<MYSQL_BIND> createBindForSend(const Lease4Ptr& lease) {
669
670 // Store lease object to ensure it remains valid.
671 lease_ = lease;
672
673 // Initialize prior to constructing the array of MYSQL_BIND structures.
674 // It sets all fields, including is_null, to zero, so we need to set
675 // is_null only if it should be true. This gives up minor performance
676 // benefit while being safe approach. For improved readability, the
677 // code that explicitly sets is_null is there, but is commented out.
678 memset(bind_, 0, sizeof(bind_));
679
680 // Set up the structures for the various components of the lease4
681 // structure.
682
683 try {
684 // address: uint32_t
685 // The address in the Lease structure is an IOAddress object. Convert
686 // this to an integer for storage.
687 addr4_ = lease_->addr_.toUint32();
688 bind_[0].buffer_type = MYSQL_TYPE_LONG;
689 bind_[0].buffer = reinterpret_cast<char*>(&addr4_);
690 bind_[0].is_unsigned = MLM_TRUE;
691 // bind_[0].is_null = &MLM_FALSE; // commented out for performance
692 // reasons, see memset() above
693
694 // hwaddr: varbinary(20) - hardware/MAC address
695 HWAddrPtr hwaddr = lease_->hwaddr_;
696 if (hwaddr) {
697 hwaddr_ = hwaddr->hwaddr_;
698 hwaddr_length_ = hwaddr->hwaddr_.size();
699
700 // Make sure that the buffer has at least length of 1, even if
701 // empty HW address is passed. This is required by some of the
702 // MySQL connectors that the buffer is set to non-null value.
703 // Otherwise, null value would be inserted into the database,
704 // rather than empty string.
705 if (hwaddr_.empty()) {
706 hwaddr_.resize(1);
707 }
708
709 bind_[1].buffer_type = MYSQL_TYPE_BLOB;
710 bind_[1].buffer = reinterpret_cast<char*>(&(hwaddr_[0]));
711 bind_[1].buffer_length = hwaddr_length_;
712 bind_[1].length = &hwaddr_length_;
713 } else {
714 bind_[1].buffer_type = MYSQL_TYPE_NULL;
715 // According to http://dev.mysql.com/doc/refman/5.5/en/
716 // c-api-prepared-statement-data-structures.html, the other
717 // fields doesn't matter if type is set to MYSQL_TYPE_NULL,
718 // but let's set them to some sane values in case earlier versions
719 // didn't have that assumption.
720 hwaddr_null_ = MLM_TRUE;
721 bind_[1].buffer = NULL;
722 bind_[1].is_null = &hwaddr_null_;
723 }
724
725 // client_id: varbinary(255)
726 if (lease_->client_id_) {
727 client_id_ = lease_->client_id_->getClientId();
728 client_id_length_ = client_id_.size();
729
730 // Make sure that the buffer has at least length of 1, even if
731 // empty client id is passed. This is required by some of the
732 // MySQL connectors that the buffer is set to non-null value.
733 // Otherwise, null value would be inserted into the database,
734 // rather than empty string.
735 if (client_id_.empty()) {
736 client_id_.resize(1);
737 }
738
739 bind_[2].buffer_type = MYSQL_TYPE_BLOB;
740 bind_[2].buffer = reinterpret_cast<char*>(&client_id_[0]);
741 bind_[2].buffer_length = client_id_length_;
742 bind_[2].length = &client_id_length_;
743 // bind_[2].is_null = &MLM_FALSE; // commented out for performance
744 // reasons, see memset() above
745 } else {
746 bind_[2].buffer_type = MYSQL_TYPE_NULL;
747 // According to http://dev.mysql.com/doc/refman/5.5/en/
748 // c-api-prepared-statement-data-structures.html, the other
749 // fields doesn't matter if type is set to MYSQL_TYPE_NULL,
750 // but let's set them to some sane values in case earlier versions
751 // didn't have that assumption.
752 client_id_null_ = MLM_TRUE;
753 bind_[2].buffer = NULL;
754 bind_[2].is_null = &client_id_null_;
755 }
756
757 // valid lifetime: unsigned int
758 bind_[3].buffer_type = MYSQL_TYPE_LONG;
759 bind_[3].buffer = reinterpret_cast<char*>(&lease_->valid_lft_);
760 bind_[3].is_unsigned = MLM_TRUE;
761 // bind_[3].is_null = &MLM_FALSE; // commented out for performance
762 // reasons, see memset() above
763
764 // expire: timestamp
765 // The lease structure holds the client last transmission time (cltt_)
766 // For convenience for external tools, this is converted to lease
767 // expiry time (expire). The relationship is given by:
768 //
769 // expire = cltt_ + valid_lft_
770 // Avoid overflow with infinite valid lifetime by using
771 // expire = cltt_ when valid_lft_ = 0xffffffff
772 uint32_t valid_lft = lease_->valid_lft_;
773 if (valid_lft == Lease::INFINITY_LFT) {
774 valid_lft = 0;
775 }
776 MySqlConnection::convertToDatabaseTime(lease_->cltt_, valid_lft,
777 expire_);
778 bind_[4].buffer_type = MYSQL_TYPE_TIMESTAMP;
779 bind_[4].buffer = reinterpret_cast<char*>(&expire_);
780 bind_[4].buffer_length = sizeof(expire_);
781 // bind_[4].is_null = &MLM_FALSE; // commented out for performance
782 // reasons, see memset() above
783
784 // subnet_id: unsigned int
785 // Can use lease_->subnet_id_ directly as it is of type uint32_t.
786 bind_[5].buffer_type = MYSQL_TYPE_LONG;
787 bind_[5].buffer = reinterpret_cast<char*>(&lease_->subnet_id_);
788 bind_[5].is_unsigned = MLM_TRUE;
789 // bind_[5].is_null = &MLM_FALSE; // commented out for performance
790 // reasons, see memset() above
791
792 // fqdn_fwd: boolean
793 bind_[6].buffer_type = MYSQL_TYPE_TINY;
794 bind_[6].buffer = reinterpret_cast<char*>(&lease_->fqdn_fwd_);
795 bind_[6].is_unsigned = MLM_TRUE;
796 // bind_[6].is_null = &MLM_FALSE; // commented out for performance
797 // reasons, see memset() above
798
799 // fqdn_rev: boolean
800 bind_[7].buffer_type = MYSQL_TYPE_TINY;
801 bind_[7].buffer = reinterpret_cast<char*>(&lease_->fqdn_rev_);
802 bind_[7].is_unsigned = MLM_TRUE;
803 // bind_[7].is_null = &MLM_FALSE; // commented out for performance
804 // reasons, see memset() above
805
806 // hostname: varchar(255)
807 // Note that previously we used MYSQL_TYPE_VARCHAR instead of
808 // MYSQL_TYPE_STRING. However, that caused 'buffer type not supported'
809 // errors on some systems running MariaDB.
810 bind_[8].buffer_type = MYSQL_TYPE_STRING;
811 bind_[8].buffer = const_cast<char*>(lease_->hostname_.c_str());
812 bind_[8].buffer_length = lease_->hostname_.length();
813 // bind_[8].is_null = &MLM_FALSE; // commented out for performance
814 // reasons, see memset() above
815
816 // state: uint32_t
817 bind_[9].buffer_type = MYSQL_TYPE_LONG;
818 bind_[9].buffer = reinterpret_cast<char*>(&lease_->state_);
819 bind_[9].is_unsigned = MLM_TRUE;
820 // bind_[9].is_null = &MLM_FALSE; // commented out for performance
821 // reasons, see memset() above
822
823 // user_context: text
824 ConstElementPtr ctx = lease->getContext();
825 if (ctx) {
826 bind_[10].buffer_type = MYSQL_TYPE_STRING;
827 std::string ctx_txt = ctx->str();
828 strncpy(user_context_, ctx_txt.c_str(), USER_CONTEXT_MAX_LEN - 1);
829 bind_[10].buffer = user_context_;
830 bind_[10].buffer_length = ctx_txt.length();
831 // bind_[10].is_null = &MLM_FALSE; // commented out for performance
832 // reasons, see memset() above
833 } else {
834 bind_[10].buffer_type = MYSQL_TYPE_NULL;
835 }
836
837 // relay_id: varbinary(255)
838 relay_id_ = lease_->relay_id_;
839 if (!relay_id_.empty()) {
840 bind_[11].buffer_type = MYSQL_TYPE_BLOB;
841 bind_[11].buffer = reinterpret_cast<char*>(&relay_id_[0]);
842 relay_id_length_ = relay_id_.size();
843 bind_[11].buffer_length = relay_id_length_;
844 bind_[11].length = &relay_id_length_;
845 } else {
846 bind_[11].buffer_type = MYSQL_TYPE_NULL;
847 relay_id_null_ = MLM_TRUE;
848 bind_[11].buffer = NULL;
849 bind_[11].is_null = &relay_id_null_;
850 }
851
852 // remote_id: varbinary(255)
853 remote_id_ = lease_->remote_id_;
854 if (!remote_id_.empty()) {
855 bind_[12].buffer_type = MYSQL_TYPE_BLOB;
856 bind_[12].buffer = reinterpret_cast<char*>(&remote_id_[0]);
857 remote_id_length_ = remote_id_.size();
858 bind_[12].buffer_length = remote_id_length_;
859 bind_[12].length = &remote_id_length_;
860 } else {
861 bind_[12].buffer_type = MYSQL_TYPE_NULL;
862 remote_id_null_ = MLM_TRUE;
863 bind_[12].buffer = NULL;
864 bind_[12].is_null = &remote_id_null_;
865 }
866
867 // pool_id: unsigned int
868 // Can use lease_->pool_id_ directly as it is of type uint32_t.
869 bind_[13].buffer_type = MYSQL_TYPE_LONG;
870 bind_[13].buffer = reinterpret_cast<char*>(&lease_->pool_id_);
871 bind_[13].is_unsigned = MLM_TRUE;
872 // bind_[13].is_null = &MLM_FALSE; // commented out for performance
873 // reasons, see memset() above
874
875 // Add the error flags
876 setErrorIndicators(bind_, error_, LEASE_COLUMNS);
877
878 // .. and check that we have the numbers correct at compile time.
879 BOOST_STATIC_ASSERT(13 < LEASE_COLUMNS);
880
881 } catch (const std::exception& ex) {
883 "Could not create bind array from Lease4: "
884 << lease_->addr_.toText() << ", reason: " << ex.what());
885 }
886
887 // Add the data to the vector. Note the end element is one after the
888 // end of the array.
889 return (std::vector<MYSQL_BIND>(&bind_[0], &bind_[LEASE_COLUMNS]));
890 }
891
897 std::vector<MYSQL_BIND> createBindForReceive() {
898
899 // Initialize MYSQL_BIND array.
900 // It sets all fields, including is_null, to zero, so we need to set
901 // is_null only if it should be true. This gives up minor performance
902 // benefit while being safe approach. For improved readability, the
903 // code that explicitly sets is_null is there, but is commented out.
904 memset(bind_, 0, sizeof(bind_));
905
906 // address: uint32_t
907 bind_[0].buffer_type = MYSQL_TYPE_LONG;
908 bind_[0].buffer = reinterpret_cast<char*>(&addr4_);
909 bind_[0].is_unsigned = MLM_TRUE;
910 // bind_[0].is_null = &MLM_FALSE; // commented out for performance
911 // reasons, see memset() above
912
913 // hwaddr: varbinary(20)
914 hwaddr_null_ = MLM_FALSE;
915 hwaddr_length_ = sizeof(hwaddr_buffer_);
916 bind_[1].buffer_type = MYSQL_TYPE_BLOB;
917 bind_[1].buffer = reinterpret_cast<char*>(hwaddr_buffer_);
918 bind_[1].buffer_length = hwaddr_length_;
919 bind_[1].length = &hwaddr_length_;
920 bind_[1].is_null = &hwaddr_null_;
921
922 // client_id: varbinary(255)
923 client_id_length_ = sizeof(client_id_buffer_);
924 bind_[2].buffer_type = MYSQL_TYPE_BLOB;
925 bind_[2].buffer = reinterpret_cast<char*>(client_id_buffer_);
926 bind_[2].buffer_length = client_id_length_;
927 bind_[2].length = &client_id_length_;
928 bind_[2].is_null = &client_id_null_;
929 // bind_[2].is_null = &MLM_FALSE; // commented out for performance
930 // reasons, see memset() above
931
932 // valid lifetime: unsigned int
933 bind_[3].buffer_type = MYSQL_TYPE_LONG;
934 bind_[3].buffer = reinterpret_cast<char*>(&valid_lifetime_);
935 bind_[3].is_unsigned = MLM_TRUE;
936 // bind_[3].is_null = &MLM_FALSE; // commented out for performance
937 // reasons, see memset() above
938
939 // expire: timestamp
940 bind_[4].buffer_type = MYSQL_TYPE_TIMESTAMP;
941 bind_[4].buffer = reinterpret_cast<char*>(&expire_);
942 bind_[4].buffer_length = sizeof(expire_);
943 // bind_[4].is_null = &MLM_FALSE; // commented out for performance
944 // reasons, see memset() above
945
946 // subnet_id: unsigned int
947 bind_[5].buffer_type = MYSQL_TYPE_LONG;
948 bind_[5].buffer = reinterpret_cast<char*>(&subnet_id_);
949 bind_[5].is_unsigned = MLM_TRUE;
950 // bind_[5].is_null = &MLM_FALSE; // commented out for performance
951 // reasons, see memset() above
952
953 // fqdn_fwd: boolean
954 bind_[6].buffer_type = MYSQL_TYPE_TINY;
955 bind_[6].buffer = reinterpret_cast<char*>(&fqdn_fwd_);
956 bind_[6].is_unsigned = MLM_TRUE;
957 // bind_[6].is_null = &MLM_FALSE; // commented out for performance
958 // reasons, see memset() above
959
960 // fqdn_rev: boolean
961 bind_[7].buffer_type = MYSQL_TYPE_TINY;
962 bind_[7].buffer = reinterpret_cast<char*>(&fqdn_rev_);
963 bind_[7].is_unsigned = MLM_TRUE;
964 // bind_[7].is_null = &MLM_FALSE; // commented out for performance
965 // reasons, see memset() above
966
967 // hostname: varchar(255)
968 // Note that previously we used MYSQL_TYPE_VARCHAR instead of
969 // MYSQL_TYPE_STRING. However, that caused 'buffer type not supported'
970 // errors on some systems running MariaDB.
971 hostname_length_ = sizeof(hostname_buffer_);
972 bind_[8].buffer_type = MYSQL_TYPE_STRING;
973 bind_[8].buffer = reinterpret_cast<char*>(hostname_buffer_);
974 bind_[8].buffer_length = hostname_length_;
975 bind_[8].length = &hostname_length_;
976 // bind_[8].is_null = &MLM_FALSE; // commented out for performance
977 // reasons, see memset() above
978
979 // state: uint32_t
980 bind_[9].buffer_type = MYSQL_TYPE_LONG;
981 bind_[9].buffer = reinterpret_cast<char*>(&state_);
982 bind_[9].is_unsigned = MLM_TRUE;
983 // bind_[9].is_null = &MLM_FALSE; // commented out for performance
984 // reasons, see memset() above
985
986 // user_context: text
987 user_context_null_ = MLM_FALSE;
988 user_context_length_ = sizeof(user_context_);
989 bind_[10].buffer_type = MYSQL_TYPE_STRING;
990 bind_[10].buffer = reinterpret_cast<char*>(user_context_);
991 bind_[10].buffer_length = user_context_length_;
992 bind_[10].length = &user_context_length_;
993 bind_[10].is_null = &user_context_null_;
994
995 // relay_id: varbinary(255)
996 relay_id_length_ = sizeof(relay_id_buffer_);
997 bind_[11].buffer_type = MYSQL_TYPE_BLOB;
998 bind_[11].buffer = reinterpret_cast<char*>(relay_id_buffer_);
999 bind_[11].buffer_length = relay_id_length_;
1000 bind_[11].length = &relay_id_length_;
1001 bind_[11].is_null = &relay_id_null_;
1002
1003 // remote_id: varbinary(255)
1004 remote_id_length_ = sizeof(remote_id_buffer_);
1005 bind_[12].buffer_type = MYSQL_TYPE_BLOB;
1006 bind_[12].buffer = reinterpret_cast<char*>(remote_id_buffer_);
1007 bind_[12].buffer_length = remote_id_length_;
1008 bind_[12].length = &remote_id_length_;
1009 bind_[12].is_null = &remote_id_null_;
1010
1011 // pool_id: unsigned int
1012 bind_[13].buffer_type = MYSQL_TYPE_LONG;
1013 bind_[13].buffer = reinterpret_cast<char*>(&pool_id_);
1014 bind_[13].is_unsigned = MLM_TRUE;
1015 // bind_[13].is_null = &MLM_FALSE; // commented out for performance
1016 // reasons, see memset() above
1017
1018 // Add the error flags
1019 setErrorIndicators(bind_, error_, LEASE_COLUMNS);
1020
1021 // .. and check that we have the numbers correct at compile time.
1022 BOOST_STATIC_ASSERT(13 < LEASE_COLUMNS);
1023
1024 // Add the data to the vector. Note the end element is one after the
1025 // end of the array.
1026 return (std::vector<MYSQL_BIND>(&bind_[0], &bind_[LEASE_COLUMNS]));
1027 }
1028
1038 // Convert times received from the database to times for the lease
1039 // structure. See the expire code of createBindForSend for
1040 // the infinite valid lifetime special case.
1041 time_t cltt = 0;
1042 // Recover from overflow
1043 uint32_t valid_lft = valid_lifetime_;
1044 if (valid_lft == Lease::INFINITY_LFT) {
1045 valid_lft = 0;
1046 }
1047 MySqlConnection::convertFromDatabaseTime(expire_, valid_lft, cltt);
1048
1049 if (client_id_null_ == MLM_TRUE) {
1050 // There's no client-id, so we pass client-id_length_ set to 0
1051 client_id_length_ = 0;
1052 }
1053
1054 // Hostname is passed to Lease4 as a string object. We have to create
1055 // it from the buffer holding hostname and the buffer length.
1056 std::string hostname(hostname_buffer_,
1057 hostname_buffer_ + hostname_length_);
1058
1059 // Set hardware address if it was set
1060 HWAddrPtr hwaddr;
1061 if (hwaddr_null_ == MLM_FALSE) {
1062 hwaddr.reset(new HWAddr(hwaddr_buffer_, hwaddr_length_, HTYPE_ETHER));
1063 }
1064
1065 // Convert user_context to string as well.
1066 std::string user_context;
1067 if (user_context_null_ == MLM_FALSE) {
1068 user_context_[user_context_length_] = '\0';
1069 user_context.assign(user_context_);
1070 }
1071
1072 // Set the user context if there is one.
1073 ConstElementPtr ctx;
1074 if (!user_context.empty()) {
1075 ctx = Element::fromJSON(user_context);
1076 if (!ctx || (ctx->getType() != Element::map)) {
1077 isc_throw(BadValue, "user context '" << user_context
1078 << "' is not a JSON map");
1079 }
1080 }
1081
1082 Lease4Ptr lease(boost::make_shared<Lease4>(addr4_, hwaddr,
1083 client_id_buffer_,
1084 client_id_length_,
1085 valid_lifetime_, cltt,
1086 subnet_id_, fqdn_fwd_,
1087 fqdn_rev_, hostname));
1088
1089 // Set state.
1090 lease->state_ = state_;
1091
1092 if (ctx) {
1093 lease->setContext(ctx);
1094 }
1095
1096 // Set relay id if it was set.
1097 if (relay_id_null_ == MLM_FALSE) {
1098 lease->relay_id_.assign(relay_id_buffer_,
1099 relay_id_buffer_ + relay_id_length_);
1100 }
1101
1102 // Set remote id if it was set.
1103 if (remote_id_null_ == MLM_FALSE) {
1104 lease->remote_id_.assign(remote_id_buffer_,
1105 remote_id_buffer_ + remote_id_length_);
1106 }
1107
1108 // Set pool ID
1109 lease->pool_id_ = pool_id_;
1110
1111 return (lease);
1112 }
1113
1124 std::string getErrorColumns() {
1125 return (getColumnsInError(error_, columns_, LEASE_COLUMNS));
1126 }
1127
1128private:
1129
1130 // Note: All array lengths are equal to the corresponding variable in the
1131 // schema.
1132 // Note: Arrays are declared fixed length for speed of creation
1133 uint32_t addr4_;
1134 MYSQL_BIND bind_[LEASE_COLUMNS];
1135 std::string columns_[LEASE_COLUMNS];
1136 my_bool error_[LEASE_COLUMNS];
1137 Lease4Ptr lease_;
1138 std::vector<uint8_t> hwaddr_;
1139 uint8_t hwaddr_buffer_[HWAddr::MAX_HWADDR_LEN];
1140 unsigned long hwaddr_length_;
1141 my_bool hwaddr_null_;
1142 std::vector<uint8_t> client_id_;
1143 uint8_t client_id_buffer_[ClientId::MAX_CLIENT_ID_LEN];
1144 unsigned long client_id_length_;
1145 my_bool client_id_null_;
1146 MYSQL_TIME expire_;
1147 uint32_t subnet_id_;
1148 uint32_t pool_id_;
1149 uint32_t valid_lifetime_;
1150 my_bool fqdn_fwd_;
1151 my_bool fqdn_rev_;
1152 char hostname_buffer_[HOSTNAME_MAX_LEN];
1153 unsigned long hostname_length_;
1154 uint32_t state_;
1155 char user_context_[USER_CONTEXT_MAX_LEN];
1156 unsigned long user_context_length_;
1157 my_bool user_context_null_;
1158 std::vector<uint8_t> relay_id_;
1159 uint8_t relay_id_buffer_[ClientId::MAX_CLIENT_ID_LEN];
1160 unsigned long relay_id_length_;
1161 my_bool relay_id_null_;
1162 std::vector<uint8_t> remote_id_;
1163 uint8_t remote_id_buffer_[ClientId::MAX_CLIENT_ID_LEN];
1164 unsigned long remote_id_length_;
1165 my_bool remote_id_null_;
1166};
1167
1180
1186
1187 static const size_t ADDRESS_COL = 0;
1188 static const size_t DUID_COL = 1;
1189 static const size_t VALID_LIFETIME_COL = 2;
1190 static const size_t EXPIRE_COL = 3;
1191 static const size_t SUBNET_ID_COL = 4;
1192 static const size_t PREF_LIFETIME_COL = 5;
1193 static const size_t LEASE_TYPE_COL = 6;
1194 static const size_t IAID_COL = 7;
1195 static const size_t PREFIX_LEN_COL = 8;
1196 static const size_t FQDN_FWD_COL = 9;
1197 static const size_t FQDN_REV_COL = 10;
1198 static const size_t HOSTNAME_COL = 11;
1199 static const size_t HWADDR_COL = 12;
1200 static const size_t HWTYPE_COL = 13;
1201 static const size_t HWADDR_SOURCE_COL = 14;
1202 static const size_t STATE_COL = 15;
1203 static const size_t USER_CONTEXT_COL = 16;
1204 static const size_t POOL_ID_COL = 17;
1206
1207 static const size_t LEASE_COLUMNS = 18;
1208
1209public:
1210
1215 MySqlLease6Exchange() : addr6_length_(16), hwaddr_length_(0),
1216 hwaddr_null_(MLM_FALSE), duid_length_(0),
1217 iaid_(0), lease_type_(0), prefix_len_(0),
1218 pref_lifetime_(0), subnet_id_(0), pool_id_(0),
1219 valid_lifetime_(0), fqdn_fwd_(false), fqdn_rev_(false),
1220 hostname_length_(0), hwtype_(0), hwaddr_source_(0),
1221 state_(0), user_context_length_(0),
1222 user_context_null_(MLM_FALSE) {
1223 memset(addr6_buffer_, 0, sizeof(addr6_buffer_));
1224 memset(duid_buffer_, 0, sizeof(duid_buffer_));
1225 memset(hostname_buffer_, 0, sizeof(hostname_buffer_));
1226 memset(hwaddr_buffer_, 0, sizeof(hwaddr_buffer_));
1227 memset(user_context_, 0, sizeof(user_context_));
1228 std::fill(&error_[0], &error_[LEASE_COLUMNS], MLM_FALSE);
1229
1230 // Set the column names (for error messages)
1231 columns_[ADDRESS_COL] = "address";
1232 columns_[DUID_COL] = "duid";
1233 columns_[VALID_LIFETIME_COL] = "valid_lifetime";
1234 columns_[EXPIRE_COL] = "expire";
1235 columns_[SUBNET_ID_COL] = "subnet_id";
1236 columns_[PREF_LIFETIME_COL] = "pref_lifetime";
1237 columns_[LEASE_TYPE_COL] = "lease_type";
1238 columns_[IAID_COL] = "iaid";
1239 columns_[PREFIX_LEN_COL] = "prefix_len";
1240 columns_[FQDN_FWD_COL] = "fqdn_fwd";
1241 columns_[FQDN_REV_COL] = "fqdn_rev";
1242 columns_[HOSTNAME_COL] = "hostname";
1243 columns_[HWADDR_COL] = "hwaddr";
1244 columns_[HWTYPE_COL] = "hwtype";
1245 columns_[HWADDR_SOURCE_COL] = "hwaddr_source";
1246 columns_[STATE_COL] = "state";
1247 columns_[USER_CONTEXT_COL] = "user_context";
1248 columns_[POOL_ID_COL] = "pool_id";
1249 BOOST_STATIC_ASSERT(17 < LEASE_COLUMNS);
1250 }
1251
1260 std::vector<MYSQL_BIND> createBindForSend(const Lease6Ptr& lease) {
1261 // Store lease object to ensure it remains valid.
1262 lease_ = lease;
1263
1264 // Ensure bind_ array clear for constructing the MYSQL_BIND structures
1265 // for this lease.
1266 // It sets all fields, including is_null, to zero, so we need to set
1267 // is_null only if it should be true. This gives up minor performance
1268 // benefit while being safe approach. For improved readability, the
1269 // code that explicitly sets is_null is there, but is commented out.
1270 memset(bind_, 0, sizeof(bind_));
1271
1272 try {
1273 // address: binary(16)
1274 addr6_ = lease->addr_.toBytes();
1275 if (addr6_.size() != 16) {
1276 isc_throw(DbOperationError, "lease6 address is not 16 bytes long");
1277 }
1278
1279 addr6_length_ = 16;
1280 bind_[0].buffer_type = MYSQL_TYPE_BLOB;
1281 bind_[0].buffer = reinterpret_cast<char*>(&addr6_[0]);
1282 bind_[0].buffer_length = 16;
1283 bind_[0].length = &addr6_length_;
1284 // bind_[0].is_null = &MLM_FALSE; // commented out for performance
1285 // reasons, see memset() above
1286
1287 // duid: varchar(130)
1288 if (!lease_->duid_) {
1289 isc_throw(DbOperationError, "lease6 for address " << lease->addr_.toText()
1290 << " is missing mandatory client-id.");
1291 }
1292 duid_ = lease_->duid_->getDuid();
1293 duid_length_ = duid_.size();
1294
1295 bind_[1].buffer_type = MYSQL_TYPE_BLOB;
1296 bind_[1].buffer = reinterpret_cast<char*>(&(duid_[0]));
1297 bind_[1].buffer_length = duid_length_;
1298 bind_[1].length = &duid_length_;
1299 // bind_[1].is_null = &MLM_FALSE; // commented out for performance
1300 // reasons, see memset() above
1301
1302 // valid lifetime: unsigned int
1303 bind_[2].buffer_type = MYSQL_TYPE_LONG;
1304 bind_[2].buffer = reinterpret_cast<char*>(&lease_->valid_lft_);
1305 bind_[2].is_unsigned = MLM_TRUE;
1306 // bind_[2].is_null = &MLM_FALSE; // commented out for performance
1307 // reasons, see memset() above
1308
1309 // expire: timestamp
1310 // The lease structure holds the client last transmission time (cltt_)
1311 // For convenience for external tools, this is converted to lease
1312 // expiry time (expire). The relationship is given by:
1313 //
1314 // expire = cltt_ + valid_lft_
1315 // Avoid overflow with infinite valid lifetime by using
1316 // expire = cltt_ when valid_lft_ = 0xffffffff
1317 uint32_t valid_lft = lease_->valid_lft_;
1318 if (valid_lft == Lease::INFINITY_LFT) {
1319 valid_lft = 0;
1320 }
1321 MySqlConnection::convertToDatabaseTime(lease_->cltt_, valid_lft,
1322 expire_);
1323 bind_[3].buffer_type = MYSQL_TYPE_TIMESTAMP;
1324 bind_[3].buffer = reinterpret_cast<char*>(&expire_);
1325 bind_[3].buffer_length = sizeof(expire_);
1326 // bind_[3].is_null = &MLM_FALSE; // commented out for performance
1327 // reasons, see memset() above
1328
1329 // subnet_id: unsigned int
1330 // Can use lease_->subnet_id_ directly as it is of type uint32_t.
1331 bind_[4].buffer_type = MYSQL_TYPE_LONG;
1332 bind_[4].buffer = reinterpret_cast<char*>(&lease_->subnet_id_);
1333 bind_[4].is_unsigned = MLM_TRUE;
1334 // bind_[4].is_null = &MLM_FALSE; // commented out for performance
1335 // reasons, see memset() above
1336
1337 // pref_lifetime: unsigned int
1338 // Can use lease_->preferred_lft_ directly as it is of type uint32_t.
1339 bind_[5].buffer_type = MYSQL_TYPE_LONG;
1340 bind_[5].buffer = reinterpret_cast<char*>(&lease_->preferred_lft_);
1341 bind_[5].is_unsigned = MLM_TRUE;
1342 // bind_[5].is_null = &MLM_FALSE; // commented out for performance
1343 // reasons, see memset() above
1344
1345 // lease_type: tinyint
1346 // Must convert to uint8_t as lease_->type_ is a LeaseType variable.
1347 lease_type_ = lease_->type_;
1348 bind_[6].buffer_type = MYSQL_TYPE_TINY;
1349 bind_[6].buffer = reinterpret_cast<char*>(&lease_type_);
1350 bind_[6].is_unsigned = MLM_TRUE;
1351 // bind_[6].is_null = &MLM_FALSE; // commented out for performance
1352 // reasons, see memset() above
1353
1354 // iaid: unsigned int
1355 // Can use lease_->iaid_ directly as it is of type uint32_t.
1356 bind_[7].buffer_type = MYSQL_TYPE_LONG;
1357 bind_[7].buffer = reinterpret_cast<char*>(&lease_->iaid_);
1358 bind_[7].is_unsigned = MLM_TRUE;
1359 // bind_[7].is_null = &MLM_FALSE; // commented out for performance
1360 // reasons, see memset() above
1361
1362 // prefix_len: unsigned tinyint
1363 // Can use lease_->prefixlen_ directly as it is uint32_t.
1364 bind_[8].buffer_type = MYSQL_TYPE_TINY;
1365 bind_[8].buffer = reinterpret_cast<char*>(&lease_->prefixlen_);
1366 bind_[8].is_unsigned = MLM_TRUE;
1367 // bind_[8].is_null = &MLM_FALSE; // commented out for performance
1368 // reasons, see memset() above
1369
1370 // fqdn_fwd: boolean
1371 bind_[9].buffer_type = MYSQL_TYPE_TINY;
1372 bind_[9].buffer = reinterpret_cast<char*>(&lease_->fqdn_fwd_);
1373 bind_[9].is_unsigned = MLM_TRUE;
1374 // bind_[9].is_null = &MLM_FALSE; // commented out for performance
1375 // reasons, see memset() above
1376
1377 // fqdn_rev: boolean
1378 bind_[10].buffer_type = MYSQL_TYPE_TINY;
1379 bind_[10].buffer = reinterpret_cast<char*>(&lease_->fqdn_rev_);
1380 bind_[10].is_unsigned = MLM_TRUE;
1381 // bind_[10].is_null = &MLM_FALSE; // commented out for performance
1382 // reasons, see memset() above
1383
1384 // hostname: varchar(255)
1385 bind_[11].buffer_type = MYSQL_TYPE_STRING;
1386 bind_[11].buffer = const_cast<char*>(lease_->hostname_.c_str());
1387 bind_[11].buffer_length = lease_->hostname_.length();
1388 // bind_[11].is_null = &MLM_FALSE; // commented out for performance
1389 // reasons, see memset() above
1390
1391 // hwaddr: varbinary(20) - hardware/MAC address
1392 HWAddrPtr hwaddr = lease_->hwaddr_;
1393 if (hwaddr) {
1394 hwaddr_ = hwaddr->hwaddr_;
1395 hwaddr_length_ = hwaddr->hwaddr_.size();
1396
1397 // Make sure that the buffer has at least length of 1, even if
1398 // empty HW address is passed. This is required by some of the
1399 // MySQL connectors that the buffer is set to non-null value.
1400 // Otherwise, null value would be inserted into the database,
1401 // rather than empty string.
1402 if (hwaddr_.empty()) {
1403 hwaddr_.resize(1);
1404 }
1405
1406 bind_[12].buffer_type = MYSQL_TYPE_BLOB;
1407 bind_[12].buffer = reinterpret_cast<char*>(&(hwaddr_[0]));
1408 bind_[12].buffer_length = hwaddr_length_;
1409 bind_[12].length = &hwaddr_length_;
1410 } else {
1411 bind_[12].buffer_type = MYSQL_TYPE_NULL;
1412 // According to http://dev.mysql.com/doc/refman/5.5/en/
1413 // c-api-prepared-statement-data-structures.html, the other
1414 // fields doesn't matter if type is set to MYSQL_TYPE_NULL,
1415 // but let's set them to some sane values in case earlier versions
1416 // didn't have that assumption.
1417 hwaddr_null_ = MLM_TRUE;
1418 bind_[12].buffer = NULL;
1419 bind_[12].is_null = &hwaddr_null_;
1420 }
1421
1422 // hardware type: unsigned short int (16 bits)
1423 if (hwaddr) {
1424 hwtype_ = lease->hwaddr_->htype_;
1425 bind_[13].buffer_type = MYSQL_TYPE_SHORT;
1426 bind_[13].buffer = reinterpret_cast<char*>(&hwtype_);
1427 bind_[13].is_unsigned = MLM_TRUE;
1428 } else {
1429 hwtype_ = 0;
1430 bind_[13].buffer_type = MYSQL_TYPE_NULL;
1431 // According to http://dev.mysql.com/doc/refman/5.5/en/
1432 // c-api-prepared-statement-data-structures.html, the other
1433 // fields doesn't matter if type is set to MYSQL_TYPE_NULL,
1434 // but let's set them to some sane values in case earlier versions
1435 // didn't have that assumption.
1436 hwaddr_null_ = MLM_TRUE;
1437 bind_[13].buffer = NULL;
1438 bind_[13].is_null = &hwaddr_null_;
1439 }
1440
1441 // hardware source: unsigned int (32 bits)
1442 if (hwaddr) {
1443 hwaddr_source_ = lease->hwaddr_->source_;
1444 bind_[14].buffer_type = MYSQL_TYPE_LONG;
1445 bind_[14].buffer = reinterpret_cast<char*>(&hwaddr_source_);
1446 bind_[14].is_unsigned = MLM_TRUE;
1447 } else {
1448 hwaddr_source_ = 0;
1449 bind_[14].buffer_type = MYSQL_TYPE_NULL;
1450 // According to http://dev.mysql.com/doc/refman/5.5/en/
1451 // c-api-prepared-statement-data-structures.html, the other
1452 // fields doesn't matter if type is set to MYSQL_TYPE_NULL,
1453 // but let's set them to some sane values in case earlier versions
1454 // didn't have that assumption.
1455 hwaddr_null_ = MLM_TRUE;
1456 bind_[14].buffer = NULL;
1457 bind_[14].is_null = &hwaddr_null_;
1458 }
1459
1460 // state: uint32_t
1461 bind_[15].buffer_type = MYSQL_TYPE_LONG;
1462 bind_[15].buffer = reinterpret_cast<char*>(&lease_->state_);
1463 bind_[15].is_unsigned = MLM_TRUE;
1464 // bind_[15].is_null = &MLM_FALSE; // commented out for performance
1465 // reasons, see memset() above
1466
1467 // user_context: text
1468 ConstElementPtr ctx = lease->getContext();
1469 if (ctx) {
1470 bind_[16].buffer_type = MYSQL_TYPE_STRING;
1471 std::string ctx_txt = ctx->str();
1472 strncpy(user_context_, ctx_txt.c_str(), USER_CONTEXT_MAX_LEN - 1);
1473 bind_[16].buffer = user_context_;
1474 bind_[16].buffer_length = ctx_txt.length();
1475 // bind_[16].is_null = &MLM_FALSE; // commented out for performance
1476 // reasons, see memset() above
1477 } else {
1478 bind_[16].buffer_type = MYSQL_TYPE_NULL;
1479 }
1480
1481 // pool_id: unsigned int
1482 // Can use lease_->pool_id_ directly as it is of type uint32_t.
1483 bind_[17].buffer_type = MYSQL_TYPE_LONG;
1484 bind_[17].buffer = reinterpret_cast<char*>(&lease_->pool_id_);
1485 bind_[17].is_unsigned = MLM_TRUE;
1486 // bind_[17].is_null = &MLM_FALSE; // commented out for performance
1487 // reasons, see memset() above
1488
1489 // Add the error flags
1490 setErrorIndicators(bind_, error_, LEASE_COLUMNS);
1491
1492 // .. and check that we have the numbers correct at compile time.
1493 BOOST_STATIC_ASSERT(17 < LEASE_COLUMNS);
1494
1495 } catch (const std::exception& ex) {
1497 "Could not create bind array from Lease6: "
1498 << lease_->addr_.toText() << ", reason: " << ex.what());
1499 }
1500
1501 // Add the data to the vector. Note the end element is one after the
1502 // end of the array.
1503 return (std::vector<MYSQL_BIND>(&bind_[0], &bind_[LEASE_COLUMNS]));
1504 }
1505
1514 std::vector<MYSQL_BIND> createBindForReceive() {
1515
1516 // Initialize MYSQL_BIND array.
1517 // It sets all fields, including is_null, to zero, so we need to set
1518 // is_null only if it should be true. This gives up minor performance
1519 // benefit while being safe approach. For improved readability, the
1520 // code that explicitly sets is_null is there, but is commented out.
1521 memset(bind_, 0, sizeof(bind_));
1522
1523 // address: binary(16)
1524 addr6_length_ = 16;
1525 bind_[0].buffer_type = MYSQL_TYPE_BLOB;
1526 bind_[0].buffer = reinterpret_cast<char*>(addr6_buffer_);
1527 bind_[0].buffer_length = addr6_length_;
1528 bind_[0].length = &addr6_length_;
1529 // bind_[0].is_null = &MLM_FALSE; // commented out for performance
1530 // reasons, see memset() above
1531
1532 // duid: varbinary(130)
1533 duid_length_ = sizeof(duid_buffer_);
1534 bind_[1].buffer_type = MYSQL_TYPE_BLOB;
1535 bind_[1].buffer = reinterpret_cast<char*>(duid_buffer_);
1536 bind_[1].buffer_length = duid_length_;
1537 bind_[1].length = &duid_length_;
1538 // bind_[1].is_null = &MLM_FALSE; // commented out for performance
1539 // reasons, see memset() above
1540
1541 // valid lifetime: unsigned int
1542 bind_[2].buffer_type = MYSQL_TYPE_LONG;
1543 bind_[2].buffer = reinterpret_cast<char*>(&valid_lifetime_);
1544 bind_[2].is_unsigned = MLM_TRUE;
1545 // bind_[2].is_null = &MLM_FALSE; // commented out for performance
1546 // reasons, see memset() above
1547
1548 // expire: timestamp
1549 bind_[3].buffer_type = MYSQL_TYPE_TIMESTAMP;
1550 bind_[3].buffer = reinterpret_cast<char*>(&expire_);
1551 bind_[3].buffer_length = sizeof(expire_);
1552 // bind_[3].is_null = &MLM_FALSE; // commented out for performance
1553 // reasons, see memset() above
1554
1555 // subnet_id: unsigned int
1556 bind_[4].buffer_type = MYSQL_TYPE_LONG;
1557 bind_[4].buffer = reinterpret_cast<char*>(&subnet_id_);
1558 bind_[4].is_unsigned = MLM_TRUE;
1559 // bind_[4].is_null = &MLM_FALSE; // commented out for performance
1560 // reasons, see memset() above
1561
1562 // pref_lifetime: unsigned int
1563 bind_[5].buffer_type = MYSQL_TYPE_LONG;
1564 bind_[5].buffer = reinterpret_cast<char*>(&pref_lifetime_);
1565 bind_[5].is_unsigned = MLM_TRUE;
1566 // bind_[5].is_null = &MLM_FALSE; // commented out for performance
1567 // reasons, see memset() above
1568
1569 // lease_type: tinyint
1570 bind_[6].buffer_type = MYSQL_TYPE_TINY;
1571 bind_[6].buffer = reinterpret_cast<char*>(&lease_type_);
1572 bind_[6].is_unsigned = MLM_TRUE;
1573 // bind_[6].is_null = &MLM_FALSE; // commented out for performance
1574 // reasons, see memset() above
1575
1576 // iaid: unsigned int
1577 bind_[7].buffer_type = MYSQL_TYPE_LONG;
1578 bind_[7].buffer = reinterpret_cast<char*>(&iaid_);
1579 bind_[7].is_unsigned = MLM_TRUE;
1580 // bind_[7].is_null = &MLM_FALSE; // commented out for performance
1581 // reasons, see memset() above
1582
1583 // prefix_len: unsigned tinyint
1584 bind_[8].buffer_type = MYSQL_TYPE_TINY;
1585 bind_[8].buffer = reinterpret_cast<char*>(&prefix_len_);
1586 bind_[8].is_unsigned = MLM_TRUE;
1587 // bind_[8].is_null = &MLM_FALSE; // commented out for performance
1588 // reasons, see memset() above
1589
1590 // fqdn_fwd: boolean
1591 bind_[9].buffer_type = MYSQL_TYPE_TINY;
1592 bind_[9].buffer = reinterpret_cast<char*>(&fqdn_fwd_);
1593 bind_[9].is_unsigned = MLM_TRUE;
1594 // bind_[9].is_null = &MLM_FALSE; // commented out for performance
1595 // reasons, see memset() above
1596
1597 // fqdn_rev: boolean
1598 bind_[10].buffer_type = MYSQL_TYPE_TINY;
1599 bind_[10].buffer = reinterpret_cast<char*>(&fqdn_rev_);
1600 bind_[10].is_unsigned = MLM_TRUE;
1601 // bind_[10].is_null = &MLM_FALSE; // commented out for performance
1602 // reasons, see memset() above
1603
1604 // hostname: varchar(255)
1605 hostname_length_ = sizeof(hostname_buffer_);
1606 bind_[11].buffer_type = MYSQL_TYPE_STRING;
1607 bind_[11].buffer = reinterpret_cast<char*>(hostname_buffer_);
1608 bind_[11].buffer_length = hostname_length_;
1609 bind_[11].length = &hostname_length_;
1610 // bind_[11].is_null = &MLM_FALSE; // commented out for performance
1611 // reasons, see memset() above
1612
1613 // hwaddr: varbinary(20)
1614 hwaddr_null_ = MLM_FALSE;
1615 hwaddr_length_ = sizeof(hwaddr_buffer_);
1616 bind_[12].buffer_type = MYSQL_TYPE_BLOB;
1617 bind_[12].buffer = reinterpret_cast<char*>(hwaddr_buffer_);
1618 bind_[12].buffer_length = hwaddr_length_;
1619 bind_[12].length = &hwaddr_length_;
1620 bind_[12].is_null = &hwaddr_null_;
1621
1622 // hardware type: unsigned short int (16 bits)
1623 bind_[13].buffer_type = MYSQL_TYPE_SHORT;
1624 bind_[13].buffer = reinterpret_cast<char*>(&hwtype_);
1625 bind_[13].is_unsigned = MLM_TRUE;
1626
1627 // hardware source: unsigned int (32 bits)
1628 bind_[14].buffer_type = MYSQL_TYPE_LONG;
1629 bind_[14].buffer = reinterpret_cast<char*>(&hwaddr_source_);
1630 bind_[14].is_unsigned = MLM_TRUE;
1631
1632 // state: uint32_t
1633 bind_[15].buffer_type = MYSQL_TYPE_LONG;
1634 bind_[15].buffer = reinterpret_cast<char*>(&state_);
1635 bind_[15].is_unsigned = MLM_TRUE;
1636 // bind_[15].is_null = &MLM_FALSE; // commented out for performance
1637 // reasons, see memset() above
1638
1639 // user_context: text
1640 user_context_null_ = MLM_FALSE;
1641 user_context_length_ = sizeof(user_context_);
1642 bind_[16].buffer_type = MYSQL_TYPE_STRING;
1643 bind_[16].buffer = reinterpret_cast<char*>(user_context_);
1644 bind_[16].buffer_length = user_context_length_;
1645 bind_[16].length = &user_context_length_;
1646 bind_[16].is_null = &user_context_null_;
1647
1648 // pool_id: unsigned int
1649 bind_[17].buffer_type = MYSQL_TYPE_LONG;
1650 bind_[17].buffer = reinterpret_cast<char*>(&pool_id_);
1651 bind_[17].is_unsigned = MLM_TRUE;
1652 // bind_[17].is_null = &MLM_FALSE; // commented out for performance
1653 // reasons, see memset() above
1654
1655 // Add the error flags
1656 setErrorIndicators(bind_, error_, LEASE_COLUMNS);
1657
1658 // .. and check that we have the numbers correct at compile time.
1659 BOOST_STATIC_ASSERT(17 < LEASE_COLUMNS);
1660
1661 // Add the data to the vector. Note the end element is one after the
1662 // end of the array.
1663 return (std::vector<MYSQL_BIND>(&bind_[0], &bind_[LEASE_COLUMNS]));
1664 }
1665
1677 // Convert lease from network-order bytes to IOAddress.
1678 IOAddress addr = IOAddress::fromBytes(AF_INET6, addr6_buffer_);
1679 std::string address = addr.toText();
1680
1681 // Set the lease type in a variable of the appropriate data type, which
1682 // has been initialized with an arbitrary (but valid) value.
1684 switch (lease_type_) {
1685 case Lease::TYPE_NA:
1686 type = Lease::TYPE_NA;
1687 break;
1688
1689 case Lease::TYPE_TA:
1690 type = Lease::TYPE_TA;
1691 break;
1692
1693 case Lease::TYPE_PD:
1694 type = Lease::TYPE_PD;
1695 break;
1696
1697 default:
1698 isc_throw(BadValue, "invalid lease type returned (" <<
1699 static_cast<int>(lease_type_) << ") for lease with "
1700 << "address " << address << ". Only 0, 1, or 2 are "
1701 << "allowed.");
1702 }
1703
1704 if (type != Lease::TYPE_PD) {
1705 prefix_len_ = 128;
1706 }
1707
1708 // Set up DUID,
1709 DuidPtr duid_ptr(new DUID(duid_buffer_, duid_length_));
1710
1711 // Hostname is passed to Lease6 as a string object, so we have to
1712 // create it from the hostname buffer and length.
1713 std::string hostname(hostname_buffer_,
1714 hostname_buffer_ + hostname_length_);
1715
1716 // Set hardware address if it was set
1717 HWAddrPtr hwaddr;
1718 if (hwaddr_null_ == MLM_FALSE) {
1719 hwaddr.reset(new HWAddr(hwaddr_buffer_, hwaddr_length_, hwtype_));
1720 hwaddr->source_ = hwaddr_source_;
1721 }
1722
1723 // Convert user_context to string as well.
1724 std::string user_context;
1725 if (user_context_null_ == MLM_FALSE) {
1726 user_context_[user_context_length_] = '\0';
1727 user_context.assign(user_context_);
1728 }
1729
1730 // Set the user context if there is one.
1731 ConstElementPtr ctx;
1732 if (!user_context.empty()) {
1733 ctx = Element::fromJSON(user_context);
1734 if (!ctx || (ctx->getType() != Element::map)) {
1735 isc_throw(BadValue, "user context '" << user_context
1736 << "' is not a JSON map");
1737 }
1738 }
1739
1740 // Create the lease and set the cltt (after converting from the
1741 // expire time retrieved from the database).
1742 Lease6Ptr result(boost::make_shared<Lease6>(type, addr, duid_ptr, iaid_,
1743 pref_lifetime_,
1744 valid_lifetime_, subnet_id_,
1745 fqdn_fwd_, fqdn_rev_,
1746 hostname, hwaddr,
1747 prefix_len_));
1748 time_t cltt = 0;
1749 // Recover from overflow (see expire code of createBindForSend).
1750 uint32_t valid_lft = valid_lifetime_;
1751 if (valid_lft == Lease::INFINITY_LFT) {
1752 valid_lft = 0;
1753 }
1754 MySqlConnection::convertFromDatabaseTime(expire_, valid_lft, cltt);
1755 // Update cltt_ and current_cltt_ explicitly.
1756 result->cltt_ = cltt;
1757 result->current_cltt_ = cltt;
1758
1759 // Set state.
1760 result->state_ = state_;
1761
1762 if (ctx) {
1763 result->setContext(ctx);
1764 }
1765
1766 // Set pool ID.
1767 result->pool_id_ = pool_id_;
1768
1769 return (result);
1770 }
1771
1782 std::string getErrorColumns() {
1783 return (getColumnsInError(error_, columns_, LEASE_COLUMNS));
1784 }
1785
1786private:
1787
1788 // Note: All array lengths are equal to the corresponding variable in the
1789 // schema.
1790 // Note: arrays are declared fixed length for speed of creation
1791 std::vector<uint8_t> addr6_;
1792 uint8_t addr6_buffer_[16];
1793 unsigned long addr6_length_;
1794 MYSQL_BIND bind_[LEASE_COLUMNS];
1795 std::string columns_[LEASE_COLUMNS];
1796 my_bool error_[LEASE_COLUMNS];
1797 Lease6Ptr lease_;
1798 std::vector<uint8_t> hwaddr_;
1799 uint8_t hwaddr_buffer_[HWAddr::MAX_HWADDR_LEN];
1800 unsigned long hwaddr_length_;
1801 my_bool hwaddr_null_;
1802 std::vector<uint8_t> duid_;
1803 uint8_t duid_buffer_[DUID::MAX_DUID_LEN];
1804 unsigned long duid_length_;
1805 MYSQL_TIME expire_;
1806 uint32_t iaid_;
1807 uint8_t lease_type_;
1808 uint8_t prefix_len_;
1809 uint32_t pref_lifetime_;
1810 uint32_t subnet_id_;
1811 uint32_t pool_id_;
1812 uint32_t valid_lifetime_;
1813 my_bool fqdn_fwd_;
1814 my_bool fqdn_rev_;
1815 char hostname_buffer_[HOSTNAME_MAX_LEN];
1816 unsigned long hostname_length_;
1817 uint16_t hwtype_;
1818 uint32_t hwaddr_source_;
1819 uint32_t state_;
1820 char user_context_[USER_CONTEXT_MAX_LEN];
1821 unsigned long user_context_length_;
1822 my_bool user_context_null_;
1823};
1824
1831
1833public:
1834
1844 MySqlLeaseStatsQuery(MySqlConnection& conn, const size_t statement_index,
1845 const bool fetch_type, const bool fetch_pool = false)
1846 : conn_(conn), statement_index_(statement_index), statement_(NULL),
1847 fetch_type_(fetch_type), fetch_pool_(fetch_pool),
1848 // Set the number of columns in the bind array based on fetch_type
1849 // This is the number of columns expected in the result set
1850 bind_(fetch_type_ ? (fetch_pool_ ? 5 : 4) : (fetch_pool_ ? 4 : 3)),
1851 subnet_id_(0), pool_id_(0), lease_type_(Lease::TYPE_NA),
1852 state_(Lease::STATE_DEFAULT), state_count_(0) {
1853 validateStatement();
1854 }
1855
1865 MySqlLeaseStatsQuery(MySqlConnection& conn, const size_t statement_index,
1866 const bool fetch_type, const SubnetID& subnet_id)
1867 : LeaseStatsQuery(subnet_id), conn_(conn), statement_index_(statement_index),
1868 statement_(NULL), fetch_type_(fetch_type), fetch_pool_(false),
1869 // Set the number of columns in the bind array based on fetch_type
1870 // This is the number of columns expected in the result set
1871 bind_(fetch_type_ ? 4 : 3), subnet_id_(0), pool_id_(0),
1872 lease_type_(Lease::TYPE_NA), state_(Lease::STATE_DEFAULT),
1873 state_count_(0) {
1874 validateStatement();
1875 }
1876
1889 MySqlLeaseStatsQuery(MySqlConnection& conn, const size_t statement_index,
1890 const bool fetch_type, const SubnetID& first_subnet_id,
1891 const SubnetID& last_subnet_id)
1892 : LeaseStatsQuery(first_subnet_id, last_subnet_id), conn_(conn),
1893 statement_index_(statement_index), statement_(NULL),
1894 fetch_type_(fetch_type), fetch_pool_(false),
1895 // Set the number of columns in the bind array based on fetch_type
1896 // This is the number of columns expected in the result set
1897 bind_(fetch_type_ ? 4 : 3), subnet_id_(0), pool_id_(0),
1898 lease_type_(Lease::TYPE_NA), state_(Lease::STATE_DEFAULT),
1899 state_count_(0) {
1900 validateStatement();
1901 }
1902
1905 (void) mysql_stmt_free_result(statement_);
1906 }
1907
1915 void start() override {
1916 // Set up where clause inputs if needed.
1918 MYSQL_BIND inbind[2];
1919 memset(inbind, 0, sizeof(inbind));
1920
1921 // Add first_subnet_id used by both single and range.
1922 inbind[0].buffer_type = MYSQL_TYPE_LONG;
1923 inbind[0].buffer = reinterpret_cast<char*>(&first_subnet_id_);
1924 inbind[0].is_unsigned = MLM_TRUE;
1925
1926 // Add last_subnet_id for range.
1927 if (getSelectMode() == SUBNET_RANGE) {
1928 inbind[1].buffer_type = MYSQL_TYPE_LONG;
1929 inbind[1].buffer = reinterpret_cast<char*>(&last_subnet_id_);
1930 inbind[1].is_unsigned = MLM_TRUE;
1931 }
1932
1933 // Bind the parameters to the statement
1934 int status = mysql_stmt_bind_param(statement_, &inbind[0]);
1935 conn_.checkError(status, statement_index_, "unable to bind parameters");
1936 }
1937
1938 int col = 0;
1939 // subnet_id: unsigned int
1940 bind_[col].buffer_type = MYSQL_TYPE_LONG;
1941 bind_[col].buffer = reinterpret_cast<char*>(&subnet_id_);
1942 bind_[col].is_unsigned = MLM_TRUE;
1943 ++col;
1944
1945 // Fetch the pool id if we were told to do so.
1946 if (fetch_pool_) {
1947 // pool id: uint32_t
1948 bind_[col].buffer_type = MYSQL_TYPE_LONG;
1949 bind_[col].buffer = reinterpret_cast<char*>(&pool_id_);
1950 bind_[col].is_unsigned = MLM_TRUE;
1951 ++col;
1952 }
1953
1954 // Fetch the lease type if we were told to do so.
1955 if (fetch_type_) {
1956 // lease type: uint32_t
1957 bind_[col].buffer_type = MYSQL_TYPE_LONG;
1958 bind_[col].buffer = reinterpret_cast<char*>(&lease_type_);
1959 bind_[col].is_unsigned = MLM_TRUE;
1960 ++col;
1961 } else {
1962 fetch_type_ = Lease::TYPE_NA;
1963 }
1964
1965 // state: uint32_t
1966 bind_[col].buffer_type = MYSQL_TYPE_LONG;
1967 bind_[col].buffer = reinterpret_cast<char*>(&state_);
1968 bind_[col].is_unsigned = MLM_TRUE;
1969 ++col;
1970
1971 // state_count_: int64_t
1972 bind_[col].buffer_type = MYSQL_TYPE_LONGLONG;
1973 bind_[col].buffer = reinterpret_cast<char*>(&state_count_);
1974 //bind_[col].is_unsigned = MLM_FALSE;
1975
1976 // Set up the MYSQL_BIND array for the data being returned
1977 // and bind it to the statement.
1978 int status = mysql_stmt_bind_result(statement_, &bind_[0]);
1979 conn_.checkError(status, statement_index_, "outbound binding failed");
1980
1981 // Execute the statement
1982 status = MysqlExecuteStatement(statement_);
1983 conn_.checkError(status, statement_index_, "unable to execute");
1984
1985 // Ensure that all the lease information is retrieved in one go to avoid
1986 // overhead of going back and forth between client and server.
1987 status = mysql_stmt_store_result(statement_);
1988 conn_.checkError(status, statement_index_, "results storage failed");
1989 }
1990
2006 bool getNextRow(LeaseStatsRow& row) override {
2007 bool have_row = false;
2008 int status = mysql_stmt_fetch(statement_);
2009 if (status == MLM_MYSQL_FETCH_SUCCESS) {
2010 row.subnet_id_ = subnet_id_;
2011 row.pool_id_ = pool_id_;
2012 row.lease_type_ = static_cast<Lease::Type>(lease_type_);
2013 row.lease_state_ = state_;
2014 if (state_count_ >= 0) {
2015 row.state_count_ = state_count_;
2016 } else {
2017 row.state_count_ = 0;
2018 if (!negative_count_) {
2019 negative_count_ = true;
2021 }
2022 }
2023 have_row = true;
2024 } else if (status != MYSQL_NO_DATA) {
2025 conn_.checkError(status, statement_index_, "getNextRow failed");
2026 }
2027
2028 return (have_row);
2029 }
2030
2031private:
2032
2036 void validateStatement() {
2037 if (statement_index_ >= MySqlLeaseMgr::NUM_STATEMENTS) {
2038 isc_throw(BadValue, "MySqlLeaseStatsQuery"
2039 " - invalid statement index" << statement_index_);
2040 }
2041
2042 statement_ = conn_.getStatement(statement_index_);
2043 }
2044
2046 MySqlConnection& conn_;
2047
2049 size_t statement_index_;
2050
2052 MYSQL_STMT *statement_;
2053
2055 bool fetch_type_;
2056
2058 bool fetch_pool_;
2059
2061 std::vector<MYSQL_BIND> bind_;
2062
2064 uint32_t subnet_id_;
2065
2067 uint32_t pool_id_;
2068
2070 uint32_t lease_type_;
2071
2073 uint32_t state_;
2074
2076 int64_t state_count_;
2077
2079 static bool negative_count_;
2080};
2081
2082// Initialize negative state count flag to false.
2083bool MySqlLeaseStatsQuery::negative_count_ = false;
2084
2085// MySqlLeaseContext Constructor
2086
2088 IOServiceAccessorPtr io_service_accessor,
2089 DbCallback db_reconnect_callback)
2090 : conn_(parameters, io_service_accessor, db_reconnect_callback) {
2091}
2092
2093// MySqlLeaseContextAlloc Constructor and Destructor
2094
2095MySqlLeaseMgr::MySqlLeaseContextAlloc::MySqlLeaseContextAlloc(
2096 const MySqlLeaseMgr& mgr) : ctx_(), mgr_(mgr) {
2097
2098 if (MultiThreadingMgr::instance().getMode()) {
2099 // multi-threaded
2100 {
2101 // we need to protect the whole pool_ operation, hence extra scope {}
2102 lock_guard<mutex> lock(mgr_.pool_->mutex_);
2103 if (!mgr_.pool_->pool_.empty()) {
2104 ctx_ = mgr_.pool_->pool_.back();
2105 mgr_.pool_->pool_.pop_back();
2106 }
2107 }
2108 if (!ctx_) {
2109 ctx_ = mgr_.createContext();
2110 }
2111 } else {
2112 // single-threaded
2113 if (mgr_.pool_->pool_.empty()) {
2114 isc_throw(Unexpected, "No available MySQL lease context?!");
2115 }
2116 ctx_ = mgr_.pool_->pool_.back();
2117 }
2118}
2119
2120MySqlLeaseMgr::MySqlLeaseContextAlloc::~MySqlLeaseContextAlloc() {
2121 if (MultiThreadingMgr::instance().getMode()) {
2122 // multi-threaded
2123 lock_guard<mutex> lock(mgr_.pool_->mutex_);
2124 mgr_.pool_->pool_.push_back(ctx_);
2125 }
2126 // If running in single-threaded mode, there's nothing to do here.
2127}
2128
2129// MySqlLeaseTrackingContextAlloc Constructor and Destructor
2130
2131MySqlLeaseMgr::MySqlLeaseTrackingContextAlloc::MySqlLeaseTrackingContextAlloc(
2132 MySqlLeaseMgr& mgr, const LeasePtr& lease) : ctx_(), mgr_(mgr), lease_(lease) {
2133
2134 if (MultiThreadingMgr::instance().getMode()) {
2135 // multi-threaded
2136 {
2137 // we need to protect the whole pool_ operation, hence extra scope {}
2138 lock_guard<mutex> lock(mgr_.pool_->mutex_);
2139 if (mgr_.hasCallbacks() && !mgr_.tryLock(lease)) {
2140 isc_throw(DbOperationError, "unable to lock the lease " << lease->addr_);
2141 }
2142 if (!mgr_.pool_->pool_.empty()) {
2143 ctx_ = mgr_.pool_->pool_.back();
2144 mgr_.pool_->pool_.pop_back();
2145 }
2146 }
2147 if (!ctx_) {
2148 ctx_ = mgr_.createContext();
2149 }
2150 } else {
2151 // single-threaded
2152 if (mgr_.pool_->pool_.empty()) {
2153 isc_throw(Unexpected, "No available MySQL lease context?!");
2154 }
2155 ctx_ = mgr_.pool_->pool_.back();
2156 }
2157}
2158
2159MySqlLeaseMgr::MySqlLeaseTrackingContextAlloc::~MySqlLeaseTrackingContextAlloc() {
2160 if (MultiThreadingMgr::instance().getMode()) {
2161 // multi-threaded
2162 lock_guard<mutex> lock(mgr_.pool_->mutex_);
2163 if (mgr_.hasCallbacks()) {
2164 mgr_.unlock(lease_);
2165 }
2166 mgr_.pool_->pool_.push_back(ctx_);
2167 }
2168 // If running in single-threaded mode, there's nothing to do here.
2169}
2170
2171// MySqlLeaseMgr Constructor and Destructor
2172
2174 : TrackingLeaseMgr(), parameters_(parameters) {
2175
2176 // Check if the extended info tables are enabled.
2177 setExtendedInfoTablesEnabled(parameters);
2178
2179 // Create unique timer name per instance.
2180 timer_name_ = "MySqlLeaseMgr[";
2181 timer_name_ += boost::lexical_cast<std::string>(reinterpret_cast<uint64_t>(this));
2182 timer_name_ += "]DbReconnectTimer";
2183
2185 timer_name_);
2186
2187 // Create an initial context.
2188 pool_.reset(new MySqlLeaseContextPool());
2189 pool_->pool_.push_back(createContext());
2190}
2191
2194
2195bool
2198
2199 // Invoke application layer connection lost callback.
2200 if (!DatabaseConnection::invokeDbLostCallback(db_reconnect_ctl)) {
2201 return (false);
2202 }
2203
2204 bool reopened = false;
2205
2206 const std::string timer_name = db_reconnect_ctl->timerName();
2207
2208 // At least one connection was lost.
2209 try {
2210 CfgDbAccessPtr cfg_db = CfgMgr::instance().getCurrentCfg()->getCfgDbAccess();
2211 LeaseMgrFactory::recreate(cfg_db->getLeaseDbAccessString());
2212 reopened = true;
2213 } catch (const std::exception& ex) {
2215 .arg(ex.what());
2216 }
2217
2218 if (reopened) {
2219 // Cancel the timer.
2220 if (TimerMgr::instance()->isTimerRegistered(timer_name)) {
2221 TimerMgr::instance()->unregisterTimer(timer_name);
2222 }
2223
2224 // Invoke application layer connection recovered callback.
2225 if (!DatabaseConnection::invokeDbRecoveredCallback(db_reconnect_ctl)) {
2226 return (false);
2227 }
2228 } else {
2229 if (!db_reconnect_ctl->checkRetries()) {
2230 // We're out of retries, log it and initiate shutdown.
2232 .arg(db_reconnect_ctl->maxRetries());
2233
2234 // Cancel the timer.
2235 if (TimerMgr::instance()->isTimerRegistered(timer_name)) {
2236 TimerMgr::instance()->unregisterTimer(timer_name);
2237 }
2238
2239 // Invoke application layer connection failed callback.
2241 return (false);
2242 }
2243
2245 .arg(db_reconnect_ctl->maxRetries() - db_reconnect_ctl->retriesLeft() + 1)
2246 .arg(db_reconnect_ctl->maxRetries())
2247 .arg(db_reconnect_ctl->retryInterval());
2248
2249 // Start the timer.
2250 if (!TimerMgr::instance()->isTimerRegistered(timer_name)) {
2251 TimerMgr::instance()->registerTimer(timer_name,
2252 std::bind(&MySqlLeaseMgr::dbReconnect, db_reconnect_ctl),
2253 db_reconnect_ctl->retryInterval(),
2255 }
2256 TimerMgr::instance()->setup(timer_name);
2257 }
2258
2259 return (true);
2260}
2261
2262// Create context.
2263
2266 MySqlLeaseContextPtr ctx(new MySqlLeaseContext(parameters_,
2269
2270 // Create ReconnectCtl for this connection.
2271 ctx->conn_.makeReconnectCtl(timer_name_);
2272
2273 // Open the database.
2274 ctx->conn_.openDatabase();
2275
2276 // Check if we have TLS when we required it.
2277 if (ctx->conn_.getTls()) {
2278 std::string cipher = ctx->conn_.getTlsCipher();
2279 if (cipher.empty()) {
2281 } else {
2284 .arg(cipher);
2285 }
2286 }
2287
2288 // Prepare all statements likely to be used.
2289 ctx->conn_.prepareStatements(tagged_statements.begin(),
2290 tagged_statements.end());
2291
2292 // Create the exchange objects for use in exchanging data between the
2293 // program and the database.
2294 ctx->exchange4_.reset(new MySqlLease4Exchange());
2295 ctx->exchange6_.reset(new MySqlLease6Exchange());
2296
2297 return (ctx);
2298}
2299
2300std::string
2302 std::stringstream tmp;
2303 tmp << "MySQL backend " << MYSQL_SCHEMA_VERSION_MAJOR;
2304 tmp << "." << MYSQL_SCHEMA_VERSION_MINOR;
2305 tmp << ", library " << mysql_get_client_info();
2306 return (tmp.str());
2307}
2308
2309// Add leases to the database. The two public methods accept a lease object
2310// (either V4 of V6), bind the contents to the appropriate prepared
2311// statement, then call common code to execute the statement.
2312
2313bool
2314MySqlLeaseMgr::addLeaseCommon(MySqlLeaseContextPtr& ctx,
2315 StatementIndex stindex,
2316 std::vector<MYSQL_BIND>& bind) {
2317 // Bind the parameters to the statement
2318 int status = mysql_stmt_bind_param(ctx->conn_.getStatement(stindex), &bind[0]);
2319 checkError(ctx, status, stindex, "unable to bind parameters");
2320
2321 // Execute the statement
2322 status = MysqlExecuteStatement(ctx->conn_.getStatement(stindex));
2323 if (status != 0) {
2324
2325 // Failure: check for the special case of duplicate entry. If this is
2326 // the case, we return false to indicate that the row was not added.
2327 // Otherwise we throw an exception.
2328 if (mysql_errno(ctx->conn_.mysql_) == ER_DUP_ENTRY) {
2329 return (false);
2330 }
2331 checkError(ctx, status, stindex, "unable to execute");
2332 }
2333
2334 // Insert succeeded
2335 return (true);
2336}
2337
2338bool
2341 .arg(lease->addr_.toText());
2342
2343 // Get a context
2344 MySqlLeaseTrackingContextAlloc get_context(*this, lease);
2345 MySqlLeaseContextPtr ctx = get_context.ctx_;
2346
2347 // Create the MYSQL_BIND array for the lease
2348 std::vector<MYSQL_BIND> bind = ctx->exchange4_->createBindForSend(lease);
2349
2350 // ... and drop to common code.
2351 auto result = addLeaseCommon(ctx, INSERT_LEASE4, bind);
2352
2353 // Update lease current expiration time (allows update between the creation
2354 // of the Lease up to the point of insertion in the database).
2355 lease->updateCurrentExpirationTime();
2356
2357 // Run installed callbacks.
2358 if (hasCallbacks()) {
2359 trackAddLease(lease);
2360 }
2361
2362 return (result);
2363}
2364
2365bool
2368 .arg(lease->addr_.toText())
2369 .arg(lease->type_);
2370
2371 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
2372
2373 // Get a context
2374 MySqlLeaseTrackingContextAlloc get_context(*this, lease);
2375 MySqlLeaseContextPtr ctx = get_context.ctx_;
2376
2377 // Create the MYSQL_BIND array for the lease
2378 std::vector<MYSQL_BIND> bind = ctx->exchange6_->createBindForSend(lease);
2379
2380 // ... and drop to common code.
2381 auto result = addLeaseCommon(ctx, INSERT_LEASE6, bind);
2382
2383 // Update lease current expiration time (allows update between the creation
2384 // of the Lease up to the point of insertion in the database).
2385 lease->updateCurrentExpirationTime();
2386
2388 static_cast<void>(addExtendedInfo6(lease));
2389 }
2390
2391 // Run installed callbacks.
2392 if (hasCallbacks()) {
2393 trackAddLease(lease);
2394 }
2395
2396 return (result);
2397}
2398
2399// Extraction of leases from the database.
2400//
2401// All getLease() methods ultimately call getLeaseCollection(). This
2402// binds the input parameters passed to it with the appropriate prepared
2403// statement and executes the statement. It then gets the results from the
2404// database. getlease() methods that expect a single result back call it
2405// with the "single" parameter set true: this causes an exception to be
2406// generated if multiple records can be retrieved from the result set. (Such
2407// an occurrence either indicates corruption in the database, or that an
2408// assumption that a query can only return a single record is incorrect.)
2409// Methods that require a collection of records have "single" set to the
2410// default value of false. The logic is the same for both Lease4 and Lease6
2411// objects, so the code is templated.
2412//
2413// Methods that require a collection of objects access this method through
2414// two interface methods (also called getLeaseCollection()). These are
2415// short enough as to be defined in the header file: all they do is to supply
2416// the appropriate MySqlLeaseXExchange object depending on the type of the
2417// LeaseCollection objects passed to them.
2418//
2419// Methods that require a single object to be returned access the method
2420// through two interface methods (called getLease()). As well as supplying
2421// the appropriate exchange object, they convert between lease collection
2422// holding zero or one leases into an appropriate Lease object.
2423
2424template <typename Exchange, typename LeaseCollection>
2425void
2426MySqlLeaseMgr::getLeaseCollection(MySqlLeaseContextPtr& ctx,
2427 StatementIndex stindex,
2428 MYSQL_BIND* bind,
2429 Exchange& exchange,
2430 LeaseCollection& result,
2431 bool single) const {
2432 int status;
2433
2434 if (bind) {
2435 // Bind the selection parameters to the statement
2436 status = mysql_stmt_bind_param(ctx->conn_.getStatement(stindex), bind);
2437 checkError(ctx, status, stindex, "unable to bind WHERE clause parameter");
2438 }
2439
2440 // Set up the MYSQL_BIND array for the data being returned and bind it to
2441 // the statement.
2442 std::vector<MYSQL_BIND> outbind = exchange->createBindForReceive();
2443 status = mysql_stmt_bind_result(ctx->conn_.getStatement(stindex), &outbind[0]);
2444 checkError(ctx, status, stindex, "unable to bind SELECT clause parameters");
2445
2446 // Execute the statement
2447 status = MysqlExecuteStatement(ctx->conn_.getStatement(stindex));
2448 checkError(ctx, status, stindex, "unable to execute");
2449
2450 // Ensure that all the lease information is retrieved in one go to avoid
2451 // overhead of going back and forth between client and server.
2452 status = mysql_stmt_store_result(ctx->conn_.getStatement(stindex));
2453 checkError(ctx, status, stindex, "unable to set up for storing all results");
2454
2455 // Set up the fetch "release" object to release resources associated
2456 // with the call to mysql_stmt_fetch when this method exits, then
2457 // retrieve the data.
2458 MySqlFreeResult fetch_release(ctx->conn_.getStatement(stindex));
2459 int count = 0;
2460 while ((status = mysql_stmt_fetch(ctx->conn_.getStatement(stindex))) == 0) {
2461 try {
2462 result.push_back(exchange->getLeaseData());
2463
2464 } catch (const isc::BadValue& ex) {
2465 // Rethrow the exception with a bit more data.
2466 isc_throw(BadValue, ex.what() << ". Statement is <" <<
2467 ctx->conn_.text_statements_[stindex] << ">");
2468 }
2469
2470 if (single && (++count > 1)) {
2471 isc_throw(MultipleRecords, "multiple records were found in the "
2472 "database where only one was expected for query "
2473 << ctx->conn_.text_statements_[stindex]);
2474 }
2475 }
2476
2477 // How did the fetch end?
2478 if (status == 1) {
2479 // Error - unable to fetch results
2480 checkError(ctx, status, stindex, "unable to fetch results");
2481 } else if (status == MYSQL_DATA_TRUNCATED) {
2482 // Data truncated - throw an exception indicating what was at fault
2483 isc_throw(DataTruncated, ctx->conn_.text_statements_[stindex]
2484 << " returned truncated data: columns affected are "
2485 << exchange->getErrorColumns());
2486 }
2487}
2488
2489void
2490MySqlLeaseMgr::getLease(MySqlLeaseContextPtr& ctx,
2491 StatementIndex stindex, MYSQL_BIND* bind,
2492 Lease4Ptr& result) const {
2493 // Create appropriate collection object and get all leases matching
2494 // the selection criteria. The "single" parameter is true to indicate
2495 // that the called method should throw an exception if multiple
2496 // matching records are found: this particular method is called when only
2497 // one or zero matches is expected.
2498 Lease4Collection collection;
2499 getLeaseCollection(ctx, stindex, bind, ctx->exchange4_, collection, true);
2500
2501 // Return single record if present, else clear the lease.
2502 if (collection.empty()) {
2503 result.reset();
2504 } else {
2505 result = *collection.begin();
2506 }
2507}
2508
2509void
2510MySqlLeaseMgr::getLease(MySqlLeaseContextPtr& ctx,
2511 StatementIndex stindex, MYSQL_BIND* bind,
2512 Lease6Ptr& result) const {
2513 // Create appropriate collection object and get all leases matching
2514 // the selection criteria. The "single" parameter is true to indicate
2515 // that the called method should throw an exception if multiple
2516 // matching records are found: this particular method is called when only
2517 // one or zero matches is expected.
2518 Lease6Collection collection;
2519 getLeaseCollection(ctx, stindex, bind, ctx->exchange6_, collection, true);
2520
2521 // Return single record if present, else clear the lease.
2522 if (collection.empty()) {
2523 result.reset();
2524 } else {
2525 result = *collection.begin();
2526 }
2527}
2528
2529// Basic lease access methods. Obtain leases from the database using various
2530// criteria.
2531
2535 .arg(addr.toText());
2536
2537 // Set up the WHERE clause value
2538 MYSQL_BIND inbind[1];
2539 memset(inbind, 0, sizeof(inbind));
2540
2541 uint32_t addr4 = addr.toUint32();
2542 inbind[0].buffer_type = MYSQL_TYPE_LONG;
2543 inbind[0].buffer = reinterpret_cast<char*>(&addr4);
2544 inbind[0].is_unsigned = MLM_TRUE;
2545
2546 // Get the data
2547 Lease4Ptr result;
2548
2549 // Get a context
2550 MySqlLeaseContextAlloc get_context(*this);
2551 MySqlLeaseContextPtr ctx = get_context.ctx_;
2552
2553 getLease(ctx, GET_LEASE4_ADDR, inbind, result);
2554
2555 return (result);
2556}
2557
2559MySqlLeaseMgr::getLease4(const HWAddr& hwaddr) const {
2561 .arg(hwaddr.toText());
2562
2563 // Set up the WHERE clause value
2564 MYSQL_BIND inbind[1];
2565 memset(inbind, 0, sizeof(inbind));
2566
2567 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
2568
2569 unsigned long hwaddr_length = hwaddr.hwaddr_.size();
2570
2571 // If the data happens to be empty, we have to create a 1 byte dummy
2572 // buffer and pass it to the binding.
2573 uint8_t single_byte_data = 0;
2574
2575 // As "buffer" is "char*" - even though the data is being read - we need
2576 // to cast away the "const"ness as well as reinterpreting the data as
2577 // a "char*". (We could avoid the "const_cast" by copying the data to a
2578 // local variable, but as the data is only being read, this introduces
2579 // an unnecessary copy).
2580 uint8_t* data = !hwaddr.hwaddr_.empty() ? const_cast<uint8_t*>(&hwaddr.hwaddr_[0])
2581 : &single_byte_data;
2582
2583 inbind[0].buffer = reinterpret_cast<char*>(data);
2584 inbind[0].buffer_length = hwaddr_length;
2585 inbind[0].length = &hwaddr_length;
2586
2587 // Get the data
2588 Lease4Collection result;
2589
2590 // Get a context
2591 MySqlLeaseContextAlloc get_context(*this);
2592 MySqlLeaseContextPtr ctx = get_context.ctx_;
2593
2594 getLeaseCollection(ctx, GET_LEASE4_HWADDR, inbind, result);
2595
2596 return (result);
2597}
2598
2600MySqlLeaseMgr::getLease4(const HWAddr& hwaddr, SubnetID subnet_id) const {
2602 .arg(subnet_id)
2603 .arg(hwaddr.toText());
2604
2605 // Set up the WHERE clause value
2606 MYSQL_BIND inbind[2];
2607 memset(inbind, 0, sizeof(inbind));
2608
2609 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
2610
2611 unsigned long hwaddr_length = hwaddr.hwaddr_.size();
2612
2613 // If the data happens to be empty, we have to create a 1 byte dummy
2614 // buffer and pass it to the binding.
2615 std::vector<uint8_t> single_byte_vec(1);
2616
2617 // As "buffer" is "char*" - even though the data is being read - we need
2618 // to cast away the "const"ness as well as reinterpreting the data as
2619 // a "char*". (We could avoid the "const_cast" by copying the data to a
2620 // local variable, but as the data is only being read, this introduces
2621 // an unnecessary copy).
2622 uint8_t* data = !hwaddr.hwaddr_.empty() ? const_cast<uint8_t*>(&hwaddr.hwaddr_[0])
2623 : &single_byte_vec[0];
2624
2625 inbind[0].buffer = reinterpret_cast<char*>(data);
2626 inbind[0].buffer_length = hwaddr_length;
2627 inbind[0].length = &hwaddr_length;
2628
2629 inbind[1].buffer_type = MYSQL_TYPE_LONG;
2630 inbind[1].buffer = reinterpret_cast<char*>(&subnet_id);
2631 inbind[1].is_unsigned = MLM_TRUE;
2632
2633 // Get the data
2634 Lease4Ptr result;
2635
2636 // Get a context
2637 MySqlLeaseContextAlloc get_context(*this);
2638 MySqlLeaseContextPtr ctx = get_context.ctx_;
2639
2640 getLease(ctx, GET_LEASE4_HWADDR_SUBID, inbind, result);
2641
2642 return (result);
2643}
2644
2646MySqlLeaseMgr::getLease4(const ClientId& clientid) const {
2648 .arg(clientid.toText());
2649
2650 // Set up the WHERE clause value
2651 MYSQL_BIND inbind[1];
2652 memset(inbind, 0, sizeof(inbind));
2653
2654 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
2655
2656 std::vector<uint8_t> client_data = clientid.getClientId();
2657 unsigned long client_data_length = client_data.size();
2658
2659 // If the data happens to be empty, we have to create a 1 byte dummy
2660 // buffer and pass it to the binding.
2661 if (client_data.empty()) {
2662 client_data.resize(1);
2663 }
2664
2665 inbind[0].buffer = reinterpret_cast<char*>(&client_data[0]);
2666 inbind[0].buffer_length = client_data_length;
2667 inbind[0].length = &client_data_length;
2668
2669 // Get the data
2670 Lease4Collection result;
2671
2672 // Get a context
2673 MySqlLeaseContextAlloc get_context(*this);
2674 MySqlLeaseContextPtr ctx = get_context.ctx_;
2675
2676 getLeaseCollection(ctx, GET_LEASE4_CLIENTID, inbind, result);
2677
2678 return (result);
2679}
2680
2682MySqlLeaseMgr::getLease4(const ClientId& clientid, SubnetID subnet_id) const {
2684 .arg(subnet_id)
2685 .arg(clientid.toText());
2686
2687 // Set up the WHERE clause value
2688 MYSQL_BIND inbind[2];
2689 memset(inbind, 0, sizeof(inbind));
2690
2691 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
2692
2693 std::vector<uint8_t> client_data = clientid.getClientId();
2694 unsigned long client_data_length = client_data.size();
2695
2696 // If the data happens to be empty, we have to create a 1 byte dummy
2697 // buffer and pass it to the binding.
2698 if (client_data.empty()) {
2699 client_data.resize(1);
2700 }
2701
2702 inbind[0].buffer = reinterpret_cast<char*>(&client_data[0]);
2703 inbind[0].buffer_length = client_data_length;
2704 inbind[0].length = &client_data_length;
2705
2706 inbind[1].buffer_type = MYSQL_TYPE_LONG;
2707 inbind[1].buffer = reinterpret_cast<char*>(&subnet_id);
2708 inbind[1].is_unsigned = MLM_TRUE;
2709
2710 // Get the data
2711 Lease4Ptr result;
2712
2713 // Get a context
2714 MySqlLeaseContextAlloc get_context(*this);
2715 MySqlLeaseContextPtr ctx = get_context.ctx_;
2716
2717 getLease(ctx, GET_LEASE4_CLIENTID_SUBID, inbind, result);
2718
2719 return (result);
2720}
2721
2725 .arg(subnet_id);
2726
2727 // Set up the WHERE clause value
2728 MYSQL_BIND inbind[1];
2729 memset(inbind, 0, sizeof(inbind));
2730
2731 // Subnet ID
2732 inbind[0].buffer_type = MYSQL_TYPE_LONG;
2733 inbind[0].buffer = reinterpret_cast<char*>(&subnet_id);
2734 inbind[0].is_unsigned = MLM_TRUE;
2735
2736 // ... and get the data
2737 Lease4Collection result;
2738
2739 // Get a context
2740 MySqlLeaseContextAlloc get_context(*this);
2741 MySqlLeaseContextPtr ctx = get_context.ctx_;
2742
2743 getLeaseCollection(ctx, GET_LEASE4_SUBID, inbind, result);
2744
2745 return (result);
2746}
2747
2749MySqlLeaseMgr::getLeases4(const std::string& hostname) const {
2751 .arg(hostname);
2752
2753 // Set up the WHERE clause value
2754 MYSQL_BIND inbind[1];
2755 memset(inbind, 0, sizeof(inbind));
2756
2757 // Hostname
2758 inbind[0].buffer_type = MYSQL_TYPE_STRING;
2759 inbind[0].buffer = const_cast<char*>(hostname.c_str());
2760 inbind[0].buffer_length = hostname.length();
2761
2762 // ... and get the data
2763 Lease4Collection result;
2764
2765 // Get a context
2766 MySqlLeaseContextAlloc get_context(*this);
2767 MySqlLeaseContextPtr ctx = get_context.ctx_;
2768
2769 getLeaseCollection(ctx, GET_LEASE4_HOSTNAME, inbind, result);
2770
2771 return (result);
2772}
2773
2777
2778 Lease4Collection result;
2779
2780 // Get a context
2781 MySqlLeaseContextAlloc get_context(*this);
2782 MySqlLeaseContextPtr ctx = get_context.ctx_;
2783
2784 getLeaseCollection(ctx, GET_LEASE4, 0, result);
2785
2786 return (result);
2787}
2788
2790MySqlLeaseMgr::getLeases4(const IOAddress& lower_bound_address,
2791 const LeasePageSize& page_size) const {
2792 // Expecting IPv4 address.
2793 if (!lower_bound_address.isV4()) {
2794 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
2795 "retrieving leases from the lease database, got "
2796 << lower_bound_address);
2797 }
2798
2800 .arg(page_size.page_size_)
2801 .arg(lower_bound_address.toText());
2802
2803 // Prepare WHERE clause
2804 MYSQL_BIND inbind[2];
2805 memset(inbind, 0, sizeof(inbind));
2806
2807 // Bind lower bound address
2808 uint32_t lb_address_data = lower_bound_address.toUint32();
2809 inbind[0].buffer_type = MYSQL_TYPE_LONG;
2810 inbind[0].buffer = reinterpret_cast<char*>(&lb_address_data);
2811 inbind[0].is_unsigned = MLM_TRUE;
2812
2813 // Bind page size value
2814 uint32_t ps = static_cast<uint32_t>(page_size.page_size_);
2815 inbind[1].buffer_type = MYSQL_TYPE_LONG;
2816 inbind[1].buffer = reinterpret_cast<char*>(&ps);
2817 inbind[1].is_unsigned = MLM_TRUE;
2818
2819 // Get the leases
2820 Lease4Collection result;
2821
2822 // Get a context
2823 MySqlLeaseContextAlloc get_context(*this);
2824 MySqlLeaseContextPtr ctx = get_context.ctx_;
2825
2826 getLeaseCollection(ctx, GET_LEASE4_PAGE, inbind, result);
2827
2828 return (result);
2829}
2830
2833 const IOAddress& addr) const {
2835 .arg(addr.toText())
2836 .arg(lease_type);
2837
2838 // Set up the WHERE clause value
2839 MYSQL_BIND inbind[2];
2840 memset(inbind, 0, sizeof(inbind));
2841
2842 // address: binary(16)
2843 std::vector<uint8_t>addr6 = addr.toBytes();
2844 if (addr6.size() != 16) {
2845 isc_throw(DbOperationError, "lease6 address is not 16 bytes long");
2846 }
2847
2848 unsigned long addr6_length = 16;
2849 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
2850 inbind[0].buffer = reinterpret_cast<char*>(&addr6[0]);
2851 inbind[0].buffer_length = 16;
2852 inbind[0].length = &addr6_length;
2853
2854 // LEASE_TYPE
2855 inbind[1].buffer_type = MYSQL_TYPE_TINY;
2856 inbind[1].buffer = reinterpret_cast<char*>(&lease_type);
2857 inbind[1].is_unsigned = MLM_TRUE;
2858
2859 Lease6Ptr result;
2860
2861 // Get a context
2862 MySqlLeaseContextAlloc get_context(*this);
2863 MySqlLeaseContextPtr ctx = get_context.ctx_;
2864
2865 getLease(ctx, GET_LEASE6_ADDR, inbind, result);
2866
2867 return (result);
2868}
2869
2872 uint32_t iaid) const {
2874 .arg(iaid)
2875 .arg(duid.toText())
2876 .arg(lease_type);
2877
2878 // Set up the WHERE clause value
2879 MYSQL_BIND inbind[3];
2880 memset(inbind, 0, sizeof(inbind));
2881
2882 // In the following statement, the DUID is being read. However, the
2883 // MySQL C interface does not use "const", so the "buffer" element
2884 // is declared as "char*" instead of "const char*". To resolve this,
2885 // the "const" is discarded before the uint8_t* is cast to char*.
2886 //
2887 // Note that the const_cast could be avoided by copying the DUID to
2888 // a writable buffer and storing the address of that in the "buffer"
2889 // element. However, this introduces a copy operation (with additional
2890 // overhead) purely to get round the structures introduced by design of
2891 // the MySQL interface (which uses the area pointed to by "buffer" as
2892 // input when specifying query parameters and as output when retrieving
2893 // data). For that reason, "const_cast" has been used.
2894 const vector<uint8_t>& duid_vector = duid.getDuid();
2895 unsigned long duid_length = duid_vector.size();
2896
2897 // Make sure that the buffer has at least length of 1, even if
2898 // empty client id is passed. This is required by some of the
2899 // MySQL connectors that the buffer is set to non-null value.
2900 // Otherwise, null value would be inserted into the database,
2901 // rather than empty string.
2902 uint8_t single_byte_data = 0;
2903 uint8_t* data = !duid_vector.empty() ? const_cast<uint8_t*>(&duid_vector[0])
2904 : &single_byte_data;
2905
2906 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
2907 inbind[0].buffer = reinterpret_cast<char*>(data);
2908 inbind[0].buffer_length = duid_length;
2909 inbind[0].length = &duid_length;
2910
2911 // IAID
2912 inbind[1].buffer_type = MYSQL_TYPE_LONG;
2913 inbind[1].buffer = reinterpret_cast<char*>(&iaid);
2914 inbind[1].is_unsigned = MLM_TRUE;
2915
2916 // LEASE_TYPE
2917 inbind[2].buffer_type = MYSQL_TYPE_TINY;
2918 inbind[2].buffer = reinterpret_cast<char*>(&lease_type);
2919 inbind[2].is_unsigned = MLM_TRUE;
2920
2921 // ... and get the data
2922 Lease6Collection result;
2923
2924 // Get a context
2925 MySqlLeaseContextAlloc get_context(*this);
2926 MySqlLeaseContextPtr ctx = get_context.ctx_;
2927
2928 getLeaseCollection(ctx, GET_LEASE6_DUID_IAID, inbind, result);
2929
2930 return (result);
2931}
2932
2935 uint32_t iaid, SubnetID subnet_id) const {
2937 .arg(iaid)
2938 .arg(subnet_id)
2939 .arg(duid.toText())
2940 .arg(lease_type);
2941
2942 // Set up the WHERE clause value
2943 MYSQL_BIND inbind[4];
2944 memset(inbind, 0, sizeof(inbind));
2945
2946 // See the earlier description of the use of "const_cast" when accessing
2947 // the DUID for an explanation of the reason.
2948 const vector<uint8_t>& duid_vector = duid.getDuid();
2949 unsigned long duid_length = duid_vector.size();
2950 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
2951 inbind[0].buffer = reinterpret_cast<char*>(
2952 const_cast<uint8_t*>(&duid_vector[0]));
2953 inbind[0].buffer_length = duid_length;
2954 inbind[0].length = &duid_length;
2955
2956 // IAID
2957 inbind[1].buffer_type = MYSQL_TYPE_LONG;
2958 inbind[1].buffer = reinterpret_cast<char*>(&iaid);
2959 inbind[1].is_unsigned = MLM_TRUE;
2960
2961 // Subnet ID
2962 inbind[2].buffer_type = MYSQL_TYPE_LONG;
2963 inbind[2].buffer = reinterpret_cast<char*>(&subnet_id);
2964 inbind[2].is_unsigned = MLM_TRUE;
2965
2966 // LEASE_TYPE
2967 inbind[3].buffer_type = MYSQL_TYPE_TINY;
2968 inbind[3].buffer = reinterpret_cast<char*>(&lease_type);
2969 inbind[3].is_unsigned = MLM_TRUE;
2970
2971 // ... and get the data
2972 Lease6Collection result;
2973
2974 // Get a context
2975 MySqlLeaseContextAlloc get_context(*this);
2976 MySqlLeaseContextPtr ctx = get_context.ctx_;
2977
2978 getLeaseCollection(ctx, GET_LEASE6_DUID_IAID_SUBID, inbind, result);
2979
2980 return (result);
2981}
2982
2986 .arg(subnet_id);
2987
2988 // Set up the WHERE clause value
2989 MYSQL_BIND inbind[1];
2990 memset(inbind, 0, sizeof(inbind));
2991
2992 // Subnet ID
2993 inbind[0].buffer_type = MYSQL_TYPE_LONG;
2994 inbind[0].buffer = reinterpret_cast<char*>(&subnet_id);
2995 inbind[0].is_unsigned = MLM_TRUE;
2996
2997 // ... and get the data
2998 Lease6Collection result;
2999
3000 // Get a context
3001 MySqlLeaseContextAlloc get_context(*this);
3002 MySqlLeaseContextPtr ctx = get_context.ctx_;
3003
3004 getLeaseCollection(ctx, GET_LEASE6_SUBID, inbind, result);
3005
3006 return (result);
3007}
3008
3011 const IOAddress& lower_bound_address,
3012 const LeasePageSize& page_size) const {
3015 .arg(page_size.page_size_)
3016 .arg(lower_bound_address.toText())
3017 .arg(subnet_id);
3018
3019 // Expecting IPv6 valid address.
3020 if (!lower_bound_address.isV6()) {
3021 isc_throw(InvalidAddressFamily, "expected IPv6 start address while "
3022 "retrieving leases from the lease database, got "
3023 << lower_bound_address);
3024 }
3025
3026 Lease6Collection result;
3027 // Prepare WHERE clause
3028 MYSQL_BIND inbind[3];
3029 memset(inbind, 0, sizeof(inbind));
3030
3031 // Bind the subnet id.
3032 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3033 inbind[0].buffer = reinterpret_cast<char*>(&subnet_id);
3034 inbind[0].is_unsigned = MLM_TRUE;
3035
3036 // Bind the lower bound address.
3037 std::vector<uint8_t> lb_addr_data = lower_bound_address.toBytes();
3038 unsigned long lb_addr_size = lb_addr_data.size();
3039 if (lb_addr_size != 16) {
3040 isc_throw(DbOperationError, "lower bound address is not 16 bytes long");
3041 }
3042 inbind[1].buffer_type = MYSQL_TYPE_BLOB;
3043 inbind[1].buffer = reinterpret_cast<char*>(&lb_addr_data[0]);
3044 inbind[1].buffer_length = lb_addr_size;
3045 inbind[1].length = &lb_addr_size;
3046
3047 // Bind page size value
3048 uint32_t ps = static_cast<uint32_t>(page_size.page_size_);
3049 inbind[2].buffer_type = MYSQL_TYPE_LONG;
3050 inbind[2].buffer = reinterpret_cast<char*>(&ps);
3051 inbind[2].is_unsigned = MLM_TRUE;
3052
3053 // Get a context
3054 MySqlLeaseContextAlloc get_context(*this);
3055 MySqlLeaseContextPtr ctx = get_context.ctx_;
3056
3057 // Get the leases
3058 getLeaseCollection(ctx, GET_LEASE6_SUBID_PAGE, inbind, result);
3059
3060 return (result);
3061}
3062
3066
3067 Lease6Collection result;
3068
3069 // Get a context
3070 MySqlLeaseContextAlloc get_context(*this);
3071 MySqlLeaseContextPtr ctx = get_context.ctx_;
3072
3073 getLeaseCollection(ctx, GET_LEASE6, 0, result);
3074
3075 return (result);
3076}
3077
3081 .arg(duid.toText());
3082
3083 // Set up the WHERE clause value
3084 MYSQL_BIND inbind[1];
3085 memset(inbind, 0, sizeof(inbind));
3086
3087 const vector<uint8_t>& duid_vector = duid.getDuid();
3088 unsigned long duid_length = duid_vector.size();
3089
3090 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
3091 inbind[0].buffer = reinterpret_cast<char*>(
3092 const_cast<uint8_t*>(&duid_vector[0]));
3093 inbind[0].buffer_length = duid_length;
3094 inbind[0].length = &duid_length;
3095
3096 Lease6Collection result;
3097
3098 // Get a context
3099 MySqlLeaseContextAlloc get_context(*this);
3100 MySqlLeaseContextPtr ctx = get_context.ctx_;
3101
3102 getLeaseCollection(ctx, GET_LEASE6_DUID, inbind, result);
3103
3104 return result;
3105}
3106
3108MySqlLeaseMgr::getLeases6(const std::string& hostname) const {
3110 .arg(hostname);
3111
3112 // Set up the WHERE clause value
3113 MYSQL_BIND inbind[1];
3114 memset(inbind, 0, sizeof(inbind));
3115
3116 // Hostname
3117 inbind[0].buffer_type = MYSQL_TYPE_STRING;
3118 inbind[0].buffer = const_cast<char*>(hostname.c_str());
3119 inbind[0].buffer_length = hostname.length();
3120
3121 // ... and get the data
3122 Lease6Collection result;
3123
3124 // Get a context
3125 MySqlLeaseContextAlloc get_context(*this);
3126 MySqlLeaseContextPtr ctx = get_context.ctx_;
3127
3128 getLeaseCollection(ctx, GET_LEASE6_HOSTNAME, inbind, result);
3129
3130 return (result);
3131}
3132
3134MySqlLeaseMgr::getLeases6(const IOAddress& lower_bound_address,
3135 const LeasePageSize& page_size) const {
3136 // Expecting IPv6 address.
3137 if (!lower_bound_address.isV6()) {
3138 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3139 "retrieving leases from the lease database, got "
3140 << lower_bound_address);
3141 }
3142
3144 .arg(page_size.page_size_)
3145 .arg(lower_bound_address.toText());
3146
3147 // Prepare WHERE clause
3148 MYSQL_BIND inbind[2];
3149 memset(inbind, 0, sizeof(inbind));
3150
3151 // Bind lower bound address
3152 std::vector<uint8_t>lb_addr = lower_bound_address.toBytes();
3153 if (lb_addr.size() != 16) {
3154 isc_throw(DbOperationError, "getLeases6() - lower bound address is not 16 bytes long");
3155 }
3156
3157 unsigned long lb_addr_length = 16;
3158 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
3159 inbind[0].buffer = reinterpret_cast<char*>(&lb_addr[0]);
3160 inbind[0].buffer_length = 16;
3161 inbind[0].length = &lb_addr_length;
3162
3163 // Bind page size value
3164 uint32_t ps = static_cast<uint32_t>(page_size.page_size_);
3165 inbind[1].buffer_type = MYSQL_TYPE_LONG;
3166 inbind[1].buffer = reinterpret_cast<char*>(&ps);
3167 inbind[1].is_unsigned = MLM_TRUE;
3168
3169 // Get the leases
3170 Lease6Collection result;
3171
3172 // Get a context
3173 MySqlLeaseContextAlloc get_context(*this);
3174 MySqlLeaseContextPtr ctx = get_context.ctx_;
3175
3176 getLeaseCollection(ctx, GET_LEASE6_PAGE, inbind, result);
3177
3178 return (result);
3179}
3180
3181void
3183 const size_t max_leases) const {
3185 .arg(max_leases);
3186 getExpiredLeasesCommon(expired_leases, max_leases, GET_LEASE4_EXPIRE);
3187}
3188
3189void
3191 const size_t max_leases) const {
3193 .arg(max_leases);
3194 getExpiredLeasesCommon(expired_leases, max_leases, GET_LEASE6_EXPIRE);
3195}
3196
3197template<typename LeaseCollection>
3198void
3199MySqlLeaseMgr::getExpiredLeasesCommon(LeaseCollection& expired_leases,
3200 const size_t max_leases,
3201 StatementIndex statement_index) const {
3202 // Set up the WHERE clause value
3203 MYSQL_BIND inbind[3];
3204 memset(inbind, 0, sizeof(inbind));
3205
3206 // Exclude reclaimed leases.
3207 uint32_t state = static_cast<uint32_t>(Lease::STATE_EXPIRED_RECLAIMED);
3208 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3209 inbind[0].buffer = reinterpret_cast<char*>(&state);
3210 inbind[0].is_unsigned = MLM_TRUE;
3211
3212 // Expiration timestamp.
3213 MYSQL_TIME expire_time;
3214 MySqlConnection::convertToDatabaseTime(time(0), expire_time);
3215 inbind[1].buffer_type = MYSQL_TYPE_TIMESTAMP;
3216 inbind[1].buffer = reinterpret_cast<char*>(&expire_time);
3217 inbind[1].buffer_length = sizeof(expire_time);
3218
3219 // If the number of leases is 0, we will return all leases. This is
3220 // achieved by setting the limit to a very high value.
3221 uint32_t limit = max_leases > 0 ? static_cast<uint32_t>(max_leases) :
3222 std::numeric_limits<uint32_t>::max();
3223 inbind[2].buffer_type = MYSQL_TYPE_LONG;
3224 inbind[2].buffer = reinterpret_cast<char*>(&limit);
3225 inbind[2].is_unsigned = MLM_TRUE;
3226
3227 // Get a context
3228 MySqlLeaseContextAlloc get_context(*this);
3229 MySqlLeaseContextPtr ctx = get_context.ctx_;
3230
3231 // Get the data
3232 getLeaseCollection(ctx, statement_index, inbind, expired_leases);
3233}
3234
3235// Update lease methods. These comprise common code that handles the actual
3236// update, and type-specific methods that set up the parameters for the prepared
3237// statement depending on the type of lease.
3238
3239template <typename LeasePtr>
3240void
3241MySqlLeaseMgr::updateLeaseCommon(MySqlLeaseContextPtr& ctx,
3242 StatementIndex stindex,
3243 MYSQL_BIND* bind,
3244 const LeasePtr& lease) {
3245
3246 // Bind the parameters to the statement
3247 int status = mysql_stmt_bind_param(ctx->conn_.getStatement(stindex), bind);
3248 checkError(ctx, status, stindex, "unable to bind parameters");
3249
3250 // Execute
3251 status = MysqlExecuteStatement(ctx->conn_.getStatement(stindex));
3252 checkError(ctx, status, stindex, "unable to execute");
3253
3254 // See how many rows were affected. The statement should only update a
3255 // single row.
3256 int affected_rows = mysql_stmt_affected_rows(ctx->conn_.getStatement(stindex));
3257
3258 // Check success case first as it is the most likely outcome.
3259 if (affected_rows == 1) {
3260 return;
3261 }
3262
3263 // If no rows affected, lease doesn't exist.
3264 if (affected_rows == 0) {
3265 isc_throw(NoSuchLease, "unable to update lease for address " <<
3266 lease->addr_.toText() << " as it does not exist");
3267 }
3268
3269 // Should not happen - primary key constraint should only have selected
3270 // one row.
3271 isc_throw(DbOperationError, "apparently updated more than one lease "
3272 "that had the address " << lease->addr_.toText());
3273}
3274
3275void
3277 const StatementIndex stindex = UPDATE_LEASE4;
3278
3280 .arg(lease->addr_.toText());
3281
3282 // Get a context
3283 MySqlLeaseTrackingContextAlloc get_context(*this, lease);
3284 MySqlLeaseContextPtr ctx = get_context.ctx_;
3285
3286 // Create the MYSQL_BIND array for the data being updated
3287 std::vector<MYSQL_BIND> bind = ctx->exchange4_->createBindForSend(lease);
3288
3289 // Set up the WHERE clause and append it to the MYSQL_BIND array
3290 MYSQL_BIND inbind[2];
3291 memset(inbind, 0, sizeof(inbind));
3292
3293 uint32_t addr4 = lease->addr_.toUint32();
3294 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3295 inbind[0].buffer = reinterpret_cast<char*>(&addr4);
3296 inbind[0].is_unsigned = MLM_TRUE;
3297
3298 bind.push_back(inbind[0]);
3299
3300 // See the expire code of createBindForSend for the
3301 // infinite valid lifetime special case.
3302 MYSQL_TIME expire;
3303 uint32_t valid_lft = lease->current_valid_lft_;
3304 if (valid_lft == Lease::INFINITY_LFT) {
3305 valid_lft = 0;
3306 }
3307 MySqlConnection::convertToDatabaseTime(lease->current_cltt_, valid_lft,
3308 expire);
3309 inbind[1].buffer_type = MYSQL_TYPE_TIMESTAMP;
3310 inbind[1].buffer = reinterpret_cast<char*>(&expire);
3311 inbind[1].buffer_length = sizeof(expire);
3312
3313 bind.push_back(inbind[1]);
3314
3315 // Drop to common update code
3316 updateLeaseCommon(ctx, stindex, &bind[0], lease);
3317
3318 // Update lease current expiration time.
3319 lease->updateCurrentExpirationTime();
3320
3321 // Run installed callbacks.
3322 if (hasCallbacks()) {
3323 trackUpdateLease(lease);
3324 }
3325}
3326
3327void
3329 const StatementIndex stindex = UPDATE_LEASE6;
3330
3332 .arg(lease->addr_.toText())
3333 .arg(lease->type_);
3334
3335 // Get the recorded action and reset it.
3336 Lease6::ExtendedInfoAction recorded_action = lease->extended_info_action_;
3337 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
3338
3339 // Get a context
3340 MySqlLeaseTrackingContextAlloc get_context(*this, lease);
3341 MySqlLeaseContextPtr ctx = get_context.ctx_;
3342
3343 // Create the MYSQL_BIND array for the data being updated
3344 std::vector<MYSQL_BIND> bind = ctx->exchange6_->createBindForSend(lease);
3345
3346 // Set up the WHERE clause and append it to the MYSQL_BIND array
3347 MYSQL_BIND inbind[2];
3348 memset(inbind, 0, sizeof(inbind));
3349
3350 // Bind the where clause address parameter.
3351 std::vector<uint8_t>addr6 = lease->addr_.toBytes();
3352 if (addr6.size() != 16) {
3353 isc_throw(DbOperationError, "updateLease6() - address is not 16 bytes long");
3354 }
3355
3356 unsigned long addr6_length = 16;
3357 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
3358 inbind[0].buffer = reinterpret_cast<char*>(&addr6[0]);
3359 inbind[0].buffer_length = 16;
3360 inbind[0].length = &addr6_length;
3361
3362 bind.push_back(inbind[0]);
3363
3364 // See the expire code of createBindForSend for the
3365 // infinite valid lifetime special case.
3366 MYSQL_TIME expire;
3367 uint32_t valid_lft = lease->current_valid_lft_;
3368 if (valid_lft == Lease::INFINITY_LFT) {
3369 valid_lft = 0;
3370 }
3371 MySqlConnection::convertToDatabaseTime(lease->current_cltt_, valid_lft,
3372 expire);
3373 inbind[1].buffer_type = MYSQL_TYPE_TIMESTAMP;
3374 inbind[1].buffer = reinterpret_cast<char*>(&expire);
3375 inbind[1].buffer_length = sizeof(expire);
3376
3377 bind.push_back(inbind[1]);
3378
3379 // Drop to common update code
3380 updateLeaseCommon(ctx, stindex, &bind[0], lease);
3381
3382 // Update lease current expiration time.
3383 lease->updateCurrentExpirationTime();
3384
3385 // Update extended info tables.
3387 switch (recorded_action) {
3389 break;
3390
3392 deleteExtendedInfo6(lease->addr_);
3393 break;
3394
3396 deleteExtendedInfo6(lease->addr_);
3397 static_cast<void>(addExtendedInfo6(lease));
3398 break;
3399 }
3400 }
3401
3402 // Run installed callbacks.
3403 if (hasCallbacks()) {
3404 trackUpdateLease(lease);
3405 }
3406}
3407
3408// Delete lease methods. Similar to other groups of methods, these comprise
3409// a per-type method that sets up the relevant MYSQL_BIND array (in this
3410// case, a single method for both V4 and V6 addresses) and a common method that
3411// handles the common processing.
3412
3413uint64_t
3414MySqlLeaseMgr::deleteLeaseCommon(MySqlLeaseContextPtr& ctx,
3415 StatementIndex stindex,
3416 MYSQL_BIND* bind) {
3417 // Bind the input parameters to the statement
3418 int status = mysql_stmt_bind_param(ctx->conn_.getStatement(stindex), bind);
3419 checkError(ctx, status, stindex, "unable to bind WHERE clause parameter");
3420
3421 // Execute
3422 status = MysqlExecuteStatement(ctx->conn_.getStatement(stindex));
3423 checkError(ctx, status, stindex, "unable to execute");
3424
3425 // See how many rows were affected. Note that the statement may delete
3426 // multiple rows.
3427 return (mysql_stmt_affected_rows(ctx->conn_.getStatement(stindex)));
3428}
3429
3430bool
3432 const IOAddress& addr = lease->addr_;
3434 .arg(addr.toText());
3435
3436 // Set up the WHERE clause value
3437 MYSQL_BIND inbind[2];
3438 memset(inbind, 0, sizeof(inbind));
3439
3440 uint32_t addr4 = addr.toUint32();
3441
3442 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3443 inbind[0].buffer = reinterpret_cast<char*>(&addr4);
3444 inbind[0].is_unsigned = MLM_TRUE;
3445
3446 // See the expire code of createBindForSend for the
3447 // infinite valid lifetime special case.
3448 MYSQL_TIME expire;
3449 uint32_t valid_lft = lease->current_valid_lft_;
3450 if (valid_lft == Lease::INFINITY_LFT) {
3451 valid_lft = 0;
3452 }
3453 MySqlConnection::convertToDatabaseTime(lease->current_cltt_, valid_lft,
3454 expire);
3455 inbind[1].buffer_type = MYSQL_TYPE_TIMESTAMP;
3456 inbind[1].buffer = reinterpret_cast<char*>(&expire);
3457 inbind[1].buffer_length = sizeof(expire);
3458
3459 // Get a context
3460 MySqlLeaseTrackingContextAlloc get_context(*this, lease);
3461 MySqlLeaseContextPtr ctx = get_context.ctx_;
3462
3463 auto affected_rows = deleteLeaseCommon(ctx, DELETE_LEASE4, inbind);
3464
3465 // Check success case first as it is the most likely outcome.
3466 if (affected_rows == 1) {
3467 if (hasCallbacks()) {
3468 trackDeleteLease(lease);
3469 }
3470 return (true);
3471 }
3472
3473 // If no rows affected, lease doesn't exist.
3474 if (affected_rows == 0) {
3475 return (false);
3476 }
3477
3478 // Should not happen - primary key constraint should only have selected
3479 // one row.
3480 isc_throw(DbOperationError, "apparently deleted more than one lease "
3481 "that had the address " << lease->addr_.toText());
3482}
3483
3484bool
3486 const IOAddress& addr = lease->addr_;
3489 .arg(addr.toText());
3490
3491 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
3492
3493 // Set up the WHERE clause value
3494 MYSQL_BIND inbind[2];
3495 memset(inbind, 0, sizeof(inbind));
3496
3497 // Bind the where clause address parameter.
3498 std::vector<uint8_t>addr6 = addr.toBytes();
3499 if (addr6.size() != 16) {
3500 isc_throw(DbOperationError, "deleteLease6() - address is not 16 bytes long");
3501 }
3502
3503 unsigned long addr6_length = 16;
3504 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
3505 inbind[0].buffer = reinterpret_cast<char*>(&addr6[0]);
3506 inbind[0].buffer_length = 16;
3507 inbind[0].length = &addr6_length;
3508
3509 // See the expire code of createBindForSend for the
3510 // infinite valid lifetime special case.
3511 MYSQL_TIME expire;
3512 uint32_t valid_lft = lease->current_valid_lft_;
3513 if (valid_lft == Lease::INFINITY_LFT) {
3514 valid_lft = 0;
3515 }
3516 MySqlConnection::convertToDatabaseTime(lease->current_cltt_, valid_lft,
3517 expire);
3518 inbind[1].buffer_type = MYSQL_TYPE_TIMESTAMP;
3519 inbind[1].buffer = reinterpret_cast<char*>(&expire);
3520 inbind[1].buffer_length = sizeof(expire);
3521
3522 // Get a context
3523 MySqlLeaseTrackingContextAlloc get_context(*this, lease);
3524 MySqlLeaseContextPtr ctx = get_context.ctx_;
3525
3526 auto affected_rows = deleteLeaseCommon(ctx, DELETE_LEASE6, inbind);
3527
3528 // Check success case first as it is the most likely outcome.
3529 if (affected_rows == 1) {
3530 // Delete references from extended info tables.
3531 // Performed by the delete cascade.
3532
3533 // Run installed callbacks.
3534 if (hasCallbacks()) {
3535 trackDeleteLease(lease);
3536 }
3537 return (true);
3538 }
3539
3540 // If no rows affected, lease doesn't exist.
3541 if (affected_rows == 0) {
3542 return (false);
3543 }
3544
3545 // Should not happen - primary key constraint should only have selected
3546 // one row.
3547 isc_throw(DbOperationError, "apparently deleted more than one lease "
3548 "that had the address " << lease->addr_.toText());
3549}
3550
3551uint64_t
3554 .arg(secs);
3555 return (deleteExpiredReclaimedLeasesCommon(secs, DELETE_LEASE4_STATE_EXPIRED));
3556}
3557
3558uint64_t
3561 .arg(secs);
3562 return (deleteExpiredReclaimedLeasesCommon(secs, DELETE_LEASE6_STATE_EXPIRED));
3563}
3564
3565uint64_t
3566MySqlLeaseMgr::deleteExpiredReclaimedLeasesCommon(const uint32_t secs,
3567 StatementIndex statement_index) {
3568 // Set up the WHERE clause value
3569 MYSQL_BIND inbind[2];
3570 memset(inbind, 0, sizeof(inbind));
3571
3572 // State is reclaimed.
3573 uint32_t state = static_cast<uint32_t>(Lease::STATE_EXPIRED_RECLAIMED);
3574 inbind[0].buffer_type = MYSQL_TYPE_LONG;
3575 inbind[0].buffer = reinterpret_cast<char*>(&state);
3576 inbind[0].is_unsigned = MLM_TRUE;
3577
3578 // Expiration timestamp.
3579 MYSQL_TIME expire_time;
3580 MySqlConnection::convertToDatabaseTime(time(0) - static_cast<time_t>(secs), expire_time);
3581 inbind[1].buffer_type = MYSQL_TYPE_TIMESTAMP;
3582 inbind[1].buffer = reinterpret_cast<char*>(&expire_time);
3583 inbind[1].buffer_length = sizeof(expire_time);
3584
3585 // Get a context
3586 MySqlLeaseContextAlloc get_context(*this);
3587 MySqlLeaseContextPtr ctx = get_context.ctx_;
3588
3589 // Get the number of deleted leases and log it.
3590 uint64_t deleted_leases = deleteLeaseCommon(ctx, statement_index, inbind);
3592 .arg(deleted_leases);
3593
3594 return (deleted_leases);
3595}
3596
3597string
3598MySqlLeaseMgr::checkLimits(ConstElementPtr const& user_context, StatementIndex const stindex) const {
3599 // No user context means no limits means allocation allowed means empty string.
3600 if (!user_context) {
3601 return string();
3602 }
3603
3604 // Get a context.
3605 MySqlLeaseContextAlloc get_context(*this);
3606 MySqlLeaseContextPtr ctx = get_context.ctx_;
3607
3608 // Create bindings.
3609 MySqlBindingCollection in_bindings({
3610 MySqlBinding::createString(user_context->str())
3611 });
3612 MySqlBindingCollection out_bindings({
3613 MySqlBinding::createString(LIMITS_TEXT_MAX_LEN)
3614 });
3615
3616 // Execute the select.
3617 std::string limit_text;
3618 ctx->conn_.selectQuery(stindex, in_bindings, out_bindings,
3619 [&limit_text] (MySqlBindingCollection const& result) {
3620 limit_text = result[0]->getString();
3621 });
3622
3623 return limit_text;
3624}
3625
3626string
3627MySqlLeaseMgr::checkLimits4(ConstElementPtr const& user_context) const {
3628 return checkLimits(user_context, CHECK_LEASE4_LIMITS);
3629}
3630
3631string
3632MySqlLeaseMgr::checkLimits6(ConstElementPtr const& user_context) const {
3633 return checkLimits(user_context, CHECK_LEASE6_LIMITS);
3634}
3635
3636bool
3637MySqlLeaseMgr::isJsonSupported() const {
3638 // Get a context.
3639 MySqlLeaseContextAlloc get_context(*this);
3640 MySqlLeaseContextPtr ctx = get_context.ctx_;
3641
3642 // Create bindings.
3643 MySqlBindingCollection in_bindings;
3644 MySqlBindingCollection out_bindings({
3646 });
3647
3648 // Execute the select.
3649 bool json_supported(false);
3650 ctx->conn_.selectQuery(IS_JSON_SUPPORTED, in_bindings, out_bindings,
3651 [&json_supported] (MySqlBindingCollection const& result) {
3652 json_supported = result[0]->getBool();
3653 });
3654
3655 return json_supported;
3656}
3657
3658size_t
3659MySqlLeaseMgr::getClassLeaseCount(const ClientClass& client_class,
3660 const Lease::Type& ltype /* = Lease::TYPE_V4*/) const {
3661 // Get a context.
3662 MySqlLeaseContextAlloc get_context(*this);
3663 MySqlLeaseContextPtr ctx = get_context.ctx_;
3664
3665 // Create bindings.
3666 MySqlBindingCollection in_bindings({
3667 MySqlBinding::createString(client_class)
3668 });
3669 if (ltype != Lease::TYPE_V4) {
3670 in_bindings.push_back(MySqlBinding::createInteger<uint8_t>(ltype));
3671 }
3672 MySqlBindingCollection out_bindings({
3673 MySqlBinding::createInteger<int64_t>()
3674 });
3675
3676 // Execute the select.
3679 size_t count(0);
3680 ctx->conn_.selectQuery(stindex, in_bindings, out_bindings,
3681 [&count] (MySqlBindingCollection const& result) {
3682 count = result[0]->getInteger<int64_t>();
3683 });
3684
3685 return count;
3686}
3687
3688void
3689MySqlLeaseMgr::recountClassLeases4() {
3690 isc_throw(NotImplemented, "MySqlLeaseMgr::recountClassLeases4() not implemented");
3691}
3692
3693void
3694MySqlLeaseMgr::recountClassLeases6() {
3695 isc_throw(NotImplemented, "MySqlLeaseMgr::recountClassLeases6() not implemented");
3696}
3697
3698void
3699MySqlLeaseMgr::clearClassLeaseCounts() {
3700 isc_throw(NotImplemented, "MySqlLeaseMgr::clearClassLeaseCounts() not implemented");
3701}
3702
3703void
3704MySqlLeaseMgr::writeLeases4(const std::string&) {
3705 isc_throw(NotImplemented, "MySqlLeaseMgr::writeLeases4() not implemented");
3706}
3707
3708void
3709MySqlLeaseMgr::writeLeases6(const std::string&) {
3710 isc_throw(NotImplemented, "MySqlLeaseMgr::writeLeases6() not implemented");
3711}
3712
3715 // Get a context
3716 MySqlLeaseContextAlloc get_context(*this);
3717 MySqlLeaseContextPtr ctx = get_context.ctx_;
3718
3719 LeaseStatsQueryPtr query(new MySqlLeaseStatsQuery(ctx->conn_,
3721 false));
3722 query->start();
3723 return(query);
3724}
3725
3728 // Get a context
3729 MySqlLeaseContextAlloc get_context(*this);
3730 MySqlLeaseContextPtr ctx = get_context.ctx_;
3731
3732 LeaseStatsQueryPtr query(new MySqlLeaseStatsQuery(ctx->conn_,
3734 false, true));
3735 query->start();
3736 return(query);
3737}
3738
3741 // Get a context
3742 MySqlLeaseContextAlloc get_context(*this);
3743 MySqlLeaseContextPtr ctx = get_context.ctx_;
3744
3745 LeaseStatsQueryPtr query(new MySqlLeaseStatsQuery(ctx->conn_,
3747 false,
3748 subnet_id));
3749 query->start();
3750 return(query);
3751}
3752
3755 const SubnetID& last_subnet_id) {
3756 // Get a context
3757 MySqlLeaseContextAlloc get_context(*this);
3758 MySqlLeaseContextPtr ctx = get_context.ctx_;
3759
3760 LeaseStatsQueryPtr query(new MySqlLeaseStatsQuery(ctx->conn_,
3762 false,
3763 first_subnet_id,
3764 last_subnet_id));
3765 query->start();
3766 return(query);
3767}
3768
3771 // Get a context
3772 MySqlLeaseContextAlloc get_context(*this);
3773 MySqlLeaseContextPtr ctx = get_context.ctx_;
3774
3775 LeaseStatsQueryPtr query(new MySqlLeaseStatsQuery(ctx->conn_,
3777 true));
3778 query->start();
3779 return(query);
3780}
3781
3784 // Get a context
3785 MySqlLeaseContextAlloc get_context(*this);
3786 MySqlLeaseContextPtr ctx = get_context.ctx_;
3787
3788 LeaseStatsQueryPtr query(new MySqlLeaseStatsQuery(ctx->conn_,
3790 true, true));
3791 query->start();
3792 return(query);
3793}
3794
3797 // Get a context
3798 MySqlLeaseContextAlloc get_context(*this);
3799 MySqlLeaseContextPtr ctx = get_context.ctx_;
3800
3801 LeaseStatsQueryPtr query(new MySqlLeaseStatsQuery(ctx->conn_,
3803 true,
3804 subnet_id));
3805 query->start();
3806 return(query);
3807}
3808
3811 const SubnetID& last_subnet_id) {
3812 // Get a context
3813 MySqlLeaseContextAlloc get_context(*this);
3814 MySqlLeaseContextPtr ctx = get_context.ctx_;
3815
3816 LeaseStatsQueryPtr query(new MySqlLeaseStatsQuery(ctx->conn_,
3818 true,
3819 first_subnet_id,
3820 last_subnet_id));
3821 query->start();
3822 return(query);
3823}
3824
3825size_t
3827 isc_throw(NotImplemented, "wipeLeases4 is not implemented for MySQL backend");
3828}
3829
3830size_t
3832 isc_throw(NotImplemented, "wipeLeases6 is not implemented for MySQL backend");
3833}
3834
3835// Miscellaneous database methods.
3836
3837std::string
3839 // Get a context
3840 MySqlLeaseContextAlloc get_context(*this);
3841 MySqlLeaseContextPtr ctx = get_context.ctx_;
3842
3843 std::string name = "";
3844 try {
3845 name = ctx->conn_.getParameter("name");
3846 } catch (...) {
3847 // Return an empty name
3848 }
3849 return (name);
3850}
3851
3852std::string
3854 return (std::string("MySQL Database"));
3855}
3856
3857std::pair<uint32_t, uint32_t>
3866
3867void
3871
3872void
3876
3877void
3878MySqlLeaseMgr::checkError(MySqlLeaseContextPtr& ctx,
3879 int status, StatementIndex index,
3880 const char* what) const {
3881 ctx->conn_.checkError(status, index, what);
3882}
3883
3884void
3886 deleteRelayId6(addr);
3887 deleteRemoteId6(addr);
3888}
3889
3890void
3891MySqlLeaseMgr::deleteRelayId6(const IOAddress& addr) {
3892 // Get a context.
3893 MySqlLeaseContextAlloc get_context(*this);
3894 MySqlLeaseContextPtr ctx = get_context.ctx_;
3895
3896 // Bind the lease address.
3897 MYSQL_BIND bind[1];
3898 memset(bind, 0, sizeof(bind));
3899
3900 std::vector<uint8_t> addr_data = addr.toBytes();
3901 // Do not check the address length as it does not really matter.
3902 unsigned long addr_size = addr_data.size();
3903 bind[0].buffer_type = MYSQL_TYPE_BLOB;
3904 bind[0].buffer = reinterpret_cast<char*>(&addr_data[0]);
3905 bind[0].buffer_length = addr_size;
3906 bind[0].length = &addr_size;
3907
3908 // Delete from lease6_relay_id table.
3910
3911 // Bind the input parameters to the statement.
3912 int status = mysql_stmt_bind_param(ctx->conn_.getStatement(stindex), bind);
3913 checkError(ctx, status, stindex, "unable to bind WHERE clause parameter");
3914
3915 // Execute.
3916 status = MysqlExecuteStatement(ctx->conn_.getStatement(stindex));
3917 checkError(ctx, status, stindex, "unable to execute");
3918}
3919
3920void
3921MySqlLeaseMgr::deleteRemoteId6(const IOAddress& addr) {
3922 // Get a context.
3923 MySqlLeaseContextAlloc get_context(*this);
3924 MySqlLeaseContextPtr ctx = get_context.ctx_;
3925
3926 // Bind the lease address.
3927 MYSQL_BIND bind[1];
3928 memset(bind, 0, sizeof(bind));
3929
3930 std::vector<uint8_t> addr_data = addr.toBytes();
3931 // Do not check the address length as it does not really matter.
3932 unsigned long addr_size = addr_data.size();
3933 bind[0].buffer_type = MYSQL_TYPE_BLOB;
3934 bind[0].buffer = reinterpret_cast<char*>(&addr_data[0]);
3935 bind[0].buffer_length = addr_size;
3936 bind[0].length = &addr_size;
3937
3938 // Delete from lease6_remote_id table.
3940
3941 // Bind the input parameters to the statement.
3942 int status = mysql_stmt_bind_param(ctx->conn_.getStatement(stindex), bind);
3943 checkError(ctx, status, stindex, "unable to bind WHERE clause parameter");
3944
3945 // Execute.
3946 status = MysqlExecuteStatement(ctx->conn_.getStatement(stindex));
3947 checkError(ctx, status, stindex, "unable to execute");
3948}
3949
3950void
3952 const vector<uint8_t>& relay_id) {
3953 // Get a context.
3954 MySqlLeaseContextAlloc get_context(*this);
3955 MySqlLeaseContextPtr ctx = get_context.ctx_;
3956
3957 // Bind the relay id.
3958 MYSQL_BIND bind[2];
3959 memset(bind, 0, sizeof(bind));
3960
3961 unsigned long relay_id_size = relay_id.size();
3962 if (relay_id_size == 0) {
3963 isc_throw(BadValue, "empty relay id");
3964 }
3965 std::vector<uint8_t> relay_id_data = relay_id;
3966 bind[0].buffer_type = MYSQL_TYPE_BLOB;
3967 bind[0].buffer = reinterpret_cast<char*>(&relay_id_data[0]);
3968 bind[0].buffer_length = relay_id_size;
3969 bind[0].length = &relay_id_size;
3970
3971 // Bind the lease address.
3972 std::vector<uint8_t> lease_addr_data = lease_addr.toBytes();
3973 unsigned long lease_addr_length = lease_addr_data.size();
3974 if (lease_addr_length != 16) {
3975 isc_throw(DbOperationError, "lease6 address is not 16 bytes long");
3976 }
3977 bind[1].buffer_type = MYSQL_TYPE_BLOB;
3978 bind[1].buffer = reinterpret_cast<char*>(&lease_addr_data[0]);
3979 bind[1].buffer_length = lease_addr_length;
3980 bind[1].length = &lease_addr_length;
3981
3982 // Add to lease6_relay_id table.
3983 StatementIndex stindex = ADD_RELAY_ID6;
3984
3985 // Bind the input parameters to the statement.
3986 int status = mysql_stmt_bind_param(ctx->conn_.getStatement(stindex), bind);
3987 checkError(ctx, status, stindex, "unable to bind WHERE clause parameter");
3988
3989 // Execute.
3990 status = MysqlExecuteStatement(ctx->conn_.getStatement(stindex));
3991 checkError(ctx, status, stindex, "unable to execute");
3992}
3993
3994void
3996 const vector<uint8_t>& remote_id) {
3997 // Get a context.
3998 MySqlLeaseContextAlloc get_context(*this);
3999 MySqlLeaseContextPtr ctx = get_context.ctx_;
4000
4001 // Bind the remote id.
4002 MYSQL_BIND bind[2];
4003 memset(bind, 0, sizeof(bind));
4004
4005 unsigned long remote_id_size = remote_id.size();
4006 if (remote_id_size == 0) {
4007 isc_throw(BadValue, "empty remote id");
4008 }
4009 std::vector<uint8_t> remote_id_data = remote_id;
4010 bind[0].buffer_type = MYSQL_TYPE_BLOB;
4011 bind[0].buffer = reinterpret_cast<char*>(&remote_id_data[0]);
4012 bind[0].buffer_length = remote_id_size;
4013 bind[0].length = &remote_id_size;
4014
4015 // Bind the lease address.
4016 std::vector<uint8_t> lease_addr_data = lease_addr.toBytes();
4017 unsigned long lease_addr_length = lease_addr_data.size();
4018 if (lease_addr_length != 16) {
4019 isc_throw(DbOperationError, "lease6 address is not 16 bytes long");
4020 }
4021 bind[1].buffer_type = MYSQL_TYPE_BLOB;
4022 bind[1].buffer = reinterpret_cast<char*>(&lease_addr_data[0]);
4023 bind[1].buffer_length = lease_addr_length;
4024 bind[1].length = &lease_addr_length;
4025
4026 // Add to lease6_remote_id table.
4028
4029 // Bind the input parameters to the statement.
4030 int status = mysql_stmt_bind_param(ctx->conn_.getStatement(stindex), bind);
4031 checkError(ctx, status, stindex, "unable to bind WHERE clause parameter");
4032
4033 // Execute.
4034 status = MysqlExecuteStatement(ctx->conn_.getStatement(stindex));
4035 checkError(ctx, status, stindex, "unable to execute");
4036}
4037
4038namespace {
4039
4040std::string
4041idToText(const OptionBuffer& id) {
4042 std::stringstream tmp;
4043 tmp << std::hex;
4044 bool delim = false;
4045 for (auto const& it : id) {
4046 if (delim) {
4047 tmp << ":";
4048 }
4049 tmp << std::setw(2) << std::setfill('0')
4050 << static_cast<unsigned int>(it);
4051 delim = true;
4052 }
4053 return (tmp.str());
4054}
4055
4056} // anonymous namespace
4057
4060 const IOAddress& lower_bound_address,
4061 const LeasePageSize& page_size,
4062 const time_t& qry_start_time /* = 0 */,
4063 const time_t& qry_end_time /* = 0 */) {
4066 .arg(page_size.page_size_)
4067 .arg(lower_bound_address.toText())
4068 .arg(idToText(relay_id))
4069 .arg(qry_start_time)
4070 .arg(qry_end_time);
4071
4072 // Expecting IPv4 address.
4073 if (!lower_bound_address.isV4()) {
4074 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
4075 "retrieving leases from the lease database, got "
4076 << lower_bound_address);
4077 }
4078
4079 // Catch 2038 bug with 32 bit time_t.
4080 if ((qry_start_time < 0) || (qry_end_time < 0)) {
4081 isc_throw(BadValue, "negative time value");
4082 }
4083
4084 bool have_qst = (qry_start_time > 0);
4085 bool have_qet = (qry_end_time > 0);
4086
4087 // Start time must be before end time.
4088 if (have_qst && have_qet && (qry_start_time > qry_end_time)) {
4089 isc_throw(BadValue, "start time must be before end time");
4090 }
4091
4092 // Prepare WHERE clause
4093 size_t bindings = 3;
4094 if (have_qst) {
4095 ++bindings;
4096 }
4097 if (have_qet) {
4098 ++bindings;
4099 }
4100 MYSQL_BIND zeroed_out;
4101 memset(&zeroed_out, 0, sizeof(zeroed_out));
4102 vector<MYSQL_BIND> inbind(bindings, zeroed_out);
4103
4104 std::vector<uint8_t> relay_id_data = relay_id;
4105 unsigned long relay_id_length = relay_id.size();
4106
4107 // If the relay id happens to be empty, we have to create a
4108 // 1 byte dummy buffer and pass it to the binding.
4109 if (relay_id_data.empty()) {
4110 relay_id_data.resize(1);
4111 }
4112
4113 // Bind relay id
4114 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
4115 inbind[0].buffer = reinterpret_cast<char*>(&relay_id_data[0]);
4116 inbind[0].buffer_length = relay_id_length;
4117 inbind[0].length = &relay_id_length;
4118
4119 // Bind lower bound address
4120 uint32_t lb_address_data = lower_bound_address.toUint32();
4121 inbind[1].buffer_type = MYSQL_TYPE_LONG;
4122 inbind[1].buffer = reinterpret_cast<char*>(&lb_address_data);
4123 inbind[1].is_unsigned = MLM_TRUE;
4124
4125 size_t index = 2;
4126 // Bind query start time.
4127 uint32_t start_time = static_cast<uint32_t>(qry_start_time);
4128 if (have_qst) {
4129 inbind[index].buffer_type = MYSQL_TYPE_LONG;
4130 inbind[index].buffer = reinterpret_cast<char*>(&start_time);
4131 inbind[index].is_unsigned = MLM_TRUE;
4132 ++index;
4133 }
4134
4135 // Bind query end time.
4136 uint32_t end_time = static_cast<uint32_t>(qry_end_time);
4137 if (have_qet) {
4138 inbind[index].buffer_type = MYSQL_TYPE_LONG;
4139 inbind[index].buffer = reinterpret_cast<char*>(&end_time);
4140 inbind[index].is_unsigned = MLM_TRUE;
4141 ++index;
4142 }
4143
4144 // Bind page size value
4145 uint32_t ps = static_cast<uint32_t>(page_size.page_size_);
4146 inbind[index].buffer_type = MYSQL_TYPE_LONG;
4147 inbind[index].buffer = reinterpret_cast<char*>(&ps);
4148 inbind[index].is_unsigned = MLM_TRUE;
4149
4151 if (have_qst && !have_qet) {
4152 stindex = GET_LEASE4_RELAYID_QST;
4153 } else if (have_qst && have_qet) {
4154 stindex = GET_LEASE4_RELAYID_QSET;
4155 } else if (!have_qst && have_qet) {
4156 stindex = GET_LEASE4_RELAYID_QET;
4157 }
4158
4159 // Get the leases
4160 Lease4Collection result;
4161
4162 // Get a context
4163 MySqlLeaseContextAlloc get_context(*this);
4164 MySqlLeaseContextPtr ctx = get_context.ctx_;
4165
4166 getLeaseCollection(ctx, stindex, inbind.data(), result);
4167
4168 return (result);
4169}
4170
4173 const IOAddress& lower_bound_address,
4174 const LeasePageSize& page_size,
4175 const time_t& qry_start_time /* = 0 */,
4176 const time_t& qry_end_time /* = 0 */) {
4179 .arg(page_size.page_size_)
4180 .arg(lower_bound_address.toText())
4181 .arg(idToText(remote_id))
4182 .arg(qry_start_time)
4183 .arg(qry_end_time);
4184
4185 // Expecting IPv4 address.
4186 if (!lower_bound_address.isV4()) {
4187 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
4188 "retrieving leases from the lease database, got "
4189 << lower_bound_address);
4190 }
4191
4192 // Catch 2038 bug with 32 bit time_t.
4193 if ((qry_start_time < 0) || (qry_end_time < 0)) {
4194 isc_throw(BadValue, "negative time value");
4195 }
4196
4197 bool have_qst = (qry_start_time > 0);
4198 bool have_qet = (qry_end_time > 0);
4199
4200 // Start time must be before end time.
4201 if (have_qst && have_qet && (qry_start_time > qry_end_time)) {
4202 isc_throw(BadValue, "start time must be before end time");
4203 }
4204
4205 // Prepare WHERE clause
4206 size_t bindings = 3;
4207 if (have_qst) {
4208 ++bindings;
4209 }
4210 if (have_qet) {
4211 ++bindings;
4212 }
4213 MYSQL_BIND zeroed_out;
4214 memset(&zeroed_out, 0, sizeof(zeroed_out));
4215 vector<MYSQL_BIND> inbind(bindings, zeroed_out);
4216
4217 std::vector<uint8_t> remote_id_data = remote_id;
4218 unsigned long remote_id_length = remote_id.size();
4219
4220 // If the remote id happens to be empty, we have to create a
4221 // 1 byte dummy buffer and pass it to the binding.
4222 if (remote_id_data.empty()) {
4223 remote_id_data.resize(1);
4224 }
4225
4226 // Bind remote id
4227 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
4228 inbind[0].buffer = reinterpret_cast<char*>(&remote_id_data[0]);
4229 inbind[0].buffer_length = remote_id_length;
4230 inbind[0].length = &remote_id_length;
4231
4232 // Bind lower bound address
4233 uint32_t lb_address_data = lower_bound_address.toUint32();
4234 inbind[1].buffer_type = MYSQL_TYPE_LONG;
4235 inbind[1].buffer = reinterpret_cast<char*>(&lb_address_data);
4236 inbind[1].is_unsigned = MLM_TRUE;
4237
4238 size_t index = 2;
4239 // Bind query start time.
4240 uint32_t start_time = static_cast<uint32_t>(qry_start_time);
4241 if (have_qst) {
4242 inbind[index].buffer_type = MYSQL_TYPE_LONG;
4243 inbind[index].buffer = reinterpret_cast<char*>(&start_time);
4244 inbind[index].is_unsigned = MLM_TRUE;
4245 ++index;
4246 }
4247
4248 // Bind query end time.
4249 uint32_t end_time = static_cast<uint32_t>(qry_end_time);
4250 if (have_qet) {
4251 inbind[index].buffer_type = MYSQL_TYPE_LONG;
4252 inbind[index].buffer = reinterpret_cast<char*>(&end_time);
4253 inbind[index].is_unsigned = MLM_TRUE;
4254 ++index;
4255 }
4256
4257 // Bind page size value
4258 uint32_t ps = static_cast<uint32_t>(page_size.page_size_);
4259 inbind[index].buffer_type = MYSQL_TYPE_LONG;
4260 inbind[index].buffer = reinterpret_cast<char*>(&ps);
4261 inbind[index].is_unsigned = MLM_TRUE;
4262
4264 if (have_qst && !have_qet) {
4265 stindex = GET_LEASE4_REMOTEID_QST;
4266 } else if (have_qst && have_qet) {
4267 stindex = GET_LEASE4_REMOTEID_QSET;
4268 } else if (!have_qst && have_qet) {
4269 stindex = GET_LEASE4_REMOTEID_QET;
4270 }
4271
4272 // Get the leases
4273 Lease4Collection result;
4274
4275 // Get a context
4276 MySqlLeaseContextAlloc get_context(*this);
4277 MySqlLeaseContextPtr ctx = get_context.ctx_;
4278
4279 getLeaseCollection(ctx, stindex, inbind.data(), result);
4280
4281 return (result);
4282}
4283
4284size_t
4286 auto check = CfgMgr::instance().getCurrentCfg()->
4287 getConsistency()->getExtendedInfoSanityCheck();
4288
4289 size_t pages = 0;
4290 size_t updated = 0;
4292 for (;;) {
4295 .arg(pages)
4296 .arg(start_addr.toText())
4297 .arg(updated);
4298
4299 // Prepare WHERE clause.
4300 MYSQL_BIND inbind[2];
4301 memset(inbind, 0, sizeof(inbind));
4302
4303 // Bind start address.
4304 uint32_t start_addr_data = start_addr.toUint32();
4305 inbind[0].buffer_type = MYSQL_TYPE_LONG;
4306 inbind[0].buffer = reinterpret_cast<char*>(&start_addr_data);
4307 inbind[0].is_unsigned = MLM_TRUE;
4308
4309 // Bind page size value.
4310 uint32_t ps = static_cast<uint32_t>(page_size.page_size_);
4311 inbind[1].buffer_type = MYSQL_TYPE_LONG;
4312 inbind[1].buffer = reinterpret_cast<char*>(&ps);
4313 inbind[1].is_unsigned = MLM_TRUE;
4314
4315 Lease4Collection leases;
4316
4317 // Get a context.
4318 {
4319 MySqlLeaseContextAlloc get_context(*this);
4320 MySqlLeaseContextPtr ctx = get_context.ctx_;
4321
4322 getLeaseCollection(ctx, GET_LEASE4_UCTX_PAGE, inbind, leases);
4323 }
4324
4325 if (leases.empty()) {
4326 // Done.
4327 break;
4328 }
4329
4330 ++pages;
4331 start_addr = leases.back()->addr_;
4332 for (auto const& lease : leases) {
4333 ConstElementPtr previous_user_context = lease->getContext();
4334 vector<uint8_t> previous_relay_id = lease->relay_id_;
4335 vector<uint8_t> previous_remote_id = lease->remote_id_;
4336 if (!previous_user_context &&
4337 previous_relay_id.empty() &&
4338 previous_remote_id.empty()) {
4339 continue;
4340 }
4341 bool modified = upgradeLease4ExtendedInfo(lease, check);
4342 try {
4343 lease->relay_id_.clear();
4344 lease->remote_id_.clear();
4345 extractLease4ExtendedInfo(lease, false);
4346 if (modified ||
4347 (previous_relay_id != lease->relay_id_) ||
4348 (previous_remote_id != lease->remote_id_)) {
4349 updateLease4(lease);
4350 ++updated;
4351 }
4352 } catch (const NoSuchLease&) {
4353 // The lease was modified in parallel:
4354 // as its extended info was processed just ignore.
4355 continue;
4356 } catch (const std::exception& ex) {
4357 // Something when wrong, for instance extract failed.
4360 .arg(lease->addr_.toText())
4361 .arg(ex.what());
4362 }
4363 }
4364 }
4365
4367 .arg(pages)
4368 .arg(updated);
4369
4370 return (updated);
4371}
4372
4375 const IOAddress& lower_bound_address,
4376 const LeasePageSize& page_size) {
4379 .arg(page_size.page_size_)
4380 .arg(lower_bound_address.toText())
4381 .arg(relay_id.toText());
4382
4383 // Expecting IPv6 valid address.
4384 if (!lower_bound_address.isV6()) {
4385 isc_throw(InvalidAddressFamily, "expected IPv6 start address while "
4386 "retrieving leases from the lease database, got "
4387 << lower_bound_address);
4388 }
4389
4390 std::vector<uint8_t> relay_id_data = relay_id.getDuid();
4391 unsigned long relay_id_size = relay_id_data.size();
4392 if (relay_id_size == 0) {
4393 isc_throw(BadValue, "empty relay id");
4394 }
4395
4396 // Bind the relay id.
4397 MYSQL_BIND inbind[3];
4398 memset(inbind, 0, sizeof(inbind));
4399
4400 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
4401 inbind[0].buffer = reinterpret_cast<char*>(&relay_id_data[0]);
4402 inbind[0].buffer_length = relay_id_size;
4403 inbind[0].length = &relay_id_size;
4404
4405 // Bind the lower bound address.
4406 std::vector<uint8_t> lb_addr_data = lower_bound_address.toBytes();
4407 unsigned long lb_addr_size = lb_addr_data.size();
4408 if (lb_addr_size != 16) {
4409 isc_throw(DbOperationError, "lower bound address is not 16 bytes long");
4410 }
4411 inbind[1].buffer_type = MYSQL_TYPE_BLOB;
4412 inbind[1].buffer = reinterpret_cast<char*>(&lb_addr_data[0]);
4413 inbind[1].buffer_length = lb_addr_size;
4414 inbind[1].length = &lb_addr_size;
4415
4416 // Bind the size value.
4417 uint32_t ps = static_cast<uint32_t>(page_size.page_size_);
4418 inbind[2].buffer_type = MYSQL_TYPE_LONG;
4419 inbind[2].buffer = reinterpret_cast<char*>(&ps);
4420 inbind[2].is_unsigned = MLM_TRUE;
4421
4422 // Get a context.
4423 MySqlLeaseContextAlloc get_context(*this);
4424 MySqlLeaseContextPtr ctx = get_context.ctx_;
4425 Lease6Collection result;
4426
4427 getLeaseCollection(ctx, GET_RELAY_ID6, inbind, result);
4428 return (result);
4429}
4430
4433 const IOAddress& lower_bound_address,
4434 const LeasePageSize& page_size) {
4437 .arg(page_size.page_size_)
4438 .arg(lower_bound_address.toText())
4439 .arg(idToText(remote_id));
4440
4441 // Expecting IPv6 valid address.
4442 if (!lower_bound_address.isV6()) {
4443 isc_throw(InvalidAddressFamily, "expected IPv6 start address while "
4444 "retrieving leases from the lease database, got "
4445 << lower_bound_address);
4446 }
4447
4448 std::vector<uint8_t> remote_id_data = remote_id;
4449 unsigned long remote_id_size = remote_id_data.size();
4450 if (remote_id_size == 0) {
4451 isc_throw(BadValue, "empty remote id");
4452 }
4453
4454 // Bind the remote id.
4455 MYSQL_BIND inbind[3];
4456 memset(inbind, 0, sizeof(inbind));
4457
4458 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
4459 inbind[0].buffer = reinterpret_cast<char*>(&remote_id_data[0]);
4460 inbind[0].buffer_length = remote_id_size;
4461 inbind[0].length = &remote_id_size;
4462
4463 // Bind the lower bound address.
4464 std::vector<uint8_t> lb_addr_data = lower_bound_address.toBytes();
4465 unsigned long lb_addr_size = lb_addr_data.size();
4466 if (lb_addr_size != 16) {
4467 isc_throw(DbOperationError, "lower bound address is not 16 bytes long");
4468 }
4469 inbind[1].buffer_type = MYSQL_TYPE_BLOB;
4470 inbind[1].buffer = reinterpret_cast<char*>(&lb_addr_data[0]);
4471 inbind[1].buffer_length = lb_addr_size;
4472 inbind[1].length = &lb_addr_size;
4473
4474 // Bind the size value.
4475 uint32_t ps = static_cast<uint32_t>(page_size.page_size_);
4476 inbind[2].buffer_type = MYSQL_TYPE_LONG;
4477 inbind[2].buffer = reinterpret_cast<char*>(&ps);
4478 inbind[2].is_unsigned = MLM_TRUE;
4479
4480 // Get a context.
4481 MySqlLeaseContextAlloc get_context(*this);
4482 MySqlLeaseContextPtr ctx = get_context.ctx_;
4483 Lease6Collection result;
4484
4485 getLeaseCollection(ctx, GET_REMOTE_ID6, inbind, result);
4486
4487 return (result);
4488}
4489
4490size_t
4492 auto check = CfgMgr::instance().getCurrentCfg()->
4493 getConsistency()->getExtendedInfoSanityCheck();
4494
4495 // First step is to wipe tables if enabled.
4498 }
4499
4500 size_t pages = 0;
4501 size_t updated = 0;
4503 for (;;) {
4506 .arg(pages)
4507 .arg(start_addr.toText())
4508 .arg(updated);
4509
4510 // Prepare WHERE clause.
4511 MYSQL_BIND inbind[2];
4512 memset(inbind, 0, sizeof(inbind));
4513
4514 // Bind start address.
4515 std::vector<uint8_t>start_addr_bytes = start_addr.toBytes();
4516 if (start_addr_bytes.size() != 16) {
4517 isc_throw(DbOperationError, "start address is not 16 bytes long");
4518 }
4519
4520 unsigned long start_addr_size = 16;
4521 inbind[0].buffer_type = MYSQL_TYPE_BLOB;
4522 inbind[0].buffer = reinterpret_cast<char*>(&start_addr_bytes[0]);
4523 inbind[0].buffer_length = 16;
4524 inbind[0].length = &start_addr_size;
4525
4526 // Bind page size value.
4527 uint32_t ps = static_cast<uint32_t>(page_size.page_size_);
4528 inbind[1].buffer_type = MYSQL_TYPE_LONG;
4529 inbind[1].buffer = reinterpret_cast<char*>(&ps);
4530 inbind[1].is_unsigned = MLM_TRUE;
4531
4532 Lease6Collection leases;
4533
4534 // Get a context.
4535 {
4536 MySqlLeaseContextAlloc get_context(*this);
4537 MySqlLeaseContextPtr ctx = get_context.ctx_;
4538
4539 getLeaseCollection(ctx, GET_LEASE6_UCTX_PAGE, inbind, leases);
4540 }
4541
4542 if (leases.empty()) {
4543 // Done.
4544 break;
4545 }
4546
4547 ++pages;
4548 start_addr = leases.back()->addr_;
4549 for (auto const& lease : leases) {
4550 try {
4551 bool modified = upgradeLease6ExtendedInfo(lease, check);
4552 if (modified) {
4553 updateLease6(lease);
4554 }
4555 bool added = (getExtendedInfoTablesEnabled() &&
4556 addExtendedInfo6(lease));
4557 if (modified || added) {
4558 ++updated;
4559 }
4560 } catch (const NoSuchLease&) {
4561 // The lease was modified in parallel:
4562 // as its extended info was processed just ignore.
4563 continue;
4564 } catch (const std::exception& ex) {
4565 // Something when wrong, for instance extract failed.
4568 .arg(lease->addr_.toText())
4569 .arg(ex.what());
4570 }
4571 }
4572 }
4573
4575 .arg(pages)
4576 .arg(updated);
4577
4578 return (updated);
4579}
4580
4581void
4583 // Get a context.
4584 MySqlLeaseContextAlloc get_context(*this);
4585 MySqlLeaseContextPtr ctx = get_context.ctx_;
4586
4588 int status = MysqlExecuteStatement(ctx->conn_.getStatement(stindex));
4589 if (status != 0) {
4590 checkError(ctx, status, stindex, "unable to execute");
4591 }
4592
4593 stindex = WIPE_REMOTE_ID6;
4594 status = MysqlExecuteStatement(ctx->conn_.getStatement(stindex));
4595 if (status != 0) {
4596 checkError(ctx, status, stindex, "unable to execute");
4597 }
4598}
4599
4600size_t
4602 // Get a context.
4603 MySqlLeaseContextAlloc get_context(*this);
4604 MySqlLeaseContextPtr ctx = get_context.ctx_;
4605
4607
4608 // Bind the output.
4609 MYSQL_BIND bind[1];
4610 memset(bind, 0, sizeof(bind));
4611
4612 int64_t count = 0;
4613 bind[0].buffer_type = MYSQL_TYPE_LONGLONG;
4614 bind[0].buffer = reinterpret_cast<char*>(&count);
4615
4616 int status = mysql_stmt_bind_result(ctx->conn_.getStatement(stindex), &bind[0]);
4617 checkError(ctx, status, stindex, "unable to bind SELECT clause parameters");
4618
4619 // Execute.
4620 status = MysqlExecuteStatement(ctx->conn_.getStatement(stindex));
4621 if (status != 0) {
4622 checkError(ctx, status, stindex, "unable to execute");
4623 }
4624
4625 status = mysql_stmt_store_result(ctx->conn_.getStatement(stindex));
4626 checkError(ctx, status, stindex, "unable to store result");
4627
4628 // Fetch the result.
4629 MySqlFreeResult fetch_release(ctx->conn_.getStatement(stindex));
4630
4631 status = mysql_stmt_fetch(ctx->conn_.getStatement(stindex));
4632 if (status != 0) {
4633 checkError(ctx, status, stindex, "unable to fetch results");
4634 }
4635 return (static_cast<size_t>(count));
4636}
4637
4638size_t
4640 // Get a context.
4641 MySqlLeaseContextAlloc get_context(*this);
4642 MySqlLeaseContextPtr ctx = get_context.ctx_;
4643
4645
4646 // Bind the output.
4647 MYSQL_BIND bind[1];
4648 memset(bind, 0, sizeof(bind));
4649
4650 int64_t count = 0;
4651 bind[0].buffer_type = MYSQL_TYPE_LONGLONG;
4652 bind[0].buffer = reinterpret_cast<char*>(&count);
4653
4654 int status = mysql_stmt_bind_result(ctx->conn_.getStatement(stindex), &bind[0]);
4655 checkError(ctx, status, stindex, "unable to bind SELECT clause parameters");
4656
4657 // Execute.
4658 status = MysqlExecuteStatement(ctx->conn_.getStatement(stindex));
4659 if (status != 0) {
4660 checkError(ctx, status, stindex, "unable to execute");
4661 }
4662
4663 status = mysql_stmt_store_result(ctx->conn_.getStatement(stindex));
4664 checkError(ctx, status, stindex, "unable to store result");
4665
4666 // Fetch the result.
4667 MySqlFreeResult fetch_release(ctx->conn_.getStatement(stindex));
4668
4669 status = mysql_stmt_fetch(ctx->conn_.getStatement(stindex));
4670 if (status != 0) {
4671 checkError(ctx, status, stindex, "unable to fetch results");
4672 }
4673 return (static_cast<size_t>(count));
4674}
4675
4676} // namespace dhcp
4677} // namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown when a function is not implemented.
A generic exception that is thrown when an unexpected error condition occurs.
static ElementPtr fromJSON(const std::string &in, bool preproc=false)
These functions will parse the given string (JSON) representation of a compound element.
Definition data.cc:798
Data is truncated.
static bool invokeDbLostCallback(const util::ReconnectCtlPtr &db_reconnect_ctl)
Invokes the connection's lost connectivity callback.
static bool invokeDbFailedCallback(const util::ReconnectCtlPtr &db_reconnect_ctl)
Invokes the connection's restore failed connectivity callback.
static bool invokeDbRecoveredCallback(const util::ReconnectCtlPtr &db_reconnect_ctl)
Invokes the connection's restored connectivity callback.
static isc::asiolink::IOServicePtr & getIOService()
Returns pointer to the IO service.
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Exception thrown on failure to execute a database function.
Invalid address family used as input to Lease Manager.
Multiple lease records found where one expected.
static MySqlBindingPtr createString(const unsigned long length)
Creates binding of text type for receiving data.
static MySqlBindingPtr createBool()
Creates binding having a bool type for receiving data.
Common MySQL Connector Pool.
static void convertToDatabaseTime(const time_t input_time, MYSQL_TIME &output_time)
Convert time_t value to database time.
static std::pair< uint32_t, uint32_t > getVersion(const ParameterMap &parameters, const IOServiceAccessorPtr &ac=IOServiceAccessorPtr(), const DbCallback &cb=DbCallback(), const std::string &timer_name=std::string())
Get the schema version.
static void convertFromDatabaseTime(const MYSQL_TIME &expire, uint32_t valid_lifetime, time_t &cltt)
Convert Database Time to Lease Times.
void checkError(const int status, const StatementIndex &index, const char *what)
Check Error and Throw Exception.
MYSQL_STMT * getStatement(StatementIndex index) const
Returns a prepared statement by an index.
static void ensureSchemaVersion(const ParameterMap &parameters, const DbCallback &cb=DbCallback(), const std::string &timer_name=std::string())
Retrieve schema version, validate it against the hardcoded version, and attempt to initialize the sch...
Fetch and Release MySQL Results.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:25
Holds Client identifier or client IPv4 address.
Definition duid.h:222
static constexpr size_t MAX_CLIENT_ID_LEN
Maximum size of a client ID.
Definition duid.h:235
Holds DUID (DHCPv6 Unique Identifier)
Definition duid.h:142
static constexpr size_t MAX_DUID_LEN
maximum duid size
Definition duid.h:155
const std::vector< uint8_t > & getDuid() const
Returns a const reference to the actual DUID value.
Definition duid.cc:33
std::string toText() const
Returns textual representation of the identifier (e.g.
Definition duid.h:88
static void recreate(const std::string &dbaccess, bool preserve_callbacks=true)
Recreate an instance of a lease manager with optionally preserving registered callbacks.
void setExtendedInfoTablesEnabled(const bool enabled)
Modifies the setting whether the lease6 extended info tables are enabled.
Definition lease_mgr.h:1018
static bool upgradeLease6ExtendedInfo(const Lease6Ptr &lease, CfgConsistency::ExtendedInfoSanity check=CfgConsistency::EXTENDED_INFO_CHECK_FIX)
Upgrade a V6 lease user context to the new extended info entry.
Definition lease_mgr.cc:756
bool getExtendedInfoTablesEnabled() const
Returns the setting indicating if lease6 extended info tables are enabled.
Definition lease_mgr.h:1010
static void extractLease4ExtendedInfo(const Lease4Ptr &lease, bool ignore_errors=true)
Extract relay and remote identifiers from the extended info.
static bool upgradeLease4ExtendedInfo(const Lease4Ptr &lease, CfgConsistency::ExtendedInfoSanity check=CfgConsistency::EXTENDED_INFO_CHECK_FIX)
The following queries are used to fulfill Bulk Lease Query queries.
Definition lease_mgr.cc:535
virtual bool addExtendedInfo6(const Lease6Ptr &lease)
Extract extended info from a lease6 and add it into tables.
Wraps value holding size of the page with leases.
Definition lease_mgr.h:46
Base class for fulfilling a statistical lease data query.
Definition lease_mgr.h:149
SubnetID first_subnet_id_
First (or only) subnet_id in the selection criteria.
Definition lease_mgr.h:222
SelectMode getSelectMode() const
Returns the selection criteria mode The value returned is based upon the constructor variant used and...
Definition lease_mgr.h:216
SubnetID last_subnet_id_
Last subnet_id in the selection criteria when a range is given.
Definition lease_mgr.h:225
Exchange MySQL and Lease4 Data.
std::vector< MYSQL_BIND > createBindForReceive()
Create BIND array to receive data.
std::vector< MYSQL_BIND > createBindForSend(const Lease4Ptr &lease)
Create MYSQL_BIND objects for Lease4 Pointer.
std::string getErrorColumns()
Return columns in error.
Lease4Ptr getLeaseData()
Copy Received Data into Lease4 Object.
Exchange MySQL and Lease6 Data.
std::vector< MYSQL_BIND > createBindForSend(const Lease6Ptr &lease)
Create MYSQL_BIND objects for Lease6 Pointer.
std::string getErrorColumns()
Return columns in error.
Lease6Ptr getLeaseData()
Copy Received Data into Lease6 Object.
std::vector< MYSQL_BIND > createBindForReceive()
Create BIND array to receive data.
MySQL Lease Context Pool.
MySqlLeaseContext(const db::DatabaseConnection::ParameterMap &parameters, db::IOServiceAccessorPtr io_service_accessor, db::DbCallback db_reconnect_callback)
Constructor.
Common MySQL and Lease Data Methods.
static std::string getColumnsInError(my_bool *error, std::string *names, size_t count)
Return columns in error.
static void setErrorIndicators(MYSQL_BIND *bind, my_bool *error, size_t count)
Set error indicators.
MySQL Lease Manager.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const override
Returns existing IPv6 lease for a given IPv6 address.
virtual std::string getDescription() const override
Returns description of the backend.
virtual size_t wipeLeases6(const SubnetID &subnet_id) override
Removed specified IPv6 leases.
virtual bool deleteLease(const Lease4Ptr &lease) override
Deletes an IPv4 lease.
virtual size_t byRemoteId6size() const override
Return the by-remote-id table size.
static std::string getDBVersion()
Local version of getDBVersion() class method.
virtual bool addLease(const Lease4Ptr &lease) override
Adds an IPv4 lease.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv6 leases.
virtual Lease4Collection getLeases4ByRemoteId(const OptionBuffer &remote_id, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size, const time_t &qry_start_time=0, const time_t &qry_end_time=0) override
Returns existing IPv4 leases with a given remote-id.
virtual LeaseStatsQueryPtr startLeaseStatsQuery4() override
Creates and runs the IPv4 lease stats query.
virtual Lease4Collection getLeases4ByRelayId(const OptionBuffer &relay_id, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size, const time_t &qry_start_time=0, const time_t &qry_end_time=0) override
The following queries are used to fulfill Bulk Lease Query queries.
virtual void rollback() override
Rollback Transactions.
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery4(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id) override
Creates and runs the IPv4 lease stats query for a single subnet.
virtual void wipeExtendedInfoTables6() override
Wipe by-relay-id table (v6).
virtual Lease6Collection getLeases6() const override
Returns all IPv6 leases.
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv4 leases.
virtual std::pair< uint32_t, uint32_t > getVersion(const std::string &timer_name=std::string()) const override
Returns backend version.
virtual Lease6Collection getLeases6ByRemoteId(const OptionBuffer &remote_id, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size) override
Returns existing IPv6 leases with a given remote-id.
virtual void addRemoteId6(const isc::asiolink::IOAddress &lease_addr, const std::vector< uint8_t > &remote_id) override
Add lease6 extended info into by-remote-id table.
virtual void commit() override
Commit Transactions.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery6(const SubnetID &subnet_id) override
Creates and runs the IPv6 lease stats query for a single subnet.
MySqlLeaseContextPtr createContext() const
Create a new context.
virtual void deleteExtendedInfo6(const isc::asiolink::IOAddress &addr) override
Extended information / Bulk Lease Query shared interface.
virtual LeaseStatsQueryPtr startPoolLeaseStatsQuery4() override
Creates and runs the IPv4 lease stats query for all subnets and pools.
virtual Lease6Collection getLeases6ByRelayId(const DUID &relay_id, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size) override
Returns existing IPv6 leases with a given relay-id.
virtual void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv6 leases.
virtual void updateLease6(const Lease6Ptr &lease6) override
Updates IPv6 lease.
MySqlLeaseMgr(const db::DatabaseConnection::ParameterMap &parameters)
Constructor.
virtual LeaseStatsQueryPtr startPoolLeaseStatsQuery6() override
Creates and runs the IPv6 lease stats query for all subnets and pools.
virtual std::string getName() const override
Returns backend name.
virtual LeaseStatsQueryPtr startLeaseStatsQuery6() override
Creates and runs the IPv6 lease stats query.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const override
Returns an IPv4 lease for specified IPv4 address.
virtual size_t upgradeExtendedInfo4(const LeasePageSize &page_size) override
Upgrade extended info (v4).
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery6(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id) override
Creates and runs the IPv6 lease stats query for a single subnet.
virtual void updateLease4(const Lease4Ptr &lease4) override
Updates IPv4 lease.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery4(const SubnetID &subnet_id) override
Creates and runs the IPv4 lease stats query for a single subnet.
virtual ~MySqlLeaseMgr()
Destructor (closes database)
virtual size_t upgradeExtendedInfo6(const LeasePageSize &page_size) override
Upgrade extended info (v6).
virtual void addRelayId6(const isc::asiolink::IOAddress &lease_addr, const std::vector< uint8_t > &relay_id) override
Add lease6 extended info into by-relay-id table.
virtual size_t wipeLeases4(const SubnetID &subnet_id) override
Removes specified IPv4 leases.
virtual Lease4Collection getLeases4() const override
Returns all IPv4 leases.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv4 leases.
static bool dbReconnect(util::ReconnectCtlPtr db_reconnect_ctl)
Attempts to reconnect the server to the lease DB backend manager.
virtual size_t byRelayId6size() const override
Return the by-relay-id table size.
MySql derivation of the statistical lease data query.
void start() override
Creates the IPv4 lease statistical data result set.
MySqlLeaseStatsQuery(MySqlConnection &conn, const size_t statement_index, const bool fetch_type, const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor to query for the stats for a range of subnets.
MySqlLeaseStatsQuery(MySqlConnection &conn, const size_t statement_index, const bool fetch_type, const SubnetID &subnet_id)
Constructor to query for a single subnet's stats.
virtual ~MySqlLeaseStatsQuery()
Destructor.
bool getNextRow(LeaseStatsRow &row) override
Fetches the next row in the result set.
MySqlLeaseStatsQuery(MySqlConnection &conn, const size_t statement_index, const bool fetch_type, const bool fetch_pool=false)
Constructor to query for all subnets' stats.
Attempt to update lease that was not there.
static const TimerMgrPtr & instance()
Returns pointer to the sole instance of the TimerMgr.
Definition timer_mgr.cc:446
Introduces callbacks into the LeaseMgr.
void trackAddLease(const LeasePtr &lease)
Invokes the callbacks when a new lease is added.
void unlock(const LeasePtr &lease)
Attempts to unlock a lease.
void trackUpdateLease(const LeasePtr &lease)
Invokes the callbacks when a lease is updated.
void trackDeleteLease(const LeasePtr &lease)
Invokes the callbacks when a lease is deleted.
bool hasCallbacks() const
Checks if any callbacks have been registered.
RAII class creating a critical section.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition macros.h:26
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition macros.h:14
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
const my_bool MLM_FALSE
MySQL false value.
const uint32_t MYSQL_SCHEMA_VERSION_MAJOR
boost::shared_ptr< IOServiceAccessor > IOServiceAccessorPtr
Pointer to an instance of IOServiceAccessor.
@ error
Definition db_log.h:118
const uint32_t MYSQL_SCHEMA_VERSION_MINOR
const my_bool MLM_TRUE
MySQL true value.
bool my_bool
my_bool type in MySQL 8.x.
std::vector< MySqlBindingPtr > MySqlBindingCollection
Collection of bindings.
const int MLM_MYSQL_FETCH_SUCCESS
check for bool size
std::function< bool(util::ReconnectCtlPtr db_reconnect_ctl)> DbCallback
Defines a callback prototype for propagating events upward.
std::function< isc::asiolink::IOServicePtr()> IOServiceAccessor
Function which returns the IOService that can be used to recover the connection.
int MysqlExecuteStatement(MYSQL_STMT *stmt)
Execute a prepared statement.
const isc::log::MessageID DHCPSRV_MYSQL_GET_HOSTNAME4
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition dhcpsrv_log.h:56
const isc::log::MessageID DHCPSRV_MYSQL_GET_EXPIRED6
const isc::log::MessageID DHCPSRV_MYSQL_ADD_ADDR4
std::string ClientClass
Defines a single class name.
Definition classify.h:42
const isc::log::MessageID DHCPSRV_MYSQL_COMMIT
const isc::log::MessageID DHCPSRV_MYSQL_DELETE_EXPIRED_RECLAIMED6
const isc::log::MessageID DHCPSRV_MYSQL_NEGATIVE_LEASES_STAT
const isc::log::MessageID DHCPSRV_MYSQL_GET_SUBID_PAGE6
const isc::log::MessageID DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO6
const isc::log::MessageID DHCPSRV_MYSQL_GET_IAID_DUID
const isc::log::MessageID DHCPSRV_MYSQL_GET_PAGE4
const isc::log::MessageID DHCPSRV_MYSQL_GET_CLIENTID
const isc::log::MessageID DHCPSRV_MYSQL_NO_TLS
const isc::log::MessageID DHCPSRV_MYSQL_GET4
boost::shared_ptr< CfgDbAccess > CfgDbAccessPtr
A pointer to the CfgDbAccess.
boost::shared_ptr< DUID > DuidPtr
Definition duid.h:136
const isc::log::MessageID DHCPSRV_MYSQL_DELETE_ADDR
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition lease.h:508
const isc::log::MessageID DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO6_ERROR
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition lease.h:673
boost::shared_ptr< LeaseStatsQuery > LeaseStatsQueryPtr
Defines a pointer to a LeaseStatsQuery.
Definition lease_mgr.h:233
const isc::log::MessageID DHCPSRV_MYSQL_LEASE_DB_RECONNECT_ATTEMPT_FAILED
const isc::log::MessageID DHCPSRV_MYSQL_GET_REMOTEID6
const isc::log::MessageID DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_PAGE
const isc::log::MessageID DHCPSRV_MYSQL_GET_ADDR4
const isc::log::MessageID DHCPSRV_MYSQL_GET_IAID_SUBID_DUID
const isc::log::MessageID DHCPSRV_MYSQL_UPDATE_ADDR6
const isc::log::MessageID DHCPSRV_MYSQL_GET_REMOTEID4
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition hwaddr.h:154
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition dhcpsrv_log.h:38
const isc::log::MessageID DHCPSRV_MYSQL_GET_SUBID6
const isc::log::MessageID DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4
const isc::log::MessageID DHCPSRV_MYSQL_GET_PAGE6
const isc::log::MessageID DHCPSRV_MYSQL_GET_EXPIRED4
const isc::log::MessageID DHCPSRV_MYSQL_UPDATE_ADDR4
const isc::log::MessageID DHCPSRV_MYSQL_GET_HWADDR
const isc::log::MessageID DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO4_ERROR
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition subnet_id.h:25
boost::shared_ptr< Lease > LeasePtr
Pointer to the lease object.
Definition lease.h:25
const isc::log::MessageID DHCPSRV_MYSQL_ADD_ADDR6
const isc::log::MessageID DHCPSRV_MYSQL_GET_HOSTNAME6
const isc::log::MessageID DHCPSRV_MYSQL_GET_VERSION
const isc::log::MessageID DHCPSRV_MYSQL_LEASE_DB_RECONNECT_ATTEMPT_SCHEDULE
const size_t HOSTNAME_MAX_LEN
Maximum length of the hostname stored in DNS.
Definition host.h:42
const isc::log::MessageID DHCPSRV_MYSQL_GET_RELAYID4
const isc::log::MessageID DHCPSRV_MYSQL_GET_SUBID4
const isc::log::MessageID DHCPSRV_MYSQL_GET6
const size_t USER_CONTEXT_MAX_LEN
Maximum length of user context.
Definition host.h:54
const isc::log::MessageID DHCPSRV_MYSQL_LEASE_DB_RECONNECT_FAILED
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition option.h:24
const isc::log::MessageID DHCPSRV_MYSQL_UPGRADE_EXTENDED_INFO6_PAGE
const isc::log::MessageID DHCPSRV_MYSQL_GET_SUBID_CLIENTID
const isc::log::MessageID DHCPSRV_MYSQL_DELETE_EXPIRED_RECLAIMED4
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition lease.h:500
const isc::log::MessageID DHCPSRV_MYSQL_ROLLBACK
@ HTYPE_ETHER
Ethernet 10Mbps.
Definition dhcp4.h:56
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition lease.h:295
boost::shared_ptr< MySqlLeaseContext > MySqlLeaseContextPtr
Type of pointers to contexts.
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition dhcpsrv_log.h:26
const isc::log::MessageID DHCPSRV_MYSQL_GET_ADDR6
const isc::log::MessageID DHCPSRV_MYSQL_GET_SUBID_HWADDR
const isc::log::MessageID DHCPSRV_MYSQL_DELETED_EXPIRED_RECLAIMED
const isc::log::MessageID DHCPSRV_MYSQL_GET_RELAYID6
const isc::log::MessageID DHCPSRV_MYSQL_GET_DUID
const isc::log::MessageID DHCPSRV_MYSQL_TLS_CIPHER
PerfMonMgrPtr mgr
PerfMonMgr singleton.
boost::shared_ptr< ReconnectCtl > ReconnectCtlPtr
Pointer to an instance of ReconnectCtl.
Defines the logger used by the top-level component of kea-lfc.
Hardware type that represents information from DHCPv4 packet.
Definition hwaddr.h:20
static const size_t MAX_HWADDR_LEN
Maximum size of a hardware address.
Definition hwaddr.h:27
std::vector< uint8_t > hwaddr_
Definition hwaddr.h:98
std::string toText(bool include_htype=true) const
Returns textual representation of a hardware address (e.g.
Definition hwaddr.cc:51
ExtendedInfoAction
Action on extended info tables.
Definition lease.h:553
@ ACTION_UPDATE
update extended info tables.
Definition lease.h:556
@ ACTION_DELETE
delete reference to the lease
Definition lease.h:555
@ ACTION_IGNORE
ignore extended info,
Definition lease.h:554
Contains a single row of lease statistical data.
Definition lease_mgr.h:64
a common structure for IPv4 and IPv6 leases
Definition lease.h:31
static const uint32_t INFINITY_LFT
Infinity (means static, i.e. never expire)
Definition lease.h:34
static const uint32_t STATE_EXPIRED_RECLAIMED
Expired and reclaimed lease.
Definition lease.h:75
Type
Type of lease or pool.
Definition lease.h:46
@ TYPE_TA
the lease contains temporary IPv6 address
Definition lease.h:48
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
Definition lease.h:49
@ TYPE_V4
IPv4 lease.
Definition lease.h:50
@ TYPE_NA
the lease contains non-temporary IPv6 address
Definition lease.h:47