Kea 2.5.8
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) {
1616
1617 // Check if the extended info tables are enabled.
1618 setExtendedInfoTablesEnabled(parameters);
1619
1620 // Check TLS support.
1621 size_t tls(0);
1622 tls += parameters.count("trust-anchor");
1623 tls += parameters.count("cert-file");
1624 tls += parameters.count("key-file");
1625 tls += parameters.count("cipher-list");
1626#ifdef HAVE_PGSQL_SSL
1627 if ((tls > 0) && !PgSqlConnection::warned_about_tls) {
1631 PQinitSSL(1);
1632 }
1633#else
1634 if (tls > 0) {
1637 isc_throw(DbOpenError, "Attempt to configure TLS for PostgreSQL "
1638 << "backend (built with this feature disabled)");
1639 }
1640#endif
1641
1642 // Create unique timer name per instance.
1643 timer_name_ = "PgSqlLeaseMgr[";
1644 timer_name_ += boost::lexical_cast<std::string>(reinterpret_cast<uint64_t>(this));
1645 timer_name_ += "]DbReconnectTimer";
1646
1648 timer_name_);
1649
1650 // Create an initial context.
1651 pool_.reset(new PgSqlLeaseContextPool());
1652 pool_->pool_.push_back(createContext());
1653}
1654
1656}
1657
1658bool
1661
1662 // Invoke application layer connection lost callback.
1663 if (!DatabaseConnection::invokeDbLostCallback(db_reconnect_ctl)) {
1664 return (false);
1665 }
1666
1667 bool reopened = false;
1668
1669 const std::string timer_name = db_reconnect_ctl->timerName();
1670
1671 // At least one connection was lost.
1672 try {
1673 CfgDbAccessPtr cfg_db = CfgMgr::instance().getCurrentCfg()->getCfgDbAccess();
1674 LeaseMgrFactory::recreate(cfg_db->getLeaseDbAccessString());
1675 reopened = true;
1676 } catch (const std::exception& ex) {
1678 .arg(ex.what());
1679 }
1680
1681 if (reopened) {
1682 // Cancel the timer.
1683 if (TimerMgr::instance()->isTimerRegistered(timer_name)) {
1684 TimerMgr::instance()->unregisterTimer(timer_name);
1685 }
1686
1687 // Invoke application layer connection recovered callback.
1688 if (!DatabaseConnection::invokeDbRecoveredCallback(db_reconnect_ctl)) {
1689 return (false);
1690 }
1691 } else {
1692 if (!db_reconnect_ctl->checkRetries()) {
1693 // We're out of retries, log it and initiate shutdown.
1695 .arg(db_reconnect_ctl->maxRetries());
1696
1697 // Cancel the timer.
1698 if (TimerMgr::instance()->isTimerRegistered(timer_name)) {
1699 TimerMgr::instance()->unregisterTimer(timer_name);
1700 }
1701
1702 // Invoke application layer connection failed callback.
1704 return (false);
1705 }
1706
1708 .arg(db_reconnect_ctl->maxRetries() - db_reconnect_ctl->retriesLeft() + 1)
1709 .arg(db_reconnect_ctl->maxRetries())
1710 .arg(db_reconnect_ctl->retryInterval());
1711
1712 // Start the timer.
1713 if (!TimerMgr::instance()->isTimerRegistered(timer_name)) {
1714 TimerMgr::instance()->registerTimer(timer_name,
1715 std::bind(&PgSqlLeaseMgr::dbReconnect, db_reconnect_ctl),
1716 db_reconnect_ctl->retryInterval(),
1718 }
1719 TimerMgr::instance()->setup(timer_name);
1720 }
1721
1722 return (true);
1723}
1724
1725// Create context.
1726
1729 PgSqlLeaseContextPtr ctx(new PgSqlLeaseContext(parameters_,
1732
1733 // Create ReconnectCtl for this connection.
1734 ctx->conn_.makeReconnectCtl(timer_name_);
1735
1736 // Open the database.
1737 ctx->conn_.openDatabase();
1738
1739 // Now prepare the SQL statements.
1740 uint32_t i = 0;
1741 for (; tagged_statements[i].text != NULL; ++i) {
1742 ctx->conn_.prepareStatement(tagged_statements[i]);
1743 }
1744
1745 // Just in case somebody foo-barred things
1746 if (i != NUM_STATEMENTS) {
1747 isc_throw(DbOpenError, "Number of statements prepared: " << i
1748 << " does not match expected count:" << NUM_STATEMENTS);
1749 }
1750
1751 // Create the exchange objects for use in exchanging data between the
1752 // program and the database.
1753 ctx->exchange4_.reset(new PgSqlLease4Exchange());
1754 ctx->exchange6_.reset(new PgSqlLease6Exchange());
1755
1756 return (ctx);
1757}
1758
1759std::string
1761 std::stringstream tmp;
1762 tmp << "PostgreSQL backend " << PGSQL_SCHEMA_VERSION_MAJOR;
1763 tmp << "." << PGSQL_SCHEMA_VERSION_MINOR;
1764 tmp << ", library " << PQlibVersion();
1765 return (tmp.str());
1766}
1767
1768bool
1769PgSqlLeaseMgr::addLeaseCommon(PgSqlLeaseContextPtr& ctx,
1770 StatementIndex stindex,
1771 PsqlBindArray& bind_array) {
1772 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
1773 tagged_statements[stindex].nbparams,
1774 &bind_array.values_[0],
1775 &bind_array.lengths_[0],
1776 &bind_array.formats_[0], 0));
1777
1778 int s = PQresultStatus(r);
1779
1780 if (s != PGRES_COMMAND_OK) {
1781 // Failure: check for the special case of duplicate entry. If this is
1782 // the case, we return false to indicate that the row was not added.
1783 // Otherwise we throw an exception.
1784 if (ctx->conn_.compareError(r, PgSqlConnection::DUPLICATE_KEY)) {
1785 return (false);
1786 }
1787 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
1788 }
1789
1790 return (true);
1791}
1792
1793bool
1796 .arg(lease->addr_.toText());
1797
1798 // Get a context
1799 PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
1800 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1801
1802 PsqlBindArray bind_array;
1803 ctx->exchange4_->createBindForSend(lease, bind_array);
1804 auto result = addLeaseCommon(ctx, INSERT_LEASE4, bind_array);
1805
1806 // Update lease current expiration time (allows update between the creation
1807 // of the Lease up to the point of insertion in the database).
1808 lease->updateCurrentExpirationTime();
1809
1810 // Run installed callbacks.
1811 if (hasCallbacks()) {
1812 trackAddLease(lease);
1813 }
1814
1815 return (result);
1816}
1817
1818bool
1821 .arg(lease->addr_.toText())
1822 .arg(lease->type_);
1823
1824 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
1825
1826 // Get a context
1827 PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
1828 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1829
1830 PsqlBindArray bind_array;
1831 ctx->exchange6_->createBindForSend(lease, bind_array);
1832
1833 auto result = addLeaseCommon(ctx, INSERT_LEASE6, bind_array);
1834
1835 // Update lease current expiration time (allows update between the creation
1836 // of the Lease up to the point of insertion in the database).
1837 lease->updateCurrentExpirationTime();
1838
1840 static_cast<void>(addExtendedInfo6(lease));
1841 }
1842
1843 // Run installed callbacks.
1844 if (hasCallbacks()) {
1845 trackAddLease(lease);
1846 }
1847
1848 return (result);
1849}
1850
1851template <typename Exchange, typename LeaseCollection>
1852void
1853PgSqlLeaseMgr::getLeaseCollection(PgSqlLeaseContextPtr& ctx,
1854 StatementIndex stindex,
1855 PsqlBindArray& bind_array,
1856 Exchange& exchange,
1857 LeaseCollection& result,
1858 bool single) const {
1859 const int n = tagged_statements[stindex].nbparams;
1860 PgSqlResult r(PQexecPrepared(ctx->conn_,
1861 tagged_statements[stindex].name, n,
1862 n > 0 ? &bind_array.values_[0] : NULL,
1863 n > 0 ? &bind_array.lengths_[0] : NULL,
1864 n > 0 ? &bind_array.formats_[0] : NULL, 0));
1865
1866 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
1867
1868 int rows = PQntuples(r);
1869 if (single && rows > 1) {
1870 isc_throw(MultipleRecords, "multiple records were found in the "
1871 "database where only one was expected for query "
1872 << tagged_statements[stindex].name);
1873 }
1874
1875 for(int i = 0; i < rows; ++i) {
1876 result.push_back(exchange->convertFromDatabase(r, i));
1877 }
1878}
1879
1880void
1881PgSqlLeaseMgr::getLease(PgSqlLeaseContextPtr& ctx,
1882 StatementIndex stindex, PsqlBindArray& bind_array,
1883 Lease4Ptr& result) const {
1884 // Create appropriate collection object and get all leases matching
1885 // the selection criteria. The "single" parameter is true to indicate
1886 // that the called method should throw an exception if multiple
1887 // matching records are found: this particular method is called when only
1888 // one or zero matches is expected.
1889 Lease4Collection collection;
1890 getLeaseCollection(ctx, stindex, bind_array, ctx->exchange4_,
1891 collection, true);
1892
1893 // Return single record if present, else clear the lease.
1894 if (collection.empty()) {
1895 result.reset();
1896 } else {
1897 result = *collection.begin();
1898 }
1899}
1900
1901void
1902PgSqlLeaseMgr::getLease(PgSqlLeaseContextPtr& ctx,
1903 StatementIndex stindex, PsqlBindArray& bind_array,
1904 Lease6Ptr& 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 Lease6Collection collection;
1911 getLeaseCollection(ctx, stindex, bind_array, ctx->exchange6_,
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
1925 .arg(addr.toText());
1926
1927 // Set up the WHERE clause value
1928 PsqlBindArray bind_array;
1929
1930 // LEASE ADDRESS
1931 std::string addr_str = boost::lexical_cast<std::string>(addr.toUint32());
1932 bind_array.add(addr_str);
1933
1934 // Get the data
1935 Lease4Ptr result;
1936
1937 // Get a context
1938 PgSqlLeaseContextAlloc get_context(*this);
1939 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1940
1941 getLease(ctx, GET_LEASE4_ADDR, bind_array, result);
1942
1943 return (result);
1944}
1945
1947PgSqlLeaseMgr::getLease4(const HWAddr& hwaddr) const {
1949 .arg(hwaddr.toText());
1950
1951 // Set up the WHERE clause value
1952 PsqlBindArray bind_array;
1953
1954 // HWADDR
1955 if (!hwaddr.hwaddr_.empty()) {
1956 bind_array.add(hwaddr.hwaddr_);
1957 } else {
1958 bind_array.add("");
1959 }
1960
1961 // Get the data
1962 Lease4Collection result;
1963
1964 // Get a context
1965 PgSqlLeaseContextAlloc get_context(*this);
1966 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1967
1968 getLeaseCollection(ctx, GET_LEASE4_HWADDR, bind_array, result);
1969
1970 return (result);
1971}
1972
1974PgSqlLeaseMgr::getLease4(const HWAddr& hwaddr, SubnetID subnet_id) const {
1976 .arg(subnet_id)
1977 .arg(hwaddr.toText());
1978
1979 // Set up the WHERE clause value
1980 PsqlBindArray bind_array;
1981
1982 // HWADDR
1983 if (!hwaddr.hwaddr_.empty()) {
1984 bind_array.add(hwaddr.hwaddr_);
1985 } else {
1986 bind_array.add("");
1987 }
1988
1989 // SUBNET_ID
1990 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
1991 bind_array.add(subnet_id_str);
1992
1993 // Get the data
1994 Lease4Ptr result;
1995
1996 // Get a context
1997 PgSqlLeaseContextAlloc get_context(*this);
1998 PgSqlLeaseContextPtr ctx = get_context.ctx_;
1999
2000 getLease(ctx, GET_LEASE4_HWADDR_SUBID, bind_array, result);
2001
2002 return (result);
2003}
2004
2006PgSqlLeaseMgr::getLease4(const ClientId& clientid) const {
2008 .arg(clientid.toText());
2009
2010 // Set up the WHERE clause value
2011 PsqlBindArray bind_array;
2012
2013 // CLIENT_ID
2014 bind_array.add(clientid.getClientId());
2015
2016 // Get the data
2017 Lease4Collection result;
2018
2019 // Get a context
2020 PgSqlLeaseContextAlloc get_context(*this);
2021 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2022
2023 getLeaseCollection(ctx, GET_LEASE4_CLIENTID, bind_array, result);
2024
2025 return (result);
2026}
2027
2029PgSqlLeaseMgr::getLease4(const ClientId& clientid, SubnetID subnet_id) const {
2031 .arg(subnet_id)
2032 .arg(clientid.toText());
2033
2034 // Set up the WHERE clause value
2035 PsqlBindArray bind_array;
2036
2037 // CLIENT_ID
2038 bind_array.add(clientid.getClientId());
2039
2040 // SUBNET_ID
2041 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
2042 bind_array.add(subnet_id_str);
2043
2044 // Get the data
2045 Lease4Ptr result;
2046
2047 // Get a context
2048 PgSqlLeaseContextAlloc get_context(*this);
2049 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2050
2051 getLease(ctx, GET_LEASE4_CLIENTID_SUBID, bind_array, result);
2052
2053 return (result);
2054}
2055
2059 .arg(subnet_id);
2060
2061 // Set up the WHERE clause value
2062 PsqlBindArray bind_array;
2063
2064 // SUBNET_ID
2065 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
2066 bind_array.add(subnet_id_str);
2067
2068 // ... and get the data
2069 Lease4Collection result;
2070
2071 // Get a context
2072 PgSqlLeaseContextAlloc get_context(*this);
2073 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2074
2075 getLeaseCollection(ctx, GET_LEASE4_SUBID, bind_array, result);
2076
2077 return (result);
2078}
2079
2081PgSqlLeaseMgr::getLeases4(const std::string& hostname) const {
2083 .arg(hostname);
2084
2085 // Set up the WHERE clause value
2086 PsqlBindArray bind_array;
2087
2088 // Hostname
2089 bind_array.add(hostname);
2090
2091 // ... and get the data
2092 Lease4Collection result;
2093
2094 // Get a context
2095 PgSqlLeaseContextAlloc get_context(*this);
2096 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2097
2098 getLeaseCollection(ctx, GET_LEASE4_HOSTNAME, bind_array, result);
2099
2100 return (result);
2101}
2102
2106
2107 // Provide empty binding array because our query has no parameters in
2108 // WHERE clause.
2109 PsqlBindArray bind_array;
2110 Lease4Collection result;
2111
2112 // Get a context
2113 PgSqlLeaseContextAlloc get_context(*this);
2114 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2115
2116 getLeaseCollection(ctx, GET_LEASE4, bind_array, result);
2117
2118 return (result);
2119}
2120
2122PgSqlLeaseMgr::getLeases4(const IOAddress& lower_bound_address,
2123 const LeasePageSize& page_size) const {
2124 // Expecting IPv4 address.
2125 if (!lower_bound_address.isV4()) {
2126 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
2127 "retrieving leases from the lease database, got "
2128 << lower_bound_address);
2129 }
2130
2132 .arg(page_size.page_size_)
2133 .arg(lower_bound_address.toText());
2134
2135 // Prepare WHERE clause
2136 PsqlBindArray bind_array;
2137
2138 // Bind lower bound address
2139 std::string lb_address_data = boost::lexical_cast<std::string>(lower_bound_address.toUint32());
2140 bind_array.add(lb_address_data);
2141
2142 // Bind page size value
2143 std::string page_size_data = boost::lexical_cast<std::string>(page_size.page_size_);
2144 bind_array.add(page_size_data);
2145
2146 // Get the leases
2147 Lease4Collection result;
2148
2149 // Get a context
2150 PgSqlLeaseContextAlloc get_context(*this);
2151 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2152
2153 getLeaseCollection(ctx, GET_LEASE4_PAGE, bind_array, result);
2154
2155 return (result);
2156}
2157
2160 const IOAddress& addr) const {
2162 .arg(addr.toText())
2163 .arg(lease_type);
2164
2165 // Set up the WHERE clause value
2166 PsqlBindArray bind_array;
2167
2168 // LEASE ADDRESS
2169 std::string addr_str = addr.toText();
2170 bind_array.add(addr_str);
2171
2172 // LEASE_TYPE
2173 std::string type_str_ = boost::lexical_cast<std::string>(lease_type);
2174 bind_array.add(type_str_);
2175
2176 // ... and get the data
2177 Lease6Ptr result;
2178
2179 // Get a context
2180 PgSqlLeaseContextAlloc get_context(*this);
2181 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2182
2183 getLease(ctx, GET_LEASE6_ADDR, bind_array, result);
2184
2185 return (result);
2186}
2187
2190 uint32_t iaid) const {
2192 .arg(iaid)
2193 .arg(duid.toText())
2194 .arg(lease_type);
2195
2196 // Set up the WHERE clause value
2197 PsqlBindArray bind_array;
2198
2199 // DUID
2200 bind_array.add(duid.getDuid());
2201
2202 // IAID
2203 std::string iaid_str = PgSqlLease6Exchange::Uiaid(iaid).dbInputString();
2204 bind_array.add(iaid_str);
2205
2206 // LEASE_TYPE
2207 std::string lease_type_str = boost::lexical_cast<std::string>(lease_type);
2208 bind_array.add(lease_type_str);
2209
2210 // ... and get the data
2211 Lease6Collection result;
2212
2213 // Get a context
2214 PgSqlLeaseContextAlloc get_context(*this);
2215 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2216
2217 getLeaseCollection(ctx, GET_LEASE6_DUID_IAID, bind_array, result);
2218
2219 return (result);
2220}
2221
2224 uint32_t iaid, SubnetID subnet_id) const {
2226 .arg(iaid)
2227 .arg(subnet_id)
2228 .arg(duid.toText())
2229 .arg(lease_type);
2230
2231 // Set up the WHERE clause value
2232 PsqlBindArray bind_array;
2233
2234 // LEASE_TYPE
2235 std::string lease_type_str = boost::lexical_cast<std::string>(lease_type);
2236 bind_array.add(lease_type_str);
2237
2238 // DUID
2239 bind_array.add(duid.getDuid());
2240
2241 // IAID
2242 std::string iaid_str = PgSqlLease6Exchange::Uiaid(iaid).dbInputString();
2243 bind_array.add(iaid_str);
2244
2245 // SUBNET ID
2246 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
2247 bind_array.add(subnet_id_str);
2248
2249 // ... and get the data
2250 Lease6Collection result;
2251
2252 // Get a context
2253 PgSqlLeaseContextAlloc get_context(*this);
2254 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2255
2256 getLeaseCollection(ctx, GET_LEASE6_DUID_IAID_SUBID, bind_array, result);
2257
2258 return (result);
2259}
2260
2264 .arg(subnet_id);
2265
2266 // Set up the WHERE clause value
2267 PsqlBindArray bind_array;
2268
2269 // SUBNET_ID
2270 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
2271 bind_array.add(subnet_id_str);
2272
2273 // ... and get the data
2274 Lease6Collection result;
2275
2276 // Get a context
2277 PgSqlLeaseContextAlloc get_context(*this);
2278 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2279
2280 getLeaseCollection(ctx, GET_LEASE6_SUBID, bind_array, result);
2281
2282 return (result);
2283}
2284
2287 const IOAddress& lower_bound_address,
2288 const LeasePageSize& page_size) const {
2291 .arg(page_size.page_size_)
2292 .arg(lower_bound_address.toText())
2293 .arg(subnet_id);
2294
2295 // Expecting IPv6 valid address.
2296 if (!lower_bound_address.isV6()) {
2297 isc_throw(InvalidAddressFamily, "expected IPv6 start address while "
2298 "retrieving leases from the lease database, got "
2299 << lower_bound_address);
2300 }
2301
2302 Lease6Collection result;
2303 // Prepare WHERE clause
2304 PsqlBindArray bind_array;
2305
2306 // Bind subnet id.
2307 std::string subnet_id_str = boost::lexical_cast<std::string>(subnet_id);
2308 bind_array.add(subnet_id_str);
2309
2310 // Bind lower bound address
2311 std::string lb_address_str = lower_bound_address.toText();
2312 bind_array.add(lb_address_str);
2313
2314 // Bind page size value
2315 std::string page_size_data =
2316 boost::lexical_cast<std::string>(page_size.page_size_);
2317 bind_array.add(page_size_data);
2318
2319 // Get a context
2320 PgSqlLeaseContextAlloc get_context(*this);
2321 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2322
2323 // Get the leases
2324 getLeaseCollection(ctx, GET_LEASE6_SUBID_PAGE, bind_array, result);
2325
2326 return (result);
2327}
2328
2332 .arg(duid.toText());
2333
2334 // Set up the WHERE clause value
2335 PsqlBindArray bind_array;
2336
2337 // DUID
2338 bind_array.add(duid.getDuid());
2339 Lease6Collection result;
2340
2341 // Get a context
2342 PgSqlLeaseContextAlloc get_context(*this);
2343 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2344
2345 // query to fetch the data
2346 getLeaseCollection(ctx, GET_LEASE6_DUID, bind_array, result);
2347
2348 return (result);
2349}
2350
2352PgSqlLeaseMgr::getLeases6(const std::string& hostname) const {
2354 .arg(hostname);
2355
2356 // Set up the WHERE clause value
2357 PsqlBindArray bind_array;
2358
2359 // Hostname
2360 bind_array.add(hostname);
2361
2362 // ... and get the data
2363 Lease6Collection result;
2364
2365 // Get a context
2366 PgSqlLeaseContextAlloc get_context(*this);
2367 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2368
2369 getLeaseCollection(ctx, GET_LEASE6_HOSTNAME, bind_array, result);
2370
2371 return (result);
2372}
2373
2377
2378 // Provide empty binding array because our query has no parameters in
2379 // WHERE clause.
2380 PsqlBindArray bind_array;
2381 Lease6Collection result;
2382
2383 // Get a context
2384 PgSqlLeaseContextAlloc get_context(*this);
2385 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2386
2387 getLeaseCollection(ctx, GET_LEASE6, bind_array, result);
2388
2389 return (result);
2390}
2391
2393PgSqlLeaseMgr::getLeases6(const IOAddress& lower_bound_address,
2394 const LeasePageSize& page_size) const {
2395 // Expecting IPv6 address.
2396 if (!lower_bound_address.isV6()) {
2397 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
2398 "retrieving leases from the lease database, got "
2399 << lower_bound_address);
2400 }
2401
2403 .arg(page_size.page_size_)
2404 .arg(lower_bound_address.toText());
2405
2406 // Prepare WHERE clause
2407 PsqlBindArray bind_array;
2408
2409 // Bind lower bound address
2410 std::string lb_address_data = lower_bound_address.toText();
2411 bind_array.add(lb_address_data);
2412
2413 // Bind page size value
2414 std::string page_size_data =
2415 boost::lexical_cast<std::string>(page_size.page_size_);
2416 bind_array.add(page_size_data);
2417
2418 // Get the leases
2419 Lease6Collection result;
2420
2421 // Get a context
2422 PgSqlLeaseContextAlloc get_context(*this);
2423 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2424
2425 getLeaseCollection(ctx, GET_LEASE6_PAGE, bind_array, result);
2426
2427 return (result);
2428}
2429
2430void
2432 const size_t max_leases) const {
2434 .arg(max_leases);
2435 getExpiredLeasesCommon(expired_leases, max_leases, GET_LEASE4_EXPIRE);
2436}
2437
2438void
2440 const size_t max_leases) const {
2442 .arg(max_leases);
2443 getExpiredLeasesCommon(expired_leases, max_leases, GET_LEASE6_EXPIRE);
2444}
2445
2446template<typename LeaseCollection>
2447void
2448PgSqlLeaseMgr::getExpiredLeasesCommon(LeaseCollection& expired_leases,
2449 const size_t max_leases,
2450 StatementIndex statement_index) const {
2451 PsqlBindArray bind_array;
2452
2453 // Exclude reclaimed leases.
2454 std::string state_str = boost::lexical_cast<std::string>(Lease::STATE_EXPIRED_RECLAIMED);
2455 bind_array.add(state_str);
2456
2457 // Expiration timestamp.
2458 std::string timestamp_str = PgSqlLeaseExchange::convertToDatabaseTime(time(0));
2459 bind_array.add(timestamp_str);
2460
2461 // If the number of leases is 0, we will return all leases. This is
2462 // achieved by setting the limit to a very high value.
2463 uint32_t limit = max_leases > 0 ? static_cast<uint32_t>(max_leases) :
2464 std::numeric_limits<uint32_t>::max();
2465 std::string limit_str = boost::lexical_cast<std::string>(limit);
2466 bind_array.add(limit_str);
2467
2468 // Get a context
2469 PgSqlLeaseContextAlloc get_context(*this);
2470 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2471
2472 // Retrieve leases from the database.
2473 getLeaseCollection(ctx, statement_index, bind_array, expired_leases);
2474}
2475
2476template<typename LeasePtr>
2477void
2478PgSqlLeaseMgr::updateLeaseCommon(PgSqlLeaseContextPtr& ctx,
2479 StatementIndex stindex,
2480 PsqlBindArray& bind_array,
2481 const LeasePtr& lease) {
2482 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
2483 tagged_statements[stindex].nbparams,
2484 &bind_array.values_[0],
2485 &bind_array.lengths_[0],
2486 &bind_array.formats_[0], 0));
2487
2488 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2489
2490 int affected_rows = boost::lexical_cast<int>(PQcmdTuples(r));
2491
2492 // Check success case first as it is the most likely outcome.
2493 if (affected_rows == 1) {
2494 return;
2495 }
2496
2497 // If no rows affected, lease doesn't exist.
2498 if (affected_rows == 0) {
2499 isc_throw(NoSuchLease, "unable to update lease for address " <<
2500 lease->addr_.toText() << " as it does not exist");
2501 }
2502
2503 // Should not happen - primary key constraint should only have selected
2504 // one row.
2505 isc_throw(DbOperationError, "apparently updated more than one lease "
2506 "that had the address " << lease->addr_.toText());
2507}
2508
2509void
2511 const StatementIndex stindex = UPDATE_LEASE4;
2512
2514 .arg(lease->addr_.toText());
2515
2516 // Get a context
2517 PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
2518 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2519
2520 // Create the BIND array for the data being updated
2521 PsqlBindArray bind_array;
2522 ctx->exchange4_->createBindForSend(lease, bind_array);
2523
2524 // Set up the WHERE clause and append it to the SQL_BIND array
2525 std::string addr4_str = boost::lexical_cast<std::string>(lease->addr_.toUint32());
2526 bind_array.add(addr4_str);
2527
2528 std::string expire_str;
2529 // Avoid overflow (see createBindForSend)
2530 if (lease->current_valid_lft_ == Lease::INFINITY_LFT) {
2531 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_, 0);
2532 } else {
2533 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_,
2534 lease->current_valid_lft_);
2535 }
2536 bind_array.add(expire_str);
2537
2538 // Drop to common update code
2539 updateLeaseCommon(ctx, stindex, bind_array, lease);
2540
2541 // Update lease current expiration time.
2542 lease->updateCurrentExpirationTime();
2543
2544 // Run installed callbacks.
2545 if (hasCallbacks()) {
2546 trackUpdateLease(lease);
2547 }
2548}
2549
2550void
2552 const StatementIndex stindex = UPDATE_LEASE6;
2553
2555 .arg(lease->addr_.toText())
2556 .arg(lease->type_);
2557
2558 // Get the recorded action and reset it.
2559 Lease6::ExtendedInfoAction recorded_action = lease->extended_info_action_;
2560 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
2561
2562 // Get a context
2563 PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
2564 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2565
2566 // Create the BIND array for the data being updated
2567 PsqlBindArray bind_array;
2568 ctx->exchange6_->createBindForSend(lease, bind_array);
2569
2570 // Set up the WHERE clause and append it to the BIND array
2571 std::string addr_str = lease->addr_.toText();
2572 bind_array.add(addr_str);
2573
2574 std::string expire_str;
2575 // Avoid overflow (see createBindForSend)
2576 if (lease->current_valid_lft_ == Lease::INFINITY_LFT) {
2577 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_, 0);
2578 } else {
2579 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_,
2580 lease->current_valid_lft_);
2581 }
2582 bind_array.add(expire_str);
2583
2584 // Drop to common update code
2585 updateLeaseCommon(ctx, stindex, bind_array, lease);
2586
2587 // Update lease current expiration time.
2588 lease->updateCurrentExpirationTime();
2589
2590 // Update extended info tables.
2592 switch (recorded_action) {
2594 break;
2595
2597 deleteExtendedInfo6(lease->addr_);
2598 break;
2599
2601 deleteExtendedInfo6(lease->addr_);
2602 static_cast<void>(addExtendedInfo6(lease));
2603 break;
2604 }
2605 }
2606
2607 // Run installed callbacks.
2608 if (hasCallbacks()) {
2609 trackUpdateLease(lease);
2610 }
2611}
2612
2613uint64_t
2614PgSqlLeaseMgr::deleteLeaseCommon(PgSqlLeaseContextPtr& ctx,
2615 StatementIndex stindex,
2616 PsqlBindArray& bind_array) {
2617 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
2618 tagged_statements[stindex].nbparams,
2619 &bind_array.values_[0],
2620 &bind_array.lengths_[0],
2621 &bind_array.formats_[0], 0));
2622
2623 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2624 int affected_rows = boost::lexical_cast<int>(PQcmdTuples(r));
2625
2626 return (affected_rows);
2627}
2628
2629bool
2631 const IOAddress& addr = lease->addr_;
2633 .arg(addr.toText());
2634
2635 // Set up the WHERE clause value
2636 PsqlBindArray bind_array;
2637
2638 std::string addr4_str = boost::lexical_cast<std::string>(addr.toUint32());
2639 bind_array.add(addr4_str);
2640
2641 std::string expire_str;
2642 // Avoid overflow (see createBindForSend)
2643 if (lease->current_valid_lft_ == Lease::INFINITY_LFT) {
2644 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_, 0);
2645 } else {
2646 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_,
2647 lease->current_valid_lft_);
2648 }
2649 bind_array.add(expire_str);
2650
2651 // Get a context
2652 PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
2653 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2654
2655 auto affected_rows = deleteLeaseCommon(ctx, DELETE_LEASE4, bind_array);
2656
2657 // Check success case first as it is the most likely outcome.
2658 if (affected_rows == 1) {
2659 if (hasCallbacks()) {
2660 trackDeleteLease(lease);
2661 }
2662 return (true);
2663 }
2664
2665 // If no rows affected, lease doesn't exist.
2666 if (affected_rows == 0) {
2667 return (false);
2668 }
2669
2670 // Should not happen - primary key constraint should only have selected
2671 // one row.
2672 isc_throw(DbOperationError, "apparently deleted more than one lease "
2673 "that had the address " << lease->addr_.toText());
2674}
2675
2676bool
2678 const IOAddress& addr = lease->addr_;
2681 .arg(addr.toText());
2682
2683 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
2684
2685 // Set up the WHERE clause value
2686 PsqlBindArray bind_array;
2687
2688 std::string addr6_str = addr.toText();
2689 bind_array.add(addr6_str);
2690
2691 std::string expire_str;
2692 // Avoid overflow (see createBindForSend)
2693 if (lease->current_valid_lft_ == Lease::INFINITY_LFT) {
2694 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_, 0);
2695 } else {
2696 expire_str = PgSqlLeaseExchange::convertToDatabaseTime(lease->current_cltt_,
2697 lease->current_valid_lft_);
2698 }
2699 bind_array.add(expire_str);
2700
2701 // Get a context
2702 PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
2703 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2704
2705 auto affected_rows = deleteLeaseCommon(ctx, DELETE_LEASE6, bind_array);
2706
2707 // Check success case first as it is the most likely outcome.
2708 if (affected_rows == 1) {
2709 // Delete references from extended info tables.
2710 // Performed by the delete cascade.
2711
2712 // Run installed callbacks.
2713 if (hasCallbacks()) {
2714 trackDeleteLease(lease);
2715 }
2716 return (true);
2717 }
2718
2719 // If no rows affected, lease doesn't exist.
2720 if (affected_rows == 0) {
2721 return (false);
2722 }
2723
2724 // Should not happen - primary key constraint should only have selected
2725 // one row.
2726 isc_throw(DbOperationError, "apparently deleted more than one lease "
2727 "that had the address " << lease->addr_.toText());
2728}
2729
2730uint64_t
2733 .arg(secs);
2734 return (deleteExpiredReclaimedLeasesCommon(secs, DELETE_LEASE4_STATE_EXPIRED));
2735}
2736
2737uint64_t
2740 .arg(secs);
2741 return (deleteExpiredReclaimedLeasesCommon(secs, DELETE_LEASE6_STATE_EXPIRED));
2742}
2743
2744uint64_t
2745PgSqlLeaseMgr::deleteExpiredReclaimedLeasesCommon(const uint32_t secs,
2746 StatementIndex statement_index) {
2747 PsqlBindArray bind_array;
2748
2749 // State is reclaimed.
2750 std::string state_str = boost::lexical_cast<std::string>(Lease::STATE_EXPIRED_RECLAIMED);
2751 bind_array.add(state_str);
2752
2753 // Expiration timestamp.
2754 std::string expiration_str = PgSqlLeaseExchange::convertToDatabaseTime(time(0) -
2755 static_cast<time_t>(secs));
2756 bind_array.add(expiration_str);
2757
2758 // Get a context
2759 PgSqlLeaseContextAlloc get_context(*this);
2760 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2761
2762 // Delete leases.
2763 return (deleteLeaseCommon(ctx, statement_index, bind_array));
2764}
2765
2766string
2767PgSqlLeaseMgr::checkLimits(ConstElementPtr const& user_context, StatementIndex const stindex) const {
2768 // No user context means no limits means allocation allowed means empty string.
2769 if (!user_context) {
2770 return string();
2771 }
2772
2773 // Get a context.
2774 PgSqlLeaseContextAlloc get_context(*this);
2775 PgSqlLeaseContextPtr ctx(get_context.ctx_);
2776
2777 // Create bindings.
2778 PsqlBindArray bind_array;
2779 std::string const user_context_str(user_context->str());
2780 bind_array.add(user_context_str);
2781
2782 // Execute the select.
2783 PgSqlResult r(PQexecPrepared(ctx->conn_,
2784 tagged_statements[stindex].name,
2785 tagged_statements[stindex].nbparams,
2786 &bind_array.values_[0],
2787 &bind_array.lengths_[0],
2788 &bind_array.formats_[0], 0));
2789 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2790
2791 std::string limits;
2792 PgSqlExchange::getColumnValue(r, 0, 0, limits);
2793 return limits;
2794}
2795
2796string
2798 return checkLimits(user_context, CHECK_LEASE4_LIMITS);
2799}
2800
2801string
2803 return checkLimits(user_context, CHECK_LEASE6_LIMITS);
2804}
2805
2806bool
2808 // Get a context.
2809 PgSqlLeaseContextAlloc get_context(*this);
2810 PgSqlLeaseContextPtr ctx(get_context.ctx_);
2811
2812 // Execute the select.
2813 StatementIndex const stindex(IS_JSON_SUPPORTED);
2814 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
2815 0, 0, 0, 0, 0));
2816 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2817
2818 bool json_supported;
2819 PgSqlExchange::getColumnValue(r, 0, 0, json_supported);
2820 return json_supported;
2821}
2822
2823size_t
2825 const Lease::Type& ltype /* = Lease::TYPE_V4*/) const {
2826 // Get a context.
2827 PgSqlLeaseContextAlloc get_context(*this);
2828 PgSqlLeaseContextPtr ctx(get_context.ctx_);
2829
2830 // Create bindings.
2831 PsqlBindArray bind_array;
2832 bind_array.add(client_class);
2833 if (ltype != Lease::TYPE_V4) {
2834 bind_array.add(ltype);
2835 }
2836
2837 // Execute the select.
2840 PgSqlResult r(PQexecPrepared(ctx->conn_,
2841 tagged_statements[stindex].name,
2842 tagged_statements[stindex].nbparams,
2843 &bind_array.values_[0],
2844 &bind_array.lengths_[0],
2845 &bind_array.formats_[0], 0));
2846 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
2847
2848 int rows = PQntuples(r);
2849 if (rows == 0) {
2850 // No entries means 0 leases.
2851 return 0;
2852 }
2853
2854 size_t count;
2855 PgSqlExchange::getColumnValue(r, 0, 0, count);
2856 return count;
2857}
2858
2859void
2861 isc_throw(NotImplemented, "PgSqlLeaseMgr::recountClassLeases4() not implemented");
2862}
2863
2864void
2866 isc_throw(NotImplemented, "PgSqlLeaseMgr::recountClassLeases6() not implemented");
2867}
2868
2869void
2871 isc_throw(NotImplemented, "PgSqlLeaseMgr::clearClassLeaseCounts() not implemented");
2872}
2873
2874void
2875PgSqlLeaseMgr::writeLeases4(const std::string&) {
2876 isc_throw(NotImplemented, "PgSqlLeaseMgr::writeLeases4() not implemented");
2877}
2878
2879void
2880PgSqlLeaseMgr::writeLeases6(const std::string&) {
2881 isc_throw(NotImplemented, "PgSqlLeaseMgr::writeLeases6() not implemented");
2882}
2883
2886 // Get a context
2887 PgSqlLeaseContextAlloc get_context(*this);
2888 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2889
2890 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2891 tagged_statements[ALL_LEASE4_STATS],
2892 false));
2893 query->start();
2894 return(query);
2895}
2896
2899 // Get a context
2900 PgSqlLeaseContextAlloc get_context(*this);
2901 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2902
2903 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2904 tagged_statements[ALL_POOL_LEASE4_STATS],
2905 false, true));
2906 query->start();
2907 return(query);
2908}
2909
2912 // Get a context
2913 PgSqlLeaseContextAlloc get_context(*this);
2914 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2915
2916 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2917 tagged_statements[SUBNET_LEASE4_STATS],
2918 false,
2919 subnet_id));
2920 query->start();
2921 return(query);
2922}
2923
2926 const SubnetID& last_subnet_id) {
2927 // Get a context
2928 PgSqlLeaseContextAlloc get_context(*this);
2929 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2930
2931 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2932 tagged_statements[SUBNET_RANGE_LEASE4_STATS],
2933 false,
2934 first_subnet_id,
2935 last_subnet_id));
2936 query->start();
2937 return(query);
2938}
2939
2942 // Get a context
2943 PgSqlLeaseContextAlloc get_context(*this);
2944 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2945
2946 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2947 tagged_statements[ALL_LEASE6_STATS],
2948 true));
2949 query->start();
2950 return(query);
2951}
2952
2955 // Get a context
2956 PgSqlLeaseContextAlloc get_context(*this);
2957 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2958
2959 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2960 tagged_statements[ALL_POOL_LEASE6_STATS],
2961 true, true));
2962 query->start();
2963 return(query);
2964}
2965
2968 // Get a context
2969 PgSqlLeaseContextAlloc get_context(*this);
2970 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2971
2972 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2973 tagged_statements[SUBNET_LEASE6_STATS],
2974 true,
2975 subnet_id));
2976 query->start();
2977 return(query);
2978}
2979
2982 const SubnetID& last_subnet_id) {
2983 // Get a context
2984 PgSqlLeaseContextAlloc get_context(*this);
2985 PgSqlLeaseContextPtr ctx = get_context.ctx_;
2986
2987 LeaseStatsQueryPtr query(new PgSqlLeaseStatsQuery(ctx->conn_,
2988 tagged_statements[SUBNET_RANGE_LEASE6_STATS],
2989 true,
2990 first_subnet_id,
2991 last_subnet_id));
2992 query->start();
2993 return(query);
2994}
2995
2996size_t
2998 isc_throw(NotImplemented, "wipeLeases4 is not implemented for PostgreSQL backend");
2999}
3000
3001size_t
3003 isc_throw(NotImplemented, "wipeLeases6 is not implemented for PostgreSQL backend");
3004}
3005
3006std::string
3008 // Get a context
3009 PgSqlLeaseContextAlloc get_context(*this);
3010 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3011
3012 std::string name = "";
3013 try {
3014 name = ctx->conn_.getParameter("name");
3015 } catch (...) {
3016 // Return an empty name
3017 }
3018 return (name);
3019}
3020
3021std::string
3023 return (std::string("PostgreSQL Database"));
3024}
3025
3026std::pair<uint32_t, uint32_t>
3027PgSqlLeaseMgr::getVersion(const string& timer_name) const {
3029
3032
3033 return (PgSqlConnection::getVersion(parameters_, ac, cb, timer_name));
3034}
3035
3036void
3039}
3040
3041void
3044}
3045
3046void
3048 deleteRelayId6(addr);
3049 deleteRemoteId6(addr);
3050}
3051
3052void
3053PgSqlLeaseMgr::deleteRelayId6(const IOAddress& addr) {
3054 // Set up the WHERE clause value.
3055 PsqlBindArray bind_array;
3056
3057 std::string addr_data = addr.toText();
3058 bind_array.add(addr_data);
3059
3060 // Get a context.
3061 PgSqlLeaseContextAlloc get_context(*this);
3062 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3063
3064 // Delete from lease6_relay_id table.
3066
3067 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
3068 tagged_statements[stindex].nbparams,
3069 &bind_array.values_[0],
3070 &bind_array.lengths_[0],
3071 &bind_array.formats_[0], 0));
3072
3073 int s = PQresultStatus(r);
3074
3075 if (s != PGRES_COMMAND_OK) {
3076 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
3077 }
3078}
3079
3080void
3081PgSqlLeaseMgr::deleteRemoteId6(const IOAddress& addr) {
3082 // Set up the WHERE clause value.
3083 PsqlBindArray bind_array;
3084
3085 std::string addr_data = addr.toText();
3086 bind_array.add(addr_data);
3087
3088 // Get a context.
3089 PgSqlLeaseContextAlloc get_context(*this);
3090 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3091
3092 // Delete from lease6_remote_id table.
3094
3095 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
3096 tagged_statements[stindex].nbparams,
3097 &bind_array.values_[0],
3098 &bind_array.lengths_[0],
3099 &bind_array.formats_[0], 0));
3100
3101 int s = PQresultStatus(r);
3102
3103 if (s != PGRES_COMMAND_OK) {
3104 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
3105 }
3106}
3107
3108void
3110 const vector<uint8_t>& relay_id) {
3111 // Set up the WHERE clause value.
3112 PsqlBindArray bind_array;
3113
3114 // Bind the relay id.
3115 if (relay_id.empty()) {
3116 isc_throw(BadValue, "empty relay id");
3117 }
3118 bind_array.add(relay_id);
3119
3120 // Bind the lease address.
3121 std::string lease_addr_data = lease_addr.toText();
3122 bind_array.add(lease_addr_data);
3123
3124 // Get a context.
3125 PgSqlLeaseContextAlloc get_context(*this);
3126 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3127
3128 // Add to lease6_remote_id table.
3129 StatementIndex stindex = ADD_RELAY_ID6;
3130
3131 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
3132 tagged_statements[stindex].nbparams,
3133 &bind_array.values_[0],
3134 &bind_array.lengths_[0],
3135 &bind_array.formats_[0], 0));
3136
3137 int s = PQresultStatus(r);
3138
3139 if (s != PGRES_COMMAND_OK) {
3140 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
3141 }
3142}
3143
3144void
3146 const vector<uint8_t>& remote_id) {
3147 // Set up the WHERE clause value.
3148 PsqlBindArray bind_array;
3149
3150 // Bind the remote id.
3151 if (remote_id.empty()) {
3152 isc_throw(BadValue, "empty remote id");
3153 }
3154 bind_array.add(remote_id);
3155
3156 // Bind the lease address.
3157 std::string lease_addr_data = lease_addr.toText();
3158 bind_array.add(lease_addr_data);
3159
3160 // Get a context.
3161 PgSqlLeaseContextAlloc get_context(*this);
3162 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3163
3164 // Add to lease6_remote_id table.
3166
3167 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
3168 tagged_statements[stindex].nbparams,
3169 &bind_array.values_[0],
3170 &bind_array.lengths_[0],
3171 &bind_array.formats_[0], 0));
3172
3173 int s = PQresultStatus(r);
3174
3175 if (s != PGRES_COMMAND_OK) {
3176 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
3177 }
3178}
3179
3180namespace {
3181
3182std::string
3183idToText(const OptionBuffer& id) {
3184 std::stringstream tmp;
3185 tmp << std::hex;
3186 bool delim = false;
3187 for (auto const& it : id) {
3188 if (delim) {
3189 tmp << ":";
3190 }
3191 tmp << std::setw(2) << std::setfill('0')
3192 << static_cast<unsigned int>(it);
3193 delim = true;
3194 }
3195 return (tmp.str());
3196}
3197
3198} // anonymous namespace
3199
3202 const IOAddress& lower_bound_address,
3203 const LeasePageSize& page_size,
3204 const time_t& qry_start_time /* = 0 */,
3205 const time_t& qry_end_time /* = 0 */) {
3206 // Expecting IPv4 address.
3207 if (!lower_bound_address.isV4()) {
3208 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
3209 "retrieving leases from the lease database, got "
3210 << lower_bound_address);
3211 }
3212
3213 // Catch 2038 bug with 32 bit time_t.
3214 if ((qry_start_time < 0) || (qry_end_time < 0)) {
3215 isc_throw(BadValue, "negative time value");
3216 }
3217
3218 bool have_qst = (qry_start_time > 0);
3219 bool have_qet = (qry_end_time > 0);
3220
3221 // Start time must be before end time.
3222 if (have_qst && have_qet && (qry_start_time > qry_end_time)) {
3223 isc_throw(BadValue, "start time must be before end time");
3224 }
3225
3228 .arg(page_size.page_size_)
3229 .arg(lower_bound_address.toText())
3230 .arg(idToText(relay_id))
3231 .arg(qry_start_time)
3232 .arg(qry_end_time);
3233
3234 // Prepare WHERE clause
3235 PsqlBindArray bind_array;
3236
3237 // Bind relay id
3238 if (!relay_id.empty()) {
3239 bind_array.add(relay_id);
3240 } else {
3241 bind_array.add("");
3242 }
3243
3244 // Bind lower bound address
3245 std::string lb_address_data =
3246 boost::lexical_cast<std::string>(lower_bound_address.toUint32());
3247 bind_array.add(lb_address_data);
3248
3249 // Bind query start time.
3250 std::string start_time_str;
3251 if (have_qst) {
3252 start_time_str = boost::lexical_cast<std::string>(qry_start_time);
3253 bind_array.add(start_time_str);
3254 }
3255
3256 // Bind query end time.
3257 std::string end_time_str;
3258 if (have_qet) {
3259 end_time_str = boost::lexical_cast<std::string>(qry_end_time);
3260 bind_array.add(end_time_str);
3261 }
3262
3263 // Bind page size value
3264 std::string page_size_data =
3265 boost::lexical_cast<std::string>(page_size.page_size_);
3266 bind_array.add(page_size_data);
3267
3269 if (have_qst && !have_qet) {
3270 stindex = GET_LEASE4_RELAYID_QST;
3271 } else if (have_qst && have_qet) {
3272 stindex = GET_LEASE4_RELAYID_QSET;
3273 } else if (!have_qst && have_qet) {
3274 stindex = GET_LEASE4_RELAYID_QET;
3275 }
3276
3277 // Get the leases
3278 Lease4Collection result;
3279
3280 // Get a context
3281 PgSqlLeaseContextAlloc get_context(*this);
3282 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3283
3284 getLeaseCollection(ctx, stindex, bind_array, result);
3285
3286 return (result);
3287}
3288
3291 const IOAddress& lower_bound_address,
3292 const LeasePageSize& page_size,
3293 const time_t& qry_start_time /* = 0 */,
3294 const time_t& qry_end_time /* = 0 */) {
3295 // Expecting IPv4 address.
3296 if (!lower_bound_address.isV4()) {
3297 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
3298 "retrieving leases from the lease database, got "
3299 << lower_bound_address);
3300 }
3301
3302 // Catch 2038 bug with 32 bit time_t.
3303 if ((qry_start_time < 0) || (qry_end_time < 0)) {
3304 isc_throw(BadValue, "negative time value");
3305 }
3306
3307 bool have_qst = (qry_start_time > 0);
3308 bool have_qet = (qry_end_time > 0);
3309
3310 // Start time must be before end time.
3311 if (have_qst && have_qet && (qry_start_time > qry_end_time)) {
3312 isc_throw(BadValue, "start time must be before end time");
3313 }
3314
3317 .arg(page_size.page_size_)
3318 .arg(lower_bound_address.toText())
3319 .arg(idToText(remote_id))
3320 .arg(qry_start_time)
3321 .arg(qry_end_time);
3322
3323 // Prepare WHERE clause
3324 PsqlBindArray bind_array;
3325
3326 // Bind remote id
3327 if (!remote_id.empty()) {
3328 bind_array.add(remote_id);
3329 } else {
3330 bind_array.add("");
3331 }
3332
3333 // Bind lower bound address
3334 std::string lb_address_data =
3335 boost::lexical_cast<std::string>(lower_bound_address.toUint32());
3336 bind_array.add(lb_address_data);
3337
3338 // Bind query start time.
3339 std::string start_time_str;
3340 if (have_qst) {
3341 start_time_str = boost::lexical_cast<std::string>(qry_start_time);
3342 bind_array.add(start_time_str);
3343 }
3344
3345 // Bind query end time.
3346 std::string end_time_str;
3347 if (have_qet) {
3348 end_time_str = boost::lexical_cast<std::string>(qry_end_time);
3349 bind_array.add(end_time_str);
3350 }
3351
3352 // Bind page size value
3353 std::string page_size_data =
3354 boost::lexical_cast<std::string>(page_size.page_size_);
3355 bind_array.add(page_size_data);
3356
3358 if (have_qst && !have_qet) {
3359 stindex = GET_LEASE4_REMOTEID_QST;
3360 } else if (have_qst && have_qet) {
3361 stindex = GET_LEASE4_REMOTEID_QSET;
3362 } else if (!have_qst && have_qet) {
3363 stindex = GET_LEASE4_REMOTEID_QET;
3364 }
3365
3366 // Get the leases
3367 Lease4Collection result;
3368
3369 // Get a context
3370 PgSqlLeaseContextAlloc get_context(*this);
3371 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3372
3373 getLeaseCollection(ctx, stindex, bind_array, result);
3374
3375 return (result);
3376}
3377
3378size_t
3380 auto check = CfgMgr::instance().getCurrentCfg()->
3381 getConsistency()->getExtendedInfoSanityCheck();
3382
3383 size_t pages = 0;
3384 size_t updated = 0;
3386 for (;;) {
3389 .arg(pages)
3390 .arg(start_addr.toText())
3391 .arg(updated);
3392
3393 // Prepare WHERE clause.
3394 PsqlBindArray bind_array;
3395
3396 // Bind start address.
3397 uint32_t start_addr_data = start_addr.toUint32();
3398 bind_array.add(start_addr_data);
3399
3400 // Bind page size value.
3401 std::string page_size_data =
3402 boost::lexical_cast<std::string>(page_size.page_size_);
3403 bind_array.add(page_size_data);
3404
3405 Lease4Collection leases;
3406
3407 // Get a context.
3408 {
3409 PgSqlLeaseContextAlloc get_context(*this);
3410 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3411
3412 getLeaseCollection(ctx, GET_LEASE4_UCTX_PAGE, bind_array, leases);
3413 }
3414
3415 if (leases.empty()) {
3416 // Done.
3417 break;
3418 }
3419
3420 ++pages;
3421 start_addr = leases.back()->addr_;
3422 for (auto const& lease : leases) {
3423 ConstElementPtr previous_user_context = lease->getContext();
3424 vector<uint8_t> previous_relay_id = lease->relay_id_;
3425 vector<uint8_t> previous_remote_id = lease->remote_id_;
3426 if (!previous_user_context &&
3427 previous_relay_id.empty() &&
3428 previous_remote_id.empty()) {
3429 continue;
3430 }
3431 bool modified = upgradeLease4ExtendedInfo(lease, check);
3432 try {
3433 lease->relay_id_.clear();
3434 lease->remote_id_.clear();
3435 extractLease4ExtendedInfo(lease, false);
3436 if (modified ||
3437 (previous_relay_id != lease->relay_id_) ||
3438 (previous_remote_id != lease->remote_id_)) {
3439 updateLease4(lease);
3440 ++updated;
3441 }
3442 } catch (const NoSuchLease&) {
3443 // The lease was modified in parallel:
3444 // as its extended info was processed just ignore.
3445 continue;
3446 } catch (const std::exception& ex) {
3447 // Something when wrong, for instance extract failed.
3450 .arg(lease->addr_.toText())
3451 .arg(ex.what());
3452 }
3453 }
3454 }
3455
3457 .arg(pages)
3458 .arg(updated);
3459
3460 return (updated);
3461}
3462
3465 const IOAddress& lower_bound_address,
3466 const LeasePageSize& page_size) {
3469 .arg(page_size.page_size_)
3470 .arg(lower_bound_address.toText())
3471 .arg(relay_id.toText());
3472
3473 // Expecting IPv6 valid address.
3474 if (!lower_bound_address.isV6()) {
3475 isc_throw(InvalidAddressFamily, "expected IPv6 start address while "
3476 "retrieving leases from the lease database, got "
3477 << lower_bound_address);
3478 }
3479
3480 std::vector<uint8_t> relay_id_data = relay_id.getDuid();
3481 if (relay_id_data.size() == 0) {
3482 isc_throw(BadValue, "empty relay id");
3483 }
3484
3485 // Set up the WHERE clause value.
3486 PsqlBindArray bind_array;
3487
3488 // Bind the relay id.
3489 bind_array.add(relay_id_data);
3490
3491 // Bind the lower bound address.
3492 std::string lb_addr_data = lower_bound_address.toText();
3493 bind_array.add(lb_addr_data);
3494
3495 // Bind page size value.
3496 std::string page_size_data =
3497 boost::lexical_cast<std::string>(page_size.page_size_);
3498 bind_array.add(page_size_data);
3499
3500 // Get a context.
3501 PgSqlLeaseContextAlloc get_context(*this);
3502 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3503 Lease6Collection result;
3504
3505 getLeaseCollection(ctx, GET_RELAY_ID6, bind_array, result);
3506 return (result);
3507}
3508
3511 const IOAddress& lower_bound_address,
3512 const LeasePageSize& page_size) {
3515 .arg(page_size.page_size_)
3516 .arg(lower_bound_address.toText())
3517 .arg(idToText(remote_id));
3518
3519 // Expecting IPv6 valid address.
3520 if (!lower_bound_address.isV6()) {
3521 isc_throw(InvalidAddressFamily, "expected IPv6 start address while "
3522 "retrieving leases from the lease database, got "
3523 << lower_bound_address);
3524 }
3525
3526 if (remote_id.size() == 0) {
3527 isc_throw(BadValue, "empty remote id");
3528 }
3529
3530 // Set up the WHERE clause value.
3531 PsqlBindArray bind_array;
3532
3533 // Bind the remote id.
3534 bind_array.add(remote_id);
3535
3536 // Bind the lower bound address.
3537 std::string lb_addr_data = lower_bound_address.toText();
3538 bind_array.add(lb_addr_data);
3539
3540 // Bind page size value.
3541 std::string page_size_data =
3542 boost::lexical_cast<std::string>(page_size.page_size_);
3543 bind_array.add(page_size_data);
3544
3545 // Get a context.
3546 PgSqlLeaseContextAlloc get_context(*this);
3547 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3548 Lease6Collection result;
3549
3550 getLeaseCollection(ctx, GET_REMOTE_ID6, bind_array, result);
3551 return (result);
3552}
3553
3554size_t
3556 auto check = CfgMgr::instance().getCurrentCfg()->
3557 getConsistency()->getExtendedInfoSanityCheck();
3558
3559 // First step is to wipe tables if enabled.
3562 }
3563
3564 size_t pages = 0;
3565 size_t updated = 0;
3567 for (;;) {
3570 .arg(pages)
3571 .arg(start_addr.toText())
3572 .arg(updated);
3573
3574 // Prepare WHERE clause.
3575 PsqlBindArray bind_array;
3576
3577 // Bind start address.
3578 std::string start_addr_str = start_addr.toText();
3579 bind_array.add(start_addr_str);
3580
3581 // Bind page size value.
3582 std::string page_size_data =
3583 boost::lexical_cast<std::string>(page_size.page_size_);
3584 bind_array.add(page_size_data);
3585
3586 Lease6Collection leases;
3587
3588 // Get a context.
3589 {
3590 PgSqlLeaseContextAlloc get_context(*this);
3591 PgSqlLeaseContextPtr ctx = get_context.ctx_;
3592
3593 getLeaseCollection(ctx, GET_LEASE6_UCTX_PAGE, bind_array, leases);
3594 }
3595
3596 if (leases.empty()) {
3597 // Done.
3598 break;
3599 }
3600
3601 ++pages;
3602 start_addr = leases.back()->addr_;
3603 for (auto const& lease : leases) {
3604 try {
3605 bool modified = upgradeLease6ExtendedInfo(lease, check);
3606 if (modified) {
3607 updateLease6(lease);
3608 }
3609 bool added = (getExtendedInfoTablesEnabled() &&
3610 addExtendedInfo6(lease));
3611 if (modified || added) {
3612 ++updated;
3613 }
3614 } catch (const NoSuchLease&) {
3615 // The lease was modified in parallel:
3616 // as its extended info was processed just ignore.
3617 continue;
3618 } catch (const std::exception& ex) {
3619 // Something when wrong, for instance extract failed.
3622 .arg(lease->addr_.toText())
3623 .arg(ex.what());
3624 }
3625 }
3626 }
3627
3629 .arg(pages)
3630 .arg(updated);
3631
3632 return (updated);
3633}
3634
3635void
3637 // Get a context.
3638 PgSqlLeaseContextAlloc get_context(*this);
3639 PgSqlLeaseContextPtr ctx(get_context.ctx_);
3640
3641 // Execute WIPE_RELAY_ID6.
3642 StatementIndex const stindex1 = WIPE_RELAY_ID6;
3643 PgSqlResult r1(PQexecPrepared(ctx->conn_, tagged_statements[stindex1].name,
3644 0, 0, 0, 0, 0));
3645 ctx->conn_.checkStatementError(r1, tagged_statements[stindex1]);
3646
3647 // Execute WIPE_REMOTE_ID6.
3648 StatementIndex const stindex2 = WIPE_REMOTE_ID6;
3649 PgSqlResult r2(PQexecPrepared(ctx->conn_, tagged_statements[stindex2].name,
3650 0, 0, 0, 0, 0));
3651 ctx->conn_.checkStatementError(r2, tagged_statements[stindex2]);
3652}
3653
3654size_t
3656 // Get a context.
3657 PgSqlLeaseContextAlloc get_context(*this);
3658 PgSqlLeaseContextPtr ctx(get_context.ctx_);
3659
3660 // Execute COUNT_RELAY_ID6.
3662 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
3663 0, 0, 0, 0, 0));
3664 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
3665 uint64_t count;
3666 PgSqlExchange::getColumnValue(r, 0, 0, count);
3667 return (static_cast<size_t>(count));
3668}
3669
3670size_t
3672 // Get a context.
3673 PgSqlLeaseContextAlloc get_context(*this);
3674 PgSqlLeaseContextPtr ctx(get_context.ctx_);
3675
3676 // Execute COUNT_REMOTE_ID6.
3678 PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
3679 0, 0, 0, 0, 0));
3680 ctx->conn_.checkStatementError(r, tagged_statements[stindex]);
3681 uint64_t count;
3682 PgSqlExchange::getColumnValue(r, 0, 0, count);
3683 return (static_cast<size_t>(count));
3684}
3685
3686} // namespace dhcp
3687} // 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 void ensureSchemaVersion(const ParameterMap &parameters, const DbCallback &cb=DbCallback(), const std::string &timer_name=std::string())
Retrieve schema version, validate it against the hardcoded version, and attempt to initialize the sch...
static std::pair< uint32_t, uint32_t > getVersion(const ParameterMap &parameters, const IOServiceAccessorPtr &ac=IOServiceAccessorPtr(), const DbCallback &cb=DbCallback(), const std::string &timer_name=std::string())
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:222
static constexpr size_t MAX_CLIENT_ID_LEN
Maximum size of a client ID.
Definition: duid.h:235
const std::vector< uint8_t > & getClientId() const
Returns reference to the client-id data.
Definition: duid.cc:69
Holds DUID (DHCPv6 Unique Identifier)
Definition: duid.h:142
static constexpr size_t MAX_DUID_LEN
maximum duid size
Definition: duid.h:155
const std::vector< uint8_t > & getDuid() const
Returns a const reference to the actual DUID value.
Definition: duid.cc:33
std::string toText() const
Returns textual representation of the identifier (e.g.
Definition: duid.h:88
static void recreate(const std::string &dbaccess, bool preserve_callbacks=true)
Recreate an instance of a lease manager with optionally preserving registered callbacks.
void setExtendedInfoTablesEnabled(const bool enabled)
Modifies the setting whether the lease6 extended info tables are enabled.
Definition: lease_mgr.h:1018
static bool upgradeLease6ExtendedInfo(const Lease6Ptr &lease, CfgConsistency::ExtendedInfoSanity check=CfgConsistency::EXTENDED_INFO_CHECK_FIX)
Upgrade a V6 lease user context to the new extended info entry.
Definition: lease_mgr.cc:767
bool getExtendedInfoTablesEnabled() const
Returns the setting indicating if lease6 extended info tables are enabled.
Definition: lease_mgr.h:1010
static void extractLease4ExtendedInfo(const Lease4Ptr &lease, bool ignore_errors=true)
Extract relay and remote identifiers from the extended info.
Definition: lease_mgr.cc:1119
static bool upgradeLease4ExtendedInfo(const Lease4Ptr &lease, CfgConsistency::ExtendedInfoSanity check=CfgConsistency::EXTENDED_INFO_CHECK_FIX)
The following queries are used to fulfill Bulk Lease Query queries.
Definition: lease_mgr.cc:535
virtual bool addExtendedInfo6(const Lease6Ptr &lease)
Extract extended info from a lease6 and add it into tables.
Definition: lease_mgr.cc:1205
Wraps value holding size of the page with leases.
Definition: lease_mgr.h:46
const size_t page_size_
Holds page size.
Definition: lease_mgr.h:56
Base class for fulfilling a statistical lease data query.
Definition: lease_mgr.h:149
SubnetID 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:136
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:505
const isc::log::MessageID DHCPSRV_PGSQL_GET_HOSTNAME6
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:670
boost::shared_ptr< LeaseStatsQuery > LeaseStatsQueryPtr
Defines a pointer to a LeaseStatsQuery.
Definition: lease_mgr.h:233
const isc::log::MessageID DHCPSRV_PGSQL_GET_IAID_SUBID_DUID
const isc::log::MessageID DHCPSRV_PGSQL_GET_ADDR4
const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO6
const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO6_ERROR
const isc::log::MessageID DHCPSRV_PGSQL_GET_HOSTNAME4
const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition: hwaddr.h:154
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition: dhcpsrv_log.h:38
const isc::log::MessageID DHCPSRV_PGSQL_ROLLBACK
const isc::log::MessageID DHCPSRV_PGSQL_GET_HWADDR
const isc::log::MessageID DHCPSRV_PGSQL_NO_TLS_SUPPORT
const isc::log::MessageID DHCPSRV_PGSQL_GET_PAGE6
const isc::log::MessageID DHCPSRV_PGSQL_DELETE_EXPIRED_RECLAIMED4
const isc::log::MessageID DHCPSRV_PGSQL_UPDATE_ADDR4
const isc::log::MessageID DHCPSRV_PGSQL_GET_SUBID_HWADDR
const isc::log::MessageID DHCPSRV_PGSQL_GET_VERSION
const isc::log::MessageID DHCPSRV_PGSQL_GET_REMOTEID4
const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_PAGE
const isc::log::MessageID DHCPSRV_PGSQL_LEASE_DB_RECONNECT_ATTEMPT_FAILED
const isc::log::MessageID DHCPSRV_PGSQL_TLS_SUPPORT
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:25
boost::shared_ptr< Lease > LeasePtr
Pointer to the lease object.
Definition: lease.h:25
const isc::log::MessageID DHCPSRV_PGSQL_GET4
const isc::log::MessageID DHCPSRV_PGSQL_ADD_ADDR6
const isc::log::MessageID DHCPSRV_PGSQL_GET_CLIENTID
const isc::log::MessageID DHCPSRV_PGSQL_GET_RELAYID6
const isc::log::MessageID DHCPSRV_PGSQL_GET_IAID_DUID
const isc::log::MessageID DHCPSRV_PGSQL_UPDATE_ADDR6
const isc::log::MessageID DHCPSRV_PGSQL_GET_RELAYID4
boost::shared_ptr< PgSqlLeaseContext > PgSqlLeaseContextPtr
Type of pointers to contexts.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
const isc::log::MessageID DHCPSRV_PGSQL_LEASE_DB_RECONNECT_FAILED
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition: lease.h:497
const isc::log::MessageID DHCPSRV_PGSQL_UPGRADE_EXTENDED_INFO4_ERROR
@ HTYPE_UNDEFINED
not specified or undefined
Definition: dhcp4.h:55
@ HTYPE_ETHER
Ethernet 10Mbps.
Definition: dhcp4.h:56
const isc::log::MessageID DHCPSRV_PGSQL_NEGATIVE_LEASES_STAT
const isc::log::MessageID DHCPSRV_PGSQL_GET_EXPIRED4
const isc::log::MessageID DHCPSRV_PGSQL_GET_EXPIRED6
const isc::log::MessageID DHCPSRV_PGSQL_LEASE_DB_RECONNECT_ATTEMPT_SCHEDULE
const isc::log::MessageID DHCPSRV_PGSQL_DELETE_ADDR
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:292
const isc::log::MessageID DHCPSRV_PGSQL_COMMIT
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition: dhcpsrv_log.h:26
const isc::log::MessageID DHCPSRV_PGSQL_GET_SUBID_PAGE6
const isc::log::MessageID DHCPSRV_PGSQL_DELETE_EXPIRED_RECLAIMED6
PerfMonMgrPtr mgr
PerfMonMgr singleton.
boost::shared_ptr< ReconnectCtl > ReconnectCtlPtr
Pointer to an instance of ReconnectCtl.
Defines the logger used by the top-level component of kea-lfc.
Define a PostgreSQL statement.
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.