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