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