Kea  1.5.0
cql_lease_mgr.cc
Go to the documentation of this file.
1 // Copyright (C) 2016-2018 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 
30 using namespace isc::data;
31 using namespace isc::db;
33 
34 namespace isc {
35 namespace dhcp {
36 
37 static constexpr size_t HOSTNAME_MAX_LEN = 255u;
38 static constexpr size_t ADDRESS6_TEXT_MAX_LEN = 39u;
39 static constexpr char NULL_USER_CONTEXT[] = "";
40 
47 class CqlLeaseExchange : public CqlExchange {
48 public:
52  CqlLeaseExchange(const CqlConnection &connection)
53  : connection_(connection), valid_lifetime_(0), expire_(0),
54  subnet_id_(0), fqdn_fwd_(cass_false), fqdn_rev_(cass_false),
55  state_(0), user_context_(NULL_USER_CONTEXT) {
56  }
57 
65  virtual void
66  createBindForSelect(AnyArray &data, StatementTag statement_tag = NULL) override = 0;
67 
75  virtual boost::any retrieve() override = 0;
76 
77 protected:
80 
83 
85  cass_int64_t valid_lifetime_;
86 
88  cass_int64_t expire_;
89 
91  cass_int32_t subnet_id_;
92 
94  cass_bool_t fqdn_fwd_;
95 
97  cass_bool_t fqdn_rev_;
98 
100  std::string hostname_;
101 
103  cass_int32_t state_;
104 
106  std::string user_context_;
107 };
108 
122 public:
130  explicit CqlLease4Exchange(const CqlConnection &connection);
131 
139  void createBindForInsert(const Lease4Ptr &lease, AnyArray &data);
140 
149  void createBindForUpdate(const Lease4Ptr &lease, AnyArray &data,
150  StatementTag statement_tag = NULL);
151 
160  void createBindForDelete(const IOAddress &address,
161  AnyArray &data,
162  StatementTag statement_tag = NULL);
163 
170  virtual void
171  createBindForSelect(AnyArray &data, StatementTag statement_tag = NULL) override;
172 
176  virtual boost::any retrieve() override;
177 
183  void getLeaseCollection(StatementTag &statement_tag, AnyArray &data,
184  Lease4Collection &result);
185 
191  void
192  getLease(StatementTag &statement_tag, AnyArray &data, Lease4Ptr &result);
193 
201  void getExpiredLeases(const size_t &max_leases, Lease4Collection &expired_leases);
202 
205 
208  // Add entry to lease4 table
209  static constexpr StatementTag INSERT_LEASE4 = "INSERT_LEASE4";
210  // Update a Lease4 entry
211  static constexpr StatementTag UPDATE_LEASE4 = "UPDATE_LEASE4";
212  // Delete from lease4 by address
213  static constexpr StatementTag DELETE_LEASE4 = "DELETE_LEASE4";
214  // Delete expired lease4s in certain state
215  static constexpr StatementTag GET_LEASE4_EXPIRE = "GET_LEASE4_EXPIRE";
216  // Get lease4
217  static constexpr StatementTag GET_LEASE4 = "GET_LEASE4";
218  // Get lease4 by address
219  static constexpr StatementTag GET_LEASE4_ADDR = "GET_LEASE4_ADDR";
220  // Get lease4 by client ID
221  static constexpr StatementTag GET_LEASE4_CLIENTID = "GET_LEASE4_CLIENTID";
222  // Get lease4 by client ID & subnet ID
223  static constexpr StatementTag GET_LEASE4_CLIENTID_SUBID = "GET_LEASE4_CLIENTID_SUBID";
224  // Get lease4 by HW address
225  static constexpr StatementTag GET_LEASE4_HWADDR = "GET_LEASE4_HWADDR";
226  // Get lease4 by HW address & subnet ID
227  static constexpr StatementTag GET_LEASE4_HWADDR_SUBID = "GET_LEASE4_HWADDR_SUBID";
228  // Get range of lease4 from first lease with a limit
229  static constexpr StatementTag GET_LEASE4_LIMIT = "GET_LEASE4_LIMIT";
230  // Get range of lease4 from address with limit (paging)
231  static constexpr StatementTag GET_LEASE4_PAGE = "GET_LEASE4_PAGE";
232  // Get lease4 by subnet ID
233  static constexpr StatementTag GET_LEASE4_SUBID = "GET_LEASE4_SUBID";
235 
236 private:
237  // Pointer to lease object
238  Lease4Ptr lease_;
239  // IPv4 address
240  cass_int32_t address_;
241  // Client identification
242  CassBlob client_id_;
243 }; // CqlLease4Exchange
244 
245 constexpr StatementTag CqlLease4Exchange::INSERT_LEASE4;
246 constexpr StatementTag CqlLease4Exchange::UPDATE_LEASE4;
247 constexpr StatementTag CqlLease4Exchange::DELETE_LEASE4;
248 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_EXPIRE;
249 constexpr StatementTag CqlLease4Exchange::GET_LEASE4;
250 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_ADDR;
251 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_CLIENTID;
252 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_CLIENTID_SUBID;
253 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_HWADDR;
254 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_HWADDR_SUBID;
255 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_LIMIT;
256 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_PAGE;
257 constexpr StatementTag CqlLease4Exchange::GET_LEASE4_SUBID;
258 
259 StatementMap CqlLease4Exchange::tagged_statements_{
260 
261  // Inserts new IPv4 lease
262  {INSERT_LEASE4,
263  {INSERT_LEASE4,
264  "INSERT INTO lease4( "
265  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
266  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
267  ") VALUES ( "
268  "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? "
269  ") "
270  "IF NOT EXISTS "}},
271 
272  // Updates existing IPv4 lease
273  {UPDATE_LEASE4,
274  {UPDATE_LEASE4,
275  "UPDATE lease4 SET "
276  "hwaddr = ?, "
277  "client_id = ?, "
278  "subnet_id = ?, "
279  "valid_lifetime = ?, "
280  "expire = ?, "
281  "fqdn_fwd = ?, "
282  "fqdn_rev = ?, "
283  "hostname = ?, "
284  "state = ?, "
285  "user_context = ? "
286  "WHERE address = ? "
287  "IF EXISTS "}},
288 
289  // Deletes existing IPv4 lease
290  {DELETE_LEASE4,
291  {DELETE_LEASE4,
292  "DELETE FROM lease4 "
293  "WHERE address = ? "
294  "IF EXISTS "}},
295 
296  // Gets up to a certain number of expired IPv4 leases
297  {GET_LEASE4_EXPIRE,
298  {GET_LEASE4_EXPIRE,
299  "SELECT "
300  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
301  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
302  "FROM lease4 "
303  "WHERE state = ? "
304  "AND expire < ? "
305  "LIMIT ? "
306  "ALLOW FILTERING "}},
307 
308  // Gets an IPv4 lease(s)
309  {GET_LEASE4,
310  {GET_LEASE4,
311  "SELECT "
312  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
313  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
314  "FROM lease4 "}},
315 
316  // Gets an IPv4 lease with specified IPv4 address
317  {GET_LEASE4_ADDR,
318  {GET_LEASE4_ADDR,
319  "SELECT "
320  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
321  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
322  "FROM lease4 "
323  "WHERE address = ? "}},
324 
325  // Gets an IPv4 lease(s) with specified client-id
326  {GET_LEASE4_CLIENTID,
327  {GET_LEASE4_CLIENTID,
328  "SELECT "
329  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
330  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
331  "FROM lease4 "
332  "WHERE client_id = ? "
333  "ALLOW FILTERING "}},
334 
335  // Gets an IPv4 lease with specified client-id and subnet-id
336  {GET_LEASE4_CLIENTID_SUBID,
337  {GET_LEASE4_CLIENTID_SUBID,
338  "SELECT "
339  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
340  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
341  "FROM lease4 "
342  "WHERE client_id = ? "
343  "AND subnet_id = ? "
344  "ALLOW FILTERING "}},
345 
346  // Gets all IPv4 leases with specified hardware address
347  {GET_LEASE4_HWADDR,
348  {GET_LEASE4_HWADDR,
349  "SELECT "
350  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
351  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
352  "FROM lease4 "
353  "WHERE hwaddr = ? "
354  "ALLOW FILTERING "}},
355 
356  // Gets an IPv4 lease with specified hardware addr and subnet-id
357  {GET_LEASE4_HWADDR_SUBID,
358  {GET_LEASE4_HWADDR_SUBID,
359  "SELECT "
360  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
361  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
362  "FROM lease4 "
363  "WHERE hwaddr = ? "
364  "AND subnet_id = ? "
365  "ALLOW FILTERING "}},
366 
367  // Get range of lease4 from first lease with a limit (paging)
368  {GET_LEASE4_LIMIT,
369  {GET_LEASE4_LIMIT,
370  "SELECT "
371  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
372  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
373  "FROM lease4 "
374  "LIMIT ? "
375  "ALLOW FILTERING "}},
376 
377  // Get range of lease4 from address with a limit (paging)
378  {GET_LEASE4_PAGE,
379  {GET_LEASE4_PAGE,
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 TOKEN(address) > TOKEN(?) "
385  "LIMIT ? "
386  "ALLOW FILTERING "}},
387 
388  // Gets an IPv4 lease(s) with specified subnet-id
389  {GET_LEASE4_SUBID,
390  {GET_LEASE4_SUBID,
391  "SELECT "
392  "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, "
393  "fqdn_fwd, fqdn_rev, hostname, state, user_context "
394  "FROM lease4 "
395  "WHERE subnet_id = ? "
396  "ALLOW FILTERING "}}
397 };
398 
399 CqlLease4Exchange::CqlLease4Exchange(const CqlConnection &connection)
400  : CqlLeaseExchange(connection), address_(0) {
401 }
402 
403 void
405  if (!lease) {
406  isc_throw(BadValue, "CqlLease4Exchange::createBindForInsert(): "
407  "Lease4 object is NULL");
408  }
409  // Store lease object to ensure it remains valid.
410  lease_ = lease;
411  // Set up the structures for the various components of the lease4
412  // structure.
413 
414  try {
415  // address: int
416  // The address in the Lease structure is an IOAddress object.
417  // Convert this to an integer for storage.
418  address_ = static_cast<cass_int32_t>(lease->addr_.toUint32());
419 
420  // hwaddr: blob
421  if (lease_->hwaddr_ && lease_->hwaddr_->hwaddr_.size() > 0) {
422  if (lease_->hwaddr_->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
424  "hardware address "
425  << lease_->hwaddr_->toText() << " of length "
426  << lease_->hwaddr_->hwaddr_.size()
427  << " exceeds maximum allowed length of "
429  }
430  hwaddr_ = lease_->hwaddr_->hwaddr_;
431  } else {
432  hwaddr_.clear();
433  }
434 
435  // client_id: blob
436  if (lease_->client_id_ && lease_->client_id_->getClientId().size() > 0) {
437  client_id_ = lease_->client_id_->getClientId();
438  } else {
439  client_id_.clear();
440  }
441 
442  // valid lifetime: bigint
443  valid_lifetime_ = static_cast<cass_int64_t>(lease_->valid_lft_);
444 
445  // expire: bigint
446  // The lease structure holds the client last transmission time
448  // For convenience for external tools, this is converted to lease
449  // expiry time (expire). The relationship is given by:
450  // expire = cltt_ + valid_lft_
451  CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
452  expire_);
453 
454  // subnet_id: int
455  subnet_id_ = static_cast<cass_int32_t>(lease_->subnet_id_);
456 
457  // fqdn_fwd: boolean
458  fqdn_fwd_ = lease_->fqdn_fwd_ ? cass_true : cass_false;
459 
460  // fqdn_rev: boolean
461  fqdn_rev_ = lease_->fqdn_rev_ ? cass_true : cass_false;
462 
463  // hostname: varchar
464  if (lease_->hostname_.size() > HOSTNAME_MAX_LEN) {
466  "hostname " << lease_->hostname_ << " of length "
467  << lease_->hostname_.size()
468  << " exceeds maximum allowed length of "
469  << HOSTNAME_MAX_LEN);
470  }
471  hostname_ = lease_->hostname_;
472 
473  // state: int
474  state_ = static_cast<cass_int32_t>(lease_->state_);
475 
476  // user_context: text
477  ConstElementPtr ctx = lease_->getContext();
478  if (ctx) {
479  user_context_ = ctx->str();
480  } else {
481  user_context_ = NULL_USER_CONTEXT;
482  }
483 
484  // Start with a fresh array.
485  data.clear();
486  data.add(&address_);
487  data.add(&hwaddr_);
488  data.add(&client_id_);
489  data.add(&valid_lifetime_);
490  data.add(&expire_);
491  data.add(&subnet_id_);
492  data.add(&fqdn_fwd_);
493  data.add(&fqdn_rev_);
494  data.add(&hostname_);
495  data.add(&state_);
496  data.add(&user_context_);
497 
498  } catch (const Exception &ex) {
499  isc_throw(DbOperationError, "CqlLease4Exchange::createBindForInsert(): "
500  "could not create bind array from Lease4: " << lease_->addr_.toText()
501  << ", reason: " << ex.what());
502  }
503 }
504 
505 void
507  StatementTag /* unused */) {
508  if (!lease) {
509  isc_throw(BadValue, "CqlLease4Exchange::createBindForUpdate(): "
510  "Lease4 object is NULL");
511  }
512  // Store lease object to ensure it remains valid.
513  lease_ = lease;
514  // Set up the structures for the various components of the lease4
515  // structure.
516 
517  try {
518  // address: int
519  // The address in the Lease structure is an IOAddress object.
520  // Convert this to an integer for storage.
521  address_ = static_cast<cass_int32_t>(lease->addr_.toUint32());
522 
523  // hwaddr: blob
524  if (lease_->hwaddr_ && lease_->hwaddr_->hwaddr_.size() > 0) {
525  if (lease_->hwaddr_->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
527  "hardware address "
528  << lease_->hwaddr_->toText() << " of length "
529  << lease_->hwaddr_->hwaddr_.size()
530  << " exceeds maximum allowed length of "
532  }
533  hwaddr_ = lease_->hwaddr_->hwaddr_;
534  } else {
535  hwaddr_.clear();
536  }
537 
538  // client_id: blob
539  if (lease_->client_id_ && lease_->client_id_->getClientId().size() > 0) {
540  client_id_ = lease_->client_id_->getClientId();
541  } else {
542  client_id_.clear();
543  }
544 
545  // valid lifetime: bigint
546  valid_lifetime_ = static_cast<cass_int64_t>(lease_->valid_lft_);
547 
548  // expire: bigint
549  // The lease structure holds the client last transmission time
551  // For convenience for external tools, this is converted to lease
552  // expiry time (expire). The relationship is given by:
553  // expire = cltt_ + valid_lft_
554  CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
555  expire_);
556 
557  // subnet_id: int
558  subnet_id_ = static_cast<cass_int32_t>(lease_->subnet_id_);
559 
560  // fqdn_fwd: boolean
561  fqdn_fwd_ = lease_->fqdn_fwd_ ? cass_true : cass_false;
562 
563  // fqdn_rev: boolean
564  fqdn_rev_ = lease_->fqdn_rev_ ? cass_true : cass_false;
565 
566  // hostname: varchar
567  if (lease_->hostname_.size() > HOSTNAME_MAX_LEN) {
569  "hostname " << lease_->hostname_ << " of length "
570  << lease_->hostname_.size()
571  << " exceeds maximum allowed length of "
572  << HOSTNAME_MAX_LEN);
573  }
574  hostname_ = lease_->hostname_;
575 
576  // state: int
577  state_ = static_cast<cass_int32_t>(lease_->state_);
578 
579  // user_context: text
580  ConstElementPtr ctx = lease_->getContext();
581  if (ctx) {
582  user_context_ = ctx->str();
583  } else {
584  user_context_ = NULL_USER_CONTEXT;
585  }
586 
587  // Start with a fresh array.
588  data.clear();
589  data.add(&hwaddr_);
590  data.add(&client_id_);
591  data.add(&subnet_id_);
592  data.add(&valid_lifetime_);
593  data.add(&expire_);
594  data.add(&fqdn_fwd_);
595  data.add(&fqdn_rev_);
596  data.add(&hostname_);
597  data.add(&state_);
598  data.add(&user_context_);
599  data.add(&address_);
600 
601  } catch (const Exception &ex) {
603  "CqlLease4Exchange::createBindUpdate(): "
604  "could not create bind array from Lease4: "
605  << lease_->addr_.toText() << ", reason: " << ex.what());
606  }
607 }
608 
609 void
611  StatementTag /* unused */) {
612  // Set up the structures for the various components of the lease4
613  // structure.
614 
615  try {
616  // address: int
617  address_ = static_cast<cass_int32_t>(address.toUint32());
618 
619  // Start with a fresh array.
620  data.clear();
621  data.add(&address_);
622 
623  } catch (const Exception &ex) {
625  "CqlLease4Exchange::createBindForDelete(): "
626  "could not create bind array with address: "
627  << address_ << ", reason: " << ex.what());
628  }
629 }
630 
631 void
633 
634  // Start with a fresh array.
635  data.clear();
636 
637  // address: blob
638  data.add(&address_);
639 
640  // hwaddr: blob
641  data.add(&hwaddr_);
642 
643  // client_id: blob
644  data.add(&client_id_);
645 
646  // valid_lifetime: bigint
647  data.add(&valid_lifetime_);
648 
649  // expire: bigint
650  data.add(&expire_);
651 
652  // subnet_id: int
653  data.add(&subnet_id_);
654 
655  // fqdn_fwd: boolean
656  data.add(&fqdn_fwd_);
657 
658  // fqdn_rev: boolean
659  data.add(&fqdn_rev_);
660 
661  // hostname: varchar
662  data.add(&hostname_);
663 
664  // state: int
665  data.add(&state_);
666 
667  // user_context: text
668  data.add(&user_context_);
669 }
670 
671 boost::any
673  try {
674  // Sanity checks
675  if (hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
677  "hardware address "
678  << HWAddr(hwaddr_, HTYPE_ETHER).toText()
679  << " of length " << hwaddr_.size()
680  << " exceeds maximum allowed length of "
682  }
683  if (client_id_.size() > ClientId::MAX_CLIENT_ID_LEN) {
685  "client ID " << ClientId(client_id_).toText()
686  << " of length " << client_id_.size()
687  << " exceeds maximum allowed length of "
689  }
690  if (hostname_.size() > HOSTNAME_MAX_LEN) {
692  "hostname" << hostname_ << " of length "
693  << hostname_.size()
694  << " exceeds maximum allowed length of "
695  << HOSTNAME_MAX_LEN);
696  }
697 
698  time_t cltt = 0;
699  CqlExchange::convertFromDatabaseTime(expire_, valid_lifetime_, cltt);
700 
701  HWAddrPtr hwaddr(new HWAddr(hwaddr_, HTYPE_ETHER));
702 
703  uint32_t addr4 = static_cast<uint32_t>(address_);
704 
705  ConstElementPtr ctx;
706  if (!user_context_.empty()) {
707  ctx = Element::fromJSON(user_context_);
708  if (!ctx || (ctx->getType() != Element::map)) {
709  isc_throw(BadValue, "user context '" << user_context_
710  << "' is not a JSON map");
711  }
712  }
713 
714  Lease4Ptr result(new Lease4(addr4, hwaddr, client_id_.data(),
715  client_id_.size(), valid_lifetime_, 0, 0,
717  hostname_));
718 
719  result->state_ = state_;
720 
721  if (ctx) {
722  result->setContext(ctx);
723  }
724 
725  return (result);
726  } catch (const Exception &ex) {
728  "CqlLease4Exchange::retrieve(): "
729  "could not convert data to Lease4, reason: "
730  << ex.what());
731  }
732 }
733 
734 void
736  Lease4Collection &result) {
737  AnyArray collection = executeSelect(connection_, data, statement_tag);
738 
739  // Transfer Lease4 objects to result.
740  for (boost::any &element : collection) {
741  result.push_back(boost::any_cast<Lease4Ptr>(element));
742  }
743 }
744 
745 void
747  Lease4Ptr &result) {
748  // This particular method is called when only one or zero matches is
749  // expected.
750  Lease4Collection collection;
751  getLeaseCollection(statement_tag, data, collection);
752 
753  // Return single record if present, else clear the lease.
754  const size_t collection_size = collection.size();
755  if (collection_size >= 2u) {
757  "CqlLease4Exchange::getLease(): multiple records were found in "
758  "the database where only one was expected for statement "
759  << statement_tag);
760  } else if (collection_size == 0u) {
761  result.reset();
762  } else {
763  result = *collection.begin();
764  }
765 }
766 
767 void
768 CqlLease4Exchange::getExpiredLeases(const size_t &max_leases,
769  Lease4Collection &expired_leases) {
770  // Set up the WHERE clause value
771  cass_int32_t keep_state = Lease::STATE_EXPIRED_RECLAIMED;
772  cass_int64_t timestamp = static_cast<cass_int64_t>(time(NULL));
773 
774  // If the number of leases is 0, we will return all leases. This is
775  // achieved by setting the limit to a very high value.
776  cass_int32_t limit = max_leases > 0u ?
777  static_cast<cass_int32_t>(max_leases) :
778  std::numeric_limits<cass_int32_t>::max();
779 
780  for (cass_int32_t state = Lease::STATE_DEFAULT;
781  state <= Lease::STATE_EXPIRED_RECLAIMED; state++) {
782  if (state == keep_state) {
783  continue;
784  }
785 
786  AnyArray data;
787  data.add(&state);
788  data.add(&timestamp);
789  data.add(&limit);
790 
791  // Retrieve leases from the database.
792  Lease4Collection temp_collection;
794  temp_collection);
795 
796  for (Lease4Ptr &lease : temp_collection) {
797  expired_leases.push_back(lease);
798  }
799  }
800 }
801 
815 public:
823  explicit CqlLease6Exchange(const CqlConnection &connection);
824 
832  void createBindForInsert(const Lease6Ptr &lease, AnyArray &data);
833 
842  void createBindForUpdate(const Lease6Ptr &lease, AnyArray &data,
843  StatementTag statement_tag = NULL);
844 
853  void createBindForDelete(const IOAddress &address,
854  AnyArray &data,
855  StatementTag statement_tag = NULL);
856 
863  virtual void
864  createBindForSelect(AnyArray &data, StatementTag statement_tag = NULL) override;
865 
869  virtual boost::any retrieve() override;
870 
876  void getLeaseCollection(StatementTag &statement_tag, AnyArray &data,
877  Lease6Collection &result);
878 
884  void
885  getLease(StatementTag &statement_tag, AnyArray &data, Lease6Ptr &result);
886 
894  void getExpiredLeases(const size_t &max_leases, Lease6Collection &expired_leases);
895 
898 
901  static constexpr StatementTag INSERT_LEASE6 = "INSERT_LEASE6";
902  static constexpr StatementTag UPDATE_LEASE6 = "UPDATE_LEASE6";
903  static constexpr StatementTag DELETE_LEASE6 = "DELETE_LEASE6";
904  static constexpr StatementTag GET_LEASE6_EXPIRE = "GET_LEASE6_EXPIRE";
905  static constexpr StatementTag GET_LEASE6_ADDR = "GET_LEASE6_ADDR";
906  static constexpr StatementTag GET_LEASE6_DUID = "GET_LEASE6_DUID";
907  static constexpr StatementTag GET_LEASE6_DUID_IAID = "GET_LEASE6_DUID_IAID";
908  static constexpr StatementTag GET_LEASE6_DUID_IAID_SUBID = "GET_LEASE6_DUID_IAID_SUBID";
909  static constexpr StatementTag GET_LEASE6_LIMIT = "GET_LEASE6_LIMIT";
910  static constexpr StatementTag GET_LEASE6_PAGE = "GET_LEASE6_PAGE";
911  // @}
912 
913 private:
915  Lease6Ptr lease_;
916 
918  std::string address_;
919 
921  cass_int64_t pref_lifetime_;
922 
924  CassBlob duid_;
925 
927  cass_int32_t iaid_;
928 
930  cass_int32_t lease_type_;
931 
933  cass_int32_t prefix_len_;
934 
936  cass_int32_t hwtype_;
937 
939  cass_int32_t hwaddr_source_;
940 }; // CqlLease6Exchange
941 
952 
954 
955  // Inserts new IPv6 lease
956  {INSERT_LEASE6,
957  {INSERT_LEASE6,
958  "INSERT INTO lease6("
959  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
960  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
961  "hwaddr_source, state, user_context "
962  ") VALUES ("
963  "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?"
964  ") "
965  "IF NOT EXISTS "}},
966 
967  // Updates existing IPv6 lease
968  {UPDATE_LEASE6,
969  {UPDATE_LEASE6,
970  "UPDATE lease6 SET "
971  "valid_lifetime = ?, "
972  "expire = ?, "
973  "pref_lifetime = ?, "
974  "duid = ?, "
975  "iaid = ?, "
976  "subnet_id = ?, "
977  "lease_type = ?, "
978  "prefix_len = ?, "
979  "fqdn_fwd = ?, "
980  "fqdn_rev = ?, "
981  "hostname = ?, "
982  "hwaddr = ?, "
983  "hwtype = ?, "
984  "hwaddr_source = ?, "
985  "state = ?, "
986  "user_context = ? "
987  "WHERE address = ? "
988  "IF EXISTS "}},
989 
990  // Deletes existing IPv6 lease
991  {DELETE_LEASE6,
992  {DELETE_LEASE6,
993  "DELETE FROM lease6 "
994  "WHERE address = ? "
995  "IF EXISTS "}},
996 
997  // Gets up to a certain number of expired IPv6 leases
998  {GET_LEASE6_EXPIRE,
999  {GET_LEASE6_EXPIRE,
1000  "SELECT "
1001  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1002  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1003  "hwaddr_source, state, user_context "
1004  "FROM lease6 "
1005  "WHERE state = ? "
1006  "AND expire < ? "
1007  "LIMIT ? "
1008  "ALLOW FILTERING "}},
1009 
1010  // Gets an IPv6 lease with specified IPv6 address
1011  {GET_LEASE6_ADDR,
1012  {GET_LEASE6_ADDR,
1013  "SELECT "
1014  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1015  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1016  "hwaddr_source, state, user_context "
1017  "FROM lease6 "
1018  "WHERE address = ? "
1019  "AND lease_type = ? "
1020  "ALLOW FILTERING "}},
1021 
1022  // Gets an IPv6 lease with specified duid
1023  {GET_LEASE6_DUID,
1024  {GET_LEASE6_DUID,
1025  "SELECT "
1026  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1027  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1028  "hwaddr_source, state, user_context "
1029  "FROM lease6 "
1030  "WHERE duid = ? "
1031  "ALLOW FILTERING "}},
1032 
1033  // Gets an IPv6 lease(s) with specified duid and iaid
1034  {GET_LEASE6_DUID_IAID,
1035  {GET_LEASE6_DUID_IAID,
1036  "SELECT "
1037  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1038  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1039  "hwaddr_source, state, user_context "
1040  "FROM lease6 "
1041  "WHERE duid = ? AND iaid = ? "
1042  "AND lease_type = ? "
1043  "ALLOW FILTERING "}},
1044 
1045  // Gets an IPv6 lease with specified duid, iaid and subnet-id
1046  {GET_LEASE6_DUID_IAID_SUBID,
1047  {GET_LEASE6_DUID_IAID_SUBID,
1048  "SELECT "
1049  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1050  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1051  "hwaddr_source, state, user_context "
1052  "FROM lease6 "
1053  "WHERE duid = ? AND iaid = ? "
1054  "AND lease_type = ? "
1055  "AND subnet_id = ? "
1056  "ALLOW FILTERING "}},
1057 
1058  // Get range of IPv6 leases from first lease with a limit (paging)
1059  {GET_LEASE6_LIMIT,
1060  {GET_LEASE6_LIMIT,
1061  "SELECT "
1062  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1063  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1064  "hwaddr_source, state, user_context "
1065  "FROM lease6 "
1066  "LIMIT ? "
1067  "ALLOW FILTERING "}},
1068 
1069  // Get range of IPv6 leases from address with a limit (paging)
1070  {GET_LEASE6_PAGE,
1071  {GET_LEASE6_PAGE,
1072  "SELECT "
1073  "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
1074  "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
1075  "hwaddr_source, state, user_context "
1076  "FROM lease6 "
1077  "WHERE TOKEN(address) > TOKEN(?) "
1078  "LIMIT ? "
1079  "ALLOW FILTERING "}}
1080 };
1081 
1083  : CqlLeaseExchange(connection), pref_lifetime_(0), iaid_(0), lease_type_(0),
1084  prefix_len_(0), hwtype_(0), hwaddr_source_(0) {
1085 }
1086 
1087 void
1089  if (!lease) {
1090  isc_throw(BadValue, "CqlLease6Exchange::createBindForInsert(): "
1091  "Lease6 object is NULL");
1092  }
1093  // Store lease object to ensure it remains valid.
1094  lease_ = lease;
1095 
1096  // Set up the structures for the various components of the lease4
1097  // structure.
1098  try {
1099  // address: varchar
1100  address_ = lease_->addr_.toText();
1101  if (address_.size() > ADDRESS6_TEXT_MAX_LEN) {
1102  isc_throw(BadValue, "address " << address_ << " of length " << address_.size()
1103  << " exceeds maximum allowed length of " << ADDRESS6_TEXT_MAX_LEN);
1104  }
1105 
1106  // valid lifetime: bigint
1107  valid_lifetime_ = static_cast<cass_int64_t>(lease_->valid_lft_);
1108 
1109  // expire: bigint
1110  // The lease structure holds the client last transmission time
1111  // (cltt_)
1112  // For convenience for external tools, this is converted to lease
1113  // expiry time (expire). The relationship is given by:
1114  // expire = cltt_ + valid_lft_
1115  CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_, expire_);
1116 
1117  // subnet_id: int
1118  subnet_id_ = static_cast<cass_int32_t>(lease_->subnet_id_);
1119 
1120  // pref_lifetime: bigint
1121  pref_lifetime_ = static_cast<cass_int64_t>(lease_->preferred_lft_);
1122 
1123  // duid: blob
1124  if (!lease_->duid_) {
1125  isc_throw(DbOperationError, "lease6 with address " << address_
1126  << " is missing mandatory duid");
1127  }
1128  duid_ = lease_->duid_->getDuid();
1129 
1130  // iaid: int
1131  iaid_ = static_cast<cass_int32_t>(lease_->iaid_);
1132 
1133  // lease_type: int
1134  lease_type_ = static_cast<cass_int32_t>(lease_->type_);
1135 
1136  // prefix_len: int
1137  prefix_len_ = static_cast<cass_int32_t>(lease_->prefixlen_);
1138 
1139  // fqdn_fwd: boolean
1140  fqdn_fwd_ = lease_->fqdn_fwd_ ? cass_true : cass_false;
1141 
1142  // fqdn_rev: boolean
1143  fqdn_rev_ = lease_->fqdn_rev_ ? cass_true : cass_false;
1144 
1145  // hostname: varchar
1146  if (lease_->hostname_.size() > HOSTNAME_MAX_LEN) {
1147  isc_throw(BadValue, "hostname" << lease_->hostname_ << " of length "
1148  << lease_->hostname_.size() << " exceeds maximum allowed length of "
1149  << HOSTNAME_MAX_LEN);
1150  }
1151  hostname_ = lease_->hostname_;
1152 
1153  // hwaddr: blob
1154  if (lease_->hwaddr_ && lease_->hwaddr_->hwaddr_.size() > 0) {
1155  if (lease_->hwaddr_->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
1156  isc_throw(DbOperationError, "hardware address " << lease_->hwaddr_->toText()
1157  << " of length " << lease_->hwaddr_->hwaddr_.size()
1158  << " exceeds maximum allowed length of " << HWAddr::MAX_HWADDR_LEN);
1159  }
1160  hwaddr_ = lease_->hwaddr_->hwaddr_;
1161  } else {
1162  hwaddr_.clear();
1163  }
1164 
1165  // hwtype: int
1166  if (lease_->hwaddr_) {
1167  hwtype_ = static_cast<cass_int32_t>(lease_->hwaddr_->htype_);
1168  } else {
1169  hwtype_ = 0;
1170  }
1171 
1172  // hwaddr_source: int
1173  if (lease_->hwaddr_) {
1174  hwaddr_source_ = static_cast<cass_int32_t>(lease_->hwaddr_->source_);
1175  } else {
1176  hwaddr_source_ = 0;
1177  }
1178 
1179  // state: int
1180  state_ = static_cast<cass_int32_t>(lease_->state_);
1181 
1182  // user_context: text
1183  ConstElementPtr ctx = lease_->getContext();
1184  if (ctx) {
1185  user_context_ = ctx->str();
1186  } else {
1187  user_context_ = NULL_USER_CONTEXT;
1188  }
1189 
1190  // Start with a fresh array.
1191  data.clear();
1192 
1193  // Add them all to data.
1194  data.add(&address_);
1195  data.add(&valid_lifetime_);
1196  data.add(&expire_);
1197  data.add(&subnet_id_);
1198  data.add(&pref_lifetime_);
1199  data.add(&duid_);
1200  data.add(&iaid_);
1201  data.add(&lease_type_);
1202  data.add(&prefix_len_);
1203  data.add(&fqdn_fwd_);
1204  data.add(&fqdn_rev_);
1205  data.add(&hostname_);
1206  data.add(&hwaddr_);
1207  data.add(&hwtype_);
1208  data.add(&hwaddr_source_);
1209  data.add(&state_);
1210  data.add(&user_context_);
1211 
1212  } catch (const Exception &ex) {
1213  isc_throw(DbOperationError, "CqlLease6Exchange::createBindForInsert(): "
1214  "could not create bind array from Lease6: " << lease_->addr_.toText()
1215  << ", reason: " << ex.what());
1216  }
1217 }
1218 
1219 void
1221  StatementTag /* unused */) {
1222  if (!lease) {
1223  isc_throw(BadValue, "CqlLease6Exchange::createBindForUpdate(): "
1224  "Lease6 object is NULL");
1225  }
1226  // Store lease object to ensure it remains valid.
1227  lease_ = lease;
1228 
1229  // Set up the structures for the various components of the lease4
1230  // structure.
1231  try {
1232  // address: varchar
1233  address_ = lease_->addr_.toText();
1234  if (address_.size() > ADDRESS6_TEXT_MAX_LEN) {
1236  "address " << address_ << " of length " << address_.size()
1237  << " exceeds maximum allowed length of "
1238  << ADDRESS6_TEXT_MAX_LEN);
1239  }
1240 
1241  // valid lifetime: bigint
1242  valid_lifetime_ = static_cast<cass_int64_t>(lease_->valid_lft_);
1243 
1244  // expire: bigint
1245  // The lease structure holds the client last transmission time
1246  // (cltt_)
1247  // For convenience for external tools, this is converted to lease
1248  // expiry time (expire). The relationship is given by:
1249  // expire = cltt_ + valid_lft_
1250  CqlExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
1251  expire_);
1252 
1253  // subnet_id: int
1254  subnet_id_ = static_cast<cass_int32_t>(lease_->subnet_id_);
1255 
1256  // pref_lifetime: bigint
1257  pref_lifetime_ = static_cast<cass_int64_t>(lease_->preferred_lft_);
1258 
1259  // duid: blob
1260  if (!lease_->duid_) {
1262  "lease6 with address " << address_
1263  << " is missing mandatory duid");
1264  }
1265  duid_ = lease_->duid_->getDuid();
1266 
1267  // iaid: int
1268  iaid_ = static_cast<cass_int32_t>(lease_->iaid_);
1269 
1270  // lease_type: int
1271  lease_type_ = static_cast<cass_int32_t>(lease_->type_);
1272 
1273  // prefix_len: int
1274  prefix_len_ = static_cast<cass_int32_t>(lease_->prefixlen_);
1275 
1276  // fqdn_fwd: boolean
1277  fqdn_fwd_ = lease_->fqdn_fwd_ ? cass_true : cass_false;
1278 
1279  // fqdn_rev: boolean
1280  fqdn_rev_ = lease_->fqdn_rev_ ? cass_true : cass_false;
1281 
1282  // hostname: varchar
1283  if (lease_->hostname_.size() > HOSTNAME_MAX_LEN) {
1285  "hostname" << lease_->hostname_ << " of length "
1286  << lease_->hostname_.size()
1287  << " exceeds maximum allowed length of "
1288  << HOSTNAME_MAX_LEN);
1289  }
1290  hostname_ = lease_->hostname_;
1291 
1292  // hwaddr: blob
1293  if (lease_->hwaddr_ && lease_->hwaddr_->hwaddr_.size() > 0) {
1294  if (lease_->hwaddr_->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
1296  "hardware address "
1297  << lease_->hwaddr_->toText() << " of length "
1298  << lease_->hwaddr_->hwaddr_.size()
1299  << " exceeds maximum allowed length of "
1301  }
1302  hwaddr_ = lease_->hwaddr_->hwaddr_;
1303  } else {
1304  hwaddr_.clear();
1305  }
1306 
1307  // hwtype: int
1308  if (lease_->hwaddr_) {
1309  hwtype_ = static_cast<cass_int32_t>(lease_->hwaddr_->htype_);
1310  } else {
1311  hwtype_ = 0;
1312  }
1313 
1314  // hwaddr_source: int
1315  if (lease_->hwaddr_) {
1316  hwaddr_source_ = static_cast<cass_int32_t>(lease_->hwaddr_->source_);
1317  } else {
1318  hwaddr_source_ = 0;
1319  }
1320 
1321  // state: int
1322  state_ = static_cast<cass_int32_t>(lease_->state_);
1323 
1324  // user_context: text
1325  ConstElementPtr ctx = lease_->getContext();
1326  if (ctx) {
1327  user_context_ = ctx->str();
1328  } else {
1329  user_context_ = NULL_USER_CONTEXT;
1330  }
1331 
1332  // Start with a fresh array.
1333  data.clear();
1334 
1335  // Add them all to data.
1336  data.add(&valid_lifetime_);
1337  data.add(&expire_);
1338  data.add(&pref_lifetime_);
1339  data.add(&duid_);
1340  data.add(&iaid_);
1341  data.add(&subnet_id_);
1342  data.add(&lease_type_);
1343  data.add(&prefix_len_);
1344  data.add(&fqdn_fwd_);
1345  data.add(&fqdn_rev_);
1346  data.add(&hostname_);
1347  data.add(&hwaddr_);
1348  data.add(&hwtype_);
1349  data.add(&hwaddr_source_);
1350  data.add(&state_);
1351  data.add(&user_context_);
1352  data.add(&address_);
1353 
1354  } catch (const Exception &ex) {
1356  "CqlLease6Exchange::createBindForUpdate(): "
1357  "could not create bind array from Lease6: "
1358  << lease_->addr_.toText() << ", reason: " << ex.what());
1359  }
1360 }
1361 
1362 void
1364  StatementTag /* unused */) {
1365 
1366  // Set up the structures for the various components of the lease4
1367  // structure.
1368  try {
1369  // address: varchar
1370  address_ = address.toText();
1371 
1372  // Start with a fresh array.
1373  data.clear();
1374  data.add(&address_);
1375 
1376  } catch (const Exception &ex) {
1378  "CqlLease6Exchange::createBindForDelete(): "
1379  "could not create bind array with address: "
1380  << address_ << ", reason: " << ex.what());
1381  }
1382 }
1383 
1384 void
1386 
1387  // Start with a fresh array.
1388  data.clear();
1389 
1390  // address: varchar
1391  data.add(&address_);
1392 
1393  // valid_lifetime_: bigint
1394  data.add(&valid_lifetime_);
1395 
1396  // expire: bigint
1397  data.add(&expire_);
1398 
1399  // subnet_id: int
1400  data.add(&subnet_id_);
1401 
1402  // pref_lifetime: bigint
1403  data.add(&pref_lifetime_);
1404 
1405  // duid: blob
1406  data.add(&duid_);
1407 
1408  // iaid: int
1409  data.add(&iaid_);
1410 
1411  // lease_type: int
1412  data.add(&lease_type_);
1413 
1414  // prefix_len: int
1415  data.add(&prefix_len_);
1416 
1417  // fqdn_fwd: boolean
1418  data.add(&fqdn_fwd_);
1419 
1420  // fqdn_rev: boolean
1421  data.add(&fqdn_rev_);
1422 
1423  // hostname: varchar
1424  data.add(&hostname_);
1425 
1426  // hwaddr: blob
1427  data.add(&hwaddr_);
1428 
1429  // hwtype: int
1430  data.add(&hwtype_);
1431 
1432  // hwaddr_source: int
1433  data.add(&hwaddr_source_);
1434 
1435  // state: int
1436  data.add(&state_);
1437 
1438  // user_context: text
1439  data.add(&user_context_);
1440 }
1441 
1442 boost::any
1444  try {
1445  // Sanity checks
1446  if (address_.size() > ADDRESS6_TEXT_MAX_LEN) {
1448  "address " << address_ << " of length " << address_.size()
1449  << " exceeds maximum allowed length of "
1450  << ADDRESS6_TEXT_MAX_LEN);
1451  }
1452  if (duid_.size() > DUID::MAX_DUID_LEN) {
1454  "duid " << DUID(duid_).toText() << " of length "
1455  << duid_.size()
1456  << " exceeds maximum allowed length of "
1457  << DUID::MAX_DUID_LEN);
1458  }
1459  if (lease_type_ != Lease::TYPE_NA && lease_type_ != Lease::TYPE_TA &&
1460  lease_type_ != Lease::TYPE_PD) {
1462  "invalid lease type "
1463  << lease_type_ << " for lease with address "
1464  << address_ << ". Expected 0, 1 or 2.");
1465  }
1466  if (hostname_.size() > HOSTNAME_MAX_LEN) {
1468  "hostname " << hostname_ << " of length "
1469  << hostname_.size()
1470  << " exceeds maximum allowed length of "
1471  << HOSTNAME_MAX_LEN);
1472  }
1473  if (hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
1475  "hwaddr " << HWAddr(hwaddr_, hwtype_).toText(false)
1476  << " of length " << hwaddr_.size()
1477  << " exceeds maximum allowed length of "
1479  }
1480 
1481  IOAddress addr(address_);
1482 
1483  DuidPtr duid(new DUID(duid_));
1484 
1485  HWAddrPtr hwaddr;
1486  if (hwaddr_.size()) {
1487  hwaddr.reset(new HWAddr(hwaddr_, hwtype_));
1488  hwaddr->source_ = hwaddr_source_;
1489  }
1490 
1491  ConstElementPtr ctx;
1492  if (!user_context_.empty()) {
1493  ctx = Element::fromJSON(user_context_);
1494  if (!ctx ||(ctx->getType() != Element::map)) {
1495  isc_throw(BadValue, "user context '" << user_context_
1496  << "' is not a JSON map");
1497  }
1498  }
1499 
1500  // Create the lease and set the cltt (after converting from the
1501  // expire time retrieved from the database).
1502  Lease6Ptr result(
1503  new Lease6(static_cast<Lease::Type>(lease_type_), addr, duid, iaid_,
1504  pref_lifetime_, valid_lifetime_, 0, 0, subnet_id_,
1505  fqdn_fwd_, fqdn_rev_, hostname_, hwaddr, prefix_len_));
1506 
1507  time_t cltt = 0;
1508  CqlExchange::convertFromDatabaseTime(expire_, valid_lifetime_, cltt);
1509  result->cltt_ = cltt;
1510 
1511  result->state_ = state_;
1512 
1513  if (ctx) {
1514  result->setContext(ctx);
1515  }
1516 
1517  return (result);
1518  } catch (const Exception &ex) {
1520  "CqlLease6Exchange::retrieve(): "
1521  "could not convert data to Lease6, reason: "
1522  << ex.what());
1523  }
1524  return Lease6Ptr();
1525 }
1526 
1527 void
1529  Lease6Collection &result) {
1530  AnyArray collection = executeSelect(connection_, data, statement_tag);
1531 
1532  // Transfer Lease6 objects to result.
1533  for (boost::any &lease : collection) {
1534  result.push_back(boost::any_cast<Lease6Ptr>(lease));
1535  }
1536 }
1537 
1538 void
1540  Lease6Ptr &result) {
1541  // This particular method is called when only one or zero matches is
1542  // expected.
1543  Lease6Collection collection;
1544  getLeaseCollection(statement_tag, data, collection);
1545 
1546  // Return single record if present, else clear the lease.
1547  const size_t collection_size = collection.size();
1548  if (collection_size >= 2u) {
1550  "CqlLease6Exchange::getLease(): multiple records were found in "
1551  "the database where only one was expected for statement "
1552  << statement_tag);
1553  } else if (collection_size == 0u) {
1554  result.reset();
1555  } else {
1556  result = *collection.begin();
1557  }
1558 }
1559 
1560 void
1561 CqlLease6Exchange::getExpiredLeases(const size_t &max_leases,
1562  Lease6Collection &expired_leases) {
1563  // Set up the WHERE clause value
1564  cass_int32_t keep_state = Lease::STATE_EXPIRED_RECLAIMED;
1565  cass_int64_t timestamp = static_cast<cass_int64_t>(time(NULL));
1566 
1567  // If the number of leases is 0, we will return all leases. This is
1568  // achieved by setting the limit to a very high value.
1569  cass_int32_t limit = max_leases > 0u ?
1570  static_cast<cass_int32_t>(max_leases) :
1571  std::numeric_limits<cass_int32_t>::max();
1572 
1573  for (cass_int32_t state = Lease::STATE_DEFAULT;
1574  state <= Lease::STATE_EXPIRED_RECLAIMED; state++) {
1575  if (state == keep_state) {
1576  continue;
1577  }
1578 
1579  AnyArray data;
1580  data.add(&state);
1581  data.add(&timestamp);
1582  data.add(&limit);
1583 
1584  // Retrieve leases from the database.
1585  Lease6Collection temp_collection;
1587  temp_collection);
1588 
1589  for (Lease6Ptr &lease : temp_collection) {
1590  expired_leases.push_back(lease);
1591  }
1592  }
1593 }
1594 
1601 public:
1611  const bool fetch_type)
1612  : conn_(conn), statement_(statement), fetch_type_(fetch_type),
1613  cummulative_rows_(), next_row_(cummulative_rows_.begin()),
1614  subnet_id_(0), lease_type_(0), lease_state_(0) {
1615  }
1616 
1627  const bool fetch_type, const SubnetID& subnet_id)
1628  : LeaseStatsQuery(subnet_id), conn_(conn), statement_(statement),
1629  fetch_type_(fetch_type), cummulative_rows_(),
1630  next_row_(cummulative_rows_.begin()),
1631  subnet_id_(0), lease_type_(0), lease_state_(0) {
1632  }
1633 
1646  const bool fetch_type, const SubnetID& first_subnet_id,
1647  const SubnetID& last_subnet_id)
1648  : LeaseStatsQuery(first_subnet_id, last_subnet_id), conn_(conn),
1649  statement_(statement), fetch_type_(fetch_type), cummulative_rows_(),
1650  next_row_(cummulative_rows_.begin()),
1651  subnet_id_(0), lease_type_(0), lease_state_(0) {
1652  }
1653 
1655  virtual ~CqlLeaseStatsQuery() {};
1656 
1663  void start();
1664 
1691  void executeSelect(const CqlConnection& connection, const AnyArray& data,
1692  StatementTag statement_tag);
1693 
1705  bool getNextRow(LeaseStatsRow& row);
1706 
1714  virtual void
1715  createBindForSelect(AnyArray& data, StatementTag statement_tag = NULL);
1716 
1719  // Return lease4 lease statistics for all subnets
1720  static constexpr StatementTag ALL_LEASE4_STATS = "ALL_LEASE4_STATS";
1722  static constexpr StatementTag SUBNET_LEASE4_STATS = "SUBNET_LEASE4_STATS";
1724  static constexpr StatementTag SUBNET_RANGE_LEASE4_STATS = "SUBNET_RANGE_LEASE4_STATS";
1725 
1726  // Return lease6 lease statistics for all subnets
1727  static constexpr StatementTag ALL_LEASE6_STATS = "ALL_LEASE6_STATS";
1729  static constexpr StatementTag SUBNET_LEASE6_STATS = "SUBNET_LEASE6_STATS";
1731  static constexpr StatementTag SUBNET_RANGE_LEASE6_STATS = "SUBNET_RANGE_LEASE6_STATS";
1733 
1736 
1737 private:
1739  CqlConnection& conn_;
1740 
1742  StatementTag statement_;
1743 
1745  bool fetch_type_;
1746 
1747 
1749  std::map<LeaseStatsRow, int> cummulative_rows_;
1750 
1752  std::map<LeaseStatsRow, int>::iterator next_row_;
1753 
1755  int subnet_id_;
1757  int lease_type_;
1759  int lease_state_;
1760 };
1761 
1768 
1770  // Return subnet_id and state of each v4 lease
1771  {ALL_LEASE4_STATS,
1772  {ALL_LEASE4_STATS,
1773  "SELECT "
1774  "subnet_id, state "
1775  "FROM lease4 "
1776  }},
1777 
1778  // Return state of each v4 lease for a single subnet
1779  {SUBNET_LEASE4_STATS,
1780  {SUBNET_LEASE4_STATS,
1781  "SELECT "
1782  "subnet_id, state "
1783  "FROM lease4 "
1784  "WHERE subnet_id = ? "
1785  }},
1786 
1787  // Return state of each v4 lease for a subnet range
1788  {SUBNET_RANGE_LEASE4_STATS,
1789  {SUBNET_RANGE_LEASE4_STATS,
1790  "SELECT "
1791  "subnet_id, state "
1792  "FROM lease4 "
1793  "WHERE subnet_id >= ? and subnet_id <= ? "
1794  "ALLOW FILTERING "
1795  }},
1796 
1797  // Return subnet_id, lease_type, and state of each v6 lease
1798  {ALL_LEASE6_STATS,
1799  {ALL_LEASE6_STATS,
1800  "SELECT "
1801  "subnet_id, lease_type, state "
1802  "FROM lease6 "
1803  }},
1804 
1805  // Return type and state of each v6 lease for a single subnet
1806  {SUBNET_LEASE6_STATS,
1807  {SUBNET_LEASE6_STATS,
1808  "SELECT "
1809  "subnet_id, lease_type, state "
1810  "FROM lease6 "
1811  "WHERE subnet_id = ? "
1812  }},
1813 
1814  // Return type and state of each v6 lease for single range
1815  {SUBNET_RANGE_LEASE6_STATS,
1816  {SUBNET_RANGE_LEASE6_STATS,
1817  "SELECT "
1818  "subnet_id, lease_type, state "
1819  "FROM lease6 "
1820  "WHERE subnet_id >= ? and subnet_id <= ? "
1821  "ALLOW FILTERING "
1822  }},
1823 
1824 };
1825 
1826 void
1828 
1829  // Set up where clause parameters as needed
1830  AnyArray data;
1831  cass_int32_t first_subnet_id_data;
1832  cass_int32_t last_subnet_id_data;
1833  if (getSelectMode() != ALL_SUBNETS) {
1834  first_subnet_id_data = static_cast<cass_int32_t>(first_subnet_id_);
1835  data.add(&first_subnet_id_data);
1836 
1837  if (getSelectMode() == SUBNET_RANGE) {
1838  last_subnet_id_data = static_cast<cass_int32_t>(last_subnet_id_);
1839  data.add(&last_subnet_id_data);
1840  }
1841  }
1842 
1843  // This gets a collection of "raw" data for all leases that match
1844  // the subnet selection criteria (all, range, or single subnets)
1845  // then rolls them up into cummulative_rows_
1846  executeSelect(conn_, data, statement_);
1847 
1848  // Set our row iterator to the beginning
1849  next_row_ = cummulative_rows_.begin();
1850 }
1851 
1852 bool
1854  // If we're past the end, punt.
1855  if (next_row_ == cummulative_rows_.end()) {
1856  return (false);
1857  }
1858 
1859  // Start by copying from the map row key
1860  row.subnet_id_ = next_row_->first.subnet_id_;
1861  row.lease_type_ = next_row_->first.lease_type_;
1862  row.lease_state_ = next_row_->first.lease_state_;
1863 
1864  // Grab the count from the map value
1865  row.state_count_ = next_row_->second;
1866 
1867  // Point to the next row.
1868  ++next_row_;
1869  return (true);
1870 }
1871 
1872 void
1874  data.clear();
1875  data.add(&subnet_id_);
1876  if (fetch_type_) {
1877  data.add(&lease_type_);
1878  }
1879 
1880  data.add(&lease_state_);
1881 }
1882 
1883 void
1885  StatementTag statement_tag) {
1886  CassError rc;
1887  CassStatement* statement = NULL;
1888  CassFuture* future = NULL;
1889  AnyArray local_data = data;
1890 
1891  // Find the query statement first.
1892  StatementMap::const_iterator it = connection.statements_.find(statement_tag);
1893  if (it == connection.statements_.end()) {
1895  "CqlLeastStatsQuery::executeSelect(): Statement "
1896  << statement_tag << "has not been prepared.");
1897  }
1898 
1899  // Bind the data before the query is executed.
1900  CqlTaggedStatement tagged_statement = it->second;
1901  if (tagged_statement.is_raw_) {
1902  // The entire query is the first element in data.
1903  std::string* query = boost::any_cast<std::string*>(local_data.back());
1904  local_data.pop_back();
1905  statement = cass_statement_new(query->c_str(), local_data.size());
1906  } else {
1907  statement = cass_prepared_bind(tagged_statement.prepared_statement_);
1908  if (!statement) {
1910  "CqlLeaseStatsQuery::executeSelect(): unable to bind statement "
1911  << tagged_statement.name_);
1912  }
1913  }
1914 
1915  // Set specific level of consistency if we're told to do so.
1916  if (connection.force_consistency_) {
1917  rc = cass_statement_set_consistency(statement, connection.consistency_);
1918  if (rc != CASS_OK) {
1919  cass_statement_free(statement);
1921  "CqlLeaseStatsQuery::executeSelect(): unable to set statement "
1922  "consistency for statement "
1923  << tagged_statement.name_
1924  << ", Cassandra error code: " << cass_error_desc(rc));
1925  }
1926  }
1927 
1928  CqlCommon::bindData(local_data, statement);
1929 
1930  // Everything's ready. Call the actual statement.
1931  future = cass_session_execute(connection.session_, statement);
1932  if (!future) {
1933  cass_statement_free(statement);
1935  "CqlLeaseStatsQuery::executeSelect(): no CassFuture for statement "
1936  << tagged_statement.name_);
1937  }
1938 
1939  // Wait for the statement execution to complete.
1940  cass_future_wait(future);
1941  const std::string error = connection.checkFutureError(
1942  "CqlLeaseStatsQuery::executeSelect(): cass_session_execute() != CASS_OK",
1943  future, statement_tag);
1944  rc = cass_future_error_code(future);
1945  if (rc != CASS_OK) {
1946  cass_future_free(future);
1947  cass_statement_free(statement);
1948  isc_throw(DbOperationError, error);
1949  }
1950 
1951  // Get column values.
1952  const CassResult* result_collection = cass_future_get_result(future);
1953 
1954  // lease type is always NA for v4
1955  if (!fetch_type_) {
1956  lease_type_ = Lease::TYPE_NA;
1957  }
1958 
1959  // Since we're currently forced to pull data for all leases, we
1960  // iterate over them, aggregating them into cummulative LeaseStatsRows
1961  AnyArray return_values;
1962  CassIterator* rows = cass_iterator_from_result(result_collection);
1963  while (cass_iterator_next(rows)) {
1964  const CassRow* row = cass_iterator_get_row(rows);
1965  createBindForSelect(return_values, statement_tag);
1966  CqlCommon::getData(row, return_values);
1967 
1968  if (lease_state_ != Lease::STATE_DEFAULT &&
1969  lease_state_ != Lease::STATE_DECLINED) {
1970  continue;
1971  }
1972 
1973  LeaseStatsRow raw_row(subnet_id_, static_cast<Lease::Type>(lease_type_),
1974  lease_state_, 1);
1975 
1976  auto cum_row = cummulative_rows_.find(raw_row);
1977  if (cum_row != cummulative_rows_.end()) {
1978  cummulative_rows_[raw_row] = cum_row->second + 1;
1979  } else {
1980  cummulative_rows_.insert(std::make_pair(raw_row, 1));
1981  }
1982  }
1983 
1984  // Free resources.
1985  cass_iterator_free(rows);
1986  cass_result_free(result_collection);
1987  cass_future_free(future);
1988  cass_statement_free(statement);
1989  return;
1990 }
1991 
1993  : LeaseMgr(), dbconn_(parameters) {
1994  dbconn_.openDatabase();
1995 
1996  // Prepare the version exchange first.
1997  dbconn_.prepareStatements(CqlVersionExchange::tagged_statements_);
1998 
1999  // Validate the schema version.
2000  std::pair<uint32_t, uint32_t> code_version(CQL_SCHEMA_VERSION_MAJOR,
2002  std::pair<uint32_t, uint32_t> db_version = getVersion();
2003  if (code_version != db_version) {
2004  isc_throw(DbOpenError, "Cassandra schema version mismatch: need version: "
2005  << code_version.first << "." << code_version.second
2006  << " found version: " << db_version.first << "."
2007  << db_version.second);
2008  }
2009 
2010  // Now prepare the rest of the exchanges.
2014 }
2015 
2017  // There is no need to close the database in this destructor: it is
2018  // closed in the destructor of the dbconn_ member variable.
2019 }
2020 
2021 std::string
2023  std::stringstream tmp;
2024  tmp << "CQL backend " << CQL_SCHEMA_VERSION_MAJOR;
2025  tmp << "." << CQL_SCHEMA_VERSION_MINOR;
2026  tmp << ", library cassandra";
2027  return tmp.str();
2028 }
2029 
2030 bool
2032  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_ADD_ADDR4)
2033  .arg(lease->addr_.toText());
2034 
2035  AnyArray data;
2036 
2037  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2038  exchange4->createBindForInsert(lease, data);
2039  try {
2040  exchange4->executeMutation(dbconn_, data, CqlLease4Exchange::INSERT_LEASE4);
2041  } catch (const Exception &exception) {
2042  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_LEASE_EXCEPTION_THROWN)
2043  .arg(exception.what());
2044  return false;
2045  }
2046  return true;
2047 }
2048 
2049 bool
2051  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_ADD_ADDR6)
2052  .arg(lease->addr_.toText());
2053 
2054  AnyArray data;
2055 
2056  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2057  exchange6->createBindForInsert(lease, data);
2058  try {
2059  exchange6->executeMutation(dbconn_, data, CqlLease6Exchange::INSERT_LEASE6);
2060  } catch (const Exception &exception) {
2061  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_LEASE_EXCEPTION_THROWN)
2062  .arg(exception.what());
2063  return false;
2064  }
2065  return true;
2066 }
2067 
2068 Lease4Ptr
2069 CqlLeaseMgr::getLease4(const IOAddress &addr) const {
2070  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_ADDR4)
2071  .arg(addr.toText());
2072 
2073  // Set up the WHERE clause value
2074  AnyArray data;
2075 
2076  cass_int32_t address = static_cast<cass_int32_t>(addr.toUint32());
2077  data.add(&address);
2078 
2079  // Get the data.
2080  Lease4Ptr result;
2081 
2082  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2083  exchange4->getLease(CqlLease4Exchange::GET_LEASE4_ADDR, data, result);
2084 
2085  return (result);
2086 }
2087 
2089 CqlLeaseMgr::getLease4(const HWAddr &hwaddr) const {
2090  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_HWADDR)
2091  .arg(hwaddr.toText());
2092 
2093  // Set up the WHERE clause value
2094  AnyArray data;
2095 
2096  CassBlob hwaddr_data(hwaddr.hwaddr_);
2097  data.add(&hwaddr_data);
2098 
2099  // Get the data.
2100  Lease4Collection result;
2101  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2102  exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_HWADDR, data, result);
2103 
2104  return (result);
2105 }
2106 
2107 Lease4Ptr
2108 CqlLeaseMgr::getLease4(const HWAddr &hwaddr, SubnetID subnet_id) const {
2110  DHCPSRV_CQL_GET_SUBID_HWADDR)
2111  .arg(subnet_id)
2112  .arg(hwaddr.toText());
2113 
2114  // Set up the WHERE clause value
2115  AnyArray data;
2116 
2117  CassBlob hwaddr_data(hwaddr.hwaddr_);
2118  data.add(&hwaddr_data);
2119 
2120  cass_int32_t subnet_id_data = static_cast<cass_int32_t>(subnet_id);
2121  data.add(&subnet_id_data);
2122 
2123  // Get the data.
2124  Lease4Ptr result;
2125  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2126  exchange4->getLease(CqlLease4Exchange::GET_LEASE4_HWADDR_SUBID, data, result);
2127 
2128  return (result);
2129 }
2130 
2132 CqlLeaseMgr::getLease4(const ClientId &clientid) const {
2133  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_CLIENTID)
2134  .arg(clientid.toText());
2135 
2136  // Set up the WHERE clause value
2137  AnyArray data;
2138 
2139  CassBlob client_id_data(clientid.getClientId());
2140  data.add(&client_id_data);
2141 
2142  // Get the data.
2143  Lease4Collection result;
2144  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2145  exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_CLIENTID, data, result);
2146 
2147  return (result);
2148 }
2149 
2150 Lease4Ptr
2151 CqlLeaseMgr::getLease4(const ClientId &clientid, const HWAddr &hwaddr,
2152  SubnetID subnet_id) const {
2158  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_CLIENTID_HWADDR_SUBID)
2159  .arg(clientid.toText())
2160  .arg(hwaddr.toText())
2161  .arg(subnet_id);
2162 
2163  isc_throw(NotImplemented, "CqlLeaseMgr::getLease4() is obsolete");
2164 }
2165 
2166 Lease4Ptr
2167 CqlLeaseMgr::getLease4(const ClientId &clientid, SubnetID subnet_id) const {
2168  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_SUBID_CLIENTID)
2169  .arg(subnet_id)
2170  .arg(clientid.toText());
2171 
2172  // Set up the WHERE clause value
2173  AnyArray data;
2174 
2175  CassBlob client_id_data(clientid.getClientId());
2176  data.add(&client_id_data);
2177 
2178  cass_int32_t subnet_id_data = static_cast<cass_int32_t>(subnet_id);
2179  data.add(&subnet_id_data);
2180 
2181  // Get the data.
2182  Lease4Ptr result;
2183  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2184  exchange4->getLease(CqlLease4Exchange::GET_LEASE4_CLIENTID_SUBID, data, result);
2185 
2186  return (result);
2187 }
2188 
2191  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_SUBID4)
2192  .arg(subnet_id);
2193 
2194  // Set up the WHERE clause value
2195  AnyArray data;
2196 
2197  cass_int32_t subnet_id_data = static_cast<cass_int32_t>(subnet_id);
2198  data.add(&subnet_id_data);
2199 
2200  // Get the data.
2201  Lease4Collection result;
2202  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2203  exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_SUBID, data, result);
2204 
2205  return (result);
2206 }
2207 
2211 
2212  // Set up the WHERE clause value
2213  AnyArray data;
2214 
2215  // Get the data.
2216  Lease4Collection result;
2217  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2218  exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4, data, result);
2219 
2220  return (result);
2221 }
2222 
2225  const LeasePageSize& page_size) const {
2226  // Expecting IPv4 address.
2227  if (!lower_bound_address.isV4()) {
2228  isc_throw(InvalidAddressFamily, "expected IPv4 address while "
2229  "retrieving leases from the lease database, got "
2230  << lower_bound_address);
2231  }
2232 
2233  if (page_size.page_size_ == 0) {
2234  isc_throw(OutOfRange, "page size of retrieved leases must not be 0");
2235  }
2236 
2237  if (page_size.page_size_ > std::numeric_limits<uint32_t>::max()) {
2238  isc_throw(OutOfRange, "page size of retrieved leases must not be greater than "
2239  << std::numeric_limits<uint32_t>::max());
2240  }
2241 
2242  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_PAGE4)
2243  .arg(page_size.page_size_)
2244  .arg(lower_bound_address.toText());
2245 
2246  AnyArray data;
2247 
2248  cass_int32_t address_data = 0;
2249  if (!lower_bound_address.isV4Zero()) {
2250  address_data = static_cast<cass_int32_t>(lower_bound_address.toUint32());
2251  data.add(&address_data);
2252  }
2253 
2254  cass_int32_t page_size_data = static_cast<cass_int32_t>(page_size.page_size_);
2255  data.add(&page_size_data);
2256 
2257  // Get the data.
2258  Lease4Collection result;
2259  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2260  exchange4->getLeaseCollection(lower_bound_address.isV4Zero() ?
2263  data, result);
2264 
2265  return (result);
2266 }
2267 
2268 Lease6Ptr
2269 CqlLeaseMgr::getLease6(Lease::Type lease_type, const IOAddress &addr) const {
2270  std::string addr_data = addr.toText();
2271  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_ADDR6)
2272  .arg(addr_data)
2273  .arg(lease_type);
2274 
2275  // Set up the WHERE clause value
2276  AnyArray data;
2277 
2278  if (addr_data.size() > ADDRESS6_TEXT_MAX_LEN) {
2280  "CqlLeaseMgr::getLease6(): "
2281  "address "
2282  << addr_data << " of length " << addr_data.size()
2283  << " exceeds maximum allowed length of "
2284  << ADDRESS6_TEXT_MAX_LEN);
2285  }
2286  data.add(&addr_data);
2287 
2288  cass_int32_t lease_type_data = static_cast<cass_int32_t>(lease_type);
2289  data.add(&lease_type_data);
2290 
2291  Lease6Ptr result;
2292  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2293  exchange6->getLease(CqlLease6Exchange::GET_LEASE6_ADDR, data, result);
2294 
2295  return (result);
2296 }
2297 
2299 CqlLeaseMgr::getLeases6(const DUID& duid) const {
2300 
2301  // Set up the WHERE clause value
2302  AnyArray data;
2303 
2304  CassBlob duid_data(duid.getDuid());
2305 
2306  data.add(&duid_data);
2307 
2308  // Get the data.
2309  Lease6Collection result;
2310  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2311  exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_DUID,
2312  data, result);
2313 
2314  return (result);
2315 }
2316 
2318 CqlLeaseMgr::getLeases6(Lease::Type lease_type, const DUID &duid, uint32_t iaid) const {
2319  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_IAID_DUID)
2320  .arg(iaid)
2321  .arg(duid.toText())
2322  .arg(lease_type);
2323 
2324  // Set up the WHERE clause value
2325  AnyArray data;
2326 
2327  CassBlob duid_data(duid.getDuid());
2328  cass_int32_t iaid_data = static_cast<cass_int32_t>(iaid);
2329 
2330  data.add(&duid_data);
2331  data.add(&iaid_data);
2332 
2333  cass_int32_t lease_type_data = static_cast<cass_int32_t>(lease_type);
2334  data.add(&lease_type_data);
2335 
2336  // Get the data.
2337  Lease6Collection result;
2338  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2339  exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_DUID_IAID, data, result);
2340 
2341  return (result);
2342 }
2343 
2345 CqlLeaseMgr::getLeases6(Lease::Type lease_type, const DUID &duid, uint32_t iaid,
2346  SubnetID subnet_id) const {
2347  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_IAID_SUBID_DUID)
2348  .arg(iaid)
2349  .arg(subnet_id)
2350  .arg(duid.toText())
2351  .arg(lease_type);
2352 
2353  // Set up the WHERE clause value
2354  AnyArray data;
2355 
2356  CassBlob duid_data(duid.getDuid());
2357  cass_int32_t iaid_data = static_cast<cass_int32_t>(iaid);
2358 
2359  data.add(&duid_data);
2360  data.add(&iaid_data);
2361 
2362  cass_int32_t lease_type_data = static_cast<cass_int32_t>(lease_type);
2363  data.add(&lease_type_data);
2364 
2365  cass_int32_t subnet_id_data = static_cast<cass_int32_t>(subnet_id);
2366  data.add(&subnet_id_data);
2367 
2368  // Get the data.
2369  Lease6Collection result;
2370  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2371  exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_DUID_IAID_SUBID, data, result);
2372 
2373  return (result);
2374 }
2375 
2378  isc_throw(NotImplemented, "getLeases6(subnet_id) is not implemented");
2379 }
2380 
2383  isc_throw(NotImplemented, "getLeases6() is not implemented");
2384 }
2385 
2388  const LeasePageSize& page_size) const {
2389  // Expecting IPv6 address.
2390  if (!lower_bound_address.isV6()) {
2391  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
2392  "retrieving leases from the lease database, got "
2393  << lower_bound_address);
2394  }
2395 
2396  if (page_size.page_size_ == 0) {
2397  isc_throw(OutOfRange, "page size of retrieved leases must not be 0");
2398  }
2399 
2400  if (page_size.page_size_ > std::numeric_limits<uint32_t>::max()) {
2401  isc_throw(OutOfRange, "page size of retrieved leases must not be greater than "
2402  << std::numeric_limits<uint32_t>::max());
2403  }
2404 
2405  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_PAGE6)
2406  .arg(page_size.page_size_)
2407  .arg(lower_bound_address.toText());
2408 
2409  AnyArray data;
2410 
2411  std::string lb_address_data;
2412  if (!lower_bound_address.isV6Zero()) {
2413  lb_address_data = lower_bound_address.toText();
2414  if (lb_address_data.size() > ADDRESS6_TEXT_MAX_LEN) {
2416  "CqlLeaseMgr::getLeases6(lower_bound_address, page_size): "
2417  "address "
2418  << lb_address_data << " of length " << lb_address_data.size()
2419  << " exceeds maximum allowed length of "
2420  << ADDRESS6_TEXT_MAX_LEN);
2421  }
2422  data.add(&lb_address_data);
2423  }
2424 
2425  cass_int32_t page_size_data = static_cast<cass_int32_t>(page_size.page_size_);
2426  data.add(&page_size_data);
2427 
2428  // Get the leases.
2429  Lease6Collection result;
2430  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2431  exchange6->getLeaseCollection(lower_bound_address.isV6Zero() ?
2434  data, result);
2435 
2436  return (result);
2437 }
2438 
2439 void
2441  const size_t max_leases) const {
2442  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_EXPIRED4)
2443  .arg(max_leases);
2444 
2445  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2446  exchange4->getExpiredLeases(max_leases, expired_leases);
2447 }
2448 
2449 void
2451  const size_t max_leases) const {
2452  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_EXPIRED6)
2453  .arg(max_leases);
2454 
2455  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2456  exchange6->getExpiredLeases(max_leases, expired_leases);
2457 }
2458 
2459 void
2461  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_UPDATE_ADDR4)
2462  .arg(lease->addr_.toText());
2463 
2464  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2465 
2466  try {
2467  AnyArray data;
2468  exchange4->createBindForUpdate(lease, data, CqlLease4Exchange::UPDATE_LEASE4);
2469  exchange4->executeMutation(dbconn_, data, CqlLease4Exchange::UPDATE_LEASE4);
2470  } catch (const StatementNotApplied &exception) {
2471  isc_throw(NoSuchLease, exception.what());
2472  }
2473 }
2474 
2475 void
2477  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_UPDATE_ADDR6)
2478  .arg(lease->addr_.toText());
2479 
2480  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2481 
2482  try {
2483  AnyArray data;
2484  exchange6->createBindForUpdate(lease, data, CqlLease6Exchange::UPDATE_LEASE6);
2485  exchange6->executeMutation(dbconn_, data, CqlLease6Exchange::UPDATE_LEASE6);
2486  } catch (const StatementNotApplied &exception) {
2487  isc_throw(NoSuchLease, exception.what());
2488  }
2489 }
2490 
2491 bool
2493  std::string addr_data = addr.toText();
2494  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_DELETE_ADDR)
2495  .arg(addr_data);
2496 
2497  // Set up the WHERE clause value
2498  AnyArray data;
2499 
2500  try {
2501  if (addr.isV4()) {
2502  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2503  exchange4->createBindForDelete(addr, data, CqlLease4Exchange::DELETE_LEASE4);
2504  exchange4->executeMutation(dbconn_, data, CqlLease4Exchange::DELETE_LEASE4);
2505  } else if (addr.isV6()) {
2506  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2507  exchange6->createBindForDelete(addr, data, CqlLease6Exchange::DELETE_LEASE6);
2508  exchange6->executeMutation(dbconn_, data, CqlLease6Exchange::DELETE_LEASE6);
2509  } else {
2510  return false;
2511  }
2512  } catch (const Exception &exception) {
2513  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_LEASE_EXCEPTION_THROWN)
2514  .arg(exception.what());
2515  return false;
2516  }
2517  return true;
2518 }
2519 
2520 uint64_t
2523  DHCPSRV_CQL_DELETE_EXPIRED_RECLAIMED4)
2524  .arg(secs);
2525  AnyArray data;
2526  uint64_t deleted = 0u;
2527  cass_int32_t limit = 1024;
2528 
2529  // State is reclaimed.
2530  cass_int32_t state = static_cast<cass_int32_t>(Lease::STATE_EXPIRED_RECLAIMED);
2531  data.add(&state);
2532 
2533  // Expiration timestamp.
2534  cass_int64_t expiration = static_cast<cass_int64_t>(time(NULL) - static_cast<time_t>(secs));
2535  data.add(&expiration);
2536 
2537  data.add(&limit);
2538 
2539  // Get the data.
2540  Lease4Collection leases;
2541  std::unique_ptr<CqlLease4Exchange> exchange4(new CqlLease4Exchange(dbconn_));
2542  exchange4->getLeaseCollection(CqlLease4Exchange::GET_LEASE4_EXPIRE, data, leases);
2543  for (Lease4Ptr &lease : leases) {
2544  if (deleteLease(lease->addr_)) {
2545  ++deleted;
2546  }
2547  }
2548  return (deleted);
2549 }
2550 
2551 uint64_t
2554  DHCPSRV_CQL_DELETE_EXPIRED_RECLAIMED6)
2555  .arg(secs);
2556  AnyArray data;
2557  uint64_t n_of_deleted_leases = 0u;
2558  cass_int32_t limit = 1024;
2559 
2560  // State is reclaimed.
2561  cass_int32_t state = static_cast<cass_int32_t>(Lease::STATE_EXPIRED_RECLAIMED);
2562  data.add(&state);
2563 
2564  // Expiration timestamp.
2565  cass_int64_t expiration = static_cast<cass_int64_t>(time(NULL) - static_cast<time_t>(secs));
2566  data.add(&expiration);
2567 
2568  data.add(&limit);
2569 
2570  // Get the data.
2571  Lease6Collection leases;
2572  std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
2573  exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_EXPIRE, data, leases);
2574  for (Lease6Ptr &lease : leases) {
2575  if (deleteLease(lease->addr_)) {
2576  ++n_of_deleted_leases;
2577  }
2578  }
2579  return n_of_deleted_leases;
2580 }
2581 
2584  LeaseStatsQueryPtr query(
2586  false));
2587  query->start();
2588  return(query);
2589 }
2590 
2593  LeaseStatsQueryPtr query(
2595  false, subnet_id));
2596  query->start();
2597  return(query);
2598 }
2599 
2602  const SubnetID& last_subnet_id) {
2603  LeaseStatsQueryPtr query(
2605  false, first_subnet_id, last_subnet_id));
2606  query->start();
2607  return(query);
2608 }
2609 
2612  LeaseStatsQueryPtr query(
2614  true));
2615  query->start();
2616  return(query);
2617 }
2618 
2621  LeaseStatsQueryPtr query(
2623  true, subnet_id));
2624  query->start();
2625  return(query);
2626 }
2627 
2630  const SubnetID& last_subnet_id) {
2631  LeaseStatsQueryPtr query(
2633  true, first_subnet_id, last_subnet_id));
2634  query->start();
2635  return(query);
2636 }
2637 
2638 size_t
2639 CqlLeaseMgr::wipeLeases4(const SubnetID & /*subnet_id*/) {
2641  isc_throw(NotImplemented, "wipeLeases4 is not implemented for Cassandra backend");
2642 }
2643 
2644 size_t
2645 CqlLeaseMgr::wipeLeases6(const SubnetID & /*subnet_id*/) {
2647  isc_throw(NotImplemented, "wipeLeases6 is not implemented for Cassandra backend");
2648 }
2649 
2650 std::string
2652  std::string name = "";
2653  try {
2654  name = dbconn_.getParameter("name");
2655  } catch (...) {
2656  // Return an empty name
2657  }
2658  return name;
2659 }
2660 
2661 std::string
2663  return std::string("Cassandra Database");
2664 }
2665 
2668  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_VERSION);
2669 
2670  std::unique_ptr<CqlVersionExchange> version_exchange(new CqlVersionExchange());
2671  return version_exchange->retrieveVersion(dbconn_);
2672 }
2673 
2674 void
2676  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_COMMIT);
2677  dbconn_.commit();
2678 }
2679 
2680 void
2682  LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_ROLLBACK);
2683  dbconn_.rollback();
2684 }
2685 
2686 } // namespace dhcp
2687 } // 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.
virtual void createBindForSelect(AnyArray &data, StatementTag statement_tag=NULL) override
Create BIND array to receive data.
static constexpr StatementTag UPDATE_LEASE4
static constexpr StatementTag GET_LEASE6_DUID_IAID
static constexpr StatementTag GET_LEASE4_SUBID
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...
std::pair< uint32_t, uint32_t > VersionPair
Pair containing major and minor versions.
Definition: lease_mgr.h:40
virtual void rollback() override
Rollback Transactions.
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.
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:67
const std::vector< uint8_t > & getClientId() const
Returns reference to the client-id data.
Definition: duid.cc:116
virtual LeaseStatsQueryPtr startLeaseStatsQuery4() override
Creates and runs the IPv4 lease stats query.
Structure that holds a lease for IPv4 address.
Definition: lease.h:256
virtual void createBindForSelect(AnyArray &data, StatementTag statement_tag=NULL) override
Create BIND array to receive data.
Structure used to bind C++ input values to dynamic CQL parameters.
Definition: cql_exchange.h:50
Abstract Lease Manager.
Definition: lease_mgr.h:222
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.
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.
static constexpr StatementTag DELETE_LEASE4
virtual bool addLease(const Lease4Ptr &lease) override
Adds an IPv4 lease.
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.
static constexpr StatementTag GET_LEASE4_ADDR
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:455
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:41
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
virtual void rollback()
Rollback Transactions.
Base class for fulfilling a statistical lease data query.
Definition: lease_mgr.h:128
Exchange Lease4 information between Kea and CQL.
Exchange Lease6 information between Kea and CQL.
void createBindForInsert(const Lease6Ptr &lease, AnyArray &data)
Create CQL_BIND objects for Lease6 Pointer.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
Cassandra Exchange.
Definition: cql_exchange.h:142
static StatementMap tagged_statements_
Cassandra statements.
Holds DUID (DHCPv6 Unique Identifier)
Definition: duid.h:27
static constexpr StatementTag GET_LEASE6_DUID_IAID_SUBID
void createBindForDelete(const IOAddress &address, AnyArray &data, StatementTag statement_tag=NULL)
Create CQL_BIND objects for Lease4 Pointer.
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.
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_LEASE4_CLIENTID_SUBID
static constexpr StatementTag GET_LEASE6_EXPIRE
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
static constexpr StatementTag GET_LEASE4_LIMIT
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.
static constexpr StatementTag GET_LEASE4
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:245
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.
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
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.
SubnetID subnet_id_
The subnet ID to which this data applies.
Definition: lease_mgr.h:114
static constexpr StatementTag GET_LEASE4_EXPIRE
static std::string getDBVersion()
Local version of getDBVersion() class method.
cass_int64_t valid_lifetime_
Lease timer.
virtual void updateLease4(const Lease4Ptr &lease4) override
Updates IPv4 lease.
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 ~CqlLeaseMgr()
Destructor (closes database)
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.
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:471
std::string user_context_
User context.
std::string getParameter(const std::string &name) const
Returns value of a connection parameter.
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:604
static constexpr StatementTag GET_LEASE4_HWADDR
the lease contains temporary IPv6 address
Definition: lease.h:40
virtual boost::any retrieve() override
Retrieves the Lease6 object in Kea format.
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.
const std::vector< uint8_t > & getDuid() const
Returns a const reference to the actual DUID value.
Definition: duid.cc:44
the lease contains non-temporary IPv6 address
Definition: lease.h:39
Ethernet 10Mbps.
Definition: dhcp4.h:56
Invalid address family used as input to Lease Manager.
Definition: db_exceptions.h:64
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: 3.0.
Defines the logger used by the top-level component of kea-dhcp-ddns.
CqlLeaseMgr(const db::DatabaseConnection::ParameterMap &parameters)
Constructor.
static constexpr StatementTag SUBNET_LEASE6_STATS
Return lease6 lease statistics for a single subnet.
Exchange used to retrieve schema version from the keyspace.
Definition: cql_exchange.h:236
virtual void createBindForSelect(AnyArray &data, StatementTag statement_tag=NULL)
Create BIND array to receive C++ data.
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
static constexpr StatementTag GET_LEASE4_CLIENTID
static constexpr StatementTag GET_LEASE4_HWADDR_SUBID
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:38
Holds Client identifier or client IPv4 address.
Definition: duid.h:111
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.
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
void createBindForDelete(const IOAddress &address, AnyArray &data, StatementTag statement_tag=NULL)
Create CQL_BIND objects for Lease4 Pointer.
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:61
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...
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.
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:64
Contains a single row of lease statistical data.
Definition: lease_mgr.h:61
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
Definition: duid.cc:74
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.
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:460
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.
virtual VersionPair retrieveVersion(const CqlConnection &connection)
Standalone method used to retrieve schema version.
virtual bool deleteLease(const isc::asiolink::IOAddress &addr) override
Deletes a lease.
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
Definition: duid.cc:121
Exception thrown on failure to execute a database function.
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.
std::string toText(bool include_htype=true) const
Returns textual representation of a hardware address (e.g.
Definition: hwaddr.cc:51
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Definition: lease.h:24
static constexpr StatementTag INSERT_LEASE4
Statement tags definitions.
CqlLease6Exchange(const CqlConnection &connection)
Constructor.