Kea 2.6.2
pgsql_lease_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2025 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
10#include <dhcp/duid.h>
11#include <dhcp/hwaddr.h>
13#include <dhcpsrv/cfgmgr.h>
14#include <dhcpsrv/dhcpsrv_log.h>
19#include <dhcpsrv/timer_mgr.h>
21
22#include <boost/make_shared.hpp>
23#include <boost/static_assert.hpp>
24
25#include <iomanip>
26#include <limits>
27#include <sstream>
28#include <string>
29#include <time.h>
30
31using namespace isc;
32using namespace isc::asiolink;
33using namespace isc::db;
34using namespace isc::dhcp;
35using namespace isc::data;
36using namespace isc::util;
37using namespace std;
38
39namespace {
40
44PgSqlTaggedStatement tagged_statements[] = {
45 // DELETE_LEASE4
46 { 2, { OID_INT8, OID_TIMESTAMP },
47 "delete_lease4",
48 "DELETE FROM lease4 WHERE address = $1 AND expire = $2" },
49
50 // DELETE_LEASE4_STATE_EXPIRED
51 { 2, { OID_INT8, OID_TIMESTAMP },
52 "delete_lease4_state_expired",
53 "DELETE FROM lease4 "
54 "WHERE state = $1 AND expire < $2" },
55
56 // DELETE_LEASE6
57 { 2, { OID_VARCHAR, OID_TIMESTAMP },
58 "delete_lease6",
59 "DELETE FROM lease6 WHERE address = cast($1 as inet) AND expire = $2"},
60
61 // DELETE_LEASE6_STATE_EXPIRED
62 { 2, { OID_INT8, OID_TIMESTAMP },
63 "delete_lease6_state_expired",
64 "DELETE FROM lease6 "
65 "WHERE state = $1 AND expire < $2" },
66
67 // GET_LEASE4
68 { 0, { OID_NONE },
69 "get_lease4",
70 "SELECT address, hwaddr, client_id, "
71 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
72 "fqdn_fwd, fqdn_rev, hostname, "
73 "state, user_context, relay_id, remote_id, pool_id "
74 "FROM lease4" },
75
76 // GET_LEASE4_ADDR
77 { 1, { OID_INT8 },
78 "get_lease4_addr",
79 "SELECT address, hwaddr, client_id, "
80 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
81 "fqdn_fwd, fqdn_rev, hostname, "
82 "state, user_context, relay_id, remote_id, pool_id "
83 "FROM lease4 "
84 "WHERE address = $1" },
85
86 // GET_LEASE4_CLIENTID
87 { 1, { OID_BYTEA },
88 "get_lease4_clientid",
89 "SELECT address, hwaddr, client_id, "
90 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
91 "fqdn_fwd, fqdn_rev, hostname, "
92 "state, user_context, relay_id, remote_id, pool_id "
93 "FROM lease4 "
94 "WHERE client_id = $1" },
95
96 // GET_LEASE4_CLIENTID_SUBID
97 { 2, { OID_BYTEA, OID_INT8 },
98 "get_lease4_clientid_subid",
99 "SELECT address, hwaddr, client_id, "
100 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
101 "fqdn_fwd, fqdn_rev, hostname, "
102 "state, user_context, relay_id, remote_id, pool_id "
103 "FROM lease4 "
104 "WHERE client_id = $1 AND subnet_id = $2" },
105
106 // GET_LEASE4_HWADDR
107 { 1, { OID_BYTEA },
108 "get_lease4_hwaddr",
109 "SELECT address, hwaddr, client_id, "
110 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
111 "fqdn_fwd, fqdn_rev, hostname, "
112 "state, user_context, relay_id, remote_id, pool_id "
113 "FROM lease4 "
114 "WHERE hwaddr = $1" },
115
116 // GET_LEASE4_HWADDR_SUBID
117 { 2, { OID_BYTEA, OID_INT8 },
118 "get_lease4_hwaddr_subid",
119 "SELECT address, hwaddr, client_id, "
120 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
121 "fqdn_fwd, fqdn_rev, hostname, "
122 "state, user_context, relay_id, remote_id, pool_id "
123 "FROM lease4 "
124 "WHERE hwaddr = $1 AND subnet_id = $2" },
125
126 // GET_LEASE4_PAGE
127 { 2, { OID_INT8, OID_INT8 },
128 "get_lease4_page",
129 "SELECT address, hwaddr, client_id, "
130 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
131 "fqdn_fwd, fqdn_rev, hostname, "
132 "state, user_context, relay_id, remote_id, pool_id "
133 "FROM lease4 "
134 "WHERE address > $1 "
135 "ORDER BY address "
136 "LIMIT $2" },
137
138 // GET_LEASE4_UCTX_PAGE
139 { 2, { OID_INT8, OID_INT8 },
140 "get_lease4_uctx_page",
141 "SELECT address, hwaddr, client_id, "
142 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
143 "fqdn_fwd, fqdn_rev, hostname, "
144 "state, user_context, relay_id, remote_id, pool_id "
145 "FROM lease4 "
146 "WHERE address > $1 AND user_context IS NOT NULL "
147 "ORDER BY address "
148 "LIMIT $2" },
149
150 // GET_LEASE4_SUBID
151 { 1, { OID_INT8 },
152 "get_lease4_subid",
153 "SELECT address, hwaddr, client_id, "
154 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
155 "fqdn_fwd, fqdn_rev, hostname, "
156 "state, user_context, relay_id, remote_id, pool_id "
157 "FROM lease4 "
158 "WHERE subnet_id = $1" },
159
160 // GET_LEASE4_HOSTNAME
161 { 1, { OID_VARCHAR },
162 "get_lease4_hostname",
163 "SELECT address, hwaddr, client_id, "
164 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
165 "fqdn_fwd, fqdn_rev, hostname, "
166 "state, user_context, relay_id, remote_id, pool_id "
167 "FROM lease4 "
168 "WHERE lower(hostname) = $1" },
169
170 // GET_LEASE4_EXPIRE
172 "get_lease4_expire",
173 "SELECT address, hwaddr, client_id, "
174 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
175 "fqdn_fwd, fqdn_rev, hostname, "
176 "state, user_context, relay_id, remote_id, pool_id "
177 "FROM lease4 "
178 "WHERE state != $1 AND valid_lifetime != 4294967295 AND expire < $2 "
179 "ORDER BY expire "
180 "LIMIT $3" },
181
182 // GET_LEASE4_RELAYID
183 { 3, { OID_BYTEA, OID_INT8, OID_INT8 },
184 "get_lease4_relayid",
185 "SELECT address, hwaddr, client_id, "
186 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
187 "fqdn_fwd, fqdn_rev, hostname, "
188 "state, user_context, relay_id, remote_id, pool_id "
189 "FROM lease4 "
190 "WHERE relay_id = $1 and address > $2 "
191 "ORDER BY address "
192 "LIMIT $3" },
193
194 // GET_LEASE4_RELAYID_QST
196 "get_lease4_relayid_qst",
197 "SELECT address, hwaddr, client_id, "
198 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
199 "fqdn_fwd, fqdn_rev, hostname, "
200 "state, user_context, relay_id, remote_id, pool_id "
201 "FROM lease4 "
202 "WHERE relay_id = $1 and address > $2 "
203 "and EXTRACT(EPOCH FROM expire) - (CASE valid_lifetime WHEN 4294967295 "
204 "THEN 0 ELSE valid_lifetime END) >= $3 "
205 "ORDER BY address "
206 "LIMIT $4" },
207
208 // GET_LEASE4_RELAYID_QSET
210 "get_lease4_relayid_qset",
211 "SELECT address, hwaddr, client_id, "
212 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
213 "fqdn_fwd, fqdn_rev, hostname, "
214 "state, user_context, relay_id, remote_id, pool_id "
215 "FROM lease4 "
216 "WHERE relay_id = $1 and address > $2 "
217 "and EXTRACT(EPOCH FROM expire) - (CASE valid_lifetime WHEN 4294967295 "
218 "THEN 0 ELSE valid_lifetime END) >= $3 "
219 "and EXTRACT(EPOCH FROM expire) - (CASE valid_lifetime WHEN 4294967295 "
220 "THEN 0 ELSE valid_lifetime END) <= $4 "
221 "ORDER BY address "
222 "LIMIT $5" },
223
224 // GET_LEASE4_RELAYID_QET
226 "get_lease4_relayid_qet",
227 "SELECT address, hwaddr, client_id, "
228 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
229 "fqdn_fwd, fqdn_rev, hostname, "
230 "state, user_context, relay_id, remote_id, pool_id "
231 "FROM lease4 "
232 "WHERE relay_id = $1 and address > $2 "
233 "and EXTRACT(EPOCH FROM expire) - (CASE valid_lifetime WHEN 4294967295 "
234 "THEN 0 ELSE valid_lifetime END) <= $3 "
235 "ORDER BY address "
236 "LIMIT $4" },
237
238 // GET_LEASE4_REMOTEID
239 { 3, { OID_BYTEA, OID_INT8, OID_INT8 },
240 "get_lease4_remoteid",
241 "SELECT address, hwaddr, client_id, "
242 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
243 "fqdn_fwd, fqdn_rev, hostname, "
244 "state, user_context, relay_id, remote_id, pool_id "
245 "FROM lease4 "
246 "WHERE remote_id = $1 and address > $2 "
247 "ORDER BY address "
248 "LIMIT $3" },
249
250 // GET_LEASE4_REMOTEID_QST
252 "get_lease4_remoteid_qst",
253 "SELECT address, hwaddr, client_id, "
254 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
255 "fqdn_fwd, fqdn_rev, hostname, "
256 "state, user_context, relay_id, remote_id, pool_id "
257 "FROM lease4 "
258 "WHERE remote_id = $1 and address > $2 "
259 "and EXTRACT(EPOCH FROM expire) - (CASE valid_lifetime WHEN 4294967295 "
260 "THEN 0 ELSE valid_lifetime END) >= $3 "
261 "ORDER BY address "
262 "LIMIT $4" },
263
264 // GET_LEASE4_REMOTEID_QSET
266 "get_lease4_remoteid_qset",
267 "SELECT address, hwaddr, client_id, "
268 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
269 "fqdn_fwd, fqdn_rev, hostname, "
270 "state, user_context, relay_id, remote_id, pool_id "
271 "FROM lease4 "
272 "WHERE remote_id = $1 and address > $2 "
273 "and EXTRACT(EPOCH FROM expire) - (CASE valid_lifetime WHEN 4294967295 "
274 "THEN 0 ELSE valid_lifetime END) >= $3 "
275 "and EXTRACT(EPOCH FROM expire) - (CASE valid_lifetime WHEN 4294967295 "
276 "THEN 0 ELSE valid_lifetime END) <= $4 "
277 "ORDER BY address "
278 "LIMIT $5" },
279
280 // GET_LEASE4_REMOTEID_QET
282 "get_lease4_remoteid_qet",
283 "SELECT address, hwaddr, client_id, "
284 "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, "
285 "fqdn_fwd, fqdn_rev, hostname, "
286 "state, user_context, relay_id, remote_id, pool_id "
287 "FROM lease4 "
288 "WHERE remote_id = $1 and address > $2 "
289 "and EXTRACT(EPOCH FROM expire) - (CASE valid_lifetime WHEN 4294967295 "
290 "THEN 0 ELSE valid_lifetime END) <= $3 "
291 "ORDER BY address "
292 "LIMIT $4" },
293
294 // GET_LEASE6
295 { 0, { OID_NONE },
296 "get_lease6",
297 "SELECT host(address), duid, valid_lifetime, "
298 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
299 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
300 "hwaddr, hwtype, hwaddr_source, "
301 "state, user_context, pool_id "
302 "FROM lease6 "
303 "ORDER BY address "},
304
305 // GET_LEASE6_ADDR
306 { 2, { OID_VARCHAR, OID_INT2 },
307 "get_lease6_addr",
308 "SELECT host(address), duid, valid_lifetime, "
309 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
310 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
311 "hwaddr, hwtype, hwaddr_source, "
312 "state, user_context, pool_id "
313 "FROM lease6 "
314 "WHERE address = cast($1 as inet) AND lease_type = $2"},
315
316 // GET_LEASE6_DUID_IAID
317 { 3, { OID_BYTEA, OID_INT8, OID_INT2 },
318 "get_lease6_duid_iaid",
319 "SELECT host(address), duid, valid_lifetime, "
320 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
321 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
322 "hwaddr, hwtype, hwaddr_source, "
323 "state, user_context, pool_id "
324 "FROM lease6 "
325 "WHERE duid = $1 AND iaid = $2 AND lease_type = $3" },
326
327 // GET_LEASE6_DUID_IAID_SUBID
329 "get_lease6_duid_iaid_subid",
330 "SELECT host(address), duid, valid_lifetime, "
331 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
332 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
333 "hwaddr, hwtype, hwaddr_source, "
334 "state, user_context, pool_id "
335 "FROM lease6 "
336 "WHERE lease_type = $1 "
337 "AND duid = $2 AND iaid = $3 AND subnet_id = $4" },
338
339 // GET_LEASE6_PAGE
340 { 2, { OID_VARCHAR, OID_INT8 },
341 "get_lease6_page",
342 "SELECT host(address), duid, valid_lifetime, "
343 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
344 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
345 "hwaddr, hwtype, hwaddr_source, "
346 "state, user_context, pool_id "
347 "FROM lease6 "
348 "WHERE address > cast($1 as inet) "
349 "ORDER BY address "
350 "LIMIT $2"},
351
352 // GET_LEASE6_UCTX_PAGE
353 { 2, { OID_VARCHAR, OID_INT8 },
354 "get_lease6_uctx_page",
355 "SELECT host(address), duid, valid_lifetime, "
356 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
357 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
358 "hwaddr, hwtype, hwaddr_source, "
359 "state, user_context, pool_id "
360 "FROM lease6 "
361 "WHERE address > cast($1 as inet) AND user_context IS NOT NULL "
362 "ORDER BY address "
363 "LIMIT $2" },
364
365 // GET_LEASE6_SUBID
366 { 1, { OID_INT8 },
367 "get_lease6_subid",
368 "SELECT host(address), duid, valid_lifetime, "
369 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
370 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
371 "hwaddr, hwtype, hwaddr_source, "
372 "state, user_context, pool_id "
373 "FROM lease6 "
374 "WHERE subnet_id = $1" },
375
376 // GET_LEASE6_SUBID_PAGE
377 { 3, { OID_INT8, OID_VARCHAR, OID_INT8 },
378 "get_lease6_subid_page",
379 "SELECT host(address), duid, valid_lifetime, "
380 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
381 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
382 "hwaddr, hwtype, hwaddr_source, "
383 "state, user_context, pool_id "
384 "FROM lease6 "
385 "WHERE subnet_id = $1 AND address > cast($2 as inet) "
386 "ORDER BY address "
387 "LIMIT $3" },
388
389 // GET_LEASE6_DUID
390 { 1, { OID_BYTEA },
391 "get_lease6_duid",
392 "SELECT host(address), duid, valid_lifetime, "
393 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
394 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
395 "hwaddr, hwtype, hwaddr_source, "
396 "state, user_context, pool_id "
397 "FROM lease6 "
398 "WHERE duid = $1" },
399
400 // GET_LEASE6_HOSTNAME
401 { 1, { OID_VARCHAR },
402 "get_lease6_hostname",
403 "SELECT host(address), duid, valid_lifetime, "
404 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
405 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
406 "hwaddr, hwtype, hwaddr_source, "
407 "state, user_context, pool_id "
408 "FROM lease6 "
409 "WHERE lower(hostname) = $1" },
410
411 // GET_LEASE6_EXPIRE
413 "get_lease6_expire",
414 "SELECT host(address), duid, valid_lifetime, "
415 "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
416 "lease_type, iaid, prefix_len, "
417 "fqdn_fwd, fqdn_rev, hostname, "
418 "hwaddr, hwtype, hwaddr_source, "
419 "state, user_context, pool_id "
420 "FROM lease6 "
421 "WHERE state != $1 AND valid_lifetime != 4294967295 AND expire < $2 "
422 "ORDER BY expire "
423 "LIMIT $3" },
424
425 // INSERT_LEASE4
429 "insert_lease4",
430 "INSERT INTO lease4(address, hwaddr, client_id, "
431 "valid_lifetime, expire, subnet_id, fqdn_fwd, fqdn_rev, hostname, "
432 "state, user_context, relay_id, remote_id, pool_id) "
433 "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)" },
434
435 // INSERT_LEASE6
439 OID_INT8},
440 "insert_lease6",
441 "INSERT INTO lease6(address, duid, valid_lifetime, "
442 "expire, subnet_id, pref_lifetime, "
443 "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, "
444 "hwaddr, hwtype, hwaddr_source, "
445 "state, user_context, pool_id) "
446 "VALUES (cast($1 as inet), $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)" },
447
448 // UPDATE_LEASE4
452 "update_lease4",
453 "UPDATE lease4 SET address = $1, hwaddr = $2, "
454 "client_id = $3, valid_lifetime = $4, expire = $5, "
455 "subnet_id = $6, fqdn_fwd = $7, fqdn_rev = $8, hostname = $9, "
456 "state = $10, user_context = $11, relay_id = $12, remote_id = $13, pool_id = $14 "
457 "WHERE address = $15 AND expire = $16" },
458
459 // UPDATE_LEASE6
464 "update_lease6",
465 "UPDATE lease6 SET address = cast($1 as inet), duid = $2, "
466 "valid_lifetime = $3, expire = $4, subnet_id = $5, "
467 "pref_lifetime = $6, lease_type = $7, iaid = $8, "
468 "prefix_len = $9, fqdn_fwd = $10, fqdn_rev = $11, hostname = $12, "
469 "hwaddr = $13, hwtype = $14, hwaddr_source = $15, "
470 "state = $16, user_context = $17, pool_id = $18 "
471 "WHERE address = cast($19 as inet) AND expire = $20" },
472
473 // ALL_LEASE4_STATS
474 { 0, { OID_NONE },
475 "all_lease4_stats",
476 "SELECT subnet_id, state, leases as state_count"
477 " FROM lease4_stat ORDER BY subnet_id, state" },
478
479 // SUBNET_LEASE4_STATS
480 { 1, { OID_INT8 },
481 "subnet_lease4_stats",
482 "SELECT subnet_id, state, leases as state_count"
483 " FROM lease4_stat "
484 " WHERE subnet_id = $1 "
485 " ORDER BY state" },
486
487 // SUBNET_RANGE_LEASE4_STATS
488 { 2, { OID_INT8, OID_INT8 },
489 "subnet_range_lease4_stats",
490 "SELECT subnet_id, state, leases as state_count"
491 " FROM lease4_stat "
492 " WHERE subnet_id >= $1 and subnet_id <= $2 "
493 " ORDER BY subnet_id, state" },
494
495 // ALL_POOL_LEASE4_STATS
496 { 0, { OID_NONE },
497 "all_pool_lease4_stats",
498 "SELECT subnet_id, pool_id, state, leases as state_count"
499 " FROM lease4_pool_stat ORDER BY subnet_id, pool_id, state" },
500
501 // ALL_LEASE6_STATS,
502 { 0, { OID_NONE },
503 "all_lease6_stats",
504 "SELECT subnet_id, lease_type, state, leases as state_count"
505 " FROM lease6_stat ORDER BY subnet_id, lease_type, state" },
506
507 // SUBNET_LEASE6_STATS
508 { 1, { OID_INT8 },
509 "subnet_lease6_stats",
510 "SELECT subnet_id, lease_type, state, leases as state_count"
511 " FROM lease6_stat "
512 " WHERE subnet_id = $1 "
513 " ORDER BY lease_type, state" },
514
515 // SUBNET_RANGE_LEASE6_STATS
516 { 2, { OID_INT8, OID_INT8 },
517 "subnet_range_lease6_stats",
518 "SELECT subnet_id, lease_type, state, leases as state_count"
519 " FROM lease6_stat "
520 " WHERE subnet_id >= $1 and subnet_id <= $2 "
521 " ORDER BY subnet_id, lease_type, state" },
522
523 // ALL_POOL_LEASE6_STATS,
524 { 0, { OID_NONE },
525 "all_pool_lease6_stats",
526 "SELECT subnet_id, pool_id, lease_type, state, leases as state_count"
527 " FROM lease6_pool_stat ORDER BY subnet_id, pool_id, lease_type, state" },
528
529 // CHECK_LEASE4_LIMITS
530 { 1, { OID_TEXT },
531 "check_lease4_limits",
532 "SELECT checkLease4Limits($1)" },
533
534 // CHECK_LEASE6_LIMITS
535 { 1, { OID_TEXT },
536 "check_lease6_limits",
537 "SELECT checkLease6Limits($1)" },
538
539 // IS_JSON_SUPPORTED
540 { 0, { OID_NONE },
541 "is_json_supported",
542 "SELECT isJsonSupported()" },
543
544 // GET_LEASE4_COUNT_BY_CLASS
545 { 1, { OID_VARCHAR },
546 "get_lease4_count_by_class",
547 "SELECT leases "
548 "FROM lease4_stat_by_client_class "
549 "WHERE client_class = $1" },
550
551 // GET_LEASE6_COUNT_BY_CLASS
552 { 2, { OID_VARCHAR, OID_INT2 },
553 "get_lease6_count_by_class",
554 "SELECT leases "
555 "FROM lease6_stat_by_client_class "
556 "WHERE client_class = $1 AND lease_type = $2" },
557
558 // WIPE_RELAY_ID6
559 { 0, { OID_NONE },
560 "wipe_relay_id6",
561 "DELETE FROM lease6_relay_id" },
562
563 // WIPE_REMOTE_ID6
564 { 0, { OID_NONE },
565 "wipe_remote_id6",
566 "DELETE FROM lease6_remote_id" },
567
568 // DELETE_RELAY_ID6
569 { 1, { OID_VARCHAR },
570 "delete_relay_id6",
571 "DELETE FROM lease6_relay_id WHERE lease_addr = cast($1 as inet)" },
572
573 // DELETE_REMOTE_ID6
574 { 1, { OID_VARCHAR },
575 "delete_remote_id6",
576 "DELETE FROM lease6_remote_id WHERE lease_addr = cast($1 as inet)" },
577
578 // ADD_RELAY_ID6
579 { 2, { OID_BYTEA, OID_VARCHAR },
580 "add_relay_id6",
581 "INSERT INTO lease6_relay_id(relay_id, lease_addr) "
582 "VALUES ($1, cast($2 as inet))" },
583
584 // ADD_REMOTE_ID6
585 { 2, { OID_BYTEA, OID_VARCHAR },
586 "add_remote_id6",
587 "INSERT INTO lease6_remote_id(remote_id, lease_addr) "
588 "VALUES ($1, cast($2 as inet))" },
589
590 // GET_RELAY_ID6
591 { 3, { OID_BYTEA, OID_VARCHAR, OID_INT8 },
592 "get_relay_id6",
593 "SELECT DISTINCT ON(l.address) "
594 "host(l.address), l.duid, l.valid_lifetime, "
595 "extract(epoch from l.expire)::bigint, l.subnet_id, l.pref_lifetime, "
596 "l.lease_type, l.iaid, l.prefix_len, l.fqdn_fwd, l.fqdn_rev, "
597 "l.hostname, l.hwaddr, l.hwtype, l.hwaddr_source, "
598 "l.state, l.user_context, l.pool_id "
599 "FROM lease6 AS l "
600 "INNER JOIN lease6_relay_id AS r "
601 " ON l.address = r.lease_addr "
602 " WHERE r.relay_id = $1 AND r.lease_addr > cast($2 as inet) "
603 "ORDER BY l.address "
604 "LIMIT $3" },
605
606 // GET_REMOTE_ID6
607 { 3, { OID_BYTEA, OID_VARCHAR, OID_INT8 },
608 "get_remote_id6",
609 "SELECT DISTINCT ON(l.address) "
610 "host(l.address), l.duid, l.valid_lifetime, "
611 "extract(epoch from l.expire)::bigint, l.subnet_id, l.pref_lifetime, "
612 "l.lease_type, l.iaid, l.prefix_len, l.fqdn_fwd, l.fqdn_rev, "
613 "l.hostname, l.hwaddr, l.hwtype, l.hwaddr_source, "
614 "l.state, l.user_context, l.pool_id "
615 "FROM lease6 AS l "
616 "INNER JOIN lease6_remote_id AS r "
617 " ON l.address = r.lease_addr "
618 " WHERE r.remote_id = $1 AND r.lease_addr > cast($2 as inet) "
619 "ORDER BY l.address "
620 "LIMIT $3" },
621
622 // COUNT_RELAY_ID6
623 { 0, { OID_NONE },
624 "count_relay_id6",
625 "SELECT COUNT(*) FROM lease6_relay_id" },
626
627 // COUNT_REMOTE_ID6
628 { 0, { OID_NONE },
629 "count_remote_id6",
630 "SELECT COUNT(*) FROM lease6_remote_id" },
631
632 // End of list sentinel
633 { 0, { 0 }, 0, 0 }
634};
635
636} // namespace
637
638namespace isc {
639namespace dhcp {
640
647public:
648
656
658
659protected:
660
662
663 std::string addr_str_;
665 std::vector<uint8_t> hwaddr_;
669 time_t expire_;
670 std::string expire_str_;
671 uint32_t subnet_id_;
672 std::string subnet_id_str_;
673 uint32_t pool_id_;
674 std::string pool_id_str_;
675 time_t cltt_;
678 std::string hostname_;
679 std::string state_str_;
680 std::string user_context_;
681 std::vector<uint8_t> addr_bin_;
683};
684
687private:
688
693
694 static const size_t ADDRESS_COL = 0;
695 static const size_t HWADDR_COL = 1;
696 static const size_t CLIENT_ID_COL = 2;
697 static const size_t VALID_LIFETIME_COL = 3;
698 static const size_t EXPIRE_COL = 4;
699 static const size_t SUBNET_ID_COL = 5;
700 static const size_t FQDN_FWD_COL = 6;
701 static const size_t FQDN_REV_COL = 7;
702 static const size_t HOSTNAME_COL = 8;
703 static const size_t STATE_COL = 9;
704 static const size_t USER_CONTEXT_COL = 10;
705 static const size_t RELAY_ID_COL = 11;
706 static const size_t REMOTE_ID_COL = 12;
707 static const size_t POOL_ID_COL = 13;
709
710 static const size_t LEASE_COLUMNS = 14;
711
712public:
713
716 : lease_(), addr4_(0), client_id_length_(0),
717 relay_id_length_(0), remote_id_length_(0) {
718
719 BOOST_STATIC_ASSERT(13 < LEASE_COLUMNS);
720
721 memset(hwaddr_buffer_, 0, sizeof(hwaddr_buffer_));
722 memset(client_id_buffer_, 0, sizeof(client_id_buffer_));
723 memset(relay_id_buffer_, 0, sizeof(relay_id_buffer_));
724 memset(remote_id_buffer_, 0, sizeof(remote_id_buffer_));
725
726 // Set the column names (for error messages)
727 columns_.push_back("address");
728 columns_.push_back("hwaddr");
729 columns_.push_back("client_id");
730 columns_.push_back("valid_lifetime");
731 columns_.push_back("expire");
732 columns_.push_back("subnet_id");
733 columns_.push_back("fqdn_fwd");
734 columns_.push_back("fqdn_rev");
735 columns_.push_back("hostname");
736 columns_.push_back("state");
737 columns_.push_back("user_context");
738 columns_.push_back("relay_id");
739 columns_.push_back("remote_id");
740 columns_.push_back("pool_id");
741 }
742
755 void createBindForSend(const Lease4Ptr& lease, PsqlBindArray& bind_array) {
756 if (!lease) {
757 isc_throw(BadValue, "createBindForSend:: Lease4 object is NULL");
758 }
759
760 // Store lease object to ensure it remains valid.
761 lease_ = lease;
762
763 try {
764 addr_str_ = boost::lexical_cast<std::string>(lease->addr_.toUint32());
765 bind_array.add(addr_str_);
766
767 if (lease->hwaddr_ && !lease->hwaddr_->hwaddr_.empty()) {
768 // PostgreSql does not provide MAX on variable length types
769 // so we have to enforce it ourselves.
770 if (lease->hwaddr_->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
771 isc_throw(DbOperationError, "Hardware address length : "
772 << lease_->hwaddr_->hwaddr_.size()
773 << " exceeds maximum allowed of: "
775 }
776 bind_array.add(lease->hwaddr_->hwaddr_);
777 } else {
778 bind_array.add("");
779 }
780
781 if (lease->client_id_) {
782 bind_array.add(lease->client_id_->getClientId());
783 } else {
784 bind_array.add("");
785 }
786
787 valid_lifetime_str_ = boost::lexical_cast<std::string>(lease->valid_lft_);
788 bind_array.add(valid_lifetime_str_);
789
790 // The lease structure holds the client last transmission time (cltt_)
791 // For convenience for external tools, this is converted to lease
792 // expiry time (expire). The relationship is given by:
793 // expire = cltt_ + valid_lft_
794 // Avoid overflow with infinite valid lifetime by using
795 // expire = cltt_ when valid_lft_ = 0xffffffff
796 if (lease_->valid_lft_ == Lease::INFINITY_LFT) {
797 expire_str_ = convertToDatabaseTime(lease->cltt_, 0);
798 } else {
799 expire_str_ = convertToDatabaseTime(lease->cltt_,
800 lease_->valid_lft_);
801 }
802 bind_array.add(expire_str_);
803
804 subnet_id_str_ = boost::lexical_cast<std::string>(lease->subnet_id_);
805 bind_array.add(subnet_id_str_);
806
807 bind_array.add(lease->fqdn_fwd_);
808
809 bind_array.add(lease->fqdn_rev_);
810
811 bind_array.add(lease->hostname_);
812
813 state_str_ = boost::lexical_cast<std::string>(lease->state_);
814 bind_array.add(state_str_);
815
816 ConstElementPtr ctx = lease->getContext();
817 if (ctx) {
818 user_context_ = ctx->str();
819 } else {
820 user_context_ = "";
821 }
822 bind_array.add(user_context_);
823
824 if (!lease->relay_id_.empty()) {
825 bind_array.add(lease->relay_id_);
826 } else {
827 bind_array.addNull();
828 }
829
830 if (!lease->remote_id_.empty()) {
831 bind_array.add(lease->remote_id_);
832 } else {
833 bind_array.addNull();
834 }
835
836 pool_id_str_ = boost::lexical_cast<std::string>(lease->pool_id_);
837 bind_array.add(pool_id_str_);
838 } catch (const std::exception& ex) {
840 "Could not create bind array from Lease4: "
841 << lease_->addr_.toText() << ", reason: " << ex.what());
842 }
843 }
844
854 try {
855 getColumnValue(r, row, ADDRESS_COL, addr4_);
856
857 convertFromBytea(r, row, HWADDR_COL, hwaddr_buffer_,
859
860 convertFromBytea(r, row, CLIENT_ID_COL, client_id_buffer_,
861 sizeof(client_id_buffer_), client_id_length_);
862
863 getColumnValue(r, row, VALID_LIFETIME_COL, valid_lifetime_);
864
866 EXPIRE_COL));
867
868 getColumnValue(r, row, SUBNET_ID_COL, subnet_id_);
869
870 // Recover from overflow (see createBindForSend)
872 cltt_ = expire_;
873 } else {
875 }
876
877 getColumnValue(r, row, FQDN_FWD_COL, fqdn_fwd_);
878
879 getColumnValue(r, row, FQDN_REV_COL, fqdn_rev_);
880
881 hostname_ = getRawColumnValue(r, row, HOSTNAME_COL);
882
883 uint32_t state;
884 getColumnValue(r, row, STATE_COL, state);
885
887 HTYPE_ETHER));
888
889 user_context_ = getRawColumnValue(r, row, USER_CONTEXT_COL);
890 ConstElementPtr ctx;
891 if (!user_context_.empty()) {
893 if (!ctx || (ctx->getType() != Element::map)) {
894 isc_throw(BadValue, "user context '" << user_context_
895 << "' is not a JSON map");
896 }
897 }
898
899 convertFromBytea(r, row, RELAY_ID_COL, relay_id_buffer_,
900 sizeof(relay_id_buffer_), relay_id_length_);
901
902 convertFromBytea(r, row, REMOTE_ID_COL, remote_id_buffer_,
903 sizeof(remote_id_buffer_), remote_id_length_);
904
905 getColumnValue(r, row, POOL_ID_COL, pool_id_);
906
907 Lease4Ptr result(boost::make_shared<Lease4>(addr4_, hwaddr,
908 client_id_buffer_,
909 client_id_length_,
913
914 result->state_ = state;
915
916 if (ctx) {
917 result->setContext(ctx);
918 }
919
920 if (relay_id_length_) {
921 result->relay_id_.assign(relay_id_buffer_,
922 relay_id_buffer_ + relay_id_length_);
923 }
924
925 if (remote_id_length_) {
926 result->remote_id_.assign(remote_id_buffer_,
927 remote_id_buffer_ + remote_id_length_);
928 }
929
930 result->pool_id_ = pool_id_;
931
932 return (result);
933 } catch (const std::exception& ex) {
935 "Could not convert data to Lease4, reason: "
936 << ex.what());
937 }
938 }
939
940private:
941
945 Lease4Ptr lease_;
946
948 uint32_t addr4_;
949 size_t client_id_length_;
950 uint8_t client_id_buffer_[ClientId::MAX_CLIENT_ID_LEN];
951 size_t relay_id_length_;
952 uint8_t relay_id_buffer_[ClientId::MAX_CLIENT_ID_LEN];
953 size_t remote_id_length_;
954 uint8_t remote_id_buffer_[ClientId::MAX_CLIENT_ID_LEN];
955};
956
959private:
960
965
966 static const size_t ADDRESS_COL = 0;
967 static const size_t DUID_COL = 1;
968 static const size_t VALID_LIFETIME_COL = 2;
969 static const size_t EXPIRE_COL = 3;
970 static const size_t SUBNET_ID_COL = 4;
971 static const size_t PREF_LIFETIME_COL = 5;
972 static const size_t LEASE_TYPE_COL = 6;
973 static const size_t IAID_COL = 7;
974 static const size_t PREFIX_LEN_COL = 8;
975 static const size_t FQDN_FWD_COL = 9;
976 static const size_t FQDN_REV_COL = 10;
977 static const size_t HOSTNAME_COL = 11;
978 static const size_t HWADDR_COL = 12;
979 static const size_t HWTYPE_COL = 13;
980 static const size_t HWADDR_SOURCE_COL = 14;
981 static const size_t STATE_COL = 15;
982 static const size_t USER_CONTEXT_COL = 16;
983 static const size_t POOL_ID_COL = 17;
985
986 static const size_t LEASE_COLUMNS = 18;
987
988public:
989
996 union Uiaid {
999 Uiaid(uint32_t val) : uval_(val) {};
1000
1003 Uiaid(int32_t val) : ival_(val) {};
1004
1006 std::string dbInputString() {
1007 return (boost::lexical_cast<std::string>(ival_));
1008 };
1009
1010 uint32_t uval_;
1011 int32_t ival_;
1012 };
1013
1015 : lease_(), duid_length_(0), duid_(duid_length_), iaid_u_(0),
1016 iaid_str_(""), lease_type_(Lease6::TYPE_NA), lease_type_str_(""),
1017 prefix_len_(0), prefix_len_str_(""), pref_lifetime_(0),
1018 preferred_lifetime_str_(""), hwtype_(0), hwtype_str_(""),
1019 hwaddr_source_(0), hwaddr_source_str_("") {
1020
1021 BOOST_STATIC_ASSERT(17 < LEASE_COLUMNS);
1022
1023 memset(duid_buffer_, 0, sizeof(duid_buffer_));
1024
1025 // Set the column names (for error messages)
1026 columns_.push_back("address");
1027 columns_.push_back("duid");
1028 columns_.push_back("valid_lifetime");
1029 columns_.push_back("expire");
1030 columns_.push_back("subnet_id");
1031 columns_.push_back("pref_lifetime");
1032 columns_.push_back("lease_type");
1033 columns_.push_back("iaid");
1034 columns_.push_back("prefix_len");
1035 columns_.push_back("fqdn_fwd");
1036 columns_.push_back("fqdn_rev");
1037 columns_.push_back("hostname");
1038 columns_.push_back("hwaddr");
1039 columns_.push_back("hwtype");
1040 columns_.push_back("hwaddr_source");
1041 columns_.push_back("state");
1042 columns_.push_back("user_context");
1043 columns_.push_back("pool_id");
1044 }
1045
1058 void createBindForSend(const Lease6Ptr& lease, PsqlBindArray& bind_array) {
1059 if (!lease) {
1060 isc_throw(BadValue, "createBindForSend:: Lease6 object is NULL");
1061 }
1062
1063 // Store lease object to ensure it remains valid.
1064 lease_ = lease;
1065 try {
1066 addr_str_ = lease_->addr_.toText();
1067 bind_array.add(addr_str_);
1068
1069 if (lease_->duid_) {
1070 bind_array.add(lease_->duid_->getDuid());
1071 } else {
1072 isc_throw (BadValue, "IPv6 Lease cannot have a null DUID");
1073 }
1074
1075 valid_lifetime_str_ = boost::lexical_cast<std::string>(lease->valid_lft_);
1076 bind_array.add(valid_lifetime_str_);
1077
1078 // The lease structure holds the client last transmission time (cltt_)
1079 // For convenience for external tools, this is converted to lease
1080 // expiry time (expire). The relationship is given by:
1081 // expire = cltt_ + valid_lft_
1082 // Avoid overflow with infinite valid lifetime by using
1083 // expire = cltt_ when valid_lft_ = 0xffffffff
1084 if (lease_->valid_lft_ == Lease::INFINITY_LFT) {
1085 expire_str_ = convertToDatabaseTime(lease->cltt_, 0);
1086 } else {
1087 expire_str_ = convertToDatabaseTime(lease->cltt_,
1088 lease_->valid_lft_);
1089 }
1090 bind_array.add(expire_str_);
1091
1092 subnet_id_str_ = boost::lexical_cast<std::string>(lease->subnet_id_);
1093 bind_array.add(subnet_id_str_);
1094
1095 preferred_lifetime_str_ = boost::lexical_cast<std::string>(lease_->preferred_lft_);
1096 bind_array.add(preferred_lifetime_str_);
1097
1098 lease_type_str_ = boost::lexical_cast<std::string>(lease_->type_);
1099 bind_array.add(lease_type_str_);
1100
1101 // The iaid is stored as an INT in lease6 table, so we must
1102 // lexically cast from an integer version to avoid out of range
1103 // exception failure upon insert.
1104 iaid_u_.uval_ = lease_->iaid_;
1105 iaid_str_ = iaid_u_.dbInputString();
1106 bind_array.add(iaid_str_);
1107
1108 prefix_len_str_ = boost::lexical_cast<std::string>
1109 (static_cast<unsigned int>(lease_->prefixlen_));
1110 bind_array.add(prefix_len_str_);
1111
1112 bind_array.add(lease->fqdn_fwd_);
1113
1114 bind_array.add(lease->fqdn_rev_);
1115
1116 bind_array.add(lease->hostname_);
1117
1118 if (lease->hwaddr_ && !lease->hwaddr_->hwaddr_.empty()) {
1119 // PostgreSql does not provide MAX on variable length types
1120 // so we have to enforce it ourselves.
1121 if (lease->hwaddr_->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
1122 isc_throw(DbOperationError, "Hardware address length : "
1123 << lease_->hwaddr_->hwaddr_.size()
1124 << " exceeds maximum allowed of: "
1126 }
1127 bind_array.add(lease->hwaddr_->hwaddr_);
1128 } else {
1129 bind_array.add("");
1130 }
1131
1132 if (lease->hwaddr_) {
1133 hwtype_str_ = boost::lexical_cast<std::string>
1134 (static_cast<unsigned int>(lease_->hwaddr_->htype_));
1135 hwaddr_source_str_ = boost::lexical_cast<std::string>
1136 (static_cast<unsigned int>(lease_->hwaddr_->source_));
1137 } else {
1138 hwtype_str_ = boost::lexical_cast<std::string>
1139 (static_cast<unsigned int>(HTYPE_UNDEFINED));
1140 hwaddr_source_str_ = boost::lexical_cast<std::string>
1141 (static_cast<unsigned int>(HWAddr::HWADDR_SOURCE_UNKNOWN));
1142 }
1143
1144 bind_array.add(hwtype_str_);
1145
1146 bind_array.add(hwaddr_source_str_);
1147
1148 state_str_ = boost::lexical_cast<std::string>(lease->state_);
1149 bind_array.add(state_str_);
1150
1151 ConstElementPtr ctx = lease->getContext();
1152 if (ctx) {
1153 user_context_ = ctx->str();
1154 } else {
1155 user_context_ = "";
1156 }
1157 bind_array.add(user_context_);
1158
1159 pool_id_str_ = boost::lexical_cast<std::string>(lease->pool_id_);
1160 bind_array.add(pool_id_str_);
1161 } catch (const std::exception& ex) {
1163 "Could not create bind array from Lease6: "
1164 << lease_->addr_.toText() << ", reason: " << ex.what());
1165 }
1166 }
1167
1177 try {
1178
1186
1187 IOAddress addr(getIPv6Value(r, row, ADDRESS_COL));
1188
1189 convertFromBytea(r, row, DUID_COL, duid_buffer_, sizeof(duid_buffer_), duid_length_);
1190 DuidPtr duid_ptr(new DUID(duid_buffer_, duid_length_));
1191
1192 getColumnValue(r, row, VALID_LIFETIME_COL, valid_lifetime_);
1193
1195 EXPIRE_COL));
1196
1197 // Recover from overflow (see createBindForSend)
1199 cltt_ = expire_;
1200 } else {
1202 }
1203
1204 getColumnValue(r, row, SUBNET_ID_COL, subnet_id_);
1205
1206 getColumnValue(r, row, PREF_LIFETIME_COL, pref_lifetime_);
1207
1208 getLeaseTypeColumnValue(r, row, LEASE_TYPE_COL, lease_type_);
1209
1210 getColumnValue(r, row, IAID_COL, iaid_u_.ival_);
1211
1212 getColumnValue(r, row, PREFIX_LEN_COL, prefix_len_);
1213
1214 getColumnValue(r, row, FQDN_FWD_COL, fqdn_fwd_);
1215
1216 getColumnValue(r, row, FQDN_REV_COL, fqdn_rev_);
1217
1218 hostname_ = getRawColumnValue(r, row, HOSTNAME_COL);
1219
1220 convertFromBytea(r, row, HWADDR_COL, hwaddr_buffer_,
1222
1223 getColumnValue(r, row, HWTYPE_COL, hwtype_);
1224
1225 getColumnValue(r, row, HWADDR_SOURCE_COL, hwaddr_source_);
1226
1227 HWAddrPtr hwaddr;
1228
1229 if (hwaddr_length_) {
1230 hwaddr.reset(new HWAddr(hwaddr_buffer_, hwaddr_length_,
1231 hwtype_));
1232
1233 hwaddr->source_ = hwaddr_source_;
1234 }
1235
1236 uint32_t state;
1237 getColumnValue(r, row, STATE_COL, state);
1238
1239 user_context_ = getRawColumnValue(r, row, USER_CONTEXT_COL);
1240 ConstElementPtr ctx;
1241 if (!user_context_.empty()) {
1243 if (!ctx || (ctx->getType() != Element::map)) {
1244 isc_throw(BadValue, "user context '" << user_context_
1245 << "' is not a JSON map");
1246 }
1247 }
1248
1249 getColumnValue(r, row, POOL_ID_COL, pool_id_);
1250
1251 if (lease_type_ != Lease::TYPE_PD) {
1252 prefix_len_ = 128;
1253 }
1254
1255 Lease6Ptr result(boost::make_shared<Lease6>(lease_type_, addr,
1256 duid_ptr,
1257 iaid_u_.uval_,
1258 pref_lifetime_,
1262 hwaddr, prefix_len_));
1263 // Update cltt_ and current_cltt_ explicitly.
1264 result->cltt_ = cltt_;
1265 result->current_cltt_ = cltt_;
1266
1267 result->state_ = state;
1268
1269 if (ctx) {
1270 result->setContext(ctx);
1271 }
1272
1273 result->pool_id_ = pool_id_;
1274
1275 return (result);
1276 } catch (const std::exception& ex) {
1278 "Could not convert data to Lease6, reason: "
1279 << ex.what());
1280 }
1281 }
1282
1295 void getLeaseTypeColumnValue(const PgSqlResult& r, const int row,
1296 const size_t col, Lease6::Type& value) const {
1297 uint32_t raw_value = 0;
1298 getColumnValue(r, row, col, raw_value);
1299 switch (raw_value) {
1300 case Lease6::TYPE_NA:
1301 case Lease6::TYPE_TA:
1302 case Lease6::TYPE_PD:
1303 value = static_cast<Lease6::Type>(raw_value);
1304 break;
1305
1306 default:
1307 isc_throw(DbOperationError, "Invalid lease type: " << raw_value
1308 << " for: " << getColumnLabel(r, col) << " row:" << row);
1309 }
1310 }
1311
1312private:
1316 Lease6Ptr lease_;
1317
1319
1320 size_t duid_length_;
1321 std::vector<uint8_t> duid_;
1322 uint8_t duid_buffer_[DUID::MAX_DUID_LEN];
1323 union Uiaid iaid_u_;
1324 std::string iaid_str_;
1325 Lease6::Type lease_type_;
1326 std::string lease_type_str_;
1327 uint8_t prefix_len_;
1328 std::string prefix_len_str_;
1329 uint32_t pref_lifetime_;
1330 std::string preferred_lifetime_str_;
1331 uint32_t hwtype_;
1332 std::string hwtype_str_;
1333 uint32_t hwaddr_source_;
1334 std::string hwaddr_source_str_;
1336};
1337
1344public:
1345
1356 const bool fetch_type, const bool fetch_pool = false)
1357 : conn_(conn), statement_(statement), result_set_(), next_row_(0),
1358 fetch_type_(fetch_type), fetch_pool_(fetch_pool) {
1359 }
1360
1370 const bool fetch_type, const SubnetID& subnet_id)
1371 : LeaseStatsQuery(subnet_id), conn_(conn), statement_(statement), result_set_(),
1372 next_row_(0), fetch_type_(fetch_type), fetch_pool_(false) {
1373 }
1374
1386 const bool fetch_type, const SubnetID& first_subnet_id,
1387 const SubnetID& last_subnet_id)
1388 : LeaseStatsQuery(first_subnet_id, last_subnet_id), conn_(conn), statement_(statement),
1389 result_set_(), next_row_(0), fetch_type_(fetch_type), fetch_pool_(false) {
1390 }
1391
1394
1404 void start() {
1405
1407 // Run the query with no where clause parameters.
1408 result_set_.reset(new PgSqlResult(PQexecPrepared(conn_, statement_.name,
1409 0, 0, 0, 0, 0)));
1410 } else {
1411 // Set up the WHERE clause values
1412 PsqlBindArray parms;
1413
1414 // Add first_subnet_id used by both single and range.
1415 parms.addTempString(boost::lexical_cast<std::string>(getFirstSubnetID()));
1416
1417 // Add last_subnet_id for range.
1418 if (getSelectMode() == SUBNET_RANGE) {
1419 // Add last_subnet_id used by range.
1420 parms.addTempString(boost::lexical_cast<std::string>(getLastSubnetID()));
1421 }
1422
1423 // Run the query with where clause parameters.
1424 result_set_.reset(new PgSqlResult(PQexecPrepared(conn_, statement_.name,
1425 parms.size(), &parms.values_[0],
1426 &parms.lengths_[0], &parms.formats_[0], 0)));
1427 }
1428
1429 conn_.checkStatementError(*result_set_, statement_);
1430 }
1431
1447 // If we're past the end, punt.
1448 if (next_row_ >= result_set_->getRows()) {
1449 return (false);
1450 }
1451
1452 // Fetch the subnet id.
1453 uint32_t col = 0;
1454 uint32_t subnet_id;
1456 row.subnet_id_ = static_cast<SubnetID>(subnet_id);
1457 ++col;
1458
1459 // Fetch the pool id if we were told to do so.
1460 if (fetch_pool_) {
1462 row.pool_id_);
1463 ++col;
1464 }
1465
1466 // Fetch the lease type if we were told to do so.
1467 if (fetch_type_) {
1468 uint32_t lease_type;
1470 lease_type);
1471 row.lease_type_ = static_cast<Lease::Type>(lease_type);
1472 ++col;
1473 } else {
1475 }
1476
1477 // Fetch the lease state.
1479 row.lease_state_);
1480 ++col;
1481
1482 // Fetch the state count.
1484 row.state_count_);
1485
1486 // Protect against negative state count.a
1487 if (row.state_count_ < 0) {
1488 row.state_count_ = 0;
1489 if (!negative_count_) {
1490 negative_count_ = true;
1492 }
1493 }
1494
1495 // Point to the next row.
1496 ++next_row_;
1497 return (true);
1498 }
1499
1500protected:
1501
1504
1507
1509 boost::shared_ptr<PgSqlResult> result_set_;
1510
1512 uint32_t next_row_;
1513
1516
1519
1521 static bool negative_count_;
1522};
1523
1524// Initialize negative state count flag to false.
1526
1527// PgSqlLeaseContext Constructor
1528
1530 IOServiceAccessorPtr io_service_accessor,
1531 DbCallback db_reconnect_callback)
1532 : conn_(parameters, io_service_accessor, db_reconnect_callback) {
1533}
1534
1535// PgSqlLeaseContextAlloc Constructor and Destructor
1536
1537PgSqlLeaseMgr::PgSqlLeaseContextAlloc::PgSqlLeaseContextAlloc(
1538 const PgSqlLeaseMgr& mgr) : ctx_(), mgr_(mgr) {
1539
1540 if (MultiThreadingMgr::instance().getMode()) {
1541 // multi-threaded
1542 {
1543 // we need to protect the whole pool_ operation, hence extra scope {}
1544 lock_guard<mutex> lock(mgr_.pool_->mutex_);
1545 if (!mgr_.pool_->pool_.empty()) {
1546 ctx_ = mgr_.pool_->pool_.back();
1547 mgr_.pool_->pool_.pop_back();
1548 }
1549 }
1550 if (!ctx_) {
1551 ctx_ = mgr_.createContext();
1552 }
1553 } else {
1554 // single-threaded
1555 if (mgr_.pool_->pool_.empty()) {
1556 isc_throw(Unexpected, "No available PostgreSQL lease context?!");
1557 }
1558 ctx_ = mgr_.pool_->pool_.back();
1559 }
1560}
1561
1562PgSqlLeaseMgr::PgSqlLeaseContextAlloc::~PgSqlLeaseContextAlloc() {
1563 if (MultiThreadingMgr::instance().getMode()) {
1564 // multi-threaded
1565 lock_guard<mutex> lock(mgr_.pool_->mutex_);
1566 mgr_.pool_->pool_.push_back(ctx_);
1567 }
1568 // If running in single-threaded mode, there's nothing to do here.
1569}
1570
1571// PgSqlLeaseTrackingContextAlloc Constructor and Destructor
1572
1573PgSqlLeaseMgr::PgSqlLeaseTrackingContextAlloc::PgSqlLeaseTrackingContextAlloc(
1574 PgSqlLeaseMgr& mgr, const LeasePtr& lease) : ctx_(), mgr_(mgr), lease_(lease) {
1575
1576 if (MultiThreadingMgr::instance().getMode()) {
1577 // multi-threaded
1578 {
1579 // we need to protect the whole pool_ operation, hence extra scope {}
1580 lock_guard<mutex> lock(mgr_.pool_->mutex_);
1581 if (mgr_.hasCallbacks() && !mgr_.tryLock(lease)) {
1582 isc_throw(DbOperationError, "unable to lock the lease " << lease->addr_);
1583 }
1584 if (!mgr_.pool_->pool_.empty()) {
1585 ctx_ = mgr_.pool_->pool_.back();
1586 mgr_.pool_->pool_.pop_back();
1587 }
1588 }
1589 if (!ctx_) {
1590 ctx_ = mgr_.createContext();
1591 }
1592 } else {
1593 // single-threaded
1594 if (mgr_.pool_->pool_.empty()) {
1595 isc_throw(Unexpected, "No available PostgreSQL lease context?!");
1596 }
1597 ctx_ = mgr_.pool_->pool_.back();
1598 }
1599}
1600
1601PgSqlLeaseMgr::PgSqlLeaseTrackingContextAlloc::~PgSqlLeaseTrackingContextAlloc() {
1602 if (MultiThreadingMgr::instance().getMode()) {
1603 // multi-threaded
1604 lock_guard<mutex> lock(mgr_.pool_->mutex_);
1605 if (mgr_.hasCallbacks()) {
1606 mgr_.unlock(lease_);
1607 }
1608 mgr_.pool_->pool_.push_back(ctx_);
1609 }
1610 // If running in single-threaded mode, there's nothing to do here.
1611}
1612
1613// PgSqlLeaseMgr Constructor and Destructor
1614
1616 : TrackingLeaseMgr(), parameters_(parameters) {
1617
1618 // Check if the extended info tables are enabled.
1619 setExtendedInfoTablesEnabled(parameters);
1620
1621 // Check TLS support.
1622 size_t tls(0);
1623 tls += parameters.count("trust-anchor");
1624 tls += parameters.count("cert-file");
1625 tls += parameters.count("key-file");
1626 tls += parameters.count("cipher-list");
1627#ifdef HAVE_PGSQL_SSL
1628 if ((tls > 0) && !PgSqlConnection::warned_about_tls) {
1632 PQinitSSL(1);
1633 }
1634#else
1635 if (tls > 0) {
1638 isc_throw(DbOpenError, "Attempt to configure TLS for PostgreSQL "
1639 << "backend (built with this feature disabled)");
1640 }
1641#endif
1642
1643 // Create unique timer name per instance.
1644 timer_name_ = "PgSqlLeaseMgr[";
1645 timer_name_ += boost::lexical_cast<std::string>(reinterpret_cast<uint64_t>(this));
1646 timer_name_ += "]DbReconnectTimer";
1647
1649 timer_name_);
1650
1651 // Create an initial context.
1652 pool_.reset(new PgSqlLeaseContextPool());
1653 pool_->pool_.push_back(createContext());
1654}
1655
1658
1659bool
1662
1663 // Invoke application layer connection lost callback.
1664 if (!DatabaseConnection::invokeDbLostCallback(db_reconnect_ctl)) {
1665 return (false);
1666 }
1667
1668 bool reopened = false;
1669
1670 const std::string timer_name = db_reconnect_ctl->timerName();
1671 bool check = db_reconnect_ctl->checkRetries();
1672
1673 // At least one connection was lost.
1674 try {
1675 CfgDbAccessPtr cfg_db = CfgMgr::instance().getCurrentCfg()->getCfgDbAccess();
1676 LeaseMgrFactory::recreate(cfg_db->getLeaseDbAccessString());
1677 reopened = true;
1678 } catch (const std::exception& ex) {
1680 .arg(ex.what());
1681 }
1682
1683 if (reopened) {
1684 // Cancel the timer.
1685 if (TimerMgr::instance()->isTimerRegistered(timer_name)) {
1686 TimerMgr::instance()->unregisterTimer(timer_name);
1687 }
1688
1689 // Invoke application layer connection recovered callback.
1690 if (!DatabaseConnection::invokeDbRecoveredCallback(db_reconnect_ctl)) {
1691 return (false);
1692 }
1693 } else {
1694 if (!check) {
1695 // We're out of retries, log it and initiate shutdown.
1697 .arg(db_reconnect_ctl->maxRetries());
1698
1699 // Cancel the timer.
1700 if (TimerMgr::instance()->isTimerRegistered(timer_name)) {
1701 TimerMgr::instance()->unregisterTimer(timer_name);
1702 }
1703
1704 // Invoke application layer connection failed callback.
1706 return (false);
1707 }
1708
1710 .arg(db_reconnect_ctl->maxRetries() - db_reconnect_ctl->retriesLeft() + 1)
1711 .arg(db_reconnect_ctl->maxRetries())
1712 .arg(db_reconnect_ctl->retryInterval());
1713
1714 // Start the timer.
1715 if (!TimerMgr::instance()->isTimerRegistered(timer_name)) {
1716 TimerMgr::instance()->registerTimer(timer_name,
1717 std::bind(&PgSqlLeaseMgr::dbReconnect, db_reconnect_ctl),
1718 db_reconnect_ctl->retryInterval(),
1720 }
1721 TimerMgr::instance()->setup(timer_name);
1722 }
1723
1724 return (true);
1725}
1726
1727// Create context.
1728
1731 PgSqlLeaseContextPtr ctx(new PgSqlLeaseContext(parameters_,
1734
1735 // Create ReconnectCtl for this connection.
1736 ctx->conn_.makeReconnectCtl(timer_name_, NetworkState::DB_CONNECTION + 2);
1737
1738 // Open the database.
1739 ctx->conn_.openDatabase();
1740
1741 // Now prepare the SQL statements.
1742 uint32_t i = 0;
1743 for (; tagged_statements[i].text != NULL; ++i) {
1744 ctx->conn_.prepareStatement(tagged_statements[i]);
1745 }
1746
1747 // Just in case somebody foo-barred things
1748 if (i != NUM_STATEMENTS) {
1749 isc_throw(DbOpenError, "Number of statements prepared: " << i
1750 << " does not match expected count:" << NUM_STATEMENTS);
1751 }
1752
1753 // Create the exchange objects for use in exchanging data between the
1754 // program and the database.
1755 ctx->exchange4_.reset(new PgSqlLease4Exchange());
1756 ctx->exchange6_.reset(new PgSqlLease6Exchange());
1757
1758 return (ctx);
1759}
1760
1761std::string
1763 std::stringstream tmp;
1764 tmp << "PostgreSQL backend " << PGSQL_SCHEMA_VERSION_MAJOR;
1765 tmp << "." << PGSQL_SCHEMA_VERSION_MINOR;
1766 tmp << ", library " << PQlibVersion();
1767 return (tmp.str());
1768}
1769
1770bool
1771PgSqlLeaseMgr::addLeaseCommon(PgSqlLeaseContextPtr& ctx,
1772 StatementIndex stindex,
1773 PsqlBindArray& bind_array) {
1774 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
1775 tagged_statements[stindex].nbparams,
1776 &bind_array.values_[0],
1777 &bind_array.lengths_[0],
1778 &bind_array.formats_[0], 0));
1779
1780 int s = PQresultStatus(r);
1781
1782 if (s != PGRES_COMMAND_OK) {
1783 // Failure: check for the special case of duplicate entry. If this is
1784 // the case, we return false to indicate that the row was not added.
1785 // Otherwise we throw an exception.
1786 if (ctx->conn_.compareError(r, PgSqlConnection::DUPLICATE_KEY)) {
1787 return (false);
1788 }
1789 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
1790 }
1791
1792 return (true);
1793}
1794
1795bool
1798 .arg(lease->addr_.toText());
1799
1800 // Get a context
1801 PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
1802 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1803
1804 PsqlBindArray bind_array;
1805 ctx->exchange4_->createBindForSend(lease, bind_array);
1806 auto result = addLeaseCommon(ctx, INSERT_LEASE4, bind_array);
1807
1808 // Update lease current expiration time (allows update between the creation
1809 // of the Lease up to the point of insertion in the database).
1810 lease->updateCurrentExpirationTime();
1811
1812 // Run installed callbacks.
1813 if (hasCallbacks()) {
1814 trackAddLease(lease);
1815 }
1816
1817 return (result);
1818}
1819
1820bool
1823 .arg(lease->addr_.toText())
1824 .arg(lease->type_);
1825
1826 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
1827
1828 // Get a context
1829 PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
1830 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1831
1832 PsqlBindArray bind_array;
1833 ctx->exchange6_->createBindForSend(lease, bind_array);
1834
1835 auto result = addLeaseCommon(ctx, INSERT_LEASE6, bind_array);
1836
1837 // Update lease current expiration time (allows update between the creation
1838 // of the Lease up to the point of insertion in the database).
1839 lease->updateCurrentExpirationTime();
1840
1842 static_cast<void>(addExtendedInfo6(lease));
1843 }
1844
1845 // Run installed callbacks.
1846 if (hasCallbacks()) {
1847 trackAddLease(lease);
1848 }
1849
1850 return (result);
1851}
1852
1853template <typename Exchange, typename LeaseCollection>
1854void
1855PgSqlLeaseMgr::getLeaseCollection(PgSqlLeaseContextPtr& ctx,
1856 StatementIndex stindex,
1857 PsqlBindArray& bind_array,
1858 Exchange& exchange,
1859 LeaseCollection& result,
1860 bool single) const {
1861 const int n = tagged_statements[stindex].nbparams;
1862 PgSqlResult r(PQexecPrepared(ctx->conn_,
1863 tagged_statements[stindex].name, n,
1864 n > 0 ? &bind_array.values_[0] : NULL,
1865 n > 0 ? &bind_array.lengths_[0] : NULL,
1866 n > 0 ? &bind_array.formats_[0] : NULL, 0));
1867
1868 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
1869
1870 int rows = PQntuples(r);
1871 if (single && rows > 1) {
1872 isc_throw(MultipleRecords, "multiple records were found in the "
1873 "database where only one was expected for query "
1874 << tagged_statements[stindex].name);
1875 }
1876
1877 for(int i = 0; i < rows; ++i) {
1878 result.push_back(exchange->convertFromDatabase(r, i));
1879 }
1880}
1881
1882void
1883PgSqlLeaseMgr::getLease(PgSqlLeaseContextPtr& ctx,
1884 StatementIndex stindex, PsqlBindArray& bind_array,
1885 Lease4Ptr& result) const {
1886 // Create appropriate collection object and get all leases matching
1887 // the selection criteria. The "single" parameter is true to indicate
1888 // that the called method should throw an exception if multiple
1889 // matching records are found: this particular method is called when only
1890 // one or zero matches is expected.
1891 Lease4Collection collection;
1892 getLeaseCollection(ctx, stindex, bind_array, ctx->exchange4_,
1893 collection, true);
1894
1895 // Return single record if present, else clear the lease.
1896 if (collection.empty()) {
1897 result.reset();
1898 } else {
1899 result = *collection.begin();
1900 }
1901}
1902
1903void
1904PgSqlLeaseMgr::getLease(PgSqlLeaseContextPtr& ctx,
1905 StatementIndex stindex, PsqlBindArray& bind_array,
1906 Lease6Ptr& result) const {
1907 // Create appropriate collection object and get all leases matching
1908 // the selection criteria. The "single" parameter is true to indicate
1909 // that the called method should throw an exception if multiple
1910 // matching records are found: this particular method is called when only
1911 // one or zero matches is expected.
1912 Lease6Collection collection;
1913 getLeaseCollection(ctx, stindex, bind_array, ctx->exchange6_,
1914 collection, true);
1915
1916 // Return single record if present, else clear the lease.
1917 if (collection.empty()) {
1918 result.reset();
1919 } else {
1920 result = *collection.begin();
1921 }
1922}
1923
1927 .arg(addr.toText());
1928
1929 // Set up the WHERE clause value
1930 PsqlBindArray bind_array;
1931
1932 // LEASE ADDRESS
1933 std::string addr_str = boost::lexical_cast<std::string>(addr.toUint32());
1934 bind_array.add(addr_str);
1935
1936 // Get the data
1938
1939 // Get a context
1940 PgSqlLeaseContextAlloc get_context(*this);
1941 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1942
1943 getLease(ctx, GET_LEASE4_ADDR, bind_array, result);
1944
1945 return (result);
1946}
1947
1949PgSqlLeaseMgr::getLease4(const HWAddr& hwaddr) const {
1951 .arg(hwaddr.toText());
1952
1953 // Set up the WHERE clause value
1954 PsqlBindArray bind_array;
1955
1956 // HWADDR
1957 if (!hwaddr.hwaddr_.empty()) {
1958 bind_array.add(hwaddr.hwaddr_);
1959 } else {
1960 bind_array.add("");
1961 }
1962
1963 // Get the data
1965
1966 // Get a context
1967 PgSqlLeaseContextAlloc get_context(*this);
1968 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1969
1970 getLeaseCollection(ctx, GET_LEASE4_HWADDR, bind_array, result);
1971
1972 return (result);
1973}
1974
1976PgSqlLeaseMgr::getLease4(const HWAddr& hwaddr, SubnetID subnet_id) const {
1978 .arg(subnet_id)
1979 .arg(hwaddr.toText());
1980
1981 // Set up the WHERE clause value
1982 PsqlBindArray bind_array;
1983
1984 // HWADDR
1985 if (!hwaddr.hwaddr_.empty()) {
1986 bind_array.add(hwaddr.hwaddr_);
1987 } else {
1988 bind_array.add("");
1989 }
1990
1991 // SUBNET_ID
1992 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
1993 bind_array.add(subnet_id_str);
1994
1995 // Get the data
1997
1998 // Get a context
1999 PgSqlLeaseContextAlloc get_context(*this);
2000 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2001
2002 getLease(ctx, GET_LEASE4_HWADDR_SUBID, bind_array, result);
2003
2004 return (result);
2005}
2006
2008PgSqlLeaseMgr::getLease4(const ClientId& clientid) const {
2010 .arg(clientid.toText());
2011
2012 // Set up the WHERE clause value
2013 PsqlBindArray bind_array;
2014
2015 // CLIENT_ID
2016 bind_array.add(clientid.getClientId());
2017
2018 // Get the data
2020
2021 // Get a context
2022 PgSqlLeaseContextAlloc get_context(*this);
2023 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2024
2025 getLeaseCollection(ctx, GET_LEASE4_CLIENTID, bind_array, result);
2026
2027 return (result);
2028}
2029
2031PgSqlLeaseMgr::getLease4(const ClientId& clientid, SubnetID subnet_id) const {
2033 .arg(subnet_id)
2034 .arg(clientid.toText());
2035
2036 // Set up the WHERE clause value
2037 PsqlBindArray bind_array;
2038
2039 // CLIENT_ID
2040 bind_array.add(clientid.getClientId());
2041
2042 // SUBNET_ID
2043 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
2044 bind_array.add(subnet_id_str);
2045
2046 // Get the data
2048
2049 // Get a context
2050 PgSqlLeaseContextAlloc get_context(*this);
2051 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2052
2053 getLease(ctx, GET_LEASE4_CLIENTID_SUBID, bind_array, result);
2054
2055 return (result);
2056}
2057
2061 .arg(subnet_id);
2062
2063 // Set up the WHERE clause value
2064 PsqlBindArray bind_array;
2065
2066 // SUBNET_ID
2067 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
2068 bind_array.add(subnet_id_str);
2069
2070 // ... and get the data
2072
2073 // Get a context
2074 PgSqlLeaseContextAlloc get_context(*this);
2075 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2076
2077 getLeaseCollection(ctx, GET_LEASE4_SUBID, bind_array, result);
2078
2079 return (result);
2080}
2081
2083PgSqlLeaseMgr::getLeases4(const std::string& hostname) const {
2085 .arg(hostname);
2086
2087 // Set up the WHERE clause value
2088 PsqlBindArray bind_array;
2089
2090 // Hostname
2091 bind_array.add(hostname);
2092
2093 // ... and get the data
2095
2096 // Get a context
2097 PgSqlLeaseContextAlloc get_context(*this);
2098 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2099
2100 getLeaseCollection(ctx, GET_LEASE4_HOSTNAME, bind_array, result);
2101
2102 return (result);
2103}
2104
2108
2109 // Provide empty binding array because our query has no parameters in
2110 // WHERE clause.
2111 PsqlBindArray bind_array;
2113
2114 // Get a context
2115 PgSqlLeaseContextAlloc get_context(*this);
2116 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2117
2118 getLeaseCollection(ctx, GET_LEASE4, bind_array, result);
2119
2120 return (result);
2121}
2122
2124PgSqlLeaseMgr::getLeases4(const IOAddress& lower_bound_address,
2125 const LeasePageSize& page_size) const {
2126 // Expecting IPv4 address.
2127 if (!lower_bound_address.isV4()) {
2128 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
2129 "retrieving leases from the lease database, got "
2130 << lower_bound_address);
2131 }
2132
2134 .arg(page_size.page_size_)
2135 .arg(lower_bound_address.toText());
2136
2137 // Prepare WHERE clause
2138 PsqlBindArray bind_array;
2139
2140 // Bind lower bound address
2141 std::string lb_address_data = boost::lexical_cast<std::string>(lower_bound_address.toUint32());
2142 bind_array.add(lb_address_data);
2143
2144 // Bind page size value
2145 std::string page_size_data = boost::lexical_cast<std::string>(page_size.page_size_);
2146 bind_array.add(page_size_data);
2147
2148 // Get the leases
2150
2151 // Get a context
2152 PgSqlLeaseContextAlloc get_context(*this);
2153 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2154
2155 getLeaseCollection(ctx, GET_LEASE4_PAGE, bind_array, result);
2156
2157 return (result);
2158}
2159
2162 const IOAddress& addr) const {
2164 .arg(addr.toText())
2165 .arg(lease_type);
2166
2167 // Set up the WHERE clause value
2168 PsqlBindArray bind_array;
2169
2170 // LEASE ADDRESS
2171 std::string addr_str = addr.toText();
2172 bind_array.add(addr_str);
2173
2174 // LEASE_TYPE
2175 std::string type_str_ = boost::lexical_cast<std::string>(lease_type);
2176 bind_array.add(type_str_);
2177
2178 // ... and get the data
2180
2181 // Get a context
2182 PgSqlLeaseContextAlloc get_context(*this);
2183 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2184
2185 getLease(ctx, GET_LEASE6_ADDR, bind_array, result);
2186
2187 return (result);
2188}
2189
2192 uint32_t iaid) const {
2194 .arg(iaid)
2195 .arg(duid.toText())
2196 .arg(lease_type);
2197
2198 // Set up the WHERE clause value
2199 PsqlBindArray bind_array;
2200
2201 // DUID
2202 bind_array.add(duid.getDuid());
2203
2204 // IAID
2205 std::string iaid_str = PgSqlLease6Exchange::Uiaid(iaid).dbInputString();
2206 bind_array.add(iaid_str);
2207
2208 // LEASE_TYPE
2209 std::string lease_type_str = boost::lexical_cast<std::string>(lease_type);
2210 bind_array.add(lease_type_str);
2211
2212 // ... and get the data
2214
2215 // Get a context
2216 PgSqlLeaseContextAlloc get_context(*this);
2217 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2218
2219 getLeaseCollection(ctx, GET_LEASE6_DUID_IAID, bind_array, result);
2220
2221 return (result);
2222}
2223
2226 uint32_t iaid, SubnetID subnet_id) const {
2228 .arg(iaid)
2229 .arg(subnet_id)
2230 .arg(duid.toText())
2231 .arg(lease_type);
2232
2233 // Set up the WHERE clause value
2234 PsqlBindArray bind_array;
2235
2236 // LEASE_TYPE
2237 std::string lease_type_str = boost::lexical_cast<std::string>(lease_type);
2238 bind_array.add(lease_type_str);
2239
2240 // DUID
2241 bind_array.add(duid.getDuid());
2242
2243 // IAID
2244 std::string iaid_str = PgSqlLease6Exchange::Uiaid(iaid).dbInputString();
2245 bind_array.add(iaid_str);
2246
2247 // SUBNET ID
2248 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
2249 bind_array.add(subnet_id_str);
2250
2251 // ... and get the data
2253
2254 // Get a context
2255 PgSqlLeaseContextAlloc get_context(*this);
2256 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2257
2258 getLeaseCollection(ctx, GET_LEASE6_DUID_IAID_SUBID, bind_array, result);
2259
2260 return (result);
2261}
2262
2266 .arg(subnet_id);
2267
2268 // Set up the WHERE clause value
2269 PsqlBindArray bind_array;
2270
2271 // SUBNET_ID
2272 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
2273 bind_array.add(subnet_id_str);
2274
2275 // ... and get the data
2277
2278 // Get a context
2279 PgSqlLeaseContextAlloc get_context(*this);
2280 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2281
2282 getLeaseCollection(ctx, GET_LEASE6_SUBID, bind_array, result);
2283
2284 return (result);
2285}
2286
2289 const IOAddress& lower_bound_address,
2290 const LeasePageSize& page_size) const {
2293 .arg(page_size.page_size_)
2294 .arg(lower_bound_address.toText())
2295 .arg(subnet_id);
2296
2297 // Expecting IPv6 valid address.
2298 if (!lower_bound_address.isV6()) {
2299 isc_throw(InvalidAddressFamily, "expected IPv6 start address while "
2300 "retrieving leases from the lease database, got "
2301 << lower_bound_address);
2302 }
2303
2305 // Prepare WHERE clause
2306 PsqlBindArray bind_array;
2307
2308 // Bind subnet id.
2309 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
2310 bind_array.add(subnet_id_str);
2311
2312 // Bind lower bound address
2313 std::string lb_address_str = lower_bound_address.toText();
2314 bind_array.add(lb_address_str);
2315
2316 // Bind page size value
2317 std::string page_size_data =
2318 boost::lexical_cast<std::string>(page_size.page_size_);
2319 bind_array.add(page_size_data);
2320
2321 // Get a context
2322 PgSqlLeaseContextAlloc get_context(*this);
2323 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2324
2325 // Get the leases
2326 getLeaseCollection(ctx, GET_LEASE6_SUBID_PAGE, bind_array, result);
2327
2328 return (result);
2329}
2330
2334 .arg(duid.toText());
2335
2336 // Set up the WHERE clause value
2337 PsqlBindArray bind_array;
2338
2339 // DUID
2340 bind_array.add(duid.getDuid());
2342
2343 // Get a context
2344 PgSqlLeaseContextAlloc get_context(*this);
2345 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2346
2347 // query to fetch the data
2348 getLeaseCollection(ctx, GET_LEASE6_DUID, bind_array, result);
2349
2350 return (result);
2351}
2352
2354PgSqlLeaseMgr::getLeases6(const std::string& hostname) const {
2356 .arg(hostname);
2357
2358 // Set up the WHERE clause value
2359 PsqlBindArray bind_array;
2360
2361 // Hostname
2362 bind_array.add(hostname);
2363
2364 // ... and get the data
2366
2367 // Get a context
2368 PgSqlLeaseContextAlloc get_context(*this);
2369 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2370
2371 getLeaseCollection(ctx, GET_LEASE6_HOSTNAME, bind_array, result);
2372
2373 return (result);
2374}
2375
2379
2380 // Provide empty binding array because our query has no parameters in
2381 // WHERE clause.
2382 PsqlBindArray bind_array;
2384
2385 // Get a context
2386 PgSqlLeaseContextAlloc get_context(*this);
2387 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2388
2389 getLeaseCollection(ctx, GET_LEASE6, bind_array, result);
2390
2391 return (result);
2392}
2393
2395PgSqlLeaseMgr::getLeases6(const IOAddress& lower_bound_address,
2396 const LeasePageSize& page_size) const {
2397 // Expecting IPv6 address.
2398 if (!lower_bound_address.isV6()) {
2399 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
2400 "retrieving leases from the lease database, got "
2401 << lower_bound_address);
2402 }
2403
2405 .arg(page_size.page_size_)
2406 .arg(lower_bound_address.toText());
2407
2408 // Prepare WHERE clause
2409 PsqlBindArray bind_array;
2410
2411 // Bind lower bound address
2412 std::string lb_address_data = lower_bound_address.toText();
2413 bind_array.add(lb_address_data);
2414
2415 // Bind page size value
2416 std::string page_size_data =
2417 boost::lexical_cast<std::string>(page_size.page_size_);
2418 bind_array.add(page_size_data);
2419
2420 // Get the leases
2422
2423 // Get a context
2424 PgSqlLeaseContextAlloc get_context(*this);
2425 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2426
2427 getLeaseCollection(ctx, GET_LEASE6_PAGE, bind_array, result);
2428
2429 return (result);
2430}
2431
2432void
2434 const size_t max_leases) const {
2436 .arg(max_leases);
2437 getExpiredLeasesCommon(expired_leases, max_leases, GET_LEASE4_EXPIRE);
2438}
2439
2440void
2442 const size_t max_leases) const {
2444 .arg(max_leases);
2445 getExpiredLeasesCommon(expired_leases, max_leases, GET_LEASE6_EXPIRE);
2446}
2447
2448template<typename LeaseCollection>
2449void
2450PgSqlLeaseMgr::getExpiredLeasesCommon(LeaseCollection& expired_leases,
2451 const size_t max_leases,
2452 StatementIndex statement_index) const {
2453 PsqlBindArray bind_array;
2454
2455 // Exclude reclaimed leases.
2456 std::string state_str = boost::lexical_cast<std::string>(Lease::STATE_EXPIRED_RECLAIMED);
2457 bind_array.add(state_str);
2458
2459 // Expiration timestamp.
2460 std::string timestamp_str = PgSqlLeaseExchange::convertToDatabaseTime(time(0));
2461 bind_array.add(timestamp_str);
2462
2463 // If the number of leases is 0, we will return all leases. This is
2464 // achieved by setting the limit to a very high value.
2465 uint32_t limit = max_leases > 0 ? static_cast<uint32_t>(max_leases) :
2466 std::numeric_limits<uint32_t>::max();
2467 std::string limit_str = boost::lexical_cast<std::string>(limit);
2468 bind_array.add(limit_str);
2469
2470 // Get a context
2471 PgSqlLeaseContextAlloc get_context(*this);
2472 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2473
2474 // Retrieve leases from the database.
2475 getLeaseCollection(ctx, statement_index, bind_array, expired_leases);
2476}
2477
2478template<typename LeasePtr>
2479void
2480PgSqlLeaseMgr::updateLeaseCommon(PgSqlLeaseContextPtr& ctx,
2481 StatementIndex stindex,
2482 PsqlBindArray& bind_array,
2483 const LeasePtr& lease) {
2484 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
2485 tagged_statements[stindex].nbparams,
2486 &bind_array.values_[0],
2487 &bind_array.lengths_[0],
2488 &bind_array.formats_[0], 0));
2489
2490 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2491
2492 int affected_rows = boost::lexical_cast<int>(PQcmdTuples(r));
2493
2494 // Check success case first as it is the most likely outcome.
2495 if (affected_rows == 1) {
2496 return;
2497 }
2498
2499 // If no rows affected, lease doesn't exist.
2500 if (affected_rows == 0) {
2501 isc_throw(NoSuchLease, "unable to update lease for address " <<
2502 lease->addr_.toText() << " either because the lease does not exist, "
2503 "it has been deleted or it has changed in the database.");
2504 }
2505
2506 // Should not happen - primary key constraint should only have selected
2507 // one row.
2508 isc_throw(DbOperationError, "apparently updated more than one lease "
2509 "that had the address " << lease->addr_.toText());
2510}
2511
2512void
2514 const StatementIndex stindex = UPDATE_LEASE4;
2515
2517 .arg(lease->addr_.toText());
2518
2519 // Get a context
2520 PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
2521 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2522
2523 // Create the BIND array for the data being updated
2524 PsqlBindArray bind_array;
2525 ctx->exchange4_->createBindForSend(lease, bind_array);
2526
2527 // Set up the WHERE clause and append it to the SQL_BIND array
2528 std::string addr4_str = boost::lexical_cast<std::string>(lease->addr_.toUint32());
2529 bind_array.add(addr4_str);
2530
2531 std::string expire_str;
2532 // Avoid overflow (see createBindForSend)
2533 if (lease->current_valid_lft_ == Lease::INFINITY_LFT) {
2534 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_, 0);
2535 } else {
2536 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_,
2537 lease->current_valid_lft_);
2538 }
2539 bind_array.add(expire_str);
2540
2541 // Drop to common update code
2542 updateLeaseCommon(ctx, stindex, bind_array, lease);
2543
2544 // Update lease current expiration time.
2545 lease->updateCurrentExpirationTime();
2546
2547 // Run installed callbacks.
2548 if (hasCallbacks()) {
2549 trackUpdateLease(lease);
2550 }
2551}
2552
2553void
2555 const StatementIndex stindex = UPDATE_LEASE6;
2556
2558 .arg(lease->addr_.toText())
2559 .arg(lease->type_);
2560
2561 // Get the recorded action and reset it.
2562 Lease6::ExtendedInfoAction recorded_action = lease->extended_info_action_;
2563 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
2564
2565 // Get a context
2566 PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
2567 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2568
2569 // Create the BIND array for the data being updated
2570 PsqlBindArray bind_array;
2571 ctx->exchange6_->createBindForSend(lease, bind_array);
2572
2573 // Set up the WHERE clause and append it to the BIND array
2574 std::string addr_str = lease->addr_.toText();
2575 bind_array.add(addr_str);
2576
2577 std::string expire_str;
2578 // Avoid overflow (see createBindForSend)
2579 if (lease->current_valid_lft_ == Lease::INFINITY_LFT) {
2580 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_, 0);
2581 } else {
2582 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_,
2583 lease->current_valid_lft_);
2584 }
2585 bind_array.add(expire_str);
2586
2587 // Drop to common update code
2588 updateLeaseCommon(ctx, stindex, bind_array, lease);
2589
2590 // Update lease current expiration time.
2591 lease->updateCurrentExpirationTime();
2592
2593 // Update extended info tables.
2595 switch (recorded_action) {
2597 break;
2598
2600 deleteExtendedInfo6(lease->addr_);
2601 break;
2602
2604 deleteExtendedInfo6(lease->addr_);
2605 static_cast<void>(addExtendedInfo6(lease));
2606 break;
2607 }
2608 }
2609
2610 // Run installed callbacks.
2611 if (hasCallbacks()) {
2612 trackUpdateLease(lease);
2613 }
2614}
2615
2616uint64_t
2617PgSqlLeaseMgr::deleteLeaseCommon(PgSqlLeaseContextPtr& ctx,
2618 StatementIndex stindex,
2619 PsqlBindArray& bind_array) {
2620 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
2621 tagged_statements[stindex].nbparams,
2622 &bind_array.values_[0],
2623 &bind_array.lengths_[0],
2624 &bind_array.formats_[0], 0));
2625
2626 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2627 int affected_rows = boost::lexical_cast<int>(PQcmdTuples(r));
2628
2629 return (affected_rows);
2630}
2631
2632bool
2634 const IOAddress& addr = lease->addr_;
2636 .arg(addr.toText());
2637
2638 // Set up the WHERE clause value
2639 PsqlBindArray bind_array;
2640
2641 std::string addr4_str = boost::lexical_cast<std::string>(addr.toUint32());
2642 bind_array.add(addr4_str);
2643
2644 std::string expire_str;
2645 // Avoid overflow (see createBindForSend)
2646 if (lease->current_valid_lft_ == Lease::INFINITY_LFT) {
2647 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_, 0);
2648 } else {
2649 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_,
2650 lease->current_valid_lft_);
2651 }
2652 bind_array.add(expire_str);
2653
2654 // Get a context
2655 PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
2656 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2657
2658 auto affected_rows = deleteLeaseCommon(ctx, DELETE_LEASE4, bind_array);
2659
2660 // Check success case first as it is the most likely outcome.
2661 if (affected_rows == 1) {
2662 if (hasCallbacks()) {
2663 trackDeleteLease(lease);
2664 }
2665 return (true);
2666 }
2667
2668 // If no rows affected, lease doesn't exist.
2669 if (affected_rows == 0) {
2670 return (false);
2671 }
2672
2673 // Should not happen - primary key constraint should only have selected
2674 // one row.
2675 isc_throw(DbOperationError, "apparently deleted more than one lease "
2676 "that had the address " << lease->addr_.toText());
2677}
2678
2679bool
2681 const IOAddress& addr = lease->addr_;
2684 .arg(addr.toText());
2685
2686 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
2687
2688 // Set up the WHERE clause value
2689 PsqlBindArray bind_array;
2690
2691 std::string addr6_str = addr.toText();
2692 bind_array.add(addr6_str);
2693
2694 std::string expire_str;
2695 // Avoid overflow (see createBindForSend)
2696 if (lease->current_valid_lft_ == Lease::INFINITY_LFT) {
2697 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_, 0);
2698 } else {
2699 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_,
2700 lease->current_valid_lft_);
2701 }
2702 bind_array.add(expire_str);
2703
2704 // Get a context
2705 PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
2706 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2707
2708 auto affected_rows = deleteLeaseCommon(ctx, DELETE_LEASE6, bind_array);
2709
2710 // Check success case first as it is the most likely outcome.
2711 if (affected_rows == 1) {
2712 // Delete references from extended info tables.
2713 // Performed by the delete cascade.
2714
2715 // Run installed callbacks.
2716 if (hasCallbacks()) {
2717 trackDeleteLease(lease);
2718 }
2719 return (true);
2720 }
2721
2722 // If no rows affected, lease doesn't exist.
2723 if (affected_rows == 0) {
2724 return (false);
2725 }
2726
2727 // Should not happen - primary key constraint should only have selected
2728 // one row.
2729 isc_throw(DbOperationError, "apparently deleted more than one lease "
2730 "that had the address " << lease->addr_.toText());
2731}
2732
2733uint64_t
2736 .arg(secs);
2737 return (deleteExpiredReclaimedLeasesCommon(secs, DELETE_LEASE4_STATE_EXPIRED));
2738}
2739
2740uint64_t
2743 .arg(secs);
2744 return (deleteExpiredReclaimedLeasesCommon(secs, DELETE_LEASE6_STATE_EXPIRED));
2745}
2746
2747uint64_t
2748PgSqlLeaseMgr::deleteExpiredReclaimedLeasesCommon(const uint32_t secs,
2749 StatementIndex statement_index) {
2750 PsqlBindArray bind_array;
2751
2752 // State is reclaimed.
2753 std::string state_str = boost::lexical_cast<std::string>(Lease::STATE_EXPIRED_RECLAIMED);
2754 bind_array.add(state_str);
2755
2756 // Expiration timestamp.
2757 std::string expiration_str = PgSqlLeaseExchange::convertToDatabaseTime(time(0) -
2758 static_cast<time_t>(secs));
2759 bind_array.add(expiration_str);
2760
2761 // Get a context
2762 PgSqlLeaseContextAlloc get_context(*this);
2763 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2764
2765 // Delete leases.
2766 return (deleteLeaseCommon(ctx, statement_index, bind_array));
2767}
2768
2769string
2770PgSqlLeaseMgr::checkLimits(ConstElementPtr const& user_context, StatementIndex const stindex) const {
2771 // No user context means no limits means allocation allowed means empty string.
2772 if (!user_context) {
2773 return string();
2774 }
2775
2776 // Get a context.
2777 PgSqlLeaseContextAlloc get_context(*this);
2778 PgSqlLeaseContextPtr ctx(get_context.ctx_);
2779
2780 // Create bindings.
2781 PsqlBindArray bind_array;
2782 std::string const user_context_str(user_context->str());
2783 bind_array.add(user_context_str);
2784
2785 // Execute the select.
2786 PgSqlResult r(PQexecPrepared(ctx->conn_,
2787 tagged_statements[stindex].name,
2788 tagged_statements[stindex].nbparams,
2789 &bind_array.values_[0],
2790 &bind_array.lengths_[0],
2791 &bind_array.formats_[0], 0));
2792 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2793
2794 std::string limits;
2795 PgSqlExchange::getColumnValue(r, 0, 0, limits);
2796 return limits;
2797}
2798
2799string
2801 return checkLimits(user_context, CHECK_LEASE4_LIMITS);
2802}
2803
2804string
2806 return checkLimits(user_context, CHECK_LEASE6_LIMITS);
2807}
2808
2809bool
2811 // Get a context.
2812 PgSqlLeaseContextAlloc get_context(*this);
2813 PgSqlLeaseContextPtr ctx(get_context.ctx_);
2814
2815 // Execute the select.
2816 StatementIndex const stindex(IS_JSON_SUPPORTED);
2817 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
2818 0, 0, 0, 0, 0));
2819 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2820
2821 bool json_supported;
2822 PgSqlExchange::getColumnValue(r, 0, 0, json_supported);
2823 return json_supported;
2824}
2825
2826size_t
2828 const Lease::Type& ltype /* = Lease::TYPE_V4*/) const {
2829 // Get a context.
2830 PgSqlLeaseContextAlloc get_context(*this);
2831 PgSqlLeaseContextPtr ctx(get_context.ctx_);
2832
2833 // Create bindings.
2834 PsqlBindArray bind_array;
2835 bind_array.add(client_class);
2836 if (ltype != Lease::TYPE_V4) {
2837 bind_array.add(ltype);
2838 }
2839
2840 // Execute the select.
2843 PgSqlResult r(PQexecPrepared(ctx->conn_,
2844 tagged_statements[stindex].name,
2845 tagged_statements[stindex].nbparams,
2846 &bind_array.values_[0],
2847 &bind_array.lengths_[0],
2848 &bind_array.formats_[0], 0));
2849 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2850
2851 int rows = PQntuples(r);
2852 if (rows == 0) {
2853 // No entries means 0 leases.
2854 return 0;
2855 }
2856
2857 size_t count;
2858 PgSqlExchange::getColumnValue(r, 0, 0, count);
2859 return count;
2860}
2861
2862void
2864 isc_throw(NotImplemented, "PgSqlLeaseMgr::recountClassLeases4() not implemented");
2865}
2866
2867void
2869 isc_throw(NotImplemented, "PgSqlLeaseMgr::recountClassLeases6() not implemented");
2870}
2871
2872void
2874 isc_throw(NotImplemented, "PgSqlLeaseMgr::clearClassLeaseCounts() not implemented");
2875}
2876
2877void
2878PgSqlLeaseMgr::writeLeases4(const std::string&) {
2879 isc_throw(NotImplemented, "PgSqlLeaseMgr::writeLeases4() not implemented");
2880}
2881
2882void
2883PgSqlLeaseMgr::writeLeases6(const std::string&) {
2884 isc_throw(NotImplemented, "PgSqlLeaseMgr::writeLeases6() not implemented");
2885}
2886
2889 // Get a context
2890 PgSqlLeaseContextAlloc get_context(*this);
2891 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2892
2893 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2894 tagged_statements[ALL_LEASE4_STATS],
2895 false));
2896 query->start();
2897 return(query);
2898}
2899
2902 // Get a context
2903 PgSqlLeaseContextAlloc get_context(*this);
2904 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2905
2906 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2907 tagged_statements[ALL_POOL_LEASE4_STATS],
2908 false, true));
2909 query->start();
2910 return(query);
2911}
2912
2915 // Get a context
2916 PgSqlLeaseContextAlloc get_context(*this);
2917 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2918
2919 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2920 tagged_statements[SUBNET_LEASE4_STATS],
2921 false,
2922 subnet_id));
2923 query->start();
2924 return(query);
2925}
2926
2929 const SubnetID& last_subnet_id) {
2930 // Get a context
2931 PgSqlLeaseContextAlloc get_context(*this);
2932 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2933
2934 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2935 tagged_statements[SUBNET_RANGE_LEASE4_STATS],
2936 false,
2937 first_subnet_id,
2938 last_subnet_id));
2939 query->start();
2940 return(query);
2941}
2942
2945 // Get a context
2946 PgSqlLeaseContextAlloc get_context(*this);
2947 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2948
2949 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2950 tagged_statements[ALL_LEASE6_STATS],
2951 true));
2952 query->start();
2953 return(query);
2954}
2955
2958 // Get a context
2959 PgSqlLeaseContextAlloc get_context(*this);
2960 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2961
2962 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2963 tagged_statements[ALL_POOL_LEASE6_STATS],
2964 true, true));
2965 query->start();
2966 return(query);
2967}
2968
2971 // Get a context
2972 PgSqlLeaseContextAlloc get_context(*this);
2973 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2974
2975 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2976 tagged_statements[SUBNET_LEASE6_STATS],
2977 true,
2978 subnet_id));
2979 query->start();
2980 return(query);
2981}
2982
2985 const SubnetID& last_subnet_id) {
2986 // Get a context
2987 PgSqlLeaseContextAlloc get_context(*this);
2988 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2989
2990 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2991 tagged_statements[SUBNET_RANGE_LEASE6_STATS],
2992 true,
2993 first_subnet_id,
2994 last_subnet_id));
2995 query->start();
2996 return(query);
2997}
2998
2999size_t
3001 isc_throw(NotImplemented, "wipeLeases4 is not implemented for PostgreSQL backend");
3002}
3003
3004size_t
3006 isc_throw(NotImplemented, "wipeLeases6 is not implemented for PostgreSQL backend");
3007}
3008
3009std::string
3011 // Get a context
3012 PgSqlLeaseContextAlloc get_context(*this);
3013 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3014
3015 std::string name = "";
3016 try {
3017 name = ctx->conn_.getParameter("name");
3018 } catch (...) {
3019 // Return an empty name
3020 }
3021 return (name);
3022}
3023
3024std::string
3026 return (std::string("PostgreSQL Database"));
3027}
3028
3029std::pair<uint32_t, uint32_t>
3038
3039void
3043
3044void
3048
3049void
3051 deleteRelayId6(addr);
3052 deleteRemoteId6(addr);
3053}
3054
3055void
3056PgSqlLeaseMgr::deleteRelayId6(const IOAddress& addr) {
3057 // Set up the WHERE clause value.
3058 PsqlBindArray bind_array;
3059
3060 std::string addr_data = addr.toText();
3061 bind_array.add(addr_data);
3062
3063 // Get a context.
3064 PgSqlLeaseContextAlloc get_context(*this);
3065 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3066
3067 // Delete from lease6_relay_id table.
3069
3070 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
3071 tagged_statements[stindex].nbparams,
3072 &bind_array.values_[0],
3073 &bind_array.lengths_[0],
3074 &bind_array.formats_[0], 0));
3075
3076 int s = PQresultStatus(r);
3077
3078 if (s != PGRES_COMMAND_OK) {
3079 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
3080 }
3081}
3082
3083void
3084PgSqlLeaseMgr::deleteRemoteId6(const IOAddress& addr) {
3085 // Set up the WHERE clause value.
3086 PsqlBindArray bind_array;
3087
3088 std::string addr_data = addr.toText();
3089 bind_array.add(addr_data);
3090
3091 // Get a context.
3092 PgSqlLeaseContextAlloc get_context(*this);
3093 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3094
3095 // Delete from lease6_remote_id table.
3097
3098 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
3099 tagged_statements[stindex].nbparams,
3100 &bind_array.values_[0],
3101 &bind_array.lengths_[0],
3102 &bind_array.formats_[0], 0));
3103
3104 int s = PQresultStatus(r);
3105
3106 if (s != PGRES_COMMAND_OK) {
3107 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
3108 }
3109}
3110
3111void
3113 const vector<uint8_t>& relay_id) {
3114 // Set up the WHERE clause value.
3115 PsqlBindArray bind_array;
3116
3117 // Bind the relay id.
3118 if (relay_id.empty()) {
3119 isc_throw(BadValue, "empty relay id");
3120 }
3121 bind_array.add(relay_id);
3122
3123 // Bind the lease address.
3124 std::string lease_addr_data = lease_addr.toText();
3125 bind_array.add(lease_addr_data);
3126
3127 // Get a context.
3128 PgSqlLeaseContextAlloc get_context(*this);
3129 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3130
3131 // Add to lease6_remote_id table.
3132 StatementIndex stindex = ADD_RELAY_ID6;
3133
3134 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
3135 tagged_statements[stindex].nbparams,
3136 &bind_array.values_[0],
3137 &bind_array.lengths_[0],
3138 &bind_array.formats_[0], 0));
3139
3140 int s = PQresultStatus(r);
3141
3142 if (s != PGRES_COMMAND_OK) {
3143 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
3144 }
3145}
3146
3147void
3149 const vector<uint8_t>& remote_id) {
3150 // Set up the WHERE clause value.
3151 PsqlBindArray bind_array;
3152
3153 // Bind the remote id.
3154 if (remote_id.empty()) {
3155 isc_throw(BadValue, "empty remote id");
3156 }
3157 bind_array.add(remote_id);
3158
3159 // Bind the lease address.
3160 std::string lease_addr_data = lease_addr.toText();
3161 bind_array.add(lease_addr_data);
3162
3163 // Get a context.
3164 PgSqlLeaseContextAlloc get_context(*this);
3165 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3166
3167 // Add to lease6_remote_id table.
3169
3170 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
3171 tagged_statements[stindex].nbparams,
3172 &bind_array.values_[0],
3173 &bind_array.lengths_[0],
3174 &bind_array.formats_[0], 0));
3175
3176 int s = PQresultStatus(r);
3177
3178 if (s != PGRES_COMMAND_OK) {
3179 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
3180 }
3181}
3182
3183namespace {
3184
3185std::string
3186idToText(const OptionBuffer& id) {
3187 std::stringstream tmp;
3188 tmp << std::hex;
3189 bool delim = false;
3190 for (auto const& it : id) {
3191 if (delim) {
3192 tmp << ":";
3193 }
3194 tmp << std::setw(2) << std::setfill('0')
3195 << static_cast<unsigned int>(it);
3196 delim = true;
3197 }
3198 return (tmp.str());
3199}
3200
3201} // anonymous namespace
3202
3205 const IOAddress& lower_bound_address,
3206 const LeasePageSize& page_size,
3207 const time_t& qry_start_time /* = 0 */,
3208 const time_t& qry_end_time /* = 0 */) {
3209 // Expecting IPv4 address.
3210 if (!lower_bound_address.isV4()) {
3211 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
3212 "retrieving leases from the lease database, got "
3213 << lower_bound_address);
3214 }
3215
3216 // Catch 2038 bug with 32 bit time_t.
3217 if ((qry_start_time < 0) || (qry_end_time < 0)) {
3218 isc_throw(BadValue, "negative time value");
3219 }
3220
3221 bool have_qst = (qry_start_time > 0);
3222 bool have_qet = (qry_end_time > 0);
3223
3224 // Start time must be before end time.
3225 if (have_qst && have_qet && (qry_start_time > qry_end_time)) {
3226 isc_throw(BadValue, "start time must be before end time");
3227 }
3228
3231 .arg(page_size.page_size_)
3232 .arg(lower_bound_address.toText())
3233 .arg(idToText(relay_id))
3234 .arg(qry_start_time)
3235 .arg(qry_end_time);
3236
3237 // Prepare WHERE clause
3238 PsqlBindArray bind_array;
3239
3240 // Bind relay id
3241 if (!relay_id.empty()) {
3242 bind_array.add(relay_id);
3243 } else {
3244 bind_array.add("");
3245 }
3246
3247 // Bind lower bound address
3248 std::string lb_address_data =
3249 boost::lexical_cast<std::string>(lower_bound_address.toUint32());
3250 bind_array.add(lb_address_data);
3251
3252 // Bind query start time.
3253 std::string start_time_str;
3254 if (have_qst) {
3255 start_time_str = boost::lexical_cast<std::string>(qry_start_time);
3256 bind_array.add(start_time_str);
3257 }
3258
3259 // Bind query end time.
3260 std::string end_time_str;
3261 if (have_qet) {
3262 end_time_str = boost::lexical_cast<std::string>(qry_end_time);
3263 bind_array.add(end_time_str);
3264 }
3265
3266 // Bind page size value
3267 std::string page_size_data =
3268 boost::lexical_cast<std::string>(page_size.page_size_);
3269 bind_array.add(page_size_data);
3270
3272 if (have_qst && !have_qet) {
3273 stindex = GET_LEASE4_RELAYID_QST;
3274 } else if (have_qst && have_qet) {
3275 stindex = GET_LEASE4_RELAYID_QSET;
3276 } else if (!have_qst && have_qet) {
3277 stindex = GET_LEASE4_RELAYID_QET;
3278 }
3279
3280 // Get the leases
3282
3283 // Get a context
3284 PgSqlLeaseContextAlloc get_context(*this);
3285 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3286
3287 getLeaseCollection(ctx, stindex, bind_array, result);
3288
3289 return (result);
3290}
3291
3294 const IOAddress& lower_bound_address,
3295 const LeasePageSize& page_size,
3296 const time_t& qry_start_time /* = 0 */,
3297 const time_t& qry_end_time /* = 0 */) {
3298 // Expecting IPv4 address.
3299 if (!lower_bound_address.isV4()) {
3300 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
3301 "retrieving leases from the lease database, got "
3302 << lower_bound_address);
3303 }
3304
3305 // Catch 2038 bug with 32 bit time_t.
3306 if ((qry_start_time < 0) || (qry_end_time < 0)) {
3307 isc_throw(BadValue, "negative time value");
3308 }
3309
3310 bool have_qst = (qry_start_time > 0);
3311 bool have_qet = (qry_end_time > 0);
3312
3313 // Start time must be before end time.
3314 if (have_qst && have_qet && (qry_start_time > qry_end_time)) {
3315 isc_throw(BadValue, "start time must be before end time");
3316 }
3317
3320 .arg(page_size.page_size_)
3321 .arg(lower_bound_address.toText())
3322 .arg(idToText(remote_id))
3323 .arg(qry_start_time)
3324 .arg(qry_end_time);
3325
3326 // Prepare WHERE clause
3327 PsqlBindArray bind_array;
3328
3329 // Bind remote id
3330 if (!remote_id.empty()) {
3331 bind_array.add(remote_id);
3332 } else {
3333 bind_array.add("");
3334 }
3335
3336 // Bind lower bound address
3337 std::string lb_address_data =
3338 boost::lexical_cast<std::string>(lower_bound_address.toUint32());
3339 bind_array.add(lb_address_data);
3340
3341 // Bind query start time.
3342 std::string start_time_str;
3343 if (have_qst) {
3344 start_time_str = boost::lexical_cast<std::string>(qry_start_time);
3345 bind_array.add(start_time_str);
3346 }
3347
3348 // Bind query end time.
3349 std::string end_time_str;
3350 if (have_qet) {
3351 end_time_str = boost::lexical_cast<std::string>(qry_end_time);
3352 bind_array.add(end_time_str);
3353 }
3354
3355 // Bind page size value
3356 std::string page_size_data =
3357 boost::lexical_cast<std::string>(page_size.page_size_);
3358 bind_array.add(page_size_data);
3359
3361 if (have_qst && !have_qet) {
3362 stindex = GET_LEASE4_REMOTEID_QST;
3363 } else if (have_qst && have_qet) {
3364 stindex = GET_LEASE4_REMOTEID_QSET;
3365 } else if (!have_qst && have_qet) {
3366 stindex = GET_LEASE4_REMOTEID_QET;
3367 }
3368
3369 // Get the leases
3371
3372 // Get a context
3373 PgSqlLeaseContextAlloc get_context(*this);
3374 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3375
3376 getLeaseCollection(ctx, stindex, bind_array, result);
3377
3378 return (result);
3379}
3380
3381size_t
3383 auto check = CfgMgr::instance().getCurrentCfg()->
3384 getConsistency()->getExtendedInfoSanityCheck();
3385
3386 size_t pages = 0;
3387 size_t updated = 0;
3389 for (;;) {
3392 .arg(pages)
3393 .arg(start_addr.toText())
3394 .arg(updated);
3395
3396 // Prepare WHERE clause.
3397 PsqlBindArray bind_array;
3398
3399 // Bind start address.
3400 uint32_t start_addr_data = start_addr.toUint32();
3401 bind_array.add(start_addr_data);
3402
3403 // Bind page size value.
3404 std::string page_size_data =
3405 boost::lexical_cast<std::string>(page_size.page_size_);
3406 bind_array.add(page_size_data);
3407
3408 Lease4Collection leases;
3409
3410 // Get a context.
3411 {
3412 PgSqlLeaseContextAlloc get_context(*this);
3413 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3414
3415 getLeaseCollection(ctx, GET_LEASE4_UCTX_PAGE, bind_array, leases);
3416 }
3417
3418 if (leases.empty()) {
3419 // Done.
3420 break;
3421 }
3422
3423 ++pages;
3424 start_addr = leases.back()->addr_;
3425 for (auto const& lease : leases) {
3426 ConstElementPtr previous_user_context = lease->getContext();
3427 vector<uint8_t> previous_relay_id = lease->relay_id_;
3428 vector<uint8_t> previous_remote_id = lease->remote_id_;
3429 if (!previous_user_context &&
3430 previous_relay_id.empty() &&
3431 previous_remote_id.empty()) {
3432 continue;
3433 }
3434 bool modified = upgradeLease4ExtendedInfo(lease, check);
3435 try {
3436 lease->relay_id_.clear();
3437 lease->remote_id_.clear();
3438 extractLease4ExtendedInfo(lease, false);
3439 if (modified ||
3440 (previous_relay_id != lease->relay_id_) ||
3441 (previous_remote_id != lease->remote_id_)) {
3442 updateLease4(lease);
3443 ++updated;
3444 }
3445 } catch (const NoSuchLease&) {
3446 // The lease was modified in parallel:
3447 // as its extended info was processed just ignore.
3448 continue;
3449 } catch (const std::exception& ex) {
3450 // Something when wrong, for instance extract failed.
3453 .arg(lease->addr_.toText())
3454 .arg(ex.what());
3455 }
3456 }
3457 }
3458
3460 .arg(pages)
3461 .arg(updated);
3462
3463 return (updated);
3464}
3465
3468 const IOAddress& lower_bound_address,
3469 const LeasePageSize& page_size) {
3472 .arg(page_size.page_size_)
3473 .arg(lower_bound_address.toText())
3474 .arg(relay_id.toText());
3475
3476 // Expecting IPv6 valid address.
3477 if (!lower_bound_address.isV6()) {
3478 isc_throw(InvalidAddressFamily, "expected IPv6 start address while "
3479 "retrieving leases from the lease database, got "
3480 << lower_bound_address);
3481 }
3482
3483 std::vector<uint8_t> relay_id_data = relay_id.getDuid();
3484 if (relay_id_data.size() == 0) {
3485 isc_throw(BadValue, "empty relay id");
3486 }
3487
3488 // Set up the WHERE clause value.
3489 PsqlBindArray bind_array;
3490
3491 // Bind the relay id.
3492 bind_array.add(relay_id_data);
3493
3494 // Bind the lower bound address.
3495 std::string lb_addr_data = lower_bound_address.toText();
3496 bind_array.add(lb_addr_data);
3497
3498 // Bind page size value.
3499 std::string page_size_data =
3500 boost::lexical_cast<std::string>(page_size.page_size_);
3501 bind_array.add(page_size_data);
3502
3503 // Get a context.
3504 PgSqlLeaseContextAlloc get_context(*this);
3505 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3507
3508 getLeaseCollection(ctx, GET_RELAY_ID6, bind_array, result);
3509 return (result);
3510}
3511
3514 const IOAddress& lower_bound_address,
3515 const LeasePageSize& page_size) {
3518 .arg(page_size.page_size_)
3519 .arg(lower_bound_address.toText())
3520 .arg(idToText(remote_id));
3521
3522 // Expecting IPv6 valid address.
3523 if (!lower_bound_address.isV6()) {
3524 isc_throw(InvalidAddressFamily, "expected IPv6 start address while "
3525 "retrieving leases from the lease database, got "
3526 << lower_bound_address);
3527 }
3528
3529 if (remote_id.size() == 0) {
3530 isc_throw(BadValue, "empty remote id");
3531 }
3532
3533 // Set up the WHERE clause value.
3534 PsqlBindArray bind_array;
3535
3536 // Bind the remote id.
3537 bind_array.add(remote_id);
3538
3539 // Bind the lower bound address.
3540 std::string lb_addr_data = lower_bound_address.toText();
3541 bind_array.add(lb_addr_data);
3542
3543 // Bind page size value.
3544 std::string page_size_data =
3545 boost::lexical_cast<std::string>(page_size.page_size_);
3546 bind_array.add(page_size_data);
3547
3548 // Get a context.
3549 PgSqlLeaseContextAlloc get_context(*this);
3550 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3552
3553 getLeaseCollection(ctx, GET_REMOTE_ID6, bind_array, result);
3554 return (result);
3555}
3556
3557size_t
3559 auto check = CfgMgr::instance().getCurrentCfg()->
3560 getConsistency()->getExtendedInfoSanityCheck();
3561
3562 // First step is to wipe tables if enabled.
3565 }
3566
3567 size_t pages = 0;
3568 size_t updated = 0;
3570 for (;;) {
3573 .arg(pages)
3574 .arg(start_addr.toText())
3575 .arg(updated);
3576
3577 // Prepare WHERE clause.
3578 PsqlBindArray bind_array;
3579
3580 // Bind start address.
3581 std::string start_addr_str = start_addr.toText();
3582 bind_array.add(start_addr_str);
3583
3584 // Bind page size value.
3585 std::string page_size_data =
3586 boost::lexical_cast<std::string>(page_size.page_size_);
3587 bind_array.add(page_size_data);
3588
3589 Lease6Collection leases;
3590
3591 // Get a context.
3592 {
3593 PgSqlLeaseContextAlloc get_context(*this);
3594 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3595
3596 getLeaseCollection(ctx, GET_LEASE6_UCTX_PAGE, bind_array, leases);
3597 }
3598
3599 if (leases.empty()) {
3600 // Done.
3601 break;
3602 }
3603
3604 ++pages;
3605 start_addr = leases.back()->addr_;
3606 for (auto const& lease : leases) {
3607 try {
3608 bool modified = upgradeLease6ExtendedInfo(lease, check);
3609 if (modified) {
3610 updateLease6(lease);
3611 }
3612 bool added = (getExtendedInfoTablesEnabled() &&
3613 addExtendedInfo6(lease));
3614 if (modified || added) {
3615 ++updated;
3616 }
3617 } catch (const NoSuchLease&) {
3618 // The lease was modified in parallel:
3619 // as its extended info was processed just ignore.
3620 continue;
3621 } catch (const std::exception& ex) {
3622 // Something when wrong, for instance extract failed.
3625 .arg(lease->addr_.toText())
3626 .arg(ex.what());
3627 }
3628 }
3629 }
3630
3632 .arg(pages)
3633 .arg(updated);
3634
3635 return (updated);
3636}
3637
3638void
3640 // Get a context.
3641 PgSqlLeaseContextAlloc get_context(*this);
3642 PgSqlLeaseContextPtr ctx(get_context.ctx_);
3643
3644 // Execute WIPE_RELAY_ID6.
3645 StatementIndex const stindex1 = WIPE_RELAY_ID6;
3646 PgSqlResult r1(PQexecPrepared(ctx->conn_, tagged_statements[stindex1].name,
3647 0, 0, 0, 0, 0));
3648 ctx->conn_.checkStatementError(r1, tagged_statements[stindex1]);
3649
3650 // Execute WIPE_REMOTE_ID6.
3651 StatementIndex const stindex2 = WIPE_REMOTE_ID6;
3652 PgSqlResult r2(PQexecPrepared(ctx->conn_, tagged_statements[stindex2].name,
3653 0, 0, 0, 0, 0));
3654 ctx->conn_.checkStatementError(r2, tagged_statements[stindex2]);
3655}
3656
3657size_t
3659 // Get a context.
3660 PgSqlLeaseContextAlloc get_context(*this);
3661 PgSqlLeaseContextPtr ctx(get_context.ctx_);
3662
3663 // Execute COUNT_RELAY_ID6.
3665 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
3666 0, 0, 0, 0, 0));
3667 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
3668 uint64_t count;
3669 PgSqlExchange::getColumnValue(r, 0, 0, count);
3670 return (static_cast<size_t>(count));
3671}
3672
3673size_t
3675 // Get a context.
3676 PgSqlLeaseContextAlloc get_context(*this);
3677 PgSqlLeaseContextPtr ctx(get_context.ctx_);
3678
3679 // Execute COUNT_REMOTE_ID6.
3681 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
3682 0, 0, 0, 0, 0));
3683 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
3684 uint64_t count;
3685 PgSqlExchange::getColumnValue(r, 0, 0, count);
3686 return (static_cast<size_t>(count));
3687}
3688
3689} // namespace dhcp
3690} // namespace isc
when the call the UDPServer carries on at the same position As a result
Definition asiodns.dox:16
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown when a function is not implemented.
static ElementPtr fromJSON(const std::string &in, bool preproc=false)
These functions will parse the given string (JSON) representation of a compound element.
Definition data.cc:798
static bool invokeDbLostCallback(const util::ReconnectCtlPtr &db_reconnect_ctl)
Invokes the connection's lost connectivity callback.
static 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.
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 open database.
Exception thrown on failure to execute a database function.
Invalid address family used as input to Lease Manager.
Multiple lease records found where one expected.
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 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...
static std::pair< uint32_t, uint32_t > getVersion(const ParameterMap &parameters, const IOServiceAccessorPtr &ac=IOServiceAccessorPtr(), const DbCallback &cb=DbCallback(), const std::string &timer_name=std::string(), unsigned int id=0)
Get the schema version.
static 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.
PgSqlExchange(const size_t num_columns=0)
Constructor.
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:28
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition cfgmgr.cc:115
Holds Client identifier or client IPv4 address.
Definition duid.h:222
static constexpr size_t MAX_CLIENT_ID_LEN
Maximum size of a client ID.
Definition duid.h:235
const std::vector< uint8_t > & getClientId() const
Returns reference to the client-id data.
Definition duid.cc:69
Holds DUID (DHCPv6 Unique Identifier)
Definition duid.h:142
static constexpr size_t MAX_DUID_LEN
maximum duid size
Definition duid.h:155
const std::vector< uint8_t > & getDuid() const
Returns a const reference to the actual DUID value.
Definition duid.cc:33
std::string toText() const
Returns textual representation of the identifier (e.g.
Definition duid.h:88
static void recreate(const std::string &dbaccess, bool preserve_callbacks=true)
Recreate an instance of a lease manager with optionally preserving registered callbacks.
void setExtendedInfoTablesEnabled(const bool enabled)
Modifies the setting whether the lease6 extended info tables are enabled.
Definition lease_mgr.h:1018
static bool upgradeLease6ExtendedInfo(const Lease6Ptr &lease, CfgConsistency::ExtendedInfoSanity check=CfgConsistency::EXTENDED_INFO_CHECK_FIX)
Upgrade a V6 lease user context to the new extended info entry.
Definition lease_mgr.cc:767
bool getExtendedInfoTablesEnabled() const
Returns the setting indicating if lease6 extended info tables are enabled.
Definition lease_mgr.h:1010
static void extractLease4ExtendedInfo(const Lease4Ptr &lease, bool ignore_errors=true)
Extract relay and remote identifiers from the extended info.
static bool upgradeLease4ExtendedInfo(const Lease4Ptr &lease, CfgConsistency::ExtendedInfoSanity check=CfgConsistency::EXTENDED_INFO_CHECK_FIX)
The following queries are used to fulfill Bulk Lease Query queries.
Definition lease_mgr.cc:535
virtual bool addExtendedInfo6(const Lease6Ptr &lease)
Extract extended info from a lease6 and add it into tables.
Wraps value holding size of the page with leases.
Definition lease_mgr.h:46
const size_t page_size_
Holds page size.
Definition lease_mgr.h:56
LeaseStatsQuery(const SelectMode &select_mode=ALL_SUBNETS)
Constructor to query statistics for all subnets.
Definition lease_mgr.cc:220
SubnetID getLastSubnetID() const
Returns the value of last subnet ID specified (or zero)
Definition lease_mgr.h:209
SubnetID getFirstSubnetID() const
Returns the value of first subnet ID specified (or zero)
Definition lease_mgr.h:204
SelectMode getSelectMode() const
Returns the selection criteria mode The value returned is based upon the constructor variant used and...
Definition lease_mgr.h:216
static const unsigned int DB_CONNECTION
The network state is being altered by the DB connection recovery mechanics.
Attempt to update lease that was not there.
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.
db::PgSqlConnection conn_
PostgreSQL connection.
std::vector< uint8_t > addr_bin_
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 void recountClassLeases6() override
Recount the leases per class for V6 leases.
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 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 startPoolLeaseStatsQuery4() override
Creates and runs the IPv4 lease stats query for all subnets and pools.
virtual std::string checkLimits6(isc::data::ConstElementPtr const &user_context) const override
Checks if the IPv6 lease limits set in the given user context are exceeded.
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 std::string checkLimits4(isc::data::ConstElementPtr const &user_context) const override
Checks if the IPv4 lease limits set in the given user context are exceeded.
virtual size_t byRemoteId6size() const override
Return the by-remote-id table size.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery4(const SubnetID &subnet_id) override
Creates and runs the IPv4 lease stats query for a single subnet.
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 uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv6 leases.
virtual void deleteExtendedInfo6(const isc::asiolink::IOAddress &addr) override
Extended information / Bulk Lease Query shared interface.
virtual void recountClassLeases4() override
Recount the leases per class for V4 leases.
virtual size_t upgradeExtendedInfo4(const LeasePageSize &page_size) override
Upgrade extended info (v4).
virtual size_t wipeLeases6(const SubnetID &subnet_id) override
Removed specified IPv6 leases.
virtual std::pair< uint32_t, uint32_t > getVersion(const std::string &timer_name=std::string()) const override
Returns backend version.
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::string getDescription() const override
Returns description of the backend.
virtual void wipeExtendedInfoTables6() override
Wipe extended info table (v6).
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 size_t upgradeExtendedInfo6(const LeasePageSize &page_size) override
Upgrade extended info (v6).
virtual size_t byRelayId6size() const override
Return the by-relay-id table size.
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 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.
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 rollback() override
Rollback Transactions.
virtual void updateLease4(const Lease4Ptr &lease4) override
Updates IPv4 lease.
virtual LeaseStatsQueryPtr startPoolLeaseStatsQuery6() override
Creates and runs the IPv6 lease stats query for all subnets and pools.
virtual void writeLeases6(const std::string &) override
Write V6 leases to a file.
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 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 void clearClassLeaseCounts() override
Clears the class-lease count map.
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 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.
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 isJsonSupported() const override
Checks if JSON support is enabled in the database.
virtual size_t getClassLeaseCount(const ClientClass &client_class, const Lease::Type &ltype=Lease::TYPE_V4) const override
Returns the class lease count for a given class and lease type.
virtual bool addLease(const Lease4Ptr &lease) override
Adds an IPv4 lease.
virtual void writeLeases4(const std::string &) override
Write V4 leases to a file.
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.
bool fetch_pool_
Indicates if query requires pool data.
PgSqlLeaseStatsQuery(PgSqlConnection &conn, PgSqlTaggedStatement &statement, const bool fetch_type, const bool fetch_pool=false)
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:446
void trackAddLease(const LeasePtr &lease)
Invokes the callbacks when a new lease is added.
void trackUpdateLease(const LeasePtr &lease)
Invokes the callbacks when a lease is updated.
void trackDeleteLease(const LeasePtr &lease)
Invokes the callbacks when a lease is deleted.
bool hasCallbacks() const
Checks if any callbacks have been registered.
RAII class creating a critical section.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
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:29
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_REMOTEID6
const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO6_PAGE
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:136
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition lease.h:505
const isc::log::MessageID DHCPSRV_PGSQL_GET_HOSTNAME6
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_PGSQL_GET_IAID_SUBID_DUID
const isc::log::MessageID DHCPSRV_PGSQL_GET_ADDR4
const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO6
const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO6_ERROR
const isc::log::MessageID DHCPSRV_PGSQL_GET_HOSTNAME4
const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4
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_GET_REMOTEID4
const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_PAGE
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:25
boost::shared_ptr< Lease > LeasePtr
Pointer to the lease object.
Definition lease.h:25
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_RELAYID6
const isc::log::MessageID DHCPSRV_PGSQL_GET_IAID_DUID
const isc::log::MessageID DHCPSRV_PGSQL_UPDATE_ADDR6
const isc::log::MessageID DHCPSRV_PGSQL_GET_RELAYID4
boost::shared_ptr< PgSqlLeaseContext > PgSqlLeaseContextPtr
Type of pointers to contexts.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition option.h:24
const isc::log::MessageID DHCPSRV_PGSQL_LEASE_DB_RECONNECT_FAILED
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition lease.h:497
const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_ERROR
@ 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:292
const isc::log::MessageID DHCPSRV_PGSQL_COMMIT
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition dhcpsrv_log.h:26
const isc::log::MessageID DHCPSRV_PGSQL_GET_SUBID_PAGE6
const isc::log::MessageID DHCPSRV_PGSQL_DELETE_EXPIRED_RECLAIMED6
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.
Define a PostgreSQL statement.
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.
void addNull(const int format=PsqlBindArray::TEXT_FMT)
Adds a NULL value to the bind 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:513
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
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.