Kea  1.9.9-git
cql_lease_mgr.cc
Go to the documentation of this file.
1 // Copyright (C) 2016-2021 Internet Systems Consortium, Inc. ("ISC")
2 // Copyright (C) 2015-2018 Deutsche Telekom AG.
3 //
4 // Authors: Razvan Becheriu <razvan.becheriu@qualitance.com>
5 // Andrei Pavel <andrei.pavel@qualitance.com>
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 // http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 
19 #include <config.h>
20 
21 #include <dhcpsrv/cql_lease_mgr.h>
23 #include <dhcpsrv/dhcpsrv_log.h>
24 
25 #include <dhcp/duid.h>
26 #include <dhcp/hwaddr.h>
27 
28 #include <asiolink/io_address.h>
29 #include <boost/make_shared.hpp>
30 
31 using namespace isc::data;
32 using namespace isc::db;
33 using namespace isc::asiolink;
34 
35 namespace isc {
36 namespace dhcp {
37 
38 static constexpr size_t HOSTNAME_MAX_LEN = 255u;
39 static constexpr size_t ADDRESS6_TEXT_MAX_LEN = 39u;
40 static constexpr char NULL_USER_CONTEXT[] = "";
41 
48 class CqlLeaseExchange : public CqlExchange {
49 public:
50 
54  CqlLeaseExchange(const CqlConnection &connection)
55  : connection_(connection), valid_lifetime_(0), expire_(0),
56  current_expire_(0), subnet_id_(0), fqdn_fwd_(cass_false),
57  fqdn_rev_(cass_false), state_(0), user_context_(NULL_USER_CONTEXT) {
58  }
59 
67  virtual void
68  createBindForSelect(AnyArray &data, StatementTag statement_tag = NULL) override = 0;
69 
77  virtual boost::any retrieve() override = 0;
78 
79 protected:
80 
83 
86 
88  cass_int64_t valid_lifetime_;
89 
91  cass_int64_t expire_;
92 
94  cass_int64_t current_expire_;
95 
97  cass_int32_t subnet_id_;
98 
100  cass_bool_t fqdn_fwd_;
101 
103  cass_bool_t fqdn_rev_;
104 
106  std::string hostname_;
107 
109  cass_int32_t state_;
110 
112  std::string user_context_;
113 };
114 
128 public:
129 
137  explicit CqlLease4Exchange(const CqlConnection &connection);
138 
146  void createBindForInsert(const Lease4Ptr &lease, AnyArray &data);
147 
156  void createBindForUpdate(const Lease4Ptr &lease, AnyArray &data,
157  StatementTag statement_tag = NULL);
158 
167  void createBindForDelete(const Lease4Ptr &lease,
168  AnyArray &data,
169  StatementTag statement_tag = NULL);
170 
177  virtual void
178  createBindForSelect(AnyArray &data, StatementTag statement_tag = NULL) override;
179 
183  virtual boost::any retrieve() override;
184 
190  void getLeaseCollection(StatementTag &statement_tag, AnyArray &data,
191  Lease4Collection &result);
192 
198  void
199  getLease(StatementTag &statement_tag, AnyArray &data, Lease4Ptr &result);
200 
208  void getExpiredLeases(const size_t &max_leases, Lease4Collection &expired_leases);
209 
212 
215  // Add entry to lease4 table
216  static constexpr StatementTag INSERT_LEASE4 = "INSERT_LEASE4";
217  // Update a Lease4 entry
218  static constexpr StatementTag UPDATE_LEASE4 = "UPDATE_LEASE4";
219  // Delete from lease4 by address
220  static constexpr StatementTag DELETE_LEASE4 = "DELETE_LEASE4";
221  // Delete expired lease4s in certain state
222  static constexpr StatementTag GET_LEASE4_EXPIRE = "GET_LEASE4_EXPIRE";
223  // Get lease4
224  static constexpr StatementTag GET_LEASE4 = "GET_LEASE4";
225  // Get lease4 by address
226  static constexpr StatementTag GET_LEASE4_ADDR = "GET_LEASE4_ADDR";
227  // Get lease4 by client ID
228  static constexpr StatementTag GET_LEASE4_CLIENTID = "GET_LEASE4_CLIENTID";
229  // Get lease4 by client ID & subnet ID
230  static constexpr StatementTag GET_LEASE4_CLIENTID_SUBID = "GET_LEASE4_CLIENTID_SUBID";
231  // Get lease4 by HW address
232  static constexpr StatementTag GET_LEASE4_HWADDR = "GET_LEASE4_HWADDR";
233  // Get lease4 by HW address & subnet ID
234  static constexpr StatementTag GET_LEASE4_HWADDR_SUBID = "GET_LEASE4_HWADDR_SUBID";
235  // Get range of lease4 from first lease with a limit
236  static constexpr StatementTag GET_LEASE4_LIMIT = "GET_LEASE4_LIMIT";
237  // Get range of lease4 from address with limit (paging)
238  static constexpr StatementTag GET_LEASE4_PAGE = "GET_LEASE4_PAGE";
239  // Get lease4 by subnet ID
240  static constexpr StatementTag GET_LEASE4_SUBID = "GET_LEASE4_SUBID";
241  // Get lease4 by hostname
242  static constexpr StatementTag GET_LEASE4_HOSTNAME = "GET_LEASE4_HOSTNAME";
244 
245 private:
246 
247  // Pointer to lease object
248  Lease4Ptr lease_;
249  // IPv4 address
250  cass_int32_t address_;
251  // Client identification
252  CassBlob client_id_;
253 }; // CqlLease4Exchange
254 
255 constexpr StatementTag CqlLease4Exchange::INSERT_LEASE4;
256 constexpr StatementTag CqlLease4Exchange::UPDATE_LEASE4;
257 constexpr StatementTag CqlLease4Exchange::DELETE_LEASE4;
258 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_EXPIRE;
259 constexpr StatementTag CqlLease4Exchange::GET_LEASE4;
260 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_ADDR;
261 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_CLIENTID;
262 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_CLIENTID_SUBID;
263 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_HWADDR;
264 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_HWADDR_SUBID;
265 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_LIMIT;
266 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_PAGE;
267 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_SUBID;
268 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_HOSTNAME;
269 
270 StatementMap CqlLease4Exchange::tagged_statements_{
271 
272  // Inserts new IPv4 lease
273  {INSERT_LEASE4,
274  {INSERT_LEASE4,
275  "INSERT INTO lease4( "
276  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
277  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
278  ") VALUES ( "
279  "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? "
280  ") "
281  "IF NOT EXISTS "
282  }},
283 
284  // Updates existing IPv4 lease
285  {UPDATE_LEASE4,
286  {UPDATE_LEASE4,
287  "UPDATE lease4 SET "
288  "hwaddr = ?, "
289  "client_id = ?, "
290  "subnet_id = ?, "
291  "valid_lifetime = ?, "
292  "expire = ?, "
293  "fqdn_fwd = ?, "
294  "fqdn_rev = ?, "
295  "hostname = ?, "
296  "state = ?, "
297  "user_context = ? "
298  "WHERE address = ? "
299  "IF expire = ? "
300  }},
301 
302  // Deletes existing IPv4 lease
303  {DELETE_LEASE4,
304  {DELETE_LEASE4,
305  "DELETE FROM lease4 "
306  "WHERE address = ? "
307  "IF expire = ? "
308  }},
309 
310  // Gets up to a certain number of expired IPv4 leases
311  {GET_LEASE4_EXPIRE,
312  {GET_LEASE4_EXPIRE,
313  "SELECT "
314  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
315  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
316  "FROM lease4 "
317  "WHERE state = ? "
318  "AND valid_lifetime < 4294967295 "
319  "AND expire < ? "
320  "LIMIT ? "
321  "ALLOW FILTERING "
322  }},
323 
324  // Gets an IPv4 lease(s)
325  {GET_LEASE4,
326  {GET_LEASE4,
327  "SELECT "
328  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
329  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
330  "FROM lease4 "
331  }},
332 
333  // Gets an IPv4 lease with specified IPv4 address
334  {GET_LEASE4_ADDR,
335  {GET_LEASE4_ADDR,
336  "SELECT "
337  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
338  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
339  "FROM lease4 "
340  "WHERE address = ? "
341  }},
342 
343  // Gets an IPv4 lease(s) with specified client-id
344  {GET_LEASE4_CLIENTID,
345  {GET_LEASE4_CLIENTID,
346  "SELECT "
347  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
348  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
349  "FROM lease4 "
350  "WHERE client_id = ? "
351  "ALLOW FILTERING "
352  }},
353 
354  // Gets an IPv4 lease with specified client-id and subnet-id
355  {GET_LEASE4_CLIENTID_SUBID,
356  {GET_LEASE4_CLIENTID_SUBID,
357  "SELECT "
358  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
359  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
360  "FROM lease4 "
361  "WHERE client_id = ? "
362  "AND subnet_id = ? "
363  "ALLOW FILTERING "
364  }},
365 
366  // Gets all IPv4 leases with specified hardware address
367  {GET_LEASE4_HWADDR,
368  {GET_LEASE4_HWADDR,
369  "SELECT "
370  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
371  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
372  "FROM lease4 "
373  "WHERE hwaddr = ? "
374  "ALLOW FILTERING "
375  }},
376 
377  // Gets an IPv4 lease with specified hardware addr and subnet-id
378  {GET_LEASE4_HWADDR_SUBID,
379  {GET_LEASE4_HWADDR_SUBID,
380  "SELECT "
381  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
382  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
383  "FROM lease4 "
384  "WHERE hwaddr = ? "
385  "AND subnet_id = ? "
386  "ALLOW FILTERING "
387  }},
388 
389  // Get range of lease4 from first lease with a limit (paging)
390  {GET_LEASE4_LIMIT,
391  {GET_LEASE4_LIMIT,
392  "SELECT "
393  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
394  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
395  "FROM lease4 "
396  "LIMIT ? "
397  "ALLOW FILTERING "
398  }},
399 
400  // Get range of lease4 from address with a limit (paging)
401  {GET_LEASE4_PAGE,
402  {GET_LEASE4_PAGE,
403  "SELECT "
404  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
405  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
406  "FROM lease4 "
407  "WHERE TOKEN(address) > TOKEN(?) "
408  "LIMIT ? "
409  "ALLOW FILTERING "
410  }},
411 
412  // Gets an IPv4 lease(s) with specified subnet-id
413  {GET_LEASE4_SUBID,
414  {GET_LEASE4_SUBID,
415  "SELECT "
416  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
417  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
418  "FROM lease4 "
419  "WHERE subnet_id = ? "
420  "ALLOW FILTERING "}},
421 
422  // Gets an IPv4 lease(s) with specified hostname
423  {GET_LEASE4_HOSTNAME,
424  {GET_LEASE4_HOSTNAME,
425  "SELECT "
426  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
427  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
428  "FROM lease4 "
429  "WHERE hostname = ? "
430  "ALLOW FILTERING "
431  }}
432 };
433 
434 CqlLease4Exchange::CqlLease4Exchange(const CqlConnection &connection)
435  : CqlLeaseExchange(connection), address_(0) {
436 }
437 
438 void
440  if (!lease) {
441  isc_throw(BadValue, "CqlLease4Exchange::createBindForInsert(): "
442  "Lease4 object is NULL");
443  }
444  // Store lease object to ensure it remains valid.
445  lease_ = lease;
446  // Set up the structures for the various components of the lease4
447  // structure.
448 
449  try {
450  // address: int
451  // The address in the Lease structure is an IOAddress object.
452  // Convert this to an integer for storage.
453  address_ = static_cast<cass_int32_t>(lease->addr_.toUint32());
454 
455  // hwaddr: blob
456  if (lease_->hwaddr_ && lease_->hwaddr_->hwaddr_.size() > 0) {
457  if (lease_->hwaddr_->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
459  "hardware address "
460  << lease_->hwaddr_->toText() << " of length "
461  << lease_->hwaddr_->hwaddr_.size()
462  << " exceeds maximum allowed length of "
464  }
465  hwaddr_ = lease_->hwaddr_->hwaddr_;
466  } else {
467  hwaddr_.clear();
468  }
469 
470  // client_id: blob
471  if (lease_->client_id_ && lease_->client_id_->getClientId().size() > 0) {
472  client_id_ = lease_->client_id_->getClientId();
473  } else {
474  client_id_.clear();
475  }
476 
477  // valid lifetime: bigint
478  valid_lifetime_ = static_cast<cass_int64_t>(lease_->valid_lft_);
479 
480  // expire: bigint
481  // The lease structure holds the client last transmission time
483  // For convenience for external tools, this is converted to lease
484  // expiry time (expire). The relationship is given by:
485  // expire = cltt_ + valid_lft_
486  CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
487  expire_);
488 
489  // subnet_id: int
490  subnet_id_ = static_cast<cass_int32_t>(lease_->subnet_id_);
491 
492  // fqdn_fwd: boolean
493  fqdn_fwd_ = lease_->fqdn_fwd_ ? cass_true : cass_false;
494 
495  // fqdn_rev: boolean
496  fqdn_rev_ = lease_->fqdn_rev_ ? cass_true : cass_false;
497 
498  // hostname: varchar
499  if (lease_->hostname_.size() > HOSTNAME_MAX_LEN) {
501  "hostname " << lease_->hostname_ << " of length "
502  << lease_->hostname_.size()
503  << " exceeds maximum allowed length of "
504  << HOSTNAME_MAX_LEN);
505  }
506  hostname_ = lease_->hostname_;
507 
508  // state: int
509  state_ = static_cast<cass_int32_t>(lease_->state_);
510 
511  // user_context: text
512  ConstElementPtr ctx = lease_->getContext();
513  if (ctx) {
514  user_context_ = ctx->str();
515  } else {
516  user_context_ = NULL_USER_CONTEXT;
517  }
518 
519  // Start with a fresh array.
520  data.clear();
521  data.add(&address_);
522  data.add(&hwaddr_);
523  data.add(&client_id_);
524  data.add(&valid_lifetime_);
525  data.add(&expire_);
526  data.add(&subnet_id_);
527  data.add(&fqdn_fwd_);
528  data.add(&fqdn_rev_);
529  data.add(&hostname_);
530  data.add(&state_);
531  data.add(&user_context_);
532 
533  } catch (const Exception &ex) {
534  isc_throw(DbOperationError, "CqlLease4Exchange::createBindForInsert(): "
535  "could not create bind array from Lease4: " << lease_->addr_.toText()
536  << ", reason: " << ex.what());
537  }
538 }
539 
540 void
542  StatementTag /* unused */) {
543  if (!lease) {
544  isc_throw(BadValue, "CqlLease4Exchange::createBindForUpdate(): "
545  "Lease4 object is NULL");
546  }
547  // Store lease object to ensure it remains valid.
548  lease_ = lease;
549  // Set up the structures for the various components of the lease4
550  // structure.
551 
552  try {
553  // address: int
554  // The address in the Lease structure is an IOAddress object.
555  // Convert this to an integer for storage.
556  address_ = static_cast<cass_int32_t>(lease->addr_.toUint32());
557 
558  // hwaddr: blob
559  if (lease_->hwaddr_ && lease_->hwaddr_->hwaddr_.size() > 0) {
560  if (lease_->hwaddr_->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
562  "hardware address "
563  << lease_->hwaddr_->toText() << " of length "
564  << lease_->hwaddr_->hwaddr_.size()
565  << " exceeds maximum allowed length of "
567  }
568  hwaddr_ = lease_->hwaddr_->hwaddr_;
569  } else {
570  hwaddr_.clear();
571  }
572 
573  // client_id: blob
574  if (lease_->client_id_ && lease_->client_id_->getClientId().size() > 0) {
575  client_id_ = lease_->client_id_->getClientId();
576  } else {
577  client_id_.clear();
578  }
579 
580  // valid lifetime: bigint
581  valid_lifetime_ = static_cast<cass_int64_t>(lease_->valid_lft_);
582 
583  // expire: bigint
584  // The lease structure holds the client last transmission time
586  // For convenience for external tools, this is converted to lease
587  // expiry time (expire). The relationship is given by:
588  // expire = cltt_ + valid_lft_
589  CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
590  expire_);
591 
592  // subnet_id: int
593  subnet_id_ = static_cast<cass_int32_t>(lease_->subnet_id_);
594 
595  // fqdn_fwd: boolean
596  fqdn_fwd_ = lease_->fqdn_fwd_ ? cass_true : cass_false;
597 
598  // fqdn_rev: boolean
599  fqdn_rev_ = lease_->fqdn_rev_ ? cass_true : cass_false;
600 
601  // hostname: varchar
602  if (lease_->hostname_.size() > HOSTNAME_MAX_LEN) {
604  "hostname " << lease_->hostname_ << " of length "
605  << lease_->hostname_.size()
606  << " exceeds maximum allowed length of "
607  << HOSTNAME_MAX_LEN);
608  }
609  hostname_ = lease_->hostname_;
610 
611  // state: int
612  state_ = static_cast<cass_int32_t>(lease_->state_);
613 
614  // user_context: text
615  ConstElementPtr ctx = lease_->getContext();
616  if (ctx) {
617  user_context_ = ctx->str();
618  } else {
619  user_context_ = NULL_USER_CONTEXT;
620  }
621 
622  // Start with a fresh array.
623  data.clear();
624  data.add(&hwaddr_);
625  data.add(&client_id_);
626  data.add(&subnet_id_);
627  data.add(&valid_lifetime_);
628  data.add(&expire_);
629  data.add(&fqdn_fwd_);
630  data.add(&fqdn_rev_);
631  data.add(&hostname_);
632  data.add(&state_);
633  data.add(&user_context_);
634  data.add(&address_);
635 
636  CqlExchange::convertToDatabaseTime(lease_->current_cltt_,
637  lease_->current_valid_lft_,
639  data.add(&current_expire_);
640  } catch (const Exception &ex) {
642  "CqlLease4Exchange::createBindUpdate(): "
643  "could not create bind array from Lease4: "
644  << lease_->addr_.toText() << ", reason: " << ex.what());
645  }
646 }
647 
648 void
650  StatementTag /* unused */) {
651  if (!lease) {
652  isc_throw(BadValue, "CqlLease4Exchange::createBindForDelete(): "
653  "Lease4 object is NULL");
654  }
655  // Store lease object to ensure it remains valid.
656  lease_ = lease;
657 
658  // Set up the structures for the various components of the lease4
659  // structure.
660  try {
661  // address: int
662  address_ = static_cast<cass_int32_t>(lease_->addr_.toUint32());
663 
664  // Start with a fresh array.
665  data.clear();
666  data.add(&address_);
667 
668  CqlExchange::convertToDatabaseTime(lease_->current_cltt_,
669  lease_->current_valid_lft_,
671  data.add(&current_expire_);
672  } catch (const Exception &ex) {
674  "CqlLease4Exchange::createBindForDelete(): "
675  "could not create bind array from Lease4: "
676  << lease_->addr_.toText() << ", reason: " << ex.what());
677  }
678 }
679 
680 void
682  // Start with a fresh array.
683  data.clear();
684 
685  // address: blob
686  data.add(&address_);
687 
688  // hwaddr: blob
689  data.add(&hwaddr_);
690 
691  // client_id: blob
692  data.add(&client_id_);
693 
694  // valid_lifetime: bigint
695  data.add(&valid_lifetime_);
696 
697  // expire: bigint
698  data.add(&expire_);
699 
700  // subnet_id: int
701  data.add(&subnet_id_);
702 
703  // fqdn_fwd: boolean
704  data.add(&fqdn_fwd_);
705 
706  // fqdn_rev: boolean
707  data.add(&fqdn_rev_);
708 
709  // hostname: varchar
710  data.add(&hostname_);
711 
712  // state: int
713  data.add(&state_);
714 
715  // user_context: text
716  data.add(&user_context_);
717 }
718 
719 boost::any
721  try {
722  // Sanity checks
723  if (hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
725  "hardware address "
726  << HWAddr(hwaddr_, HTYPE_ETHER).toText()
727  << " of length " << hwaddr_.size()
728  << " exceeds maximum allowed length of "
730  }
731  if (client_id_.size() > ClientId::MAX_CLIENT_ID_LEN) {
733  "client ID " << ClientId(client_id_).toText()
734  << " of length " << client_id_.size()
735  << " exceeds maximum allowed length of "
737  }
738  if (hostname_.size() > HOSTNAME_MAX_LEN) {
740  "hostname" << hostname_ << " of length "
741  << hostname_.size()
742  << " exceeds maximum allowed length of "
743  << HOSTNAME_MAX_LEN);
744  }
745 
746  time_t cltt = 0;
748 
749  HWAddrPtr hwaddr = boost::make_shared<HWAddr>(hwaddr_, HTYPE_ETHER);
750 
751  uint32_t addr4 = static_cast<uint32_t>(address_);
752 
753  ConstElementPtr ctx;
754  if (!user_context_.empty()) {
755  ctx = Element::fromJSON(user_context_);
756  if (!ctx || (ctx->getType() != Element::map)) {
757  isc_throw(BadValue, "user context '" << user_context_
758  << "' is not a JSON map");
759  }
760  }
761 
762  Lease4Ptr result(boost::make_shared<Lease4>(addr4, hwaddr, client_id_.data(),
763  client_id_.size(), valid_lifetime_,
765  hostname_));
766 
767  result->state_ = state_;
768 
769  if (ctx) {
770  result->setContext(ctx);
771  }
772 
773  return (result);
774  } catch (const Exception &ex) {
776  "CqlLease4Exchange::retrieve(): "
777  "could not convert data to Lease4, reason: "
778  << ex.what());
779  }
780 }
781 
782 void
784  Lease4Collection &result) {
785  AnyArray collection = executeSelect(connection_, data, statement_tag);
786 
787  // Transfer Lease4 objects to result.
788  for (boost::any &element : collection) {
789  result.push_back(boost::any_cast<Lease4Ptr>(element));
790  }
791 }
792 
793 void
795  Lease4Ptr &result) {
796  // This particular method is called when only one or zero matches is
797  // expected.
798  Lease4Collection collection;
799  getLeaseCollection(statement_tag, data, collection);
800 
801  // Return single record if present, else clear the lease.
802  const size_t collection_size = collection.size();
803  if (collection_size >= 2u) {
805  "CqlLease4Exchange::getLease(): multiple records were found in "
806  "the database where only one was expected for statement "
807  << statement_tag);
808  } else if (collection_size == 0u) {
809  result.reset();
810  } else {
811  result = *collection.begin();
812  }
813 }
814 
815 void
816 CqlLease4Exchange::getExpiredLeases(const size_t &max_leases,
817  Lease4Collection &expired_leases) {
818  // Set up the WHERE clause value
819  cass_int32_t keep_state = Lease::STATE_EXPIRED_RECLAIMED;
820  cass_int64_t timestamp = static_cast<cass_int64_t>(time(NULL));
821 
822  // If the number of leases is 0, we will return all leases. This is
823  // achieved by setting the limit to a very high value.
824  cass_int32_t limit = max_leases > 0u ? static_cast<cass_int32_t>(max_leases) :
825  std::numeric_limits<cass_int32_t>::max();
826 
827  for (cass_int32_t state = Lease::STATE_DEFAULT;
828  state <= Lease::STATE_EXPIRED_RECLAIMED; ++state) {
829  if (state == keep_state) {
830  continue;
831  }
832 
833  AnyArray data;
834  data.add(&state);
835  data.add(&timestamp);
836  data.add(&limit);
837 
838  // Retrieve leases from the database.
839  Lease4Collection temp_collection;
840  getLeaseCollection(CqlLease4Exchange::GET_LEASE4_EXPIRE, data,
841  temp_collection);
842 
843  for (Lease4Ptr &lease : temp_collection) {
844  expired_leases.push_back(lease);
845  }
846  }
847 }
848 
862 public:
863 
871  explicit CqlLease6Exchange(const CqlConnection &connection);
872 
880  void createBindForInsert(const Lease6Ptr &lease, AnyArray &data);
881 
890  void createBindForUpdate(const Lease6Ptr &lease, AnyArray &data,
891  StatementTag statement_tag = NULL);
892 
901  void createBindForDelete(const Lease6Ptr &lease,
902  AnyArray &data,
903  StatementTag statement_tag = NULL);
904 
911  virtual void
912  createBindForSelect(AnyArray &data, StatementTag statement_tag = NULL) override;
913 
917  virtual boost::any retrieve() override;
918 
924  void getLeaseCollection(StatementTag &statement_tag, AnyArray &data,
925  Lease6Collection &result);
926 
932  void
933  getLease(StatementTag &statement_tag, AnyArray &data, Lease6Ptr &result);
934 
942  void getExpiredLeases(const size_t &max_leases, Lease6Collection &expired_leases);
943 
946 
949  static constexpr StatementTag INSERT_LEASE6 = "INSERT_LEASE6";
950  static constexpr StatementTag UPDATE_LEASE6 = "UPDATE_LEASE6";
951  static constexpr StatementTag DELETE_LEASE6 = "DELETE_LEASE6";
952  static constexpr StatementTag GET_LEASE6_EXPIRE = "GET_LEASE6_EXPIRE";
953  static constexpr StatementTag GET_LEASE6_ADDR = "GET_LEASE6_ADDR";
954  static constexpr StatementTag GET_LEASE6_DUID = "GET_LEASE6_DUID";
955  static constexpr StatementTag GET_LEASE6_DUID_IAID = "GET_LEASE6_DUID_IAID";
956  static constexpr StatementTag GET_LEASE6_DUID_IAID_SUBID = "GET_LEASE6_DUID_IAID_SUBID";
957  static constexpr StatementTag GET_LEASE6_LIMIT = "GET_LEASE6_LIMIT";
958  static constexpr StatementTag GET_LEASE6_PAGE = "GET_LEASE6_PAGE";
959  static constexpr StatementTag GET_LEASE6_HOSTNAME = "GET_LEASE6_HOSTNAME";
960  // @}
961 
962 private:
963 
965  Lease6Ptr lease_;
966 
968  std::string address_;
969 
971  cass_int64_t pref_lifetime_;
972 
974  CassBlob duid_;
975 
977  cass_int32_t iaid_;
978 
980  cass_int32_t lease_type_;
981 
983  cass_int32_t prefix_len_;
984 
986  cass_int32_t hwtype_;
987 
989  cass_int32_t hwaddr_source_;
990 }; // CqlLease6Exchange
991 
1003 
1005 
1006  // Inserts new IPv6 lease
1007  {INSERT_LEASE6,
1008  {INSERT_LEASE6,
1009  "INSERT INTO lease6("
1010  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1011  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1012  "hwaddr_source, state, user_context "
1013  ") VALUES ("
1014  "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?"
1015  ") "
1016  "IF NOT EXISTS "
1017  }},
1018 
1019  // Updates existing IPv6 lease
1020  {UPDATE_LEASE6,
1021  {UPDATE_LEASE6,
1022  "UPDATE lease6 SET "
1023  "valid_lifetime = ?, "
1024  "expire = ?, "
1025  "pref_lifetime = ?, "
1026  "duid = ?, "
1027  "iaid = ?, "
1028  "subnet_id = ?, "
1029  "lease_type = ?, "
1030  "prefix_len = ?, "
1031  "fqdn_fwd = ?, "
1032  "fqdn_rev = ?, "
1033  "hostname = ?, "
1034  "hwaddr = ?, "
1035  "hwtype = ?, "
1036  "hwaddr_source = ?, "
1037  "state = ?, "
1038  "user_context = ? "
1039  "WHERE address = ? "
1040  "IF expire = ? "
1041  }},
1042 
1043  // Deletes existing IPv6 lease
1044  {DELETE_LEASE6,
1045  {DELETE_LEASE6,
1046  "DELETE FROM lease6 "
1047  "WHERE address = ? "
1048  "IF expire = ? "
1049  }},
1050 
1051  // Gets up to a certain number of expired IPv6 leases
1052  {GET_LEASE6_EXPIRE,
1053  {GET_LEASE6_EXPIRE,
1054  "SELECT "
1055  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1056  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1057  "hwaddr_source, state, user_context "
1058  "FROM lease6 "
1059  "WHERE state = ? "
1060  "AND valid_lifetime < 4294967295 "
1061  "AND expire < ? "
1062  "LIMIT ? "
1063  "ALLOW FILTERING "
1064  }},
1065 
1066  // Gets an IPv6 lease with specified IPv6 address
1067  {GET_LEASE6_ADDR,
1068  {GET_LEASE6_ADDR,
1069  "SELECT "
1070  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1071  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1072  "hwaddr_source, state, user_context "
1073  "FROM lease6 "
1074  "WHERE address = ? "
1075  "AND lease_type = ? "
1076  "ALLOW FILTERING "
1077  }},
1078 
1079  // Gets an IPv6 lease with specified duid
1080  {GET_LEASE6_DUID,
1081  {GET_LEASE6_DUID,
1082  "SELECT "
1083  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1084  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1085  "hwaddr_source, state, user_context "
1086  "FROM lease6 "
1087  "WHERE duid = ? "
1088  "ALLOW FILTERING "
1089  }},
1090 
1091  // Gets an IPv6 lease(s) with specified duid and iaid
1092  {GET_LEASE6_DUID_IAID,
1093  {GET_LEASE6_DUID_IAID,
1094  "SELECT "
1095  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1096  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1097  "hwaddr_source, state, user_context "
1098  "FROM lease6 "
1099  "WHERE duid = ? AND iaid = ? "
1100  "AND lease_type = ? "
1101  "ALLOW FILTERING "
1102  }},
1103 
1104  // Gets an IPv6 lease with specified duid, iaid and subnet-id
1105  {GET_LEASE6_DUID_IAID_SUBID,
1106  {GET_LEASE6_DUID_IAID_SUBID,
1107  "SELECT "
1108  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1109  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1110  "hwaddr_source, state, user_context "
1111  "FROM lease6 "
1112  "WHERE duid = ? AND iaid = ? "
1113  "AND lease_type = ? "
1114  "AND subnet_id = ? "
1115  "ALLOW FILTERING "
1116  }},
1117 
1118  // Get range of IPv6 leases from first lease with a limit (paging)
1119  {GET_LEASE6_LIMIT,
1120  {GET_LEASE6_LIMIT,
1121  "SELECT "
1122  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1123  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1124  "hwaddr_source, state, user_context "
1125  "FROM lease6 "
1126  "LIMIT ? "
1127  "ALLOW FILTERING "
1128  }},
1129 
1130  // Get range of IPv6 leases from address with a limit (paging)
1131  {GET_LEASE6_PAGE,
1132  {GET_LEASE6_PAGE,
1133  "SELECT "
1134  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1135  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1136  "hwaddr_source, state, user_context "
1137  "FROM lease6 "
1138  "WHERE TOKEN(address) > TOKEN(?) "
1139  "LIMIT ? "
1140  "ALLOW FILTERING "
1141  }},
1142 
1143  // Gets an IPv6 lease(s) with specified hostname
1144  {GET_LEASE6_HOSTNAME,
1145  {GET_LEASE6_HOSTNAME,
1146  "SELECT "
1147  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1148  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1149  "hwaddr_source, state, user_context "
1150  "FROM lease6 "
1151  "WHERE hostname = ? "
1152  "ALLOW FILTERING "
1153  }}
1154 };
1155 
1157  : CqlLeaseExchange(connection), pref_lifetime_(0), iaid_(0), lease_type_(0),
1158  prefix_len_(0), hwtype_(0), hwaddr_source_(0) {
1159 }
1160 
1161 void
1163  if (!lease) {
1164  isc_throw(BadValue, "CqlLease6Exchange::createBindForInsert(): "
1165  "Lease6 object is NULL");
1166  }
1167  // Store lease object to ensure it remains valid.
1168  lease_ = lease;
1169 
1170  // Set up the structures for the various components of the lease4
1171  // structure.
1172  try {
1173  // address: varchar
1174  address_ = lease_->addr_.toText();
1175  if (address_.size() > ADDRESS6_TEXT_MAX_LEN) {
1176  isc_throw(BadValue, "address " << address_ << " of length " << address_.size()
1177  << " exceeds maximum allowed length of " << ADDRESS6_TEXT_MAX_LEN);
1178  }
1179 
1180  // valid lifetime: bigint
1181  valid_lifetime_ = static_cast<cass_int64_t>(lease_->valid_lft_);
1182 
1183  // expire: bigint
1184  // The lease structure holds the client last transmission time
1185  // (cltt_)
1186  // For convenience for external tools, this is converted to lease
1187  // expiry time (expire). The relationship is given by:
1188  // expire = cltt_ + valid_lft_
1189  CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
1190  expire_);
1191 
1192  // subnet_id: int
1193  subnet_id_ = static_cast<cass_int32_t>(lease_->subnet_id_);
1194 
1195  // pref_lifetime: bigint
1196  pref_lifetime_ = static_cast<cass_int64_t>(lease_->preferred_lft_);
1197 
1198  // duid: blob
1199  if (!lease_->duid_) {
1200  isc_throw(DbOperationError, "lease6 with address " << address_
1201  << " is missing mandatory duid");
1202  }
1203  duid_ = lease_->duid_->getDuid();
1204 
1205  // iaid: int
1206  iaid_ = static_cast<cass_int32_t>(lease_->iaid_);
1207 
1208  // lease_type: int
1209  lease_type_ = static_cast<cass_int32_t>(lease_->type_);
1210 
1211  // prefix_len: int
1212  prefix_len_ = static_cast<cass_int32_t>(lease_->prefixlen_);
1213 
1214  // fqdn_fwd: boolean
1215  fqdn_fwd_ = lease_->fqdn_fwd_ ? cass_true : cass_false;
1216 
1217  // fqdn_rev: boolean
1218  fqdn_rev_ = lease_->fqdn_rev_ ? cass_true : cass_false;
1219 
1220  // hostname: varchar
1221  if (lease_->hostname_.size() > HOSTNAME_MAX_LEN) {
1222  isc_throw(BadValue, "hostname" << lease_->hostname_ << " of length "
1223  << lease_->hostname_.size() << " exceeds maximum allowed length of "
1224  << HOSTNAME_MAX_LEN);
1225  }
1226  hostname_ = lease_->hostname_;
1227 
1228  // hwaddr: blob
1229  if (lease_->hwaddr_ && lease_->hwaddr_->hwaddr_.size() > 0) {
1230  if (lease_->hwaddr_->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
1231  isc_throw(DbOperationError, "hardware address " << lease_->hwaddr_->toText()
1232  << " of length " << lease_->hwaddr_->hwaddr_.size()
1233  << " exceeds maximum allowed length of " << HWAddr::MAX_HWADDR_LEN);
1234  }
1235  hwaddr_ = lease_->hwaddr_->hwaddr_;
1236  } else {
1237  hwaddr_.clear();
1238  }
1239 
1240  // hwtype: int
1241  if (lease_->hwaddr_) {
1242  hwtype_ = static_cast<cass_int32_t>(lease_->hwaddr_->htype_);
1243  } else {
1244  hwtype_ = 0;
1245  }
1246 
1247  // hwaddr_source: int
1248  if (lease_->hwaddr_) {
1249  hwaddr_source_ = static_cast<cass_int32_t>(lease_->hwaddr_->source_);
1250  } else {
1251  hwaddr_source_ = 0;
1252  }
1253 
1254  // state: int
1255  state_ = static_cast<cass_int32_t>(lease_->state_);
1256 
1257  // user_context: text
1258  ConstElementPtr ctx = lease_->getContext();
1259  if (ctx) {
1260  user_context_ = ctx->str();
1261  } else {
1262  user_context_ = NULL_USER_CONTEXT;
1263  }
1264 
1265  // Start with a fresh array.
1266  data.clear();
1267 
1268  // Add them all to data.
1269  data.add(&address_);
1270  data.add(&valid_lifetime_);
1271  data.add(&expire_);
1272  data.add(&subnet_id_);
1273  data.add(&pref_lifetime_);
1274  data.add(&duid_);
1275  data.add(&iaid_);
1276  data.add(&lease_type_);
1277  data.add(&prefix_len_);
1278  data.add(&fqdn_fwd_);
1279  data.add(&fqdn_rev_);
1280  data.add(&hostname_);
1281  data.add(&hwaddr_);
1282  data.add(&hwtype_);
1283  data.add(&hwaddr_source_);
1284  data.add(&state_);
1285  data.add(&user_context_);
1286 
1287  } catch (const Exception &ex) {
1288  isc_throw(DbOperationError, "CqlLease6Exchange::createBindForInsert(): "
1289  "could not create bind array from Lease6: " << lease_->addr_.toText()
1290  << ", reason: " << ex.what());
1291  }
1292 }
1293 
1294 void
1296  StatementTag /* unused */) {
1297  if (!lease) {
1298  isc_throw(BadValue, "CqlLease6Exchange::createBindForUpdate(): "
1299  "Lease6 object is NULL");
1300  }
1301  // Store lease object to ensure it remains valid.
1302  lease_ = lease;
1303 
1304  // Set up the structures for the various components of the lease4
1305  // structure.
1306  try {
1307  // address: varchar
1308  address_ = lease_->addr_.toText();
1309  if (address_.size() > ADDRESS6_TEXT_MAX_LEN) {
1311  "address " << address_ << " of length " << address_.size()
1312  << " exceeds maximum allowed length of "
1313  << ADDRESS6_TEXT_MAX_LEN);
1314  }
1315 
1316  // valid lifetime: bigint
1317  valid_lifetime_ = static_cast<cass_int64_t>(lease_->valid_lft_);
1318 
1319  // expire: bigint
1320  // The lease structure holds the client last transmission time
1321  // (cltt_)
1322  // For convenience for external tools, this is converted to lease
1323  // expiry time (expire). The relationship is given by:
1324  // expire = cltt_ + valid_lft_
1325  CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
1326  expire_);
1327 
1328  // subnet_id: int
1329  subnet_id_ = static_cast<cass_int32_t>(lease_->subnet_id_);
1330 
1331  // pref_lifetime: bigint
1332  pref_lifetime_ = static_cast<cass_int64_t>(lease_->preferred_lft_);
1333 
1334  // duid: blob
1335  if (!lease_->duid_) {
1337  "lease6 with address " << address_
1338  << " is missing mandatory duid");
1339  }
1340  duid_ = lease_->duid_->getDuid();
1341 
1342  // iaid: int
1343  iaid_ = static_cast<cass_int32_t>(lease_->iaid_);
1344 
1345  // lease_type: int
1346  lease_type_ = static_cast<cass_int32_t>(lease_->type_);
1347 
1348  // prefix_len: int
1349  prefix_len_ = static_cast<cass_int32_t>(lease_->prefixlen_);
1350 
1351  // fqdn_fwd: boolean
1352  fqdn_fwd_ = lease_->fqdn_fwd_ ? cass_true : cass_false;
1353 
1354  // fqdn_rev: boolean
1355  fqdn_rev_ = lease_->fqdn_rev_ ? cass_true : cass_false;
1356 
1357  // hostname: varchar
1358  if (lease_->hostname_.size() > HOSTNAME_MAX_LEN) {
1360  "hostname" << lease_->hostname_ << " of length "
1361  << lease_->hostname_.size()
1362  << " exceeds maximum allowed length of "
1363  << HOSTNAME_MAX_LEN);
1364  }
1365  hostname_ = lease_->hostname_;
1366 
1367  // hwaddr: blob
1368  if (lease_->hwaddr_ && lease_->hwaddr_->hwaddr_.size() > 0) {
1369  if (lease_->hwaddr_->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
1371  "hardware address "
1372  << lease_->hwaddr_->toText() << " of length "
1373  << lease_->hwaddr_->hwaddr_.size()
1374  << " exceeds maximum allowed length of "
1376  }
1377  hwaddr_ = lease_->hwaddr_->hwaddr_;
1378  } else {
1379  hwaddr_.clear();
1380  }
1381 
1382  // hwtype: int
1383  if (lease_->hwaddr_) {
1384  hwtype_ = static_cast<cass_int32_t>(lease_->hwaddr_->htype_);
1385  } else {
1386  hwtype_ = 0;
1387  }
1388 
1389  // hwaddr_source: int
1390  if (lease_->hwaddr_) {
1391  hwaddr_source_ = static_cast<cass_int32_t>(lease_->hwaddr_->source_);
1392  } else {
1393  hwaddr_source_ = 0;
1394  }
1395 
1396  // state: int
1397  state_ = static_cast<cass_int32_t>(lease_->state_);
1398 
1399  // user_context: text
1400  ConstElementPtr ctx = lease_->getContext();
1401  if (ctx) {
1402  user_context_ = ctx->str();
1403  } else {
1404  user_context_ = NULL_USER_CONTEXT;
1405  }
1406 
1407  // Start with a fresh array.
1408  data.clear();
1409 
1410  // Add them all to data.
1411  data.add(&valid_lifetime_);
1412  data.add(&expire_);
1413  data.add(&pref_lifetime_);
1414  data.add(&duid_);
1415  data.add(&iaid_);
1416  data.add(&subnet_id_);
1417  data.add(&lease_type_);
1418  data.add(&prefix_len_);
1419  data.add(&fqdn_fwd_);
1420  data.add(&fqdn_rev_);
1421  data.add(&hostname_);
1422  data.add(&hwaddr_);
1423  data.add(&hwtype_);
1424  data.add(&hwaddr_source_);
1425  data.add(&state_);
1426  data.add(&user_context_);
1427  data.add(&address_);
1428 
1429  CqlExchange::convertToDatabaseTime(lease_->current_cltt_,
1430  lease_->current_valid_lft_,
1431  current_expire_);
1432  data.add(&current_expire_);
1433  } catch (const Exception &ex) {
1435  "CqlLease6Exchange::createBindForUpdate(): "
1436  "could not create bind array from Lease6: "
1437  << lease_->addr_.toText() << ", reason: " << ex.what());
1438  }
1439 }
1440 
1441 void
1443  StatementTag /* unused */) {
1444  if (!lease) {
1445  isc_throw(BadValue, "CqlLease6Exchange::createBindForDelete(): "
1446  "Lease6 object is NULL");
1447  }
1448  // Store lease object to ensure it remains valid.
1449  lease_ = lease;
1450 
1451  // Set up the structures for the various components of the lease4
1452  // structure.
1453  try {
1454  // address: varchar
1455  address_ = lease_->addr_.toText();
1456  if (address_.size() > ADDRESS6_TEXT_MAX_LEN) {
1458  "address " << address_ << " of length " << address_.size()
1459  << " exceeds maximum allowed length of "
1460  << ADDRESS6_TEXT_MAX_LEN);
1461  }
1462 
1463  // Start with a fresh array.
1464  data.clear();
1465  data.add(&address_);
1466 
1467  CqlExchange::convertToDatabaseTime(lease_->current_cltt_,
1468  lease_->current_valid_lft_,
1469  current_expire_);
1470  data.add(&current_expire_);
1471  } catch (const Exception &ex) {
1473  "CqlLease6Exchange::createBindForDelete(): "
1474  "could not create bind array from Lease6: "
1475  << lease_->addr_.toText() << ", reason: " << ex.what());
1476  }
1477 }
1478 
1479 void
1481  // Start with a fresh array.
1482  data.clear();
1483 
1484  // address: varchar
1485  data.add(&address_);
1486 
1487  // valid_lifetime_: bigint
1488  data.add(&valid_lifetime_);
1489 
1490  // expire: bigint
1491  data.add(&expire_);
1492 
1493  // subnet_id: int
1494  data.add(&subnet_id_);
1495 
1496  // pref_lifetime: bigint
1497  data.add(&pref_lifetime_);
1498 
1499  // duid: blob
1500  data.add(&duid_);
1501 
1502  // iaid: int
1503  data.add(&iaid_);
1504 
1505  // lease_type: int
1506  data.add(&lease_type_);
1507 
1508  // prefix_len: int
1509  data.add(&prefix_len_);
1510 
1511  // fqdn_fwd: boolean
1512  data.add(&fqdn_fwd_);
1513 
1514  // fqdn_rev: boolean
1515  data.add(&fqdn_rev_);
1516 
1517  // hostname: varchar
1518  data.add(&hostname_);
1519 
1520  // hwaddr: blob
1521  data.add(&hwaddr_);
1522 
1523  // hwtype: int
1524  data.add(&hwtype_);
1525 
1526  // hwaddr_source: int
1527  data.add(&hwaddr_source_);
1528 
1529  // state: int
1530  data.add(&state_);
1531 
1532  // user_context: text
1533  data.add(&user_context_);
1534 }
1535 
1536 boost::any
1538  try {
1539  // Sanity checks
1540  if (address_.size() > ADDRESS6_TEXT_MAX_LEN) {
1542  "address " << address_ << " of length " << address_.size()
1543  << " exceeds maximum allowed length of "
1544  << ADDRESS6_TEXT_MAX_LEN);
1545  }
1546  if (duid_.size() > DUID::MAX_DUID_LEN) {
1548  "duid " << DUID(duid_).toText() << " of length "
1549  << duid_.size()
1550  << " exceeds maximum allowed length of "
1551  << DUID::MAX_DUID_LEN);
1552  }
1553  if (lease_type_ != Lease::TYPE_NA && lease_type_ != Lease::TYPE_TA &&
1554  lease_type_ != Lease::TYPE_PD) {
1556  "invalid lease type "
1557  << lease_type_ << " for lease with address "
1558  << address_ << ". Expected 0, 1 or 2.");
1559  }
1560  if (hostname_.size() > HOSTNAME_MAX_LEN) {
1562  "hostname " << hostname_ << " of length "
1563  << hostname_.size()
1564  << " exceeds maximum allowed length of "
1565  << HOSTNAME_MAX_LEN);
1566  }
1567  if (hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
1569  "hwaddr " << HWAddr(hwaddr_, hwtype_).toText(false)
1570  << " of length " << hwaddr_.size()
1571  << " exceeds maximum allowed length of "
1573  }
1574 
1575  IOAddress addr(address_);
1576 
1577  DuidPtr duid(boost::make_shared<DUID>(duid_));
1578 
1579  HWAddrPtr hwaddr;
1580  if (hwaddr_.size()) {
1581  hwaddr = boost::make_shared<HWAddr>(hwaddr_, hwtype_);
1582  hwaddr->source_ = hwaddr_source_;
1583  }
1584 
1585  ConstElementPtr ctx;
1586  if (!user_context_.empty()) {
1587  ctx = Element::fromJSON(user_context_);
1588  if (!ctx ||(ctx->getType() != Element::map)) {
1589  isc_throw(BadValue, "user context '" << user_context_
1590  << "' is not a JSON map");
1591  }
1592  }
1593 
1594  // Create the lease and set the cltt (after converting from the
1595  // expire time retrieved from the database).
1596  Lease6Ptr result(boost::make_shared<Lease6>(static_cast<Lease::Type>(lease_type_), addr, duid,
1597  iaid_, pref_lifetime_, valid_lifetime_,
1599  hwaddr, prefix_len_));
1600 
1601  time_t cltt = 0;
1603  // Update cltt_ and current_cltt_ explicitly.
1604  result->cltt_ = cltt;
1605  result->current_cltt_ = cltt;
1606 
1607  result->state_ = state_;
1608 
1609  if (ctx) {
1610  result->setContext(ctx);
1611  }
1612 
1613  return (result);
1614  } catch (const Exception &ex) {
1616  "CqlLease6Exchange::retrieve(): "
1617  "could not convert data to Lease6, reason: "
1618  << ex.what());
1619  }
1620  return Lease6Ptr();
1621 }
1622 
1623 void
1625  Lease6Collection &result) {
1626  AnyArray collection = executeSelect(connection_, data, statement_tag);
1627 
1628  // Transfer Lease6 objects to result.
1629  for (boost::any &lease : collection) {
1630  result.push_back(boost::any_cast<Lease6Ptr>(lease));
1631  }
1632 }
1633 
1634 void
1636  Lease6Ptr &result) {
1637  // This particular method is called when only one or zero matches is
1638  // expected.
1639  Lease6Collection collection;
1640  getLeaseCollection(statement_tag, data, collection);
1641 
1642  // Return single record if present, else clear the lease.
1643  const size_t collection_size = collection.size();
1644  if (collection_size >= 2u) {
1646  "CqlLease6Exchange::getLease(): multiple records were found in "
1647  "the database where only one was expected for statement "
1648  << statement_tag);
1649  } else if (collection_size == 0u) {
1650  result.reset();
1651  } else {
1652  result = *collection.begin();
1653  }
1654 }
1655 
1656 void
1657 CqlLease6Exchange::getExpiredLeases(const size_t &max_leases,
1658  Lease6Collection &expired_leases) {
1659  // Set up the WHERE clause value
1660  cass_int32_t keep_state = Lease::STATE_EXPIRED_RECLAIMED;
1661  cass_int64_t timestamp = static_cast<cass_int64_t>(time(NULL));
1662 
1663  // If the number of leases is 0, we will return all leases. This is
1664  // achieved by setting the limit to a very high value.
1665  cass_int32_t limit = max_leases > 0u ? static_cast<cass_int32_t>(max_leases) :
1666  std::numeric_limits<cass_int32_t>::max();
1667 
1668  for (cass_int32_t state = Lease::STATE_DEFAULT;
1669  state <= Lease::STATE_EXPIRED_RECLAIMED; ++state) {
1670  if (state == keep_state) {
1671  continue;
1672  }
1673 
1674  AnyArray data;
1675  data.add(&state);
1676  data.add(&timestamp);
1677  data.add(&limit);
1678 
1679  // Retrieve leases from the database.
1680  Lease6Collection temp_collection;
1681  getLeaseCollection(CqlLease6Exchange::GET_LEASE6_EXPIRE, data,
1682  temp_collection);
1683 
1684  for (Lease6Ptr &lease : temp_collection) {
1685  expired_leases.push_back(lease);
1686  }
1687  }
1688 }
1689 
1696 public:
1697 
1707  const bool fetch_type)
1708  : conn_(conn), statement_(statement), fetch_type_(fetch_type),
1709  cumulative_rows_(), next_row_(cumulative_rows_.begin()),
1710  subnet_id_(0), lease_type_(0), state_(0) {
1711  }
1712 
1723  const bool fetch_type, const SubnetID& subnet_id)
1724  : LeaseStatsQuery(subnet_id), conn_(conn), statement_(statement),
1725  fetch_type_(fetch_type), cumulative_rows_(),
1726  next_row_(cumulative_rows_.begin()),
1727  subnet_id_(0), lease_type_(0), state_(0) {
1728  }
1729 
1742  const bool fetch_type, const SubnetID& first_subnet_id,
1743  const SubnetID& last_subnet_id)
1744  : LeaseStatsQuery(first_subnet_id, last_subnet_id), conn_(conn),
1745  statement_(statement), fetch_type_(fetch_type), cumulative_rows_(),
1746  next_row_(cumulative_rows_.begin()),
1747  subnet_id_(0), lease_type_(0), state_(0) {
1748  }
1749 
1751  virtual ~CqlLeaseStatsQuery() {};
1752 
1759  void start();
1760 
1787  void executeSelect(const CqlConnection& connection, const AnyArray& data,
1788  StatementTag statement_tag);
1789 
1801  bool getNextRow(LeaseStatsRow& row);
1802 
1810  virtual void
1811  createBindForSelect(AnyArray& data, StatementTag statement_tag = NULL);
1812 
1815  // Return lease4 lease statistics for all subnets
1816  static constexpr StatementTag ALL_LEASE4_STATS = "ALL_LEASE4_STATS";
1818  static constexpr StatementTag SUBNET_LEASE4_STATS = "SUBNET_LEASE4_STATS";
1820  static constexpr StatementTag SUBNET_RANGE_LEASE4_STATS = "SUBNET_RANGE_LEASE4_STATS";
1821 
1822  // Return lease6 lease statistics for all subnets
1823  static constexpr StatementTag ALL_LEASE6_STATS = "ALL_LEASE6_STATS";
1825  static constexpr StatementTag SUBNET_LEASE6_STATS = "SUBNET_LEASE6_STATS";
1827  static constexpr StatementTag SUBNET_RANGE_LEASE6_STATS = "SUBNET_RANGE_LEASE6_STATS";
1829 
1832 
1833 private:
1834 
1836  CqlConnection& conn_;
1837 
1839  StatementTag statement_;
1840 
1842  bool fetch_type_;
1843 
1844 
1846  std::map<LeaseStatsRow, int> cumulative_rows_;
1847 
1849  std::map<LeaseStatsRow, int>::iterator next_row_;
1850 
1852  cass_int32_t subnet_id_;
1853 
1855  cass_int32_t lease_type_;
1856 
1858  cass_int32_t state_;
1859 };
1860 
1867 
1869  // Return subnet_id and state of each v4 lease
1870  {ALL_LEASE4_STATS,
1871  {ALL_LEASE4_STATS,
1872  "SELECT "
1873  "subnet_id, state "
1874  "FROM lease4 "
1875  }},
1876 
1877  // Return state of each v4 lease for a single subnet
1878  {SUBNET_LEASE4_STATS,
1879  {SUBNET_LEASE4_STATS,
1880  "SELECT "
1881  "subnet_id, state "
1882  "FROM lease4 "
1883  "WHERE subnet_id = ? "
1884  }},
1885 
1886  // Return state of each v4 lease for a subnet range
1887  {SUBNET_RANGE_LEASE4_STATS,
1888  {SUBNET_RANGE_LEASE4_STATS,
1889  "SELECT "
1890  "subnet_id, state "
1891  "FROM lease4 "
1892  "WHERE subnet_id >= ? and subnet_id <= ? "
1893  "ALLOW FILTERING "
1894  }},
1895 
1896  // Return subnet_id, lease_type, and state of each v6 lease
1897  {ALL_LEASE6_STATS,
1898  {ALL_LEASE6_STATS,
1899  "SELECT "
1900  "subnet_id, lease_type, state "
1901  "FROM lease6 "
1902  }},
1903 
1904  // Return type and state of each v6 lease for a single subnet
1905  {SUBNET_LEASE6_STATS,
1906  {SUBNET_LEASE6_STATS,
1907  "SELECT "
1908  "subnet_id, lease_type, state "
1909  "FROM lease6 "
1910  "WHERE subnet_id = ? "
1911  }},
1912 
1913  // Return type and state of each v6 lease for single range
1914  {SUBNET_RANGE_LEASE6_STATS,
1915  {SUBNET_RANGE_LEASE6_STATS,
1916  "SELECT "
1917  "subnet_id, lease_type, state "
1918  "FROM lease6 "
1919  "WHERE subnet_id >= ? and subnet_id <= ? "
1920  "ALLOW FILTERING "
1921  }},
1922 };
1923 
1924 void
1926  // Set up where clause parameters as needed
1927  AnyArray data;
1928  cass_int32_t first_subnet_id_data;
1929  cass_int32_t last_subnet_id_data;
1930  if (getSelectMode() != ALL_SUBNETS) {
1931  first_subnet_id_data = static_cast<cass_int32_t>(first_subnet_id_);
1932  data.add(&first_subnet_id_data);
1933 
1934  if (getSelectMode() == SUBNET_RANGE) {
1935  last_subnet_id_data = static_cast<cass_int32_t>(last_subnet_id_);
1936  data.add(&last_subnet_id_data);
1937  }
1938  }
1939 
1940  // This gets a collection of "raw" data for all leases that match
1941  // the subnet selection criteria (all, range, or single subnets)
1942  // then rolls them up into cumulative_rows_
1943  executeSelect(conn_, data, statement_);
1944 
1945  // Set our row iterator to the beginning
1946  next_row_ = cumulative_rows_.begin();
1947 }
1948 
1949 bool
1951  // If we're past the end, punt.
1952  if (next_row_ == cumulative_rows_.end()) {
1953  return (false);
1954  }
1955 
1956  // Start by copying from the map row key
1957  row.subnet_id_ = next_row_->first.subnet_id_;
1958  row.lease_type_ = next_row_->first.lease_type_;
1959  row.lease_state_ = next_row_->first.lease_state_;
1960 
1961  // Grab the count from the map value
1962  row.state_count_ = next_row_->second;
1963 
1964  // Point to the next row.
1965  ++next_row_;
1966  return (true);
1967 }
1968 
1969 void
1971  data.clear();
1972  data.add(&subnet_id_);
1973  if (fetch_type_) {
1974  data.add(&lease_type_);
1975  }
1976 
1977  data.add(&state_);
1978 }
1979 
1980 void
1982  StatementTag statement_tag) {
1983  CassError rc;
1984  CassStatement* statement = NULL;
1985  CassFuture* future = NULL;
1986  AnyArray local_data = data;
1987 
1988  // Find the query statement first.
1989  StatementMap::const_iterator it = connection.statements_.find(statement_tag);
1990  if (it == connection.statements_.end()) {
1992  "CqlLeastStatsQuery::executeSelect(): Statement "
1993  << statement_tag << "has not been prepared.");
1994  }
1995 
1996  // Bind the data before the query is executed.
1997  CqlTaggedStatement tagged_statement = it->second;
1998  if (tagged_statement.is_raw_) {
1999  // The entire query is the first element in data.
2000  std::string* query = boost::any_cast<std::string*>(local_data.back());
2001  local_data.pop_back();
2002  statement = cass_statement_new(query->c_str(), local_data.size());
2003  } else {
2004  statement = cass_prepared_bind(tagged_statement.prepared_statement_);
2005  if (!statement) {
2007  "CqlLeaseStatsQuery::executeSelect(): unable to bind statement "
2008  << tagged_statement.name_);
2009  }
2010  }
2011 
2012  // Set specific level of consistency if we're told to do so.
2013  if (connection.force_consistency_) {
2014  rc = cass_statement_set_consistency(statement, connection.consistency_);
2015  if (rc != CASS_OK) {
2016  cass_statement_free(statement);
2018  "CqlLeaseStatsQuery::executeSelect(): unable to set statement "
2019  "consistency for statement "
2020  << tagged_statement.name_
2021  << ", Cassandra error code: " << cass_error_desc(rc));
2022  }
2023  if (connection.serial_consistency_ != CASS_CONSISTENCY_UNKNOWN) {
2024  rc = cass_statement_set_serial_consistency(statement, connection.serial_consistency_);
2025  if (rc != CASS_OK) {
2026  cass_statement_free(statement);
2028  "CqlExchange::executeSelect(): unable to set statement "
2029  "serial consistency for statement "
2030  << tagged_statement.name_
2031  << ", Cassandra error code: " << cass_error_desc(rc));
2032  }
2033  }
2034  }
2035 
2036  CqlCommon::bindData(local_data, statement);
2037 
2038  // Everything's ready. Call the actual statement.
2039  future = cass_session_execute(connection.session_, statement);
2040  if (!future) {
2041  cass_statement_free(statement);
2043  "CqlLeaseStatsQuery::executeSelect(): no CassFuture for statement "
2044  << tagged_statement.name_);
2045  }
2046 
2047  // Wait for the statement execution to complete.
2048  cass_future_wait(future);
2049  const std::string error = connection.checkFutureError(
2050  "CqlLeaseStatsQuery::executeSelect(): cass_session_execute() != CASS_OK",
2051  future, statement_tag);
2052  rc = cass_future_error_code(future);
2053  if (rc != CASS_OK) {
2054  cass_future_free(future);
2055  cass_statement_free(statement);
2056  isc_throw(DbOperationError, error);
2057  }
2058 
2059  // Get column values.
2060  const CassResult* result_collection = cass_future_get_result(future);
2061 
2062  // lease type is always NA for v4
2063  if (!fetch_type_) {
2064  lease_type_ = Lease::TYPE_NA;
2065  }
2066 
2067  // Since we're currently forced to pull data for all leases, we
2068  // iterate over them, aggregating them into cumulative LeaseStatsRows
2069  AnyArray return_values;
2070  CassIterator* rows = cass_iterator_from_result(result_collection);
2071  while (cass_iterator_next(rows)) {
2072  const CassRow* row = cass_iterator_get_row(rows);
2073  createBindForSelect(return_values, statement_tag);
2074  CqlCommon::getData(row, return_values);
2075 
2076  if (state_ != Lease::STATE_DEFAULT &&
2077  state_ != Lease::STATE_DECLINED) {
2078  continue;
2079  }
2080 
2081  LeaseStatsRow raw_row(subnet_id_, static_cast<Lease::Type>(lease_type_),
2082  state_, 1);
2083 
2084  auto cum_row = cumulative_rows_.find(raw_row);
2085  if (cum_row != cumulative_rows_.end()) {
2086  cumulative_rows_[raw_row] = cum_row->second + 1;
2087  } else {
2088  cumulative_rows_.insert(std::make_pair(raw_row, 1));
2089  }
2090  }
2091 
2092  // Free resources.
2093  cass_iterator_free(rows);
2094  cass_result_free(result_collection);
2095  cass_future_free(future);
2096  cass_statement_free(statement);
2097  return;
2098 }
2099 
2101  : parameters_(parameters), dbconn_(parameters) {
2102  // Validate the schema version first.
2103  std::pair<uint32_t, uint32_t> code_version(CQL_SCHEMA_VERSION_MAJOR,
2105  std::pair<uint32_t, uint32_t> db_version = getVersion();
2106  if (code_version != db_version) {
2107  isc_throw(DbOpenError, "Cassandra schema version mismatch: need version: "
2108  << code_version.first << "." << code_version.second
2109  << " found version: " << db_version.first << "."
2110  << db_version.second);
2111  }
2112 
2113  // Open the database.
2114  dbconn_.openDatabase();
2115 
2116  // Now prepare the rest of the exchanges.
2118  dbconn_.prepareStatements(CqlLease6Exchange::tagged_statements_);
2120 }
2121 
2123  // There is no need to close the database in this destructor: it is
2124  // closed in the destructor of the dbconn_ member variable.
2125 }
2126 
2127 std::string
2129  std::stringstream tmp;
2130  tmp << "CQL backend " << CQL_SCHEMA_VERSION_MAJOR;
2131  tmp << "." << CQL_SCHEMA_VERSION_MINOR;
2132  tmp << ", library cassandra";
2133  return tmp.str();
2134 }
2135 
2136 bool
2139  .arg(lease->addr_.toText());
2140 
2141  AnyArray data;
2142 
2143  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2144  exchange4->createBindForInsert(lease, data);
2145  try {
2146  exchange4->executeMutation(dbconn_, data, CqlLease4Exchange::INSERT_LEASE4);
2147  } catch (const Exception &exception) {
2149  .arg(exception.what());
2150  return false;
2151  }
2152 
2153  // Update lease current expiration time (allows update between the creation
2154  // of the Lease up to the point of insertion in the database).
2155  lease->updateCurrentExpirationTime();
2156 
2157  return true;
2158 }
2159 
2160 bool
2163  .arg(lease->addr_.toText());
2164 
2165  AnyArray data;
2166 
2167  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2168  exchange6->createBindForInsert(lease, data);
2169  try {
2170  exchange6->executeMutation(dbconn_, data, CqlLease6Exchange::INSERT_LEASE6);
2171  } catch (const Exception &exception) {
2173  .arg(exception.what());
2174  return false;
2175  }
2176 
2177  // Update lease current expiration time (allows update between the creation
2178  // of the Lease up to the point of insertion in the database).
2179  lease->updateCurrentExpirationTime();
2180 
2181  return true;
2182 }
2183 
2184 Lease4Ptr
2185 CqlLeaseMgr::getLease4(const IOAddress &addr) const {
2187  .arg(addr.toText());
2188 
2189  // Set up the WHERE clause value
2190  AnyArray data;
2191 
2192  cass_int32_t addr4 = static_cast<cass_int32_t>(addr.toUint32());
2193  data.add(&addr4);
2194 
2195  // Get the data.
2196  Lease4Ptr result;
2197 
2198  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2199  exchange4->getLease(CqlLease4Exchange::GET_LEASE4_ADDR, data, result);
2200 
2201  return (result);
2202 }
2203 
2205 CqlLeaseMgr::getLease4(const HWAddr &hwaddr) const {
2207  .arg(hwaddr.toText());
2208 
2209  // Set up the WHERE clause value
2210  AnyArray data;
2211 
2212  CassBlob hwaddr_data(hwaddr.hwaddr_);
2213  data.add(&hwaddr_data);
2214 
2215  // Get the data.
2216  Lease4Collection result;
2217  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2218  exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_HWADDR, data, result);
2219 
2220  return (result);
2221 }
2222 
2223 Lease4Ptr
2224 CqlLeaseMgr::getLease4(const HWAddr &hwaddr, SubnetID subnet_id) const {
2227  .arg(subnet_id)
2228  .arg(hwaddr.toText());
2229 
2230  // Set up the WHERE clause value
2231  AnyArray data;
2232 
2233  CassBlob hwaddr_data(hwaddr.hwaddr_);
2234  data.add(&hwaddr_data);
2235 
2236  cass_int32_t subnet_id_data = static_cast<cass_int32_t>(subnet_id);
2237  data.add(&subnet_id_data);
2238 
2239  // Get the data.
2240  Lease4Ptr result;
2241  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2242  exchange4->getLease(CqlLease4Exchange::GET_LEASE4_HWADDR_SUBID, data, result);
2243 
2244  return (result);
2245 }
2246 
2248 CqlLeaseMgr::getLease4(const ClientId &clientid) const {
2250  .arg(clientid.toText());
2251 
2252  // Set up the WHERE clause value
2253  AnyArray data;
2254 
2255  CassBlob client_id_data(clientid.getClientId());
2256  data.add(&client_id_data);
2257 
2258  // Get the data.
2259  Lease4Collection result;
2260  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2261  exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_CLIENTID, data, result);
2262 
2263  return (result);
2264 }
2265 
2266 Lease4Ptr
2267 CqlLeaseMgr::getLease4(const ClientId &clientid, SubnetID subnet_id) const {
2269  .arg(subnet_id)
2270  .arg(clientid.toText());
2271 
2272  // Set up the WHERE clause value
2273  AnyArray data;
2274 
2275  CassBlob client_id_data(clientid.getClientId());
2276  data.add(&client_id_data);
2277 
2278  cass_int32_t subnet_id_data = static_cast<cass_int32_t>(subnet_id);
2279  data.add(&subnet_id_data);
2280 
2281  // Get the data.
2282  Lease4Ptr result;
2283  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2284  exchange4->getLease(CqlLease4Exchange::GET_LEASE4_CLIENTID_SUBID, data, result);
2285 
2286  return (result);
2287 }
2288 
2292  .arg(subnet_id);
2293 
2294  // Set up the WHERE clause value
2295  AnyArray data;
2296 
2297  cass_int32_t subnet_id_data = static_cast<cass_int32_t>(subnet_id);
2298  data.add(&subnet_id_data);
2299 
2300  // Get the data.
2301  Lease4Collection result;
2302  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2303  exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_SUBID, data, result);
2304 
2305  return (result);
2306 }
2307 
2309 CqlLeaseMgr::getLeases4(const std::string& hostname) const {
2311  .arg(hostname);
2312 
2313  // Set up the WHERE clause value
2314  AnyArray data;
2315 
2316  std::string hostname_data(hostname);
2317  data.add(&hostname_data);
2318 
2319  // Get the data.
2320  Lease4Collection result;
2321  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2322  exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_HOSTNAME, data, result);
2323 
2324  return (result);
2325 }
2326 
2330 
2331  // Set up the WHERE clause value
2332  AnyArray data;
2333 
2334  // Get the data.
2335  Lease4Collection result;
2336  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2337  exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4, data, result);
2338 
2339  return (result);
2340 }
2341 
2344  const LeasePageSize& page_size) const {
2345  // Expecting IPv4 address.
2346  if (!lower_bound_address.isV4()) {
2347  isc_throw(InvalidAddressFamily, "expected IPv4 address while "
2348  "retrieving leases from the lease database, got "
2349  << lower_bound_address);
2350  }
2351 
2352  if (page_size.page_size_ == 0) {
2353  isc_throw(OutOfRange, "page size of retrieved leases must not be 0");
2354  }
2355 
2356  if (page_size.page_size_ > std::numeric_limits<uint32_t>::max()) {
2357  isc_throw(OutOfRange, "page size of retrieved leases must not be greater than "
2358  << std::numeric_limits<uint32_t>::max());
2359  }
2360 
2362  .arg(page_size.page_size_)
2363  .arg(lower_bound_address.toText());
2364 
2365  AnyArray data;
2366 
2367  cass_int32_t address_data = 0;
2368  if (!lower_bound_address.isV4Zero()) {
2369  address_data = static_cast<cass_int32_t>(lower_bound_address.toUint32());
2370  data.add(&address_data);
2371  }
2372 
2373  cass_int32_t page_size_data = static_cast<cass_int32_t>(page_size.page_size_);
2374  data.add(&page_size_data);
2375 
2376  // Get the data.
2377  Lease4Collection result;
2378  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2379  exchange4->getLeaseCollection(lower_bound_address.isV4Zero() ?
2380  CqlLease4Exchange::GET_LEASE4_LIMIT :
2382  data, result);
2383 
2384  return (result);
2385 }
2386 
2387 Lease6Ptr
2388 CqlLeaseMgr::getLease6(Lease::Type lease_type, const IOAddress &addr) const {
2389  std::string addr_data = addr.toText();
2391  .arg(addr_data)
2392  .arg(lease_type);
2393 
2394  // Set up the WHERE clause value
2395  AnyArray data;
2396 
2397  if (addr_data.size() > ADDRESS6_TEXT_MAX_LEN) {
2399  "CqlLeaseMgr::getLease6(): "
2400  "address "
2401  << addr_data << " of length " << addr_data.size()
2402  << " exceeds maximum allowed length of "
2403  << ADDRESS6_TEXT_MAX_LEN);
2404  }
2405  data.add(&addr_data);
2406 
2407  cass_int32_t lease_type_data = static_cast<cass_int32_t>(lease_type);
2408  data.add(&lease_type_data);
2409 
2410  Lease6Ptr result;
2411  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2412  exchange6->getLease(CqlLease6Exchange::GET_LEASE6_ADDR, data, result);
2413 
2414  return (result);
2415 }
2416 
2418 CqlLeaseMgr::getLeases6(const DUID& duid) const {
2419 
2420  // Set up the WHERE clause value
2421  AnyArray data;
2422 
2423  CassBlob duid_data(duid.getDuid());
2424 
2425  data.add(&duid_data);
2426 
2427  // Get the data.
2428  Lease6Collection result;
2429  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2430  exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_DUID,
2431  data, result);
2432 
2433  return (result);
2434 }
2435 
2437 CqlLeaseMgr::getLeases6(Lease::Type lease_type, const DUID &duid, uint32_t iaid) const {
2439  .arg(iaid)
2440  .arg(duid.toText())
2441  .arg(lease_type);
2442 
2443  // Set up the WHERE clause value
2444  AnyArray data;
2445 
2446  CassBlob duid_data(duid.getDuid());
2447  cass_int32_t iaid_data = static_cast<cass_int32_t>(iaid);
2448 
2449  data.add(&duid_data);
2450  data.add(&iaid_data);
2451 
2452  cass_int32_t lease_type_data = static_cast<cass_int32_t>(lease_type);
2453  data.add(&lease_type_data);
2454 
2455  // Get the data.
2456  Lease6Collection result;
2457  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2458  exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_DUID_IAID, data, result);
2459 
2460  return (result);
2461 }
2462 
2464 CqlLeaseMgr::getLeases6(Lease::Type lease_type, const DUID &duid, uint32_t iaid,
2465  SubnetID subnet_id) const {
2467  .arg(iaid)
2468  .arg(subnet_id)
2469  .arg(duid.toText())
2470  .arg(lease_type);
2471 
2472  // Set up the WHERE clause value
2473  AnyArray data;
2474 
2475  CassBlob duid_data(duid.getDuid());
2476  cass_int32_t iaid_data = static_cast<cass_int32_t>(iaid);
2477 
2478  data.add(&duid_data);
2479  data.add(&iaid_data);
2480 
2481  cass_int32_t lease_type_data = static_cast<cass_int32_t>(lease_type);
2482  data.add(&lease_type_data);
2483 
2484  cass_int32_t subnet_id_data = static_cast<cass_int32_t>(subnet_id);
2485  data.add(&subnet_id_data);
2486 
2487  // Get the data.
2488  Lease6Collection result;
2489  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2490  exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_DUID_IAID_SUBID, data, result);
2491 
2492  return (result);
2493 }
2494 
2497  isc_throw(NotImplemented, "getLeases6(subnet_id) is not implemented");
2498 }
2499 
2501 CqlLeaseMgr::getLeases6(const std::string& hostname) const {
2503  .arg(hostname);
2504 
2505  // Set up the WHERE clause value
2506  AnyArray data;
2507 
2508  std::string hostname_data(hostname);
2509  data.add(&hostname_data);
2510 
2511  // Get the data.
2512  Lease6Collection result;
2513  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2514  exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_HOSTNAME, data, result);
2515 
2516  return (result);
2517 }
2518 
2521  isc_throw(NotImplemented, "getLeases6() is not implemented");
2522 }
2523 
2526  const LeasePageSize& page_size) const {
2527  // Expecting IPv6 address.
2528  if (!lower_bound_address.isV6()) {
2529  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
2530  "retrieving leases from the lease database, got "
2531  << lower_bound_address);
2532  }
2533 
2534  if (page_size.page_size_ == 0) {
2535  isc_throw(OutOfRange, "page size of retrieved leases must not be 0");
2536  }
2537 
2538  if (page_size.page_size_ > std::numeric_limits<uint32_t>::max()) {
2539  isc_throw(OutOfRange, "page size of retrieved leases must not be greater than "
2540  << std::numeric_limits<uint32_t>::max());
2541  }
2542 
2544  .arg(page_size.page_size_)
2545  .arg(lower_bound_address.toText());
2546 
2547  AnyArray data;
2548 
2549  std::string lb_address_data;
2550  if (!lower_bound_address.isV6Zero()) {
2551  lb_address_data = lower_bound_address.toText();
2552  if (lb_address_data.size() > ADDRESS6_TEXT_MAX_LEN) {
2554  "CqlLeaseMgr::getLeases6(lower_bound_address, page_size): "
2555  "address "
2556  << lb_address_data << " of length " << lb_address_data.size()
2557  << " exceeds maximum allowed length of "
2558  << ADDRESS6_TEXT_MAX_LEN);
2559  }
2560  data.add(&lb_address_data);
2561  }
2562 
2563  cass_int32_t page_size_data = static_cast<cass_int32_t>(page_size.page_size_);
2564  data.add(&page_size_data);
2565 
2566  // Get the leases.
2567  Lease6Collection result;
2568  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2569  exchange6->getLeaseCollection(lower_bound_address.isV6Zero() ?
2570  CqlLease6Exchange::GET_LEASE6_LIMIT :
2572  data, result);
2573 
2574  return (result);
2575 }
2576 
2577 void
2579  const size_t max_leases) const {
2581  .arg(max_leases);
2582 
2583  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2584  exchange4->getExpiredLeases(max_leases, expired_leases);
2585 }
2586 
2587 void
2589  const size_t max_leases) const {
2591  .arg(max_leases);
2592 
2593  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2594  exchange6->getExpiredLeases(max_leases, expired_leases);
2595 }
2596 
2597 void
2600  .arg(lease->addr_.toText());
2601 
2602  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2603 
2604  try {
2605  AnyArray data;
2606  exchange4->createBindForUpdate(lease, data, CqlLease4Exchange::UPDATE_LEASE4);
2607  exchange4->executeMutation(dbconn_, data, CqlLease4Exchange::UPDATE_LEASE4);
2608  } catch (const StatementNotApplied &exception) {
2609  isc_throw(NoSuchLease, exception.what());
2610  }
2611 
2612  // Update lease current expiration time.
2613  lease->updateCurrentExpirationTime();
2614 }
2615 
2616 void
2619  .arg(lease->addr_.toText());
2620 
2621  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2622 
2623  try {
2624  AnyArray data;
2625  exchange6->createBindForUpdate(lease, data, CqlLease6Exchange::UPDATE_LEASE6);
2626  exchange6->executeMutation(dbconn_, data, CqlLease6Exchange::UPDATE_LEASE6);
2627  } catch (const StatementNotApplied &exception) {
2628  isc_throw(NoSuchLease, exception.what());
2629  }
2630 
2631  // Update lease current expiration time.
2632  lease->updateCurrentExpirationTime();
2633 }
2634 
2635 bool
2637  const IOAddress &addr = lease->addr_;
2638  std::string addr_data = addr.toText();
2640  .arg(addr_data);
2641 
2642  // Set up the WHERE clause value
2643  AnyArray data;
2644 
2645  std::unique_ptr<CqlLease4Exchange> exchange4(
2646  new CqlLease4Exchange(dbconn_));
2647 
2648  try {
2649  exchange4->createBindForDelete(lease, data, CqlLease4Exchange::DELETE_LEASE4);
2650  exchange4->executeMutation(dbconn_, data, CqlLease4Exchange::DELETE_LEASE4);
2651  } catch (const Exception &exception) {
2653  .arg(exception.what());
2654  return false;
2655  }
2656  return true;
2657 }
2658 
2659 bool
2661  const IOAddress &addr = lease->addr_;
2662  std::string addr_data = addr.toText();
2664  .arg(addr_data);
2665 
2666  // Set up the WHERE clause value
2667  AnyArray data;
2668 
2669  std::unique_ptr<CqlLease6Exchange> exchange6(
2670  new CqlLease6Exchange(dbconn_));
2671 
2672  try {
2673  exchange6->createBindForDelete(lease, data, CqlLease6Exchange::DELETE_LEASE6);
2674  exchange6->executeMutation(dbconn_, data, CqlLease6Exchange::DELETE_LEASE6);
2675  } catch (const Exception &exception) {
2677  .arg(exception.what());
2678  return false;
2679  }
2680  return true;
2681 }
2682 
2683 uint64_t
2687  .arg(secs);
2688  AnyArray data;
2689  uint64_t deleted = 0u;
2690  cass_int32_t limit = 1024;
2691 
2692  // State is reclaimed.
2693  cass_int32_t state = static_cast<cass_int32_t>(Lease::STATE_EXPIRED_RECLAIMED);
2694  data.add(&state);
2695 
2696  // Expiration timestamp.
2697  cass_int64_t expiration = static_cast<cass_int64_t>(time(NULL) - static_cast<time_t>(secs));
2698  data.add(&expiration);
2699 
2700  data.add(&limit);
2701 
2702  // Get the data.
2703  Lease4Collection leases;
2704  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2705  exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_EXPIRE, data, leases);
2706  for (Lease4Ptr &lease : leases) {
2707  if (deleteLease(lease)) {
2708  ++deleted;
2709  }
2710  }
2711  return (deleted);
2712 }
2713 
2714 uint64_t
2718  .arg(secs);
2719  AnyArray data;
2720  uint64_t deleted = 0u;
2721  cass_int32_t limit = 1024;
2722 
2723  // State is reclaimed.
2724  cass_int32_t state = static_cast<cass_int32_t>(Lease::STATE_EXPIRED_RECLAIMED);
2725  data.add(&state);
2726 
2727  // Expiration timestamp.
2728  cass_int64_t expiration = static_cast<cass_int64_t>(time(NULL) - static_cast<time_t>(secs));
2729  data.add(&expiration);
2730 
2731  data.add(&limit);
2732 
2733  // Get the data.
2734  Lease6Collection leases;
2735  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2736  exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_EXPIRE, data, leases);
2737  for (Lease6Ptr &lease : leases) {
2738  if (deleteLease(lease)) {
2739  ++deleted;
2740  }
2741  }
2742  return (deleted);
2743 }
2744 
2747  LeaseStatsQueryPtr query(
2748  new CqlLeaseStatsQuery(dbconn_, CqlLeaseStatsQuery::ALL_LEASE4_STATS,
2749  false));
2750  query->start();
2751  return(query);
2752 }
2753 
2756  LeaseStatsQueryPtr query(
2757  new CqlLeaseStatsQuery(dbconn_, CqlLeaseStatsQuery::SUBNET_LEASE4_STATS,
2758  false, subnet_id));
2759  query->start();
2760  return(query);
2761 }
2762 
2765  const SubnetID& last_subnet_id) {
2766  LeaseStatsQueryPtr query(
2767  new CqlLeaseStatsQuery(dbconn_, CqlLeaseStatsQuery::SUBNET_RANGE_LEASE4_STATS,
2768  false, first_subnet_id, last_subnet_id));
2769  query->start();
2770  return(query);
2771 }
2772 
2775  LeaseStatsQueryPtr query(
2776  new CqlLeaseStatsQuery(dbconn_, CqlLeaseStatsQuery::ALL_LEASE6_STATS,
2777  true));
2778  query->start();
2779  return(query);
2780 }
2781 
2784  LeaseStatsQueryPtr query(
2785  new CqlLeaseStatsQuery(dbconn_, CqlLeaseStatsQuery::SUBNET_LEASE6_STATS,
2786  true, subnet_id));
2787  query->start();
2788  return(query);
2789 }
2790 
2793  const SubnetID& last_subnet_id) {
2794  LeaseStatsQueryPtr query(
2795  new CqlLeaseStatsQuery(dbconn_, CqlLeaseStatsQuery::SUBNET_RANGE_LEASE6_STATS,
2796  true, first_subnet_id, last_subnet_id));
2797  query->start();
2798  return(query);
2799 }
2800 
2801 size_t
2802 CqlLeaseMgr::wipeLeases4(const SubnetID & /*subnet_id*/) {
2804  isc_throw(NotImplemented, "wipeLeases4 is not implemented for Cassandra backend");
2805 }
2806 
2807 size_t
2808 CqlLeaseMgr::wipeLeases6(const SubnetID & /*subnet_id*/) {
2810  isc_throw(NotImplemented, "wipeLeases6 is not implemented for Cassandra backend");
2811 }
2812 
2813 std::string
2815  std::string name = "";
2816  try {
2817  name = dbconn_.getParameter("name");
2818  } catch (...) {
2819  // Return an empty name
2820  }
2821  return name;
2822 }
2823 
2824 std::string
2826  return std::string("Cassandra Database");
2827 }
2828 
2832 
2833  return CqlConnection::getVersion(parameters_);
2834 }
2835 
2836 void
2839  dbconn_.commit();
2840 }
2841 
2842 void
2845  dbconn_.rollback();
2846 }
2847 
2848 } // namespace dhcp
2849 } // namespace isc
Database statement not applied.
Definition: db_exceptions.h:20
void createBindForInsert(const Lease4Ptr &lease, AnyArray &data)
Create CQL_BIND objects for Lease4 Pointer.
const std::vector< uint8_t > & getDuid() const
Returns a const reference to the actual DUID value.
Definition: duid.cc:46
virtual void createBindForSelect(AnyArray &data, StatementTag statement_tag=NULL) override
Create BIND array to receive data.
void createBindForDelete(const Lease4Ptr &lease, AnyArray &data, StatementTag statement_tag=NULL)
Create CQL_BIND objects for Lease4 Pointer.
const isc::log::MessageID DHCPSRV_CQL_COMMIT
static constexpr StatementTag GET_LEASE6_DUID_IAID
boost::shared_ptr< DUID > DuidPtr
Definition: duid.h:20
const CqlConnection & connection_
Database connection.
StatementMap statements_
Pointer to external array of tagged statements containing statement name, array of names of bind para...
bool deleteLease(const Lease4Ptr &lease) overridefinal
Deletes an IPv4 lease.
virtual void rollback() override
Rollback Transactions.
static std::pair< uint32_t, uint32_t > getVersion(const ParameterMap &parameters)
Get the schema version.
virtual void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv6 leases.
boost::shared_ptr< LeaseStatsQuery > LeaseStatsQueryPtr
Defines a pointer to a LeaseStatsQuery.
Definition: lease_mgr.h:207
cass_bool_t fqdn_rev_
Has reverse DNS update been performed?
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs) override
Deletes all expired and reclaimed DHCPv4 leases.
CqlLeaseExchange(const CqlConnection &connection)
Constructor.
void start()
Creates the lease statistical data result set.
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
Definition: duid.cc:122
Base CQL derivation of the statistical lease data query.
A generic exception that is thrown when a function is not implemented.
static const uint32_t STATE_EXPIRED_RECLAIMED
Expired and reclaimed lease.
Definition: lease.h:79
virtual LeaseStatsQueryPtr startLeaseStatsQuery4() override
Creates and runs the IPv4 lease stats query.
SelectMode getSelectMode() const
Returns the selection criteria mode The value returned is based upon the constructor variant used and...
Definition: lease_mgr.h:190
virtual void createBindForSelect(AnyArray &data, StatementTag statement_tag=NULL) override
Create BIND array to receive data.
const isc::log::MessageID DHCPSRV_CQL_DELETE_EXPIRED_RECLAIMED4
Structure used to bind C++ input values to dynamic CQL parameters.
Definition: cql_exchange.h:50
virtual boost::any retrieve() override
Retrieves the Lease4 object in Kea format.
static constexpr StatementTag GET_LEASE6_LIMIT
StatementTag name_
Short description of the query.
virtual void commit()
Commit Transactions.
const isc::log::MessageID DHCPSRV_CQL_DELETE_ADDR
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.
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition: hwaddr.h:154
const CassPrepared * prepared_statement_
Internal Cassandra object representing the prepared statement.
const isc::log::MessageID DHCPSRV_CQL_GET_VERSION
virtual bool addLease(const Lease4Ptr &lease) override
Adds an IPv4 lease.
const isc::log::MessageID DHCPSRV_CQL_GET4
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 LeaseStatsQueryPtr startSubnetLeaseStatsQuery6(const SubnetID &subnet_id) override
Creates and runs the IPv6 lease stats query for a single subnet.
static const size_t MAX_CLIENT_ID_LEN
Maximum size of a client ID.
Definition: duid.h:128
static const size_t MAX_HWADDR_LEN
Maximum size of a hardware address.
Definition: hwaddr.h:27
bool force_consistency_
CQL consistency enabled.
Attempt to update lease that was not there.
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition: lease.h:487
void prepareStatements(StatementMap &statements)
Prepare statements.
CassBlob hwaddr_
Hardware address.
void openDatabase()
Open database.
the lease contains IPv6 prefix (for prefix delegation)
Definition: lease.h:53
static void getData(const CassRow *row, AnyArray &data)
Retrieves data returned by Cassandra.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs) override
Deletes all expired and reclaimed DHCPv6 leases.
std::vector< uint8_t > hwaddr_
Definition: hwaddr.h:98
const isc::log::MessageID DHCPSRV_CQL_GET_IAID_DUID
virtual void rollback()
Rollback Transactions.
Base class for fulfilling a statistical lease data query.
Definition: lease_mgr.h:128
std::string toText(bool include_htype=true) const
Returns textual representation of a hardware address (e.g.
Definition: hwaddr.cc:51
const isc::log::MessageID DHCPSRV_CQL_GET_PAGE6
Exchange Lease4 information between Kea and CQL.
Exchange Lease6 information between Kea and CQL.
const isc::log::MessageID DHCPSRV_CQL_LEASE_EXCEPTION_THROWN
void createBindForInsert(const Lease6Ptr &lease, AnyArray &data)
Create CQL_BIND objects for Lease6 Pointer.
const isc::log::MessageID DHCPSRV_CQL_GET_ADDR4
Cassandra Exchange.
Definition: cql_exchange.h:142
const isc::log::MessageID DHCPSRV_CQL_ADD_ADDR6
static StatementMap tagged_statements_
Cassandra statements.
Holds DUID (DHCPv6 Unique Identifier)
Definition: duid.h:27
static constexpr StatementTag GET_LEASE6_DUID_IAID_SUBID
Exception thrown on failure to open database.
char const *const StatementTag
Statement index representing the statement name.
virtual void updateLease6(const Lease6Ptr &lease6) override
Updates IPv6 lease.
const isc::log::MessageID DHCPSRV_CQL_GET_EXPIRED4
bool getNextRow(LeaseStatsRow &row)
Fetches the next row in the result set.
Multiple lease records found where one expected.
Definition: db_exceptions.h:28
static constexpr StatementTag GET_LEASE6_EXPIRE
const isc::log::MessageID DHCPSRV_CQL_UPDATE_ADDR4
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery4(const SubnetID &subnet_id) override
Creates and runs the IPv4 lease stats query for a single subnet.
virtual Lease4Collection getLeases4() const override
Returns all IPv4 leases.
const size_t page_size_
Holds page size.
Definition: lease_mgr.h:53
Defines a single statement or query.
virtual ~CqlLeaseStatsQuery()
Destructor.
static constexpr StatementTag SUBNET_RANGE_LEASE4_STATS
Return lease4 lease statistics for a range of subnets.
CqlLeaseStatsQuery(CqlConnection &conn, StatementTag &statement, const bool fetch_type)
Constructor to query for all subnets' stats.
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:283
void add(const boost::any &value)
Add a value at the end of the vector.
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition: dhcpsrv_log.h:38
virtual size_t wipeLeases4(const SubnetID &subnet_id) override
Removes specified IPv4 leases.
static void convertToDatabaseTime(const time_t &cltt, const uint32_t &valid_lifetime, cass_int64_t &expire)
CassConsistency consistency_
CQL consistency.
SubnetID last_subnet_id_
Last subnet_id in the selection criteria when a range is given.
Definition: lease_mgr.h:199
const isc::log::MessageID DHCPSRV_CQL_GET_ADDR6
static constexpr StatementTag INSERT_LEASE6
Statement tags definitions.
std::vector< cass_byte_t > CassBlob
Host identifier converted to Cassandra data type.
Definition: cql_exchange.h:37
CassSession * session_
CQL session handle.
const std::vector< uint8_t > & getClientId() const
Returns reference to the client-id data.
Definition: duid.cc:117
SubnetID subnet_id_
The subnet ID to which this data applies.
Definition: lease_mgr.h:114
static std::string getDBVersion()
Local version of getDBVersion() class method.
cass_int64_t valid_lifetime_
Lease timer.
const isc::log::MessageID DHCPSRV_CQL_GET_CLIENTID
virtual void updateLease4(const Lease4Ptr &lease4) override
Updates IPv4 lease.
virtual ~CqlLeaseMgr()
Destructor (closes database)
const isc::log::MessageID DHCPSRV_CQL_GET_EXPIRED6
virtual size_t wipeLeases6(const SubnetID &subnet_id) override
Removed specified IPv6 leases.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
virtual VersionPair getVersion() const override
Returns backend version.
void createBindForUpdate(const Lease4Ptr &lease, AnyArray &data, StatementTag statement_tag=NULL)
Create CQL_BIND objects for Lease4 Pointer.
std::string user_context_
User context.
std::pair< uint32_t, uint32_t > VersionPair
Pair containing major and minor versions.
void createBindForDelete(const Lease6Ptr &lease, AnyArray &data, StatementTag statement_tag=NULL)
Create CQL_BIND objects for Lease4 Pointer.
CqlLeaseStatsQuery(CqlConnection &conn, StatementTag &statement, const bool fetch_type, const SubnetID &subnet_id)
Constructor to query for a single subnet's stats.
static constexpr StatementTag GET_LEASE6_PAGE
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:640
the lease contains temporary IPv6 address
Definition: lease.h:52
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
Definition: duid.cc:75
virtual boost::any retrieve() override
Retrieves the Lease6 object in Kea format.
static constexpr StatementTag GET_LEASE6_HOSTNAME
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
void getExpiredLeases(const size_t &max_leases, Lease4Collection &expired_leases)
Returns expired leases.
virtual std::string getDescription() const override
Returns description of the backend.
cass_int64_t expire_
Lease expiry time.
the lease contains non-temporary IPv6 address
Definition: lease.h:51
Ethernet 10Mbps.
Definition: dhcp4.h:56
const isc::log::MessageID DHCPSRV_CQL_ROLLBACK
Invalid address family used as input to Lease Manager.
Definition: db_exceptions.h:71
CqlLeaseStatsQuery(CqlConnection &conn, StatementTag &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.
void createBindForUpdate(const Lease6Ptr &lease, AnyArray &data, StatementTag statement_tag=NULL)
Create CQL_BIND objects for Lease6 Pointer.
This is a base class for exceptions thrown from the DNS library module.
constexpr uint32_t CQL_SCHEMA_VERSION_MAJOR
Define CQL schema version: 5.0.
Defines the logger used by the top-level component of kea-dhcp-ddns.
const isc::log::MessageID DHCPSRV_CQL_GET_SUBID_HWADDR
static void convertFromDatabaseTime(const cass_int64_t &expire, const cass_int64_t &valid_lifetime, time_t &cltt)
Converts time from Cassandra format.
CqlLeaseMgr(const db::DatabaseConnection::ParameterMap &parameters)
Constructor.
static constexpr StatementTag SUBNET_LEASE6_STATS
Return lease6 lease statistics for a single subnet.
virtual void createBindForSelect(AnyArray &data, StatementTag statement_tag=NULL)
Create BIND array to receive C++ data.
std::string getParameter(const std::string &name) const
Returns value of a connection parameter.
void getExpiredLeases(const size_t &max_leases, Lease6Collection &expired_leases)
Returns expired leases.
std::string hostname_
Client hostname.
static const size_t MAX_DUID_LEN
maximum duid size As defined in RFC 8415, section 11.1
Definition: duid.h:31
const isc::log::MessageID DHCPSRV_CQL_GET_HOSTNAME6
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const override
Returns existing IPv6 lease for a given IPv6 address.
uint32_t lease_state_
The lease_state to which the count applies.
Definition: lease_mgr.h:118
Type
Type of lease or pool.
Definition: lease.h:50
Holds Client identifier or client IPv4 address.
Definition: duid.h:111
const isc::log::MessageID DHCPSRV_CQL_GET_SUBID_CLIENTID
static void bindData(const AnyArray &data, CassStatement *statement)
Assigns values to every column of an INSERT or an UPDATE statement.
void getLease(StatementTag &statement_tag, AnyArray &data, Lease4Ptr &result)
Retrieves one IPv4 lease.
static StatementMap tagged_statements_
Cassandra statements.
std::unordered_map< StatementTag, CqlTaggedStatement, StatementTagHash, StatementTagEqual > StatementMap
A container for all statements.
cass_int64_t current_expire_
Expiration time of lease before update.
CassConsistency serial_consistency_
CQL serial consistency.
const isc::log::MessageID DHCPSRV_CQL_GET_PAGE4
AnyArray executeSelect(const CqlConnection &connection, const AnyArray &where_values, StatementTag statement_tag, const bool &single=false)
Executes SELECT statements.
constexpr uint32_t CQL_SCHEMA_VERSION_MINOR
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
Hardware type that represents information from DHCPv4 packet.
Definition: hwaddr.h:20
static constexpr StatementTag DELETE_LEASE6
static StatementMap tagged_statements_
Cassandra statements.
static const uint32_t STATE_DEFAULT
A lease in the default state.
Definition: lease.h:73
SubnetID first_subnet_id_
First (or only) subnet_id in the selection criteria.
Definition: lease_mgr.h:192
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
const isc::log::MessageID DHCPSRV_CQL_GET_HWADDR
static constexpr StatementTag GET_LEASE6_ADDR
static constexpr StatementTag ALL_LEASE6_STATS
virtual LeaseStatsQueryPtr startLeaseStatsQuery6() override
Creates and runs the IPv6 lease stats query.
int64_t state_count_
state_count The count of leases in the lease state
Definition: lease_mgr.h:120
cass_int32_t state_
Lease state.
cass_int32_t subnet_id_
Subnet identifier.
const isc::log::MessageID DHCPSRV_CQL_UPDATE_ADDR6
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
static const uint32_t STATE_DECLINED
Declined lease.
Definition: lease.h:76
Contains a single row of lease statistical data.
Definition: lease_mgr.h:61
Wraps value holding size of the page with leases.
Definition: lease_mgr.h:43
void getLeaseCollection(StatementTag &statement_tag, AnyArray &data, Lease6Collection &result)
Retrieves zero or more IPv6 leases.
virtual std::string getName() const override
Returns name of the database.
Lease::Type lease_type_
The lease_type to which the count applies.
Definition: lease_mgr.h:116
Common CQL connector pool.
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
static constexpr StatementTag SUBNET_LEASE4_STATS
Return lease4 lease statistics for a single subnet.
static constexpr StatementTag SUBNET_RANGE_LEASE6_STATS
Return lease6 lease statistics for a range of subnets.
const isc::log::MessageID DHCPSRV_CQL_DELETE_EXPIRED_RECLAIMED6
const isc::log::MessageID DHCPSRV_CQL_GET_HOSTNAME4
static constexpr StatementTag UPDATE_LEASE6
static const std::string checkFutureError(const std::string &what, CassFuture *future, StatementTag statement_tag=NULL)
Check for errors.
void getLease(StatementTag &statement_tag, AnyArray &data, Lease6Ptr &result)
Retrieves one IPv6 lease.
void getLeaseCollection(StatementTag &statement_tag, AnyArray &data, Lease4Collection &result)
Retrieves zero or more IPv4 leases.
static constexpr StatementTag GET_LEASE6_DUID
cass_bool_t fqdn_fwd_
Has forward DNS update been performed?
static constexpr StatementTag GET_LEASE4_PAGE
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:492
Common CQL and Lease Data Methods.
virtual void commit() override
Commit Transactions.
static constexpr StatementTag ALL_LEASE4_STATS
Statement tags definitions.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const override
Basic lease access methods.
Exception thrown on failure to execute a database function.
const isc::log::MessageID DHCPSRV_CQL_GET_IAID_SUBID_DUID
void executeSelect(const CqlConnection &connection, const AnyArray &data, StatementTag statement_tag)
Executes protocol specific lease query SELECT statement.
bool is_raw_
Should the statement be executed raw or with binds?
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv4 leases.
virtual Lease6Collection getLeases6() const override
Returns all IPv6 leases.
const isc::log::MessageID DHCPSRV_CQL_ADD_ADDR4
const isc::log::MessageID DHCPSRV_CQL_GET_SUBID4
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Definition: lease.h:24
CqlLease6Exchange(const CqlConnection &connection)
Constructor.