Kea 2.2.0
pgsql_lease_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2022 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
10#include <dhcp/duid.h>
11#include <dhcp/hwaddr.h>
13#include <dhcpsrv/cfgmgr.h>
14#include <dhcpsrv/dhcpsrv_log.h>
18#include <dhcpsrv/timer_mgr.h>
20
21#include <boost/make_shared.hpp>
22#include <boost/static_assert.hpp>
23
24#include <iomanip>
25#include <limits>
26#include <sstream>
27#include <string>
28#include <time.h>
29
30using namespace isc;
31using namespace isc::asiolink;
32using namespace isc::db;
33using namespace isc::dhcp;
34using namespace isc::data;
35using namespace isc::util;
36using namespace std;
37
38namespace {
39
43PgSqlTaggedStatement tagged_statements[] = {
44 // DELETE_LEASE4
45 { 2, { OID_INT8, OID_TIMESTAMP },
46 "delete_lease4",
47 "DELETE FROM lease4 WHERE address = $1 AND expire = $2"},
48
49 // DELETE_LEASE4_STATE_EXPIRED
50 { 2, { OID_INT8, OID_TIMESTAMP },
51 "delete_lease4_state_expired",
52 "DELETE FROM lease4 "
53 "WHERE state = $1 AND expire < $2"},
54
55 // DELETE_LEASE6
56 { 2, { OID_VARCHAR, OID_TIMESTAMP },
57 "delete_lease6",
58 "DELETE FROM lease6 WHERE address = $1 AND expire = $2"},
59
60 // DELETE_LEASE6_STATE_EXPIRED
61 { 2, { OID_INT8, OID_TIMESTAMP },
62 "delete_lease6_state_expired",
63 "DELETE FROM lease6 "
64 "WHERE state = $1 AND expire < $2"},
65
66 // GET_LEASE4
67 { 0, { OID_NONE },
68 "get_lease4",
69 "SELECT address, hwaddr, client_id, "
70 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
71 "fqdn_fwd, fqdn_rev, hostname, "
72 "state, user_context "
73 "FROM lease4"},
74
75 // GET_LEASE4_ADDR
76 { 1, { OID_INT8 },
77 "get_lease4_addr",
78 "SELECT address, hwaddr, client_id, "
79 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
80 "fqdn_fwd, fqdn_rev, hostname, "
81 "state, user_context "
82 "FROM lease4 "
83 "WHERE address = $1"},
84
85 // GET_LEASE4_CLIENTID
86 { 1, { OID_BYTEA },
87 "get_lease4_clientid",
88 "SELECT address, hwaddr, client_id, "
89 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
90 "fqdn_fwd, fqdn_rev, hostname, "
91 "state, user_context "
92 "FROM lease4 "
93 "WHERE client_id = $1"},
94
95 // GET_LEASE4_CLIENTID_SUBID
96 { 2, { OID_BYTEA, OID_INT8 },
97 "get_lease4_clientid_subid",
98 "SELECT address, hwaddr, client_id, "
99 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
100 "fqdn_fwd, fqdn_rev, hostname, "
101 "state, user_context "
102 "FROM lease4 "
103 "WHERE client_id = $1 AND subnet_id = $2"},
104
105 // GET_LEASE4_HWADDR
106 { 1, { OID_BYTEA },
107 "get_lease4_hwaddr",
108 "SELECT address, hwaddr, client_id, "
109 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
110 "fqdn_fwd, fqdn_rev, hostname, "
111 "state, user_context "
112 "FROM lease4 "
113 "WHERE hwaddr = $1"},
114
115 // GET_LEASE4_HWADDR_SUBID
116 { 2, { OID_BYTEA, OID_INT8 },
117 "get_lease4_hwaddr_subid",
118 "SELECT address, hwaddr, client_id, "
119 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
120 "fqdn_fwd, fqdn_rev, hostname, "
121 "state, user_context "
122 "FROM lease4 "
123 "WHERE hwaddr = $1 AND subnet_id = $2"},
124
125 // GET_LEASE4_PAGE
126 { 2, { OID_INT8, OID_INT8 },
127 "get_lease4_page",
128 "SELECT address, hwaddr, client_id, "
129 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
130 "fqdn_fwd, fqdn_rev, hostname, "
131 "state, user_context "
132 "FROM lease4 "
133 "WHERE address > $1 "
134 "ORDER BY address "
135 "LIMIT $2"},
136
137 // GET_LEASE4_SUBID
138 { 1, { OID_INT8 },
139 "get_lease4_subid",
140 "SELECT address, hwaddr, client_id, "
141 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
142 "fqdn_fwd, fqdn_rev, hostname, "
143 "state, user_context "
144 "FROM lease4 "
145 "WHERE subnet_id = $1"},
146
147 // GET_LEASE4_HOSTNAME
148 { 1, { OID_VARCHAR },
149 "get_lease4_hostname",
150 "SELECT address, hwaddr, client_id, "
151 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
152 "fqdn_fwd, fqdn_rev, hostname, "
153 "state, user_context "
154 "FROM lease4 "
155 "WHERE lower(hostname) = $1"},
156
157 // GET_LEASE4_EXPIRE
159 "get_lease4_expire",
160 "SELECT address, hwaddr, client_id, "
161 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
162 "fqdn_fwd, fqdn_rev, hostname, "
163 "state, user_context "
164 "FROM lease4 "
165 "WHERE state != $1 AND valid_lifetime != 4294967295 AND expire < $2 "
166 "ORDER BY expire "
167 "LIMIT $3"},
168
169 // GET_LEASE6
170 { 0, { OID_NONE },
171 "get_lease6",
172 "SELECT address, duid, valid_lifetime, "
173 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
174 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
175 "hwaddr, hwtype, hwaddr_source, "
176 "state, user_context "
177 "FROM lease6"},
178
179 // GET_LEASE6_ADDR
180 { 2, { OID_VARCHAR, OID_INT2 },
181 "get_lease6_addr",
182 "SELECT address, duid, valid_lifetime, "
183 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
184 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
185 "hwaddr, hwtype, hwaddr_source, "
186 "state, user_context "
187 "FROM lease6 "
188 "WHERE address = $1 AND lease_type = $2"},
189
190 // GET_LEASE6_DUID_IAID
191 { 3, { OID_BYTEA, OID_INT8, OID_INT2 },
192 "get_lease6_duid_iaid",
193 "SELECT address, duid, valid_lifetime, "
194 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
195 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
196 "hwaddr, hwtype, hwaddr_source, "
197 "state, user_context "
198 "FROM lease6 "
199 "WHERE duid = $1 AND iaid = $2 AND lease_type = $3"},
200
201 // GET_LEASE6_DUID_IAID_SUBID
203 "get_lease6_duid_iaid_subid",
204 "SELECT address, duid, valid_lifetime, "
205 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
206 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
207 "hwaddr, hwtype, hwaddr_source, "
208 "state, user_context "
209 "FROM lease6 "
210 "WHERE lease_type = $1 "
211 "AND duid = $2 AND iaid = $3 AND subnet_id = $4"},
212
213 // GET_LEASE6_PAGE
214 { 2, { OID_VARCHAR, OID_INT8 },
215 "get_lease6_page",
216 "SELECT address, duid, valid_lifetime, "
217 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
218 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
219 "hwaddr, hwtype, hwaddr_source, "
220 "state, user_context "
221 "FROM lease6 "
222 "WHERE address > $1 "
223 "ORDER BY address "
224 "LIMIT $2"},
225
226 // GET_LEASE6_SUBID
227 { 1, { OID_INT8 },
228 "get_lease6_subid",
229 "SELECT address, duid, valid_lifetime, "
230 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
231 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
232 "hwaddr, hwtype, hwaddr_source, "
233 "state, user_context "
234 "FROM lease6 "
235 "WHERE subnet_id = $1"},
236
237 // GET_LEASE6_DUID
238 { 1, { OID_BYTEA },
239 "get_lease6_duid",
240 "SELECT address, duid, valid_lifetime, "
241 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
242 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
243 "hwaddr, hwtype, hwaddr_source, "
244 "state, user_context "
245 "FROM lease6 "
246 "WHERE duid = $1"},
247
248 // GET_LEASE6_HOSTNAME
249 { 1, { OID_VARCHAR },
250 "get_lease6_hostname",
251 "SELECT address, duid, valid_lifetime, "
252 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
253 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
254 "hwaddr, hwtype, hwaddr_source, "
255 "state, user_context "
256 "FROM lease6 "
257 "WHERE lower(hostname) = $1"},
258
259 // GET_LEASE6_EXPIRE
261 "get_lease6_expire",
262 "SELECT address, duid, valid_lifetime, "
263 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
264 "lease_type, iaid, prefix_len, "
265 "fqdn_fwd, fqdn_rev, hostname, "
266 "hwaddr, hwtype, hwaddr_source, "
267 "state, user_context "
268 "FROM lease6 "
269 "WHERE state != $1 AND valid_lifetime != 4294967295 AND expire < $2 "
270 "ORDER BY expire "
271 "LIMIT $3"},
272
273 // INSERT_LEASE4
276 "insert_lease4",
277 "INSERT INTO lease4(address, hwaddr, client_id, "
278 "valid_lifetime, expire, subnet_id, fqdn_fwd, fqdn_rev, hostname, "
279 "state, user_context) "
280 "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)"},
281
282 // INSERT_LEASE6
286 "insert_lease6",
287 "INSERT INTO lease6(address, duid, valid_lifetime, "
288 "expire, subnet_id, pref_lifetime, "
289 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
290 "hwaddr, hwtype, hwaddr_source, "
291 "state, user_context) "
292 "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)"},
293
294 // UPDATE_LEASE4
297 "update_lease4",
298 "UPDATE lease4 SET address = $1, hwaddr = $2, "
299 "client_id = $3, valid_lifetime = $4, expire = $5, "
300 "subnet_id = $6, fqdn_fwd = $7, fqdn_rev = $8, hostname = $9, "
301 "state = $10, user_context = $11 "
302 "WHERE address = $12 AND expire = $13"},
303
304 // UPDATE_LEASE6
309 "update_lease6",
310 "UPDATE lease6 SET address = $1, duid = $2, "
311 "valid_lifetime = $3, expire = $4, subnet_id = $5, "
312 "pref_lifetime = $6, lease_type = $7, iaid = $8, "
313 "prefix_len = $9, fqdn_fwd = $10, fqdn_rev = $11, hostname = $12, "
314 "hwaddr = $13, hwtype = $14, hwaddr_source = $15, "
315 "state = $16, user_context = $17 "
316 "WHERE address = $18 AND expire = $19"},
317
318 // ALL_LEASE4_STATS
319 { 0, { OID_NONE },
320 "all_lease4_stats",
321 "SELECT subnet_id, state, leases as state_count"
322 " FROM lease4_stat ORDER BY subnet_id, state"},
323
324 // SUBNET_LEASE4_STATS
325 { 1, { OID_INT8 },
326 "subnet_lease4_stats",
327 "SELECT subnet_id, state, leases as state_count"
328 " FROM lease4_stat "
329 " WHERE subnet_id = $1 "
330 " ORDER BY state"},
331
332 // SUBNET_RANGE_LEASE4_STATS
333 { 2, { OID_INT8, OID_INT8 },
334 "subnet_range_lease4_stats",
335 "SELECT subnet_id, state, leases as state_count"
336 " FROM lease4_stat "
337 " WHERE subnet_id >= $1 and subnet_id <= $2 "
338 " ORDER BY subnet_id, state"},
339
340 // ALL_LEASE6_STATS,
341 { 0, { OID_NONE },
342 "all_lease6_stats",
343 "SELECT subnet_id, lease_type, state, leases as state_count"
344 " FROM lease6_stat ORDER BY subnet_id, lease_type, state" },
345
346 // SUBNET_LEASE6_STATS
347 { 1, { OID_INT8 },
348 "subnet_lease6_stats",
349 "SELECT subnet_id, lease_type, state, leases as state_count"
350 " FROM lease6_stat "
351 " WHERE subnet_id = $1 "
352 " ORDER BY lease_type, state" },
353
354 // SUBNET_RANGE_LEASE6_STATS
355 { 2, { OID_INT8, OID_INT8 },
356 "subnet_range_lease6_stats",
357 "SELECT subnet_id, lease_type, state, leases as state_count"
358 " FROM lease6_stat "
359 " WHERE subnet_id >= $1 and subnet_id <= $2 "
360 " ORDER BY subnet_id, lease_type, state" },
361
362 // CHECK_LEASE4_LIMITS
363 { 1, { OID_TEXT },
364 "check_lease4_limits",
365 "SELECT checkLease4Limits($1)" },
366
367 // CHECK_LEASE6_LIMITS
368 { 1, { OID_TEXT },
369 "check_lease6_limits",
370 "SELECT checkLease6Limits($1)" },
371
372 // IS_JSON_SUPPORTED
373 { 0, { OID_NONE },
374 "is_json_supported",
375 "SELECT isJsonSupported()" },
376
377 // GET_LEASE4_COUNT_BY_CLASS
378 { 1, { OID_VARCHAR },
379 "get_lease4_count_by_class",
380 "SELECT leases "
381 "FROM lease4_stat_by_client_class "
382 "WHERE client_class = $1"},
383
384 // GET_LEASE6_COUNT_BY_CLASS
385 { 2, { OID_VARCHAR, OID_INT2 },
386 "get_lease6_count_by_class",
387 "SELECT leases "
388 "FROM lease6_stat_by_client_class "
389 "WHERE client_class = $1 AND lease_type = $2"},
390
391 // End of list sentinel
392 { 0, { 0 }, NULL, NULL}
393};
394
395} // namespace
396
397namespace isc {
398namespace dhcp {
399
406public:
407
412 fqdn_fwd_(false), fqdn_rev_(false), hostname_(""), state_str_(""),
413 user_context_("") {
414 }
415
417
418protected:
419
421
422 std::string addr_str_;
424 std::vector<uint8_t> hwaddr_;
428 time_t expire_;
429 std::string expire_str_;
430 uint32_t subnet_id_;
431 std::string subnet_id_str_;
432 time_t cltt_;
435 std::string hostname_;
436 std::string state_str_;
437 std::string user_context_;
439};
440
443private:
444
449 static const size_t ADDRESS_COL = 0;
450 static const size_t HWADDR_COL = 1;
451 static const size_t CLIENT_ID_COL = 2;
452 static const size_t VALID_LIFETIME_COL = 3;
453 static const size_t EXPIRE_COL = 4;
454 static const size_t SUBNET_ID_COL = 5;
455 static const size_t FQDN_FWD_COL = 6;
456 static const size_t FQDN_REV_COL = 7;
457 static const size_t HOSTNAME_COL = 8;
458 static const size_t STATE_COL = 9;
459 static const size_t USER_CONTEXT_COL = 10;
461 static const size_t LEASE_COLUMNS = 11;
462
463public:
464
467 : lease_(), addr4_(0), client_id_length_(0) {
468
469 BOOST_STATIC_ASSERT(9 < LEASE_COLUMNS);
470
471 memset(hwaddr_buffer_, 0, sizeof(hwaddr_buffer_));
472 memset(client_id_buffer_, 0, sizeof(client_id_buffer_));
473
474 // Set the column names (for error messages)
475 columns_.push_back("address");
476 columns_.push_back("hwaddr");
477 columns_.push_back("client_id");
478 columns_.push_back("valid_lifetime");
479 columns_.push_back("expire");
480 columns_.push_back("subnet_id");
481 columns_.push_back("fqdn_fwd");
482 columns_.push_back("fqdn_rev");
483 columns_.push_back("hostname");
484 columns_.push_back("state");
485 columns_.push_back("user_context");
486 }
487
500 void createBindForSend(const Lease4Ptr& lease, PsqlBindArray& bind_array) {
501 if (!lease) {
502 isc_throw(BadValue, "createBindForSend:: Lease4 object is NULL");
503 }
504
505 // Store lease object to ensure it remains valid.
506 lease_ = lease;
507
508 try {
509 addr_str_ = boost::lexical_cast<std::string>(lease->addr_.toUint32());
510 bind_array.add(addr_str_);
511
512 if (lease->hwaddr_ && !lease->hwaddr_->hwaddr_.empty()) {
513 // PostgreSql does not provide MAX on variable length types
514 // so we have to enforce it ourselves.
515 if (lease->hwaddr_->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
516 isc_throw(DbOperationError, "Hardware address length : "
517 << lease_->hwaddr_->hwaddr_.size()
518 << " exceeds maximum allowed of: "
520 }
521 bind_array.add(lease->hwaddr_->hwaddr_);
522 } else {
523 bind_array.add("");
524 }
525
526 if (lease->client_id_) {
527 bind_array.add(lease->client_id_->getClientId());
528 } else {
529 bind_array.add("");
530 }
531
532 valid_lifetime_str_ = boost::lexical_cast<std::string>(lease->valid_lft_);
533 bind_array.add(valid_lifetime_str_);
534
535 // The lease structure holds the client last transmission time (cltt_)
536 // For convenience for external tools, this is converted to lease
537 // expiry time (expire). The relationship is given by:
538 // expire = cltt_ + valid_lft_
539 // Avoid overflow with infinite valid lifetime by using
540 // expire = cltt_ when valid_lft_ = 0xffffffff
541 if (lease_->valid_lft_ == Lease::INFINITY_LFT) {
542 expire_str_ = convertToDatabaseTime(lease->cltt_, 0);
543 } else {
544 expire_str_ = convertToDatabaseTime(lease->cltt_,
545 lease_->valid_lft_);
546 }
547 bind_array.add(expire_str_);
548
549 subnet_id_str_ = boost::lexical_cast<std::string>(lease->subnet_id_);
550 bind_array.add(subnet_id_str_);
551
552 bind_array.add(lease->fqdn_fwd_);
553
554 bind_array.add(lease->fqdn_rev_);
555
556 bind_array.add(lease->hostname_);
557
558 state_str_ = boost::lexical_cast<std::string>(lease->state_);
559 bind_array.add(state_str_);
560
561 ConstElementPtr ctx = lease->getContext();
562 if (ctx) {
563 user_context_ = ctx->str();
564 } else {
565 user_context_ = "";
566 }
567 bind_array.add(user_context_);
568 } catch (const std::exception& ex) {
570 "Could not create bind array from Lease4: "
571 << lease_->addr_.toText() << ", reason: " << ex.what());
572 }
573 }
574
584 try {
585 getColumnValue(r, row, ADDRESS_COL, addr4_);
586
587 convertFromBytea(r, row, HWADDR_COL, hwaddr_buffer_,
589
590 convertFromBytea(r, row, CLIENT_ID_COL, client_id_buffer_,
591 sizeof(client_id_buffer_), client_id_length_);
592
593 getColumnValue(r, row, VALID_LIFETIME_COL, valid_lifetime_);
594
596 EXPIRE_COL));
597
598 getColumnValue(r, row , SUBNET_ID_COL, subnet_id_);
599
600 // Recover from overflow (see createBindForSend)
602 cltt_ = expire_;
603 } else {
605 }
606
607 getColumnValue(r, row, FQDN_FWD_COL, fqdn_fwd_);
608
609 getColumnValue(r, row, FQDN_REV_COL, fqdn_rev_);
610
611 hostname_ = getRawColumnValue(r, row, HOSTNAME_COL);
612
613 uint32_t state;
614 getColumnValue(r, row , STATE_COL, state);
615
617 HTYPE_ETHER));
618
619 user_context_ = getRawColumnValue(r, row, USER_CONTEXT_COL);
620 ConstElementPtr ctx;
621 if (!user_context_.empty()) {
623 if (!ctx || (ctx->getType() != Element::map)) {
624 isc_throw(BadValue, "user context '" << user_context_
625 << "' is not a JSON map");
626 }
627 }
628
629 Lease4Ptr result(boost::make_shared<Lease4>(addr4_, hwaddr,
630 client_id_buffer_,
631 client_id_length_,
635
636 result->state_ = state;
637
638 if (ctx) {
639 result->setContext(ctx);
640 }
641
642 return (result);
643 } catch (const std::exception& ex) {
645 "Could not convert data to Lease4, reason: "
646 << ex.what());
647 }
648 }
649
650private:
651
655 Lease4Ptr lease_;
656
658 uint32_t addr4_;
659 size_t client_id_length_;
660 uint8_t client_id_buffer_[ClientId::MAX_CLIENT_ID_LEN];
661};
662
665private:
666
671
672 static const int ADDRESS_COL = 0;
673 static const int DUID_COL = 1;
674 static const int VALID_LIFETIME_COL = 2;
675 static const int EXPIRE_COL = 3;
676 static const int SUBNET_ID_COL = 4;
677 static const int PREF_LIFETIME_COL = 5;
678 static const int LEASE_TYPE_COL = 6;
679 static const int IAID_COL = 7;
680 static const int PREFIX_LEN_COL = 8;
681 static const int FQDN_FWD_COL = 9;
682 static const int FQDN_REV_COL = 10;
683 static const int HOSTNAME_COL = 11;
684 static const int HWADDR_COL = 12;
685 static const int HWTYPE_COL = 13;
686 static const int HWADDR_SOURCE_COL = 14;
687 static const int STATE_COL = 15;
688 static const size_t USER_CONTEXT_COL = 16;
690
691 static const size_t LEASE_COLUMNS = 17;
692
693public:
694
701 union Uiaid {
704 Uiaid(uint32_t val) : uval_(val){};
705
708 Uiaid(int32_t val) : ival_(val){};
709
711 std::string dbInputString() {
712 return (boost::lexical_cast<std::string>(ival_));
713 };
714
715 uint32_t uval_;
716 int32_t ival_;
717 };
718
720 : lease_(), duid_length_(0), duid_(duid_length_), iaid_u_(0),
721 iaid_str_(""), lease_type_(Lease6::TYPE_NA), lease_type_str_(""),
722 prefix_len_(0), prefix_len_str_(""), pref_lifetime_(0),
723 preferred_lifetime_str_(""), hwtype_(0), hwtype_str_(""),
724 hwaddr_source_(0), hwaddr_source_str_("") {
725
726 BOOST_STATIC_ASSERT(15 < LEASE_COLUMNS);
727
728 memset(duid_buffer_, 0, sizeof(duid_buffer_));
729
730 // Set the column names (for error messages)
731 columns_.push_back("address");
732 columns_.push_back("duid");
733 columns_.push_back("valid_lifetime");
734 columns_.push_back("expire");
735 columns_.push_back("subnet_id");
736 columns_.push_back("pref_lifetime");
737 columns_.push_back("lease_type");
738 columns_.push_back("iaid");
739 columns_.push_back("prefix_len");
740 columns_.push_back("fqdn_fwd");
741 columns_.push_back("fqdn_rev");
742 columns_.push_back("hostname");
743 columns_.push_back("hwaddr");
744 columns_.push_back("hwtype");
745 columns_.push_back("hwaddr_source");
746 columns_.push_back("state");
747 columns_.push_back("user_context");
748 }
749
762 void createBindForSend(const Lease6Ptr& lease, PsqlBindArray& bind_array) {
763 if (!lease) {
764 isc_throw(BadValue, "createBindForSend:: Lease6 object is NULL");
765 }
766
767 // Store lease object to ensure it remains valid.
768 lease_ = lease;
769 try {
770 addr_str_ = lease_->addr_.toText();
771 bind_array.add(addr_str_);
772
773 if (lease_->duid_) {
774 bind_array.add(lease_->duid_->getDuid());
775 } else {
776 isc_throw (BadValue, "IPv6 Lease cannot have a null DUID");
777 }
778
779 valid_lifetime_str_ = boost::lexical_cast<std::string>(lease->valid_lft_);
780 bind_array.add(valid_lifetime_str_);
781
782 // The lease structure holds the client last transmission time (cltt_)
783 // For convenience for external tools, this is converted to lease
784 // expiry time (expire). The relationship is given by:
785 // expire = cltt_ + valid_lft_
786 // Avoid overflow with infinite valid lifetime by using
787 // expire = cltt_ when valid_lft_ = 0xffffffff
788 if (lease_->valid_lft_ == Lease::INFINITY_LFT) {
789 expire_str_ = convertToDatabaseTime(lease->cltt_, 0);
790 } else {
791 expire_str_ = convertToDatabaseTime(lease->cltt_,
792 lease_->valid_lft_);
793 }
794 bind_array.add(expire_str_);
795
796 subnet_id_str_ = boost::lexical_cast<std::string>(lease->subnet_id_);
797 bind_array.add(subnet_id_str_);
798
799 preferred_lifetime_str_ = boost::lexical_cast<std::string>(lease_->preferred_lft_);
800 bind_array.add(preferred_lifetime_str_);
801
802 lease_type_str_ = boost::lexical_cast<std::string>(lease_->type_);
803 bind_array.add(lease_type_str_);
804
805 // The iaid is stored as an INT in lease6 table, so we must
806 // lexically cast from an integer version to avoid out of range
807 // exception failure upon insert.
808 iaid_u_.uval_ = lease_->iaid_;
809 iaid_str_ = iaid_u_.dbInputString();
810 bind_array.add(iaid_str_);
811
812 prefix_len_str_ = boost::lexical_cast<std::string>
813 (static_cast<unsigned int>(lease_->prefixlen_));
814 bind_array.add(prefix_len_str_);
815
816 bind_array.add(lease->fqdn_fwd_);
817
818 bind_array.add(lease->fqdn_rev_);
819
820 bind_array.add(lease->hostname_);
821
822 if (lease->hwaddr_ && !lease->hwaddr_->hwaddr_.empty()) {
823 // PostgreSql does not provide MAX on variable length types
824 // so we have to enforce it ourselves.
825 if (lease->hwaddr_->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
826 isc_throw(DbOperationError, "Hardware address length : "
827 << lease_->hwaddr_->hwaddr_.size()
828 << " exceeds maximum allowed of: "
830 }
831 bind_array.add(lease->hwaddr_->hwaddr_);
832 } else {
833 bind_array.add("");
834 }
835
836 if (lease->hwaddr_) {
837 hwtype_str_ = boost::lexical_cast<std::string>
838 (static_cast<unsigned int>(lease_->hwaddr_->htype_));
839 hwaddr_source_str_ = boost::lexical_cast<std::string>
840 (static_cast<unsigned int>(lease_->hwaddr_->source_));
841 } else {
842 hwtype_str_ = boost::lexical_cast<std::string>
843 (static_cast<unsigned int>(HTYPE_UNDEFINED));
844 hwaddr_source_str_ = boost::lexical_cast<std::string>
845 (static_cast<unsigned int>(HWAddr::HWADDR_SOURCE_UNKNOWN));
846 }
847
848 bind_array.add(hwtype_str_);
849
850 bind_array.add(hwaddr_source_str_);
851
852 state_str_ = boost::lexical_cast<std::string>(lease->state_);
853 bind_array.add(state_str_);
854
855 ConstElementPtr ctx = lease->getContext();
856 if (ctx) {
857 user_context_ = ctx->str();
858 } else {
859 user_context_ = "";
860 }
861 bind_array.add(user_context_);
862 } catch (const std::exception& ex) {
864 "Could not create bind array from Lease6: "
865 << lease_->addr_.toText() << ", reason: " << ex.what());
866 }
867 }
868
878 try {
879
887
888 IOAddress addr(getIPv6Value(r, row, ADDRESS_COL));
889
890 convertFromBytea(r, row, DUID_COL, duid_buffer_, sizeof(duid_buffer_), duid_length_);
891 DuidPtr duid_ptr(new DUID(duid_buffer_, duid_length_));
892
893 getColumnValue(r, row, VALID_LIFETIME_COL, valid_lifetime_);
894
896 EXPIRE_COL));
897
898 // Recover from overflow (see createBindForSend)
900 cltt_ = expire_;
901 } else {
903 }
904
905 getColumnValue(r, row , SUBNET_ID_COL, subnet_id_);
906
907 getColumnValue(r, row , PREF_LIFETIME_COL, pref_lifetime_);
908
909 getLeaseTypeColumnValue(r, row, LEASE_TYPE_COL, lease_type_);
910
911 getColumnValue(r, row , IAID_COL, iaid_u_.ival_);
912
913 getColumnValue(r, row , PREFIX_LEN_COL, prefix_len_);
914
915 getColumnValue(r, row, FQDN_FWD_COL, fqdn_fwd_);
916
917 getColumnValue(r, row, FQDN_REV_COL, fqdn_rev_);
918
919 hostname_ = getRawColumnValue(r, row, HOSTNAME_COL);
920
921 convertFromBytea(r, row, HWADDR_COL, hwaddr_buffer_,
923
924 getColumnValue(r, row , HWTYPE_COL, hwtype_);
925
926 getColumnValue(r, row , HWADDR_SOURCE_COL, hwaddr_source_);
927
928 HWAddrPtr hwaddr;
929
930 if (hwaddr_length_) {
931 hwaddr.reset(new HWAddr(hwaddr_buffer_, hwaddr_length_,
932 hwtype_));
933
934 hwaddr->source_ = hwaddr_source_;
935 }
936
937 uint32_t state;
938 getColumnValue(r, row , STATE_COL, state);
939
940 user_context_ = getRawColumnValue(r, row, USER_CONTEXT_COL);
941 ConstElementPtr ctx;
942 if (!user_context_.empty()) {
944 if (!ctx || (ctx->getType() != Element::map)) {
945 isc_throw(BadValue, "user context '" << user_context_
946 << "' is not a JSON map");
947 }
948 }
949
950 Lease6Ptr result(boost::make_shared<Lease6>(lease_type_, addr,
951 duid_ptr,
952 iaid_u_.uval_,
953 pref_lifetime_,
957 hwaddr, prefix_len_));
958 // Update cltt_ and current_cltt_ explicitly.
959 result->cltt_ = cltt_;
960 result->current_cltt_ = cltt_;
961
962 result->state_ = state;
963
964 if (ctx) {
965 result->setContext(ctx);
966 }
967
968 return (result);
969 } catch (const std::exception& ex) {
971 "Could not convert data to Lease6, reason: "
972 << ex.what());
973 }
974 }
975
988 void getLeaseTypeColumnValue(const PgSqlResult& r, const int row,
989 const size_t col, Lease6::Type& value) const {
990 uint32_t raw_value = 0;
991 getColumnValue(r, row , col, raw_value);
992 switch (raw_value) {
993 case Lease6::TYPE_NA:
994 case Lease6::TYPE_TA:
995 case Lease6::TYPE_PD:
996 value = static_cast<Lease6::Type>(raw_value);
997 break;
998
999 default:
1000 isc_throw(DbOperationError, "Invalid lease type: " << raw_value
1001 << " for: " << getColumnLabel(r, col) << " row:" << row);
1002 }
1003 }
1004
1005private:
1009 Lease6Ptr lease_;
1010
1012
1013 size_t duid_length_;
1014 std::vector<uint8_t> duid_;
1015 uint8_t duid_buffer_[DUID::MAX_DUID_LEN];
1016 union Uiaid iaid_u_;
1017 std::string iaid_str_;
1018 Lease6::Type lease_type_;
1019 std::string lease_type_str_;
1020 uint8_t prefix_len_;
1021 std::string prefix_len_str_;
1022 uint32_t pref_lifetime_;
1023 std::string preferred_lifetime_str_;
1024 uint32_t hwtype_;
1025 std::string hwtype_str_;
1026 uint32_t hwaddr_source_;
1027 std::string hwaddr_source_str_;
1029};
1030
1037public:
1038
1048 const bool fetch_type)
1049 : conn_(conn), statement_(statement), result_set_(), next_row_(0),
1050 fetch_type_(fetch_type) {
1051 }
1052
1062 const bool fetch_type, const SubnetID& subnet_id)
1063 : LeaseStatsQuery(subnet_id), conn_(conn), statement_(statement), result_set_(),
1064 next_row_(0), fetch_type_(fetch_type) {
1065 }
1066
1078 const bool fetch_type, const SubnetID& first_subnet_id,
1079 const SubnetID& last_subnet_id)
1080 : LeaseStatsQuery(first_subnet_id, last_subnet_id), conn_(conn), statement_(statement),
1081 result_set_(), next_row_(0), fetch_type_(fetch_type) {
1082 }
1083
1086
1096 void start() {
1097
1098 if (getSelectMode() == ALL_SUBNETS) {
1099 // Run the query with no where clause parameters.
1100 result_set_.reset(new PgSqlResult(PQexecPrepared(conn_, statement_.name,
1101 0, 0, 0, 0, 0)));
1102 } else {
1103 // Set up the WHERE clause values
1104 PsqlBindArray parms;
1105
1106 // Add first_subnet_id used by both single and range.
1107 parms.addTempString(boost::lexical_cast<std::string>(getFirstSubnetID()));
1108
1109 // Add last_subnet_id for range.
1110 if (getSelectMode() == SUBNET_RANGE) {
1111 // Add last_subnet_id used by range.
1112 parms.addTempString(boost::lexical_cast<std::string>(getLastSubnetID()));
1113 }
1114
1115 // Run the query with where clause parameters.
1116 result_set_.reset(new PgSqlResult(PQexecPrepared(conn_, statement_.name,
1117 parms.size(), &parms.values_[0],
1118 &parms.lengths_[0], &parms.formats_[0], 0)));
1119 }
1120
1122 }
1123
1139 // If we're past the end, punt.
1140 if (next_row_ >= result_set_->getRows()) {
1141 return (false);
1142 }
1143
1144 // Fetch the subnet id.
1145 uint32_t col = 0;
1146 uint32_t subnet_id;
1148 row.subnet_id_ = static_cast<SubnetID>(subnet_id);
1149 ++col;
1150
1151 // Fetch the lease type if we were told to do so.
1152 if (fetch_type_) {
1153 uint32_t lease_type;
1155 lease_type);
1156 row.lease_type_ = static_cast<Lease::Type>(lease_type);
1157 ++col;
1158 } else {
1160 }
1161
1162 // Fetch the lease state.
1164 row.lease_state_);
1165 ++col;
1166
1167 // Fetch the state count.
1169 row.state_count_);
1170
1171 // Protect against negative state count.a
1172 if (row.state_count_ < 0) {
1173 row.state_count_ = 0;
1174 if (!negative_count_) {
1175 negative_count_ = true;
1177 }
1178 }
1179
1180 // Point to the next row.
1181 ++next_row_;
1182 return (true);
1183 }
1184
1185protected:
1186
1189
1192
1194 boost::shared_ptr<PgSqlResult> result_set_;
1195
1197 uint32_t next_row_;
1198
1201
1203 static bool negative_count_;
1204};
1205
1206// Initialize negative state count flag to false.
1208
1209// PgSqlLeaseContext Constructor
1210
1212 IOServiceAccessorPtr io_service_accessor,
1213 DbCallback db_reconnect_callback)
1214 : conn_(parameters, io_service_accessor, db_reconnect_callback) {
1215}
1216
1217// PgSqlLeaseContextAlloc Constructor and Destructor
1218
1219PgSqlLeaseMgr::PgSqlLeaseContextAlloc::PgSqlLeaseContextAlloc(
1220 const PgSqlLeaseMgr& mgr) : ctx_(), mgr_(mgr) {
1221
1222 if (MultiThreadingMgr::instance().getMode()) {
1223 // multi-threaded
1224 {
1225 // we need to protect the whole pool_ operation, hence extra scope {}
1226 lock_guard<mutex> lock(mgr_.pool_->mutex_);
1227 if (!mgr_.pool_->pool_.empty()) {
1228 ctx_ = mgr_.pool_->pool_.back();
1229 mgr_.pool_->pool_.pop_back();
1230 }
1231 }
1232 if (!ctx_) {
1233 ctx_ = mgr_.createContext();
1234 }
1235 } else {
1236 // single-threaded
1237 if (mgr_.pool_->pool_.empty()) {
1238 isc_throw(Unexpected, "No available PostgreSQL lease context?!");
1239 }
1240 ctx_ = mgr_.pool_->pool_.back();
1241 }
1242}
1243
1244PgSqlLeaseMgr::PgSqlLeaseContextAlloc::~PgSqlLeaseContextAlloc() {
1245 if (MultiThreadingMgr::instance().getMode()) {
1246 // multi-threaded
1247 lock_guard<mutex> lock(mgr_.pool_->mutex_);
1248 mgr_.pool_->pool_.push_back(ctx_);
1249 }
1250 // If running in single-threaded mode, there's nothing to do here.
1251}
1252
1253// PgSqlLeaseMgr Constructor and Destructor
1254
1256 : parameters_(parameters), timer_name_("") {
1257
1258 // Create unique timer name per instance.
1259 timer_name_ = "PgSqlLeaseMgr[";
1260 timer_name_ += boost::lexical_cast<std::string>(reinterpret_cast<uint64_t>(this));
1261 timer_name_ += "]DbReconnectTimer";
1262
1263 // Check TLS support.
1264 size_t tls(0);
1265 tls += parameters.count("trust-anchor");
1266 tls += parameters.count("cert-file");
1267 tls += parameters.count("key-file");
1268 tls += parameters.count("cipher-list");
1269#ifdef HAVE_PGSQL_SSL
1270 if ((tls > 0) && !PgSqlConnection::warned_about_tls) {
1274 PQinitSSL(1);
1275 }
1276#else
1277 if (tls > 0) {
1280 isc_throw(DbOpenError, "Attempt to configure TLS for PostgreSQL "
1281 << "backend (built with this feature disabled)");
1282 }
1283#endif
1284
1285 // Validate schema version first.
1286 std::pair<uint32_t, uint32_t> code_version(PGSQL_SCHEMA_VERSION_MAJOR,
1288 std::pair<uint32_t, uint32_t> db_version = getVersion();
1289 if (code_version != db_version) {
1291 "PostgreSQL schema version mismatch: need version: "
1292 << code_version.first << "." << code_version.second
1293 << " found version: " << db_version.first << "."
1294 << db_version.second);
1295 }
1296
1297 // Create an initial context.
1298 pool_.reset(new PgSqlLeaseContextPool());
1299 pool_->pool_.push_back(createContext());
1300}
1301
1303}
1304
1305bool
1308
1309 // Invoke application layer connection lost callback.
1310 if (!DatabaseConnection::invokeDbLostCallback(db_reconnect_ctl)) {
1311 return (false);
1312 }
1313
1314 bool reopened = false;
1315
1316 const std::string timer_name = db_reconnect_ctl->timerName();
1317
1318 // At least one connection was lost.
1319 try {
1320 CfgDbAccessPtr cfg_db = CfgMgr::instance().getCurrentCfg()->getCfgDbAccess();
1322 LeaseMgrFactory::create(cfg_db->getLeaseDbAccessString());
1323 reopened = true;
1324 } catch (const std::exception& ex) {
1326 .arg(ex.what());
1327 }
1328
1329 if (reopened) {
1330 // Cancel the timer.
1331 if (TimerMgr::instance()->isTimerRegistered(timer_name)) {
1332 TimerMgr::instance()->unregisterTimer(timer_name);
1333 }
1334
1335 // Invoke application layer connection recovered callback.
1336 if (!DatabaseConnection::invokeDbRecoveredCallback(db_reconnect_ctl)) {
1337 return (false);
1338 }
1339 } else {
1340 if (!db_reconnect_ctl->checkRetries()) {
1341 // We're out of retries, log it and initiate shutdown.
1343 .arg(db_reconnect_ctl->maxRetries());
1344
1345 // Cancel the timer.
1346 if (TimerMgr::instance()->isTimerRegistered(timer_name)) {
1347 TimerMgr::instance()->unregisterTimer(timer_name);
1348 }
1349
1350 // Invoke application layer connection failed callback.
1352 return (false);
1353 }
1354
1356 .arg(db_reconnect_ctl->maxRetries() - db_reconnect_ctl->retriesLeft() + 1)
1357 .arg(db_reconnect_ctl->maxRetries())
1358 .arg(db_reconnect_ctl->retryInterval());
1359
1360 // Start the timer.
1361 if (!TimerMgr::instance()->isTimerRegistered(timer_name)) {
1362 TimerMgr::instance()->registerTimer(timer_name,
1363 std::bind(&PgSqlLeaseMgr::dbReconnect, db_reconnect_ctl),
1364 db_reconnect_ctl->retryInterval(),
1366 }
1367 TimerMgr::instance()->setup(timer_name);
1368 }
1369
1370 return (true);
1371}
1372
1373// Create context.
1374
1377 PgSqlLeaseContextPtr ctx(new PgSqlLeaseContext(parameters_,
1380
1381 // Open the database.
1382 ctx->conn_.openDatabase();
1383
1384 // Now prepare the SQL statements.
1385 uint32_t i = 0;
1386 for (; tagged_statements[i].text != NULL; ++i) {
1387 ctx->conn_.prepareStatement(tagged_statements[i]);
1388 }
1389
1390 // Just in case somebody foo-barred things
1391 if (i != NUM_STATEMENTS) {
1392 isc_throw(DbOpenError, "Number of statements prepared: " << i
1393 << " does not match expected count:" << NUM_STATEMENTS);
1394 }
1395
1396 // Create the exchange objects for use in exchanging data between the
1397 // program and the database.
1398 ctx->exchange4_.reset(new PgSqlLease4Exchange());
1399 ctx->exchange6_.reset(new PgSqlLease6Exchange());
1400
1401 // Create ReconnectCtl for this connection.
1402 ctx->conn_.makeReconnectCtl(timer_name_);
1403
1404 return (ctx);
1405}
1406
1407std::string
1409 std::stringstream tmp;
1410 tmp << "PostgreSQL backend " << PGSQL_SCHEMA_VERSION_MAJOR;
1411 tmp << "." << PGSQL_SCHEMA_VERSION_MINOR;
1412 tmp << ", library " << PQlibVersion();
1413 return (tmp.str());
1414}
1415
1416bool
1417PgSqlLeaseMgr::addLeaseCommon(PgSqlLeaseContextPtr& ctx,
1418 StatementIndex stindex,
1419 PsqlBindArray& bind_array) {
1420 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
1421 tagged_statements[stindex].nbparams,
1422 &bind_array.values_[0],
1423 &bind_array.lengths_[0],
1424 &bind_array.formats_[0], 0));
1425
1426 int s = PQresultStatus(r);
1427
1428 if (s != PGRES_COMMAND_OK) {
1429 // Failure: check for the special case of duplicate entry. If this is
1430 // the case, we return false to indicate that the row was not added.
1431 // Otherwise we throw an exception.
1432 if (ctx->conn_.compareError(r, PgSqlConnection::DUPLICATE_KEY)) {
1433 return (false);
1434 }
1435 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
1436 }
1437
1438 return (true);
1439}
1440
1441bool
1444 .arg(lease->addr_.toText());
1445
1446 // Get a context
1447 PgSqlLeaseContextAlloc get_context(*this);
1448 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1449
1450 PsqlBindArray bind_array;
1451 ctx->exchange4_->createBindForSend(lease, bind_array);
1452 auto result = addLeaseCommon(ctx, INSERT_LEASE4, bind_array);
1453
1454 // Update lease current expiration time (allows update between the creation
1455 // of the Lease up to the point of insertion in the database).
1456 lease->updateCurrentExpirationTime();
1457
1458 return (result);
1459}
1460
1461bool
1464 .arg(lease->addr_.toText())
1465 .arg(lease->type_);
1466
1467 // Get a context
1468 PgSqlLeaseContextAlloc get_context(*this);
1469 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1470
1471 PsqlBindArray bind_array;
1472 ctx->exchange6_->createBindForSend(lease, bind_array);
1473
1474 auto result = addLeaseCommon(ctx, INSERT_LEASE6, bind_array);
1475
1476 // Update lease current expiration time (allows update between the creation
1477 // of the Lease up to the point of insertion in the database).
1478 lease->updateCurrentExpirationTime();
1479
1480 return (result);
1481}
1482
1483template <typename Exchange, typename LeaseCollection>
1484void
1485PgSqlLeaseMgr::getLeaseCollection(PgSqlLeaseContextPtr& ctx,
1486 StatementIndex stindex,
1487 PsqlBindArray& bind_array,
1488 Exchange& exchange,
1489 LeaseCollection& result,
1490 bool single) const {
1491 const int n = tagged_statements[stindex].nbparams;
1492 PgSqlResult r(PQexecPrepared(ctx->conn_,
1493 tagged_statements[stindex].name, n,
1494 n > 0 ? &bind_array.values_[0] : NULL,
1495 n > 0 ? &bind_array.lengths_[0] : NULL,
1496 n > 0 ? &bind_array.formats_[0] : NULL, 0));
1497
1498 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
1499
1500 int rows = PQntuples(r);
1501 if (single && rows > 1) {
1502 isc_throw(MultipleRecords, "multiple records were found in the "
1503 "database where only one was expected for query "
1504 << tagged_statements[stindex].name);
1505 }
1506
1507 for(int i = 0; i < rows; ++ i) {
1508 result.push_back(exchange->convertFromDatabase(r, i));
1509 }
1510}
1511
1512void
1513PgSqlLeaseMgr::getLease(PgSqlLeaseContextPtr& ctx,
1514 StatementIndex stindex, PsqlBindArray& bind_array,
1515 Lease4Ptr& result) const {
1516 // Create appropriate collection object and get all leases matching
1517 // the selection criteria. The "single" parameter is true to indicate
1518 // that the called method should throw an exception if multiple
1519 // matching records are found: this particular method is called when only
1520 // one or zero matches is expected.
1521 Lease4Collection collection;
1522 getLeaseCollection(ctx, stindex, bind_array, ctx->exchange4_,
1523 collection, true);
1524
1525 // Return single record if present, else clear the lease.
1526 if (collection.empty()) {
1527 result.reset();
1528 } else {
1529 result = *collection.begin();
1530 }
1531}
1532
1533void
1534PgSqlLeaseMgr::getLease(PgSqlLeaseContextPtr& ctx,
1535 StatementIndex stindex, PsqlBindArray& bind_array,
1536 Lease6Ptr& result) const {
1537 // Create appropriate collection object and get all leases matching
1538 // the selection criteria. The "single" parameter is true to indicate
1539 // that the called method should throw an exception if multiple
1540 // matching records are found: this particular method is called when only
1541 // one or zero matches is expected.
1542 Lease6Collection collection;
1543 getLeaseCollection(ctx, stindex, bind_array, ctx->exchange6_,
1544 collection, true);
1545
1546 // Return single record if present, else clear the lease.
1547 if (collection.empty()) {
1548 result.reset();
1549 } else {
1550 result = *collection.begin();
1551 }
1552}
1553
1557 .arg(addr.toText());
1558
1559 // Set up the WHERE clause value
1560 PsqlBindArray bind_array;
1561
1562 // LEASE ADDRESS
1563 std::string addr_str = boost::lexical_cast<std::string>(addr.toUint32());
1564 bind_array.add(addr_str);
1565
1566 // Get the data
1567 Lease4Ptr result;
1568
1569 // Get a context
1570 PgSqlLeaseContextAlloc get_context(*this);
1571 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1572
1573 getLease(ctx, GET_LEASE4_ADDR, bind_array, result);
1574
1575 return (result);
1576}
1577
1579PgSqlLeaseMgr::getLease4(const HWAddr& hwaddr) const {
1581 .arg(hwaddr.toText());
1582
1583 // Set up the WHERE clause value
1584 PsqlBindArray bind_array;
1585
1586 // HWADDR
1587 if (!hwaddr.hwaddr_.empty()) {
1588 bind_array.add(hwaddr.hwaddr_);
1589 } else {
1590 bind_array.add("");
1591 }
1592
1593 // Get the data
1594 Lease4Collection result;
1595
1596 // Get a context
1597 PgSqlLeaseContextAlloc get_context(*this);
1598 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1599
1600 getLeaseCollection(ctx, GET_LEASE4_HWADDR, bind_array, result);
1601
1602 return (result);
1603}
1604
1606PgSqlLeaseMgr::getLease4(const HWAddr& hwaddr, SubnetID subnet_id) const {
1608 .arg(subnet_id)
1609 .arg(hwaddr.toText());
1610
1611 // Set up the WHERE clause value
1612 PsqlBindArray bind_array;
1613
1614 // HWADDR
1615 if (!hwaddr.hwaddr_.empty()) {
1616 bind_array.add(hwaddr.hwaddr_);
1617 } else {
1618 bind_array.add("");
1619 }
1620
1621 // SUBNET_ID
1622 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
1623 bind_array.add(subnet_id_str);
1624
1625 // Get the data
1626 Lease4Ptr result;
1627
1628 // Get a context
1629 PgSqlLeaseContextAlloc get_context(*this);
1630 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1631
1632 getLease(ctx, GET_LEASE4_HWADDR_SUBID, bind_array, result);
1633
1634 return (result);
1635}
1636
1638PgSqlLeaseMgr::getLease4(const ClientId& clientid) const {
1640 .arg(clientid.toText());
1641
1642 // Set up the WHERE clause value
1643 PsqlBindArray bind_array;
1644
1645 // CLIENT_ID
1646 bind_array.add(clientid.getClientId());
1647
1648 // Get the data
1649 Lease4Collection result;
1650
1651 // Get a context
1652 PgSqlLeaseContextAlloc get_context(*this);
1653 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1654
1655 getLeaseCollection(ctx, GET_LEASE4_CLIENTID, bind_array, result);
1656
1657 return (result);
1658}
1659
1661PgSqlLeaseMgr::getLease4(const ClientId& clientid, SubnetID subnet_id) const {
1663 .arg(subnet_id)
1664 .arg(clientid.toText());
1665
1666 // Set up the WHERE clause value
1667 PsqlBindArray bind_array;
1668
1669 // CLIENT_ID
1670 bind_array.add(clientid.getClientId());
1671
1672 // SUBNET_ID
1673 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
1674 bind_array.add(subnet_id_str);
1675
1676 // Get the data
1677 Lease4Ptr result;
1678
1679 // Get a context
1680 PgSqlLeaseContextAlloc get_context(*this);
1681 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1682
1683 getLease(ctx, GET_LEASE4_CLIENTID_SUBID, bind_array, result);
1684
1685 return (result);
1686}
1687
1691 .arg(subnet_id);
1692
1693 // Set up the WHERE clause value
1694 PsqlBindArray bind_array;
1695
1696 // SUBNET_ID
1697 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
1698 bind_array.add(subnet_id_str);
1699
1700 // ... and get the data
1701 Lease4Collection result;
1702
1703 // Get a context
1704 PgSqlLeaseContextAlloc get_context(*this);
1705 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1706
1707 getLeaseCollection(ctx, GET_LEASE4_SUBID, bind_array, result);
1708
1709 return (result);
1710}
1711
1713PgSqlLeaseMgr::getLeases4(const std::string& hostname) const {
1715 .arg(hostname);
1716
1717 // Set up the WHERE clause value
1718 PsqlBindArray bind_array;
1719
1720 // Hostname
1721 bind_array.add(hostname);
1722
1723 // ... and get the data
1724 Lease4Collection result;
1725
1726 // Get a context
1727 PgSqlLeaseContextAlloc get_context(*this);
1728 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1729
1730 getLeaseCollection(ctx, GET_LEASE4_HOSTNAME, bind_array, result);
1731
1732 return (result);
1733}
1734
1738
1739 // Provide empty binding array because our query has no parameters in
1740 // WHERE clause.
1741 PsqlBindArray bind_array;
1742 Lease4Collection result;
1743
1744 // Get a context
1745 PgSqlLeaseContextAlloc get_context(*this);
1746 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1747
1748 getLeaseCollection(ctx, GET_LEASE4, bind_array, result);
1749
1750 return (result);
1751}
1752
1754PgSqlLeaseMgr::getLeases4(const IOAddress& lower_bound_address,
1755 const LeasePageSize& page_size) const {
1756 // Expecting IPv4 address.
1757 if (!lower_bound_address.isV4()) {
1758 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
1759 "retrieving leases from the lease database, got "
1760 << lower_bound_address);
1761 }
1762
1764 .arg(page_size.page_size_)
1765 .arg(lower_bound_address.toText());
1766
1767 // Prepare WHERE clause
1768 PsqlBindArray bind_array;
1769
1770 // Bind lower bound address
1771 std::string lb_address_data = boost::lexical_cast<std::string>(lower_bound_address.toUint32());
1772 bind_array.add(lb_address_data);
1773
1774 // Bind page size value
1775 std::string page_size_data = boost::lexical_cast<std::string>(page_size.page_size_);
1776 bind_array.add(page_size_data);
1777
1778 // Get the leases
1779 Lease4Collection result;
1780
1781 // Get a context
1782 PgSqlLeaseContextAlloc get_context(*this);
1783 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1784
1785 getLeaseCollection(ctx, GET_LEASE4_PAGE, bind_array, result);
1786
1787 return (result);
1788}
1789
1792 const IOAddress& addr) const {
1794 .arg(addr.toText())
1795 .arg(lease_type);
1796
1797 // Set up the WHERE clause value
1798 PsqlBindArray bind_array;
1799
1800 // LEASE ADDRESS
1801 std::string addr_str = addr.toText();
1802 bind_array.add(addr_str);
1803
1804 // LEASE_TYPE
1805 std::string type_str_ = boost::lexical_cast<std::string>(lease_type);
1806 bind_array.add(type_str_);
1807
1808 // ... and get the data
1809 Lease6Ptr result;
1810
1811 // Get a context
1812 PgSqlLeaseContextAlloc get_context(*this);
1813 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1814
1815 getLease(ctx, GET_LEASE6_ADDR, bind_array, result);
1816
1817 return (result);
1818}
1819
1822 uint32_t iaid) const {
1824 .arg(iaid)
1825 .arg(duid.toText())
1826 .arg(lease_type);
1827
1828 // Set up the WHERE clause value
1829 PsqlBindArray bind_array;
1830
1831 // DUID
1832 bind_array.add(duid.getDuid());
1833
1834 // IAID
1835 std::string iaid_str = PgSqlLease6Exchange::Uiaid(iaid).dbInputString();
1836 bind_array.add(iaid_str);
1837
1838 // LEASE_TYPE
1839 std::string lease_type_str = boost::lexical_cast<std::string>(lease_type);
1840 bind_array.add(lease_type_str);
1841
1842 // ... and get the data
1843 Lease6Collection result;
1844
1845 // Get a context
1846 PgSqlLeaseContextAlloc get_context(*this);
1847 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1848
1849 getLeaseCollection(ctx, GET_LEASE6_DUID_IAID, bind_array, result);
1850
1851 return (result);
1852}
1853
1856 uint32_t iaid, SubnetID subnet_id) const {
1858 .arg(iaid)
1859 .arg(subnet_id)
1860 .arg(duid.toText())
1861 .arg(lease_type);
1862
1863 // Set up the WHERE clause value
1864 PsqlBindArray bind_array;
1865
1866 // LEASE_TYPE
1867 std::string lease_type_str = boost::lexical_cast<std::string>(lease_type);
1868 bind_array.add(lease_type_str);
1869
1870 // DUID
1871 bind_array.add(duid.getDuid());
1872
1873 // IAID
1874 std::string iaid_str = PgSqlLease6Exchange::Uiaid(iaid).dbInputString();
1875 bind_array.add(iaid_str);
1876
1877 // SUBNET ID
1878 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
1879 bind_array.add(subnet_id_str);
1880
1881 // ... and get the data
1882 Lease6Collection result;
1883
1884 // Get a context
1885 PgSqlLeaseContextAlloc get_context(*this);
1886 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1887
1888 getLeaseCollection(ctx, GET_LEASE6_DUID_IAID_SUBID, bind_array, result);
1889
1890 return (result);
1891}
1892
1896 .arg(subnet_id);
1897
1898 // Set up the WHERE clause value
1899 PsqlBindArray bind_array;
1900
1901 // SUBNET_ID
1902 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
1903 bind_array.add(subnet_id_str);
1904
1905 // ... and get the data
1906 Lease6Collection result;
1907
1908 // Get a context
1909 PgSqlLeaseContextAlloc get_context(*this);
1910 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1911
1912 getLeaseCollection(ctx, GET_LEASE6_SUBID, bind_array, result);
1913
1914 return (result);
1915}
1916
1920 .arg(duid.toText());
1921
1922 // Set up the WHERE clause value
1923 PsqlBindArray bind_array;
1924
1925 // DUID
1926 bind_array.add(duid.getDuid());
1927 Lease6Collection result;
1928
1929 // Get a context
1930 PgSqlLeaseContextAlloc get_context(*this);
1931 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1932
1933 // query to fetch the data
1934 getLeaseCollection(ctx, GET_LEASE6_DUID, bind_array, result);
1935
1936 return (result);
1937}
1938
1940PgSqlLeaseMgr::getLeases6(const std::string& hostname) const {
1942 .arg(hostname);
1943
1944 // Set up the WHERE clause value
1945 PsqlBindArray bind_array;
1946
1947 // Hostname
1948 bind_array.add(hostname);
1949
1950 // ... and get the data
1951 Lease6Collection result;
1952
1953 // Get a context
1954 PgSqlLeaseContextAlloc get_context(*this);
1955 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1956
1957 getLeaseCollection(ctx, GET_LEASE6_HOSTNAME, bind_array, result);
1958
1959 return (result);
1960}
1961
1965
1966 // Provide empty binding array because our query has no parameters in
1967 // WHERE clause.
1968 PsqlBindArray bind_array;
1969 Lease6Collection result;
1970
1971 // Get a context
1972 PgSqlLeaseContextAlloc get_context(*this);
1973 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1974
1975 getLeaseCollection(ctx, GET_LEASE6, bind_array, result);
1976
1977 return (result);
1978}
1979
1981PgSqlLeaseMgr::getLeases6(const IOAddress& lower_bound_address,
1982 const LeasePageSize& page_size) const {
1983 // Expecting IPv6 address.
1984 if (!lower_bound_address.isV6()) {
1985 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1986 "retrieving leases from the lease database, got "
1987 << lower_bound_address);
1988 }
1989
1991 .arg(page_size.page_size_)
1992 .arg(lower_bound_address.toText());
1993
1994 // Prepare WHERE clause
1995 PsqlBindArray bind_array;
1996
1997 // In IPv6 we compare addresses represented as strings. The IPv6 zero address
1998 // is ::, so it is greater than any other address. In this special case, we
1999 // just use 0 for comparison which should be lower than any real IPv6 address.
2000 std::string lb_address_data = "0";
2001 if (!lower_bound_address.isV6Zero()) {
2002 lb_address_data = lower_bound_address.toText();
2003 }
2004
2005 // Bind lower bound address
2006 bind_array.add(lb_address_data);
2007
2008 // Bind page size value
2009 std::string page_size_data = boost::lexical_cast<std::string>(page_size.page_size_);
2010 bind_array.add(page_size_data);
2011
2012 // Get the leases
2013 Lease6Collection result;
2014
2015 // Get a context
2016 PgSqlLeaseContextAlloc get_context(*this);
2017 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2018
2019 getLeaseCollection(ctx, GET_LEASE6_PAGE, bind_array, result);
2020
2021 return (result);
2022}
2023
2024void
2026 const size_t max_leases) const {
2028 .arg(max_leases);
2029 getExpiredLeasesCommon(expired_leases, max_leases, GET_LEASE4_EXPIRE);
2030}
2031
2032void
2034 const size_t max_leases) const {
2036 .arg(max_leases);
2037 getExpiredLeasesCommon(expired_leases, max_leases, GET_LEASE6_EXPIRE);
2038}
2039
2040template<typename LeaseCollection>
2041void
2042PgSqlLeaseMgr::getExpiredLeasesCommon(LeaseCollection& expired_leases,
2043 const size_t max_leases,
2044 StatementIndex statement_index) const {
2045 PsqlBindArray bind_array;
2046
2047 // Exclude reclaimed leases.
2048 std::string state_str = boost::lexical_cast<std::string>(Lease::STATE_EXPIRED_RECLAIMED);
2049 bind_array.add(state_str);
2050
2051 // Expiration timestamp.
2052 std::string timestamp_str = PgSqlLeaseExchange::convertToDatabaseTime(time(0));
2053 bind_array.add(timestamp_str);
2054
2055 // If the number of leases is 0, we will return all leases. This is
2056 // achieved by setting the limit to a very high value.
2057 uint32_t limit = max_leases > 0 ? static_cast<uint32_t>(max_leases) :
2058 std::numeric_limits<uint32_t>::max();
2059 std::string limit_str = boost::lexical_cast<std::string>(limit);
2060 bind_array.add(limit_str);
2061
2062 // Get a context
2063 PgSqlLeaseContextAlloc get_context(*this);
2064 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2065
2066 // Retrieve leases from the database.
2067 getLeaseCollection(ctx, statement_index, bind_array, expired_leases);
2068}
2069
2070template<typename LeasePtr>
2071void
2072PgSqlLeaseMgr::updateLeaseCommon(PgSqlLeaseContextPtr& ctx,
2073 StatementIndex stindex,
2074 PsqlBindArray& bind_array,
2075 const LeasePtr& lease) {
2076 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
2077 tagged_statements[stindex].nbparams,
2078 &bind_array.values_[0],
2079 &bind_array.lengths_[0],
2080 &bind_array.formats_[0], 0));
2081
2082 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2083
2084 int affected_rows = boost::lexical_cast<int>(PQcmdTuples(r));
2085
2086 // Check success case first as it is the most likely outcome.
2087 if (affected_rows == 1) {
2088 return;
2089 }
2090
2091 // If no rows affected, lease doesn't exist.
2092 if (affected_rows == 0) {
2093 isc_throw(NoSuchLease, "unable to update lease for address " <<
2094 lease->addr_.toText() << " as it does not exist");
2095 }
2096
2097 // Should not happen - primary key constraint should only have selected
2098 // one row.
2099 isc_throw(DbOperationError, "apparently updated more than one lease "
2100 "that had the address " << lease->addr_.toText());
2101}
2102
2103void
2105 const StatementIndex stindex = UPDATE_LEASE4;
2106
2108 .arg(lease->addr_.toText());
2109
2110 // Get a context
2111 PgSqlLeaseContextAlloc get_context(*this);
2112 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2113
2114 // Create the BIND array for the data being updated
2115 PsqlBindArray bind_array;
2116 ctx->exchange4_->createBindForSend(lease, bind_array);
2117
2118 // Set up the WHERE clause and append it to the SQL_BIND array
2119 std::string addr4_str = boost::lexical_cast<std::string>(lease->addr_.toUint32());
2120 bind_array.add(addr4_str);
2121
2122 std::string expire_str;
2123 // Avoid overflow (see createBindForSend)
2124 if (lease->current_valid_lft_ == Lease::INFINITY_LFT) {
2125 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_, 0);
2126 } else {
2127 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_,
2128 lease->current_valid_lft_);
2129 }
2130 bind_array.add(expire_str);
2131
2132 // Drop to common update code
2133 updateLeaseCommon(ctx, stindex, bind_array, lease);
2134
2135 // Update lease current expiration time.
2136 lease->updateCurrentExpirationTime();
2137}
2138
2139void
2141 const StatementIndex stindex = UPDATE_LEASE6;
2142
2144 .arg(lease->addr_.toText())
2145 .arg(lease->type_);
2146
2147 // Get a context
2148 PgSqlLeaseContextAlloc get_context(*this);
2149 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2150
2151 // Create the BIND array for the data being updated
2152 PsqlBindArray bind_array;
2153 ctx->exchange6_->createBindForSend(lease, bind_array);
2154
2155 // Set up the WHERE clause and append it to the BIND array
2156 std::string addr_str = lease->addr_.toText();
2157 bind_array.add(addr_str);
2158
2159 std::string expire_str;
2160 // Avoid overflow (see createBindForSend)
2161 if (lease->current_valid_lft_ == Lease::INFINITY_LFT) {
2162 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_, 0);
2163 } else {
2164 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_,
2165 lease->current_valid_lft_);
2166 }
2167 bind_array.add(expire_str);
2168
2169 // Drop to common update code
2170 updateLeaseCommon(ctx, stindex, bind_array, lease);
2171
2172 // Update lease current expiration time.
2173 lease->updateCurrentExpirationTime();
2174}
2175
2176uint64_t
2177PgSqlLeaseMgr::deleteLeaseCommon(StatementIndex stindex,
2178 PsqlBindArray& bind_array) {
2179 // Get a context
2180 PgSqlLeaseContextAlloc get_context(*this);
2181 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2182
2183 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
2184 tagged_statements[stindex].nbparams,
2185 &bind_array.values_[0],
2186 &bind_array.lengths_[0],
2187 &bind_array.formats_[0], 0));
2188
2189 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2190 int affected_rows = boost::lexical_cast<int>(PQcmdTuples(r));
2191
2192 return (affected_rows);
2193}
2194
2195bool
2197 const IOAddress& addr = lease->addr_;
2199 .arg(addr.toText());
2200
2201 // Set up the WHERE clause value
2202 PsqlBindArray bind_array;
2203
2204 std::string addr4_str = boost::lexical_cast<std::string>(addr.toUint32());
2205 bind_array.add(addr4_str);
2206
2207 std::string expire_str;
2208 // Avoid overflow (see createBindForSend)
2209 if (lease->current_valid_lft_ == Lease::INFINITY_LFT) {
2210 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_, 0);
2211 } else {
2212 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_,
2213 lease->current_valid_lft_);
2214 }
2215 bind_array.add(expire_str);
2216
2217 auto affected_rows = deleteLeaseCommon(DELETE_LEASE4, bind_array);
2218
2219 // Check success case first as it is the most likely outcome.
2220 if (affected_rows == 1) {
2221 return (true);
2222 }
2223
2224 // If no rows affected, lease doesn't exist.
2225 if (affected_rows == 0) {
2226 return (false);
2227 }
2228
2229 // Should not happen - primary key constraint should only have selected
2230 // one row.
2231 isc_throw(DbOperationError, "apparently deleted more than one lease "
2232 "that had the address " << lease->addr_.toText());
2233}
2234
2235bool
2237 const IOAddress& addr = lease->addr_;
2240 .arg(addr.toText());
2241
2242 // Set up the WHERE clause value
2243 PsqlBindArray bind_array;
2244
2245 std::string addr6_str = addr.toText();
2246 bind_array.add(addr6_str);
2247
2248 std::string expire_str;
2249 // Avoid overflow (see createBindForSend)
2250 if (lease->current_valid_lft_ == Lease::INFINITY_LFT) {
2251 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_, 0);
2252 } else {
2253 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_,
2254 lease->current_valid_lft_);
2255 }
2256 bind_array.add(expire_str);
2257
2258 auto affected_rows = deleteLeaseCommon(DELETE_LEASE6, bind_array);
2259
2260 // Check success case first as it is the most likely outcome.
2261 if (affected_rows == 1) {
2262 return (true);
2263 }
2264
2265 // If no rows affected, lease doesn't exist.
2266 if (affected_rows == 0) {
2267 return (false);
2268 }
2269
2270 // Should not happen - primary key constraint should only have selected
2271 // one row.
2272 isc_throw(DbOperationError, "apparently deleted more than one lease "
2273 "that had the address " << lease->addr_.toText());
2274}
2275
2276uint64_t
2279 .arg(secs);
2280 return (deleteExpiredReclaimedLeasesCommon(secs, DELETE_LEASE4_STATE_EXPIRED));
2281}
2282
2283uint64_t
2286 .arg(secs);
2287 return (deleteExpiredReclaimedLeasesCommon(secs, DELETE_LEASE6_STATE_EXPIRED));
2288}
2289
2290uint64_t
2291PgSqlLeaseMgr::deleteExpiredReclaimedLeasesCommon(const uint32_t secs,
2292 StatementIndex statement_index) {
2293 PsqlBindArray bind_array;
2294
2295 // State is reclaimed.
2296 std::string state_str = boost::lexical_cast<std::string>(Lease::STATE_EXPIRED_RECLAIMED);
2297 bind_array.add(state_str);
2298
2299 // Expiration timestamp.
2300 std::string expiration_str = PgSqlLeaseExchange::convertToDatabaseTime(time(0) -
2301 static_cast<time_t>(secs));
2302 bind_array.add(expiration_str);
2303
2304 // Delete leases.
2305 return (deleteLeaseCommon(statement_index, bind_array));
2306}
2307
2308string
2309PgSqlLeaseMgr::checkLimits(ConstElementPtr const& user_context, StatementIndex const stindex) const {
2310 // No user context means no limits means allocation allowed means empty string.
2311 if (!user_context) {
2312 return string();
2313 }
2314
2315 // Get a context.
2316 PgSqlLeaseContextAlloc get_context(*this);
2317 PgSqlLeaseContextPtr ctx(get_context.ctx_);
2318
2319 // Create bindings.
2320 PsqlBindArray bind_array;
2321 std::string const user_context_str(user_context->str());
2322 bind_array.add(user_context_str);
2323
2324 // Execute the select.
2325 PgSqlResult r(PQexecPrepared(ctx->conn_,
2326 tagged_statements[stindex].name,
2327 tagged_statements[stindex].nbparams,
2328 &bind_array.values_[0],
2329 &bind_array.lengths_[0],
2330 &bind_array.formats_[0], 0));
2331 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2332
2333 std::string limits;
2334 PgSqlExchange::getColumnValue(r, 0, 0, limits);
2335 return limits;
2336}
2337
2338string
2339PgSqlLeaseMgr::checkLimits4(ConstElementPtr const& user_context) const {
2340 return checkLimits(user_context, CHECK_LEASE4_LIMITS);
2341}
2342
2343string
2344PgSqlLeaseMgr::checkLimits6(ConstElementPtr const& user_context) const {
2345 return checkLimits(user_context, CHECK_LEASE6_LIMITS);
2346}
2347
2348bool
2349PgSqlLeaseMgr::isJsonSupported() const {
2350 // Get a context.
2351 PgSqlLeaseContextAlloc get_context(*this);
2352 PgSqlLeaseContextPtr ctx(get_context.ctx_);
2353
2354 // Execute the select.
2355 StatementIndex const stindex(IS_JSON_SUPPORTED);
2356 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
2357 0, 0, 0, 0, 0));
2358 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2359
2360 bool json_supported;
2361 PgSqlExchange::getColumnValue(r, 0, 0, json_supported);
2362 return json_supported;
2363}
2364
2365size_t
2366PgSqlLeaseMgr::getClassLeaseCount(const ClientClass& client_class,
2367 const Lease::Type& ltype /* = Lease::TYPE_V4*/) const {
2368 // Get a context.
2369 PgSqlLeaseContextAlloc get_context(*this);
2370 PgSqlLeaseContextPtr ctx(get_context.ctx_);
2371
2372 // Create bindings.
2373 PsqlBindArray bind_array;
2374 bind_array.add(client_class);
2375 if (ltype != Lease::TYPE_V4) {
2376 bind_array.add(ltype);
2377 }
2378
2379 // Execute the select.
2382 PgSqlResult r(PQexecPrepared(ctx->conn_,
2383 tagged_statements[stindex].name,
2384 tagged_statements[stindex].nbparams,
2385 &bind_array.values_[0],
2386 &bind_array.lengths_[0],
2387 &bind_array.formats_[0], 0));
2388 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2389
2390 int rows = PQntuples(r);
2391 if (rows == 0) {
2392 // No entries means 0 leases.
2393 return 0;
2394 }
2395
2396 size_t count;
2397 PgSqlExchange::getColumnValue(r, 0, 0, count);
2398 return count;
2399}
2400
2401void
2402PgSqlLeaseMgr::recountClassLeases4() {
2403 isc_throw(NotImplemented, "PgSqlLeaseMgr::recountClassLeases4() not implemented");
2404}
2405
2406void
2407PgSqlLeaseMgr::recountClassLeases6() {
2408 isc_throw(NotImplemented, "PgSqlLeaseMgr::recountClassLeases6() not implemented");
2409}
2410
2411void
2412PgSqlLeaseMgr::clearClassLeaseCounts() {
2413 isc_throw(NotImplemented, "PgSqlLeaseMgr::clearClassLeaseCounts() not implemented");
2414}
2415
2418 // Get a context
2419 PgSqlLeaseContextAlloc get_context(*this);
2420 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2421
2422 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2423 tagged_statements[ALL_LEASE4_STATS],
2424 false));
2425 query->start();
2426 return(query);
2427}
2428
2431 // Get a context
2432 PgSqlLeaseContextAlloc get_context(*this);
2433 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2434
2435 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2436 tagged_statements[SUBNET_LEASE4_STATS],
2437 false,
2438 subnet_id));
2439 query->start();
2440 return(query);
2441}
2442
2445 const SubnetID& last_subnet_id) {
2446 // Get a context
2447 PgSqlLeaseContextAlloc get_context(*this);
2448 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2449
2450 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2451 tagged_statements[SUBNET_RANGE_LEASE4_STATS],
2452 false,
2453 first_subnet_id,
2454 last_subnet_id));
2455 query->start();
2456 return(query);
2457}
2458
2461 // Get a context
2462 PgSqlLeaseContextAlloc get_context(*this);
2463 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2464
2465 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2466 tagged_statements[ALL_LEASE6_STATS],
2467 true));
2468 query->start();
2469 return(query);
2470}
2471
2474 // Get a context
2475 PgSqlLeaseContextAlloc get_context(*this);
2476 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2477
2478 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2479 tagged_statements[SUBNET_LEASE6_STATS],
2480 true,
2481 subnet_id));
2482 query->start();
2483 return(query);
2484}
2485
2488 const SubnetID& last_subnet_id) {
2489 // Get a context
2490 PgSqlLeaseContextAlloc get_context(*this);
2491 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2492
2493 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2494 tagged_statements[SUBNET_RANGE_LEASE6_STATS],
2495 true,
2496 first_subnet_id,
2497 last_subnet_id));
2498 query->start();
2499 return(query);
2500}
2501
2502size_t
2504 isc_throw(NotImplemented, "wipeLeases4 is not implemented for PostgreSQL backend");
2505}
2506
2507size_t
2509 isc_throw(NotImplemented, "wipeLeases6 is not implemented for PostgreSQL backend");
2510}
2511
2512std::string
2514 // Get a context
2515 PgSqlLeaseContextAlloc get_context(*this);
2516 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2517
2518 std::string name = "";
2519 try {
2520 name = ctx->conn_.getParameter("name");
2521 } catch (...) {
2522 // Return an empty name
2523 }
2524 return (name);
2525}
2526
2527std::string
2529 return (std::string("PostgreSQL Database"));
2530}
2531
2532std::pair<uint32_t, uint32_t>
2535
2536 return (PgSqlConnection::getVersion(parameters_));
2537}
2538
2539void
2542}
2543
2544void
2547}
2548
2549} // namespace dhcp
2550} // 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:764
static bool invokeDbLostCallback(const util::ReconnectCtlPtr &db_reconnect_ctl)
Invokes the connection's lost connectivity callback.
static std::string redactedAccessString(const ParameterMap &parameters)
Redact database access string.
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.
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Exception thrown on failure to open database.
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
Common PgSql Connector Pool.
static bool warned_about_tls
Emit the TLS support warning only once.
static const char DUPLICATE_KEY[]
Define the PgSql error state for a duplicate key error.
static std::pair< uint32_t, uint32_t > getVersion(const ParameterMap &parameters)
Get the schema version.
void checkStatementError(const PgSqlResult &r, PgSqlTaggedStatement &statement)
Checks result of the r object.
Base class for marshalling data to and from PostgreSQL.
static const char * getRawColumnValue(const PgSqlResult &r, const int row, const size_t col)
Gets a pointer to the raw column value in a result set row.
static std::string convertToDatabaseTime(const time_t input_time)
Converts UTC time_t value to a text representation in local time.
static std::string getColumnLabel(const PgSqlResult &r, const size_t col)
Fetches the name of the column in a result set.
static void convertFromBytea(const PgSqlResult &r, const int row, const size_t col, uint8_t *buffer, const size_t buffer_size, size_t &bytes_converted)
Converts a column in a row in a result set to a binary bytes.
static void getColumnValue(const PgSqlResult &r, const int row, const size_t col, std::string &value)
Fetches text column value as a string.
static time_t convertFromDatabaseTime(const std::string &db_time_val)
Converts time stamp from the database to a time_t.
std::vector< std::string > columns_
Stores text labels for columns, currently only used for logging and errors.
static isc::asiolink::IOAddress getIPv6Value(const PgSqlResult &r, const int row, const size_t col)
Converts a column in a row in a result set into IPv6 address.
RAII wrapper for PostgreSQL Result sets.
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:111
static const size_t MAX_CLIENT_ID_LEN
Maximum size of a client ID.
Definition: duid.h:128
const std::vector< uint8_t > & getClientId() const
Returns reference to the client-id data.
Definition: duid.cc:117
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
Definition: duid.cc:122
Holds DUID (DHCPv6 Unique Identifier)
Definition: duid.h:27
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
Definition: duid.cc:75
static const size_t MAX_DUID_LEN
maximum duid size As defined in RFC 8415, section 11.1
Definition: duid.h:31
const std::vector< uint8_t > & getDuid() const
Returns a const reference to the actual DUID value.
Definition: duid.cc:46
static void create(const std::string &dbaccess)
Create an instance of a lease manager.
static void destroy()
Destroy lease manager.
static isc::asiolink::IOServicePtr & getIOService()
Returns pointer to the IO service.
Definition: lease_mgr.h:791
Wraps value holding size of the page with leases.
Definition: lease_mgr.h:44
const size_t page_size_
Holds page size.
Definition: lease_mgr.h:54
Base class for fulfilling a statistical lease data query.
Definition: lease_mgr.h:129
SubnetID getLastSubnetID() const
Returns the value of last subnet ID specified (or zero)
Definition: lease_mgr.h:184
SubnetID getFirstSubnetID() const
Returns the value of first subnet ID specified (or zero)
Definition: lease_mgr.h:179
SelectMode getSelectMode() const
Returns the selection criteria mode The value returned is based upon the constructor variant used and...
Definition: lease_mgr.h:191
Attempt to update lease that was not there.
Supports exchanging IPv4 leases with PostgreSQL.
Lease4Ptr convertFromDatabase(const PgSqlResult &r, int row)
Creates a Lease4 object from a given row in a result set.
void createBindForSend(const Lease4Ptr &lease, PsqlBindArray &bind_array)
Creates the bind array for sending Lease4 data to the database.
Supports exchanging IPv6 leases with PostgreSQL.
void createBindForSend(const Lease6Ptr &lease, PsqlBindArray &bind_array)
Creates the bind array for sending Lease6 data to the database.
void getLeaseTypeColumnValue(const PgSqlResult &r, const int row, const size_t col, Lease6::Type &value) const
Fetches an integer text column as a Lease6::Type.
Lease6Ptr convertFromDatabase(const PgSqlResult &r, int row)
Creates a Lease6 object from a given row in a result set.
PostgreSQL Lease Context Pool.
PostgreSQL Lease Context.
PgSqlLeaseContext(const db::DatabaseConnection::ParameterMap &parameters, db::IOServiceAccessorPtr io_service_accessor, db::DbCallback db_reconnect_callback)
Constructor.
Base class for marshalling leases to and from PostgreSQL.
uint8_t hwaddr_buffer_[HWAddr::MAX_HWADDR_LEN]
std::vector< uint8_t > hwaddr_
std::string addr_str_
Common Instance members used for binding and conversion.
PostgreSQL Lease Manager.
virtual LeaseStatsQueryPtr startLeaseStatsQuery4() override
Creates and runs the IPv4 lease stats query.
virtual size_t wipeLeases4(const SubnetID &subnet_id) override
Removes specified IPv4 leases.
PgSqlLeaseContextPtr createContext() const
Create a new context.
virtual Lease4Collection getLeases4() const override
Returns all IPv4 leases.
virtual LeaseStatsQueryPtr startLeaseStatsQuery6() override
Creates and runs the IPv6 lease stats query.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv4 leases.
static std::string getDBVersion()
Local version of getDBVersion() class method.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery4(const SubnetID &subnet_id) override
Creates and runs the IPv4 lease stats query for a single subnet.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv6 leases.
virtual size_t wipeLeases6(const SubnetID &subnet_id) override
Removed specified IPv6 leases.
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv4 leases.
virtual void updateLease6(const Lease6Ptr &lease6) override
Updates IPv6 lease.
virtual std::pair< uint32_t, uint32_t > getVersion() const override
Returns backend version.
virtual std::string getDescription() const override
Returns description of the backend.
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 commit() override
Commit Transactions.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery6(const SubnetID &subnet_id) override
Creates and runs the IPv6 lease stats query for a single subnet.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const override
Returns existing IPv6 lease for a given IPv6 address.
virtual Lease6Collection getLeases6() const override
Returns all IPv6 leases.
StatementIndex
Statement Tags.
virtual void rollback() override
Rollback Transactions.
virtual void updateLease4(const Lease4Ptr &lease4) override
Updates IPv4 lease.
virtual void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv6 leases.
virtual std::string getName() const override
Returns backend name.
PgSqlLeaseMgr(const db::DatabaseConnection::ParameterMap &parameters)
Constructor.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const override
Returns an IPv4 lease for specified IPv4 address.
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.
static bool dbReconnect(util::ReconnectCtlPtr db_reconnect_ctl)
Attempts to reconnect the server to the lease DB backend manager.
virtual ~PgSqlLeaseMgr()
Destructor (closes database)
virtual bool addLease(const Lease4Ptr &lease) override
Adds an IPv4 lease.
virtual bool deleteLease(const Lease4Ptr &lease) override
Deletes an IPv4 lease.
Base PgSql derivation of the statistical lease data query.
bool fetch_type_
Indicates if query supplies lease type.
boost::shared_ptr< PgSqlResult > result_set_
The result set returned by Postgres.
PgSqlLeaseStatsQuery(PgSqlConnection &conn, PgSqlTaggedStatement &statement, 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.
PgSqlConnection & conn_
Database connection to use to execute the query.
virtual ~PgSqlLeaseStatsQuery()
Destructor.
PgSqlTaggedStatement & statement_
The query's prepared statement.
static bool negative_count_
Received negative state count showing a problem.
bool getNextRow(LeaseStatsRow &row)
Fetches the next row in the result set.
PgSqlLeaseStatsQuery(PgSqlConnection &conn, PgSqlTaggedStatement &statement, const bool fetch_type)
Constructor to query for all subnets' stats.
PgSqlLeaseStatsQuery(PgSqlConnection &conn, PgSqlTaggedStatement &statement, const bool fetch_type, const SubnetID &subnet_id)
Constructor to query for a single subnet's stats.
void start()
Creates the lease statistical data result set.
uint32_t next_row_
Index of the next row to fetch.
static const TimerMgrPtr & instance()
Returns pointer to the sole instance of the TimerMgr.
Definition: timer_mgr.cc:449
RAII class creating a critical section.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
static const uint32_t HWADDR_SOURCE_UNKNOWN
Used when actual origin is not known, e.g.
Definition: hwaddr.h:41
#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:27
const size_t OID_INT2
boost::shared_ptr< IOServiceAccessor > IOServiceAccessorPtr
Pointer to an instance of IOServiceAccessor.
const size_t OID_VARCHAR
const size_t OID_NONE
Constants for PostgreSQL data types These are defined by PostgreSQL in <catalog/pg_type....
const size_t OID_TIMESTAMP
const size_t OID_TEXT
const size_t OID_BOOL
const uint32_t PGSQL_SCHEMA_VERSION_MINOR
const size_t OID_INT8
const size_t OID_BYTEA
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.
const uint32_t PGSQL_SCHEMA_VERSION_MAJOR
Define the PostgreSQL backend version.
const isc::log::MessageID DHCPSRV_PGSQL_GET_SUBID4
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
const isc::log::MessageID DHCPSRV_PGSQL_ADD_ADDR4
std::string ClientClass
Defines a single class name.
Definition: classify.h:42
const isc::log::MessageID DHCPSRV_PGSQL_GET_SUBID_CLIENTID
const isc::log::MessageID DHCPSRV_PGSQL_GET_ADDR6
const isc::log::MessageID DHCPSRV_PGSQL_GET_DUID
const isc::log::MessageID DHCPSRV_PGSQL_GET6
const isc::log::MessageID DHCPSRV_PGSQL_GET_SUBID6
const isc::log::MessageID DHCPSRV_PGSQL_GET_PAGE4
boost::shared_ptr< CfgDbAccess > CfgDbAccessPtr
A pointer to the CfgDbAccess.
boost::shared_ptr< DUID > DuidPtr
Definition: duid.h:20
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:503
const isc::log::MessageID DHCPSRV_PGSQL_GET_HOSTNAME6
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:661
boost::shared_ptr< LeaseStatsQuery > LeaseStatsQueryPtr
Defines a pointer to a LeaseStatsQuery.
Definition: lease_mgr.h:208
const isc::log::MessageID DHCPSRV_PGSQL_GET_IAID_SUBID_DUID
const isc::log::MessageID DHCPSRV_PGSQL_GET_ADDR4
const isc::log::MessageID DHCPSRV_PGSQL_GET_HOSTNAME4
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_PGSQL_ROLLBACK
const isc::log::MessageID DHCPSRV_PGSQL_GET_HWADDR
const isc::log::MessageID DHCPSRV_PGSQL_NO_TLS_SUPPORT
const isc::log::MessageID DHCPSRV_PGSQL_GET_PAGE6
const isc::log::MessageID DHCPSRV_PGSQL_DELETE_EXPIRED_RECLAIMED4
const isc::log::MessageID DHCPSRV_PGSQL_UPDATE_ADDR4
const isc::log::MessageID DHCPSRV_PGSQL_GET_SUBID_HWADDR
const isc::log::MessageID DHCPSRV_PGSQL_GET_VERSION
const isc::log::MessageID DHCPSRV_PGSQL_LEASE_DB_RECONNECT_ATTEMPT_FAILED
const isc::log::MessageID DHCPSRV_PGSQL_TLS_SUPPORT
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:24
boost::shared_ptr< Lease > LeasePtr
Pointer to the lease object.
Definition: lease.h:22
const isc::log::MessageID DHCPSRV_PGSQL_GET4
const isc::log::MessageID DHCPSRV_PGSQL_ADD_ADDR6
const isc::log::MessageID DHCPSRV_PGSQL_GET_CLIENTID
const isc::log::MessageID DHCPSRV_PGSQL_GET_IAID_DUID
const isc::log::MessageID DHCPSRV_PGSQL_UPDATE_ADDR6
boost::shared_ptr< PgSqlLeaseContext > PgSqlLeaseContextPtr
Type of pointers to contexts.
const isc::log::MessageID DHCPSRV_PGSQL_LEASE_DB_RECONNECT_FAILED
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition: lease.h:498
@ HTYPE_UNDEFINED
not specified or undefined
Definition: dhcp4.h:55
@ HTYPE_ETHER
Ethernet 10Mbps.
Definition: dhcp4.h:56
const isc::log::MessageID DHCPSRV_PGSQL_NEGATIVE_LEASES_STAT
const isc::log::MessageID DHCPSRV_PGSQL_GET_EXPIRED4
const isc::log::MessageID DHCPSRV_PGSQL_GET_EXPIRED6
const isc::log::MessageID DHCPSRV_PGSQL_LEASE_DB_RECONNECT_ATTEMPT_SCHEDULE
const isc::log::MessageID DHCPSRV_PGSQL_DELETE_ADDR
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:284
const isc::log::MessageID DHCPSRV_PGSQL_COMMIT
const isc::log::MessageID DHCPSRV_PGSQL_DELETE_EXPIRED_RECLAIMED6
Definition: edns.h:19
boost::shared_ptr< ReconnectCtl > ReconnectCtlPtr
Pointer to an instance of ReconnectCtl.
Defines the logger used by the top-level component of kea-lfc.
Define a PostgreSQL statement.
const char * name
Short name of the query.
void addTempString(const std::string &str)
Binds the given string to the bind array.
std::vector< const char * > values_
Vector of pointers to the data values.
std::vector< int > formats_
Vector of "format" for each value.
void add(const char *value)
Adds a char array to bind array based.
size_t size() const
Fetches the number of entries in the array.
std::string toText() const
Dumps the contents of the array to a string.
std::vector< int > lengths_
Vector of data lengths for each value.
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
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:514
Contains a single row of lease statistical data.
Definition: lease_mgr.h:62
int64_t state_count_
state_count The count of leases in the lease state
Definition: lease_mgr.h:121
uint32_t lease_state_
The lease_state to which the count applies.
Definition: lease_mgr.h:119
SubnetID subnet_id_
The subnet ID to which this data applies.
Definition: lease_mgr.h:115
Lease::Type lease_type_
The lease_type to which the count applies.
Definition: lease_mgr.h:117
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
Union for marshalling IAID into and out of the database IAID is defined in the RFC as 4 octets,...
std::string dbInputString()
Return a string representing the signed 32-bit value.