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