Kea  2.3.5-git
memfile_lease_mgr.cc
Go to the documentation of this file.
1 // Copyright (C) 2012-2023 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
12 #include <dhcpsrv/cfgmgr.h>
14 #include <dhcpsrv/dhcpsrv_log.h>
17 #include <dhcpsrv/timer_mgr.h>
18 #include <exceptions/exceptions.h>
19 #include <stats/stats_mgr.h>
21 #include <util/pid_file.h>
22 
23 #include <cstdio>
24 #include <cstring>
25 #include <errno.h>
26 #include <iostream>
27 #include <limits>
28 #include <sstream>
29 
30 namespace {
31 
39 const char* KEA_LFC_EXECUTABLE_ENV_NAME = "KEA_LFC_EXECUTABLE";
40 
41 } // namespace
42 
43 using namespace isc::asiolink;
44 using namespace isc::data;
45 using namespace isc::db;
46 using namespace isc::util;
47 using namespace isc::stats;
48 
49 namespace isc {
50 namespace dhcp {
51 
66 class LFCSetup {
67 public:
68 
77 
81  ~LFCSetup();
82 
94  void setup(const uint32_t lfc_interval,
95  const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
96  const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
97  bool run_once_now = false);
98 
100  void execute();
101 
105  bool isRunning() const;
106 
108  int getExitStatus() const;
109 
110 private:
111 
114  boost::scoped_ptr<ProcessSpawn> process_;
115 
118 
120  pid_t pid_;
121 
126  TimerMgrPtr timer_mgr_;
127 };
128 
129 LFCSetup::LFCSetup(asiolink::IntervalTimer::Callback callback)
130  : process_(), callback_(callback), pid_(0),
131  timer_mgr_(TimerMgr::instance()) {
132 }
133 
135  try {
136  // Remove the timer. This will throw an exception if the timer does not
137  // exist. There are several possible reasons for this:
138  // a) It hasn't been registered (although if the LFC Setup instance
139  // exists it means that the timer must have been registered or that
140  // such registration has been attempted).
141  // b) The registration may fail if the duplicate timer exists or if the
142  // TimerMgr's worker thread is running but if this happens it is a
143  // programming error.
144  // c) The program is shutting down and the timer has been removed by
145  // another component.
146  timer_mgr_->unregisterTimer("memfile-lfc");
147 
148  } catch (const std::exception& ex) {
149  // We don't want exceptions being thrown from the destructor so we just
150  // log a message here. The message is logged at debug severity as
151  // we don't want an error message output during shutdown.
154  }
155 }
156 
157 void
158 LFCSetup::setup(const uint32_t lfc_interval,
159  const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
160  const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
161  bool run_once_now) {
162 
163  // If to nothing to do, punt
164  if (lfc_interval == 0 && !run_once_now) {
165  return;
166  }
167 
168  // Start preparing the command line for kea-lfc.
169  std::string executable;
170  char* c_executable = getenv(KEA_LFC_EXECUTABLE_ENV_NAME);
171  if (!c_executable) {
172  executable = KEA_LFC_EXECUTABLE;
173  } else {
174  executable = c_executable;
175  }
176 
177  // Gather the base file name.
178  std::string lease_file = lease_file4 ? lease_file4->getFilename() :
179  lease_file6->getFilename();
180 
181  // Create the other names by appending suffixes to the base name.
182  ProcessArgs args;
183  // Universe: v4 or v6.
184  args.push_back(lease_file4 ? "-4" : "-6");
185 
186  // Previous file.
187  args.push_back("-x");
188  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
190  // Input file.
191  args.push_back("-i");
192  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
194  // Output file.
195  args.push_back("-o");
196  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
198  // Finish file.
199  args.push_back("-f");
200  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
202  // PID file.
203  args.push_back("-p");
204  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
206 
207  // The configuration file is currently unused.
208  args.push_back("-c");
209  args.push_back("ignored-path");
210 
211  // Create the process (do not start it yet).
212  process_.reset(new ProcessSpawn(LeaseMgr::getIOService(), executable, args));
213 
214  // If we've been told to run it once now, invoke the callback directly.
215  if (run_once_now) {
216  callback_();
217  }
218 
219  // If it's supposed to run periodically, setup that now.
220  if (lfc_interval > 0) {
221  // Set the timer to call callback function periodically.
223 
224  // Multiple the lfc_interval value by 1000 as this value specifies
225  // a timeout in seconds, whereas the setup() method expects the
226  // timeout in milliseconds.
227  timer_mgr_->registerTimer("memfile-lfc", callback_, lfc_interval * 1000,
229  timer_mgr_->setup("memfile-lfc");
230  }
231 }
232 
233 void
235  try {
237  .arg(process_->getCommandLine());
238  pid_ = process_->spawn();
239 
240  } catch (const ProcessSpawnError&) {
242  }
243 }
244 
245 bool
247  return (process_ && process_->isRunning(pid_));
248 }
249 
250 int
252  if (!process_) {
253  isc_throw(InvalidOperation, "unable to obtain LFC process exit code: "
254  " the process is null");
255  }
256  return (process_->getExitStatus(pid_));
257 }
258 
259 
266 public:
270  : rows_(0), next_pos_(rows_.end()) {
271  };
272 
277  : LeaseStatsQuery(subnet_id), rows_(0), next_pos_(rows_.end()) {
278  };
279 
284  MemfileLeaseStatsQuery(const SubnetID& first_subnet_id, const SubnetID& last_subnet_id)
285  : LeaseStatsQuery(first_subnet_id, last_subnet_id), rows_(0), next_pos_(rows_.end()) {
286  };
287 
290 
301  virtual bool getNextRow(LeaseStatsRow& row) {
302  if (next_pos_ == rows_.end()) {
303  return (false);
304  }
305 
306  row = *next_pos_;
307  ++next_pos_;
308  return (true);
309  }
310 
312  int getRowCount() const {
313  return (rows_.size());
314  }
315 
316 protected:
318  std::vector<LeaseStatsRow> rows_;
319 
321  std::vector<LeaseStatsRow>::iterator next_pos_;
322 };
323 
334 public:
339  : MemfileLeaseStatsQuery(), storage4_(storage4) {
340  };
341 
346  MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& subnet_id)
347  : MemfileLeaseStatsQuery(subnet_id), storage4_(storage4) {
348  };
349 
355  MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& first_subnet_id,
356  const SubnetID& last_subnet_id)
357  : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage4_(storage4) {
358  };
359 
362 
377  void start() {
378  const Lease4StorageSubnetIdIndex& idx
379  = storage4_.get<SubnetIdIndexTag>();
380 
381  // Set lower and upper bounds based on select mode
382  Lease4StorageSubnetIdIndex::const_iterator lower;
383  Lease4StorageSubnetIdIndex::const_iterator upper;
384  switch (getSelectMode()) {
385  case ALL_SUBNETS:
386  lower = idx.begin();
387  upper = idx.end();
388  break;
389 
390  case SINGLE_SUBNET:
391  lower = idx.lower_bound(getFirstSubnetID());
392  upper = idx.upper_bound(getFirstSubnetID());
393  break;
394 
395  case SUBNET_RANGE:
396  lower = idx.lower_bound(getFirstSubnetID());
397  upper = idx.upper_bound(getLastSubnetID());
398  break;
399  }
400 
401  // Return an empty set if there are no rows.
402  if (lower == upper) {
403  return;
404  }
405 
406  // Iterate over the leases in order by subnet, accumulating per
407  // subnet counts for each state of interest. As we finish each
408  // subnet, add the appropriate rows to our result set.
409  SubnetID cur_id = 0;
410  int64_t assigned = 0;
411  int64_t declined = 0;
412  for (Lease4StorageSubnetIdIndex::const_iterator lease = lower;
413  lease != upper; ++lease) {
414  // If we've hit the next subnet, add rows for the current subnet
415  // and wipe the accumulators
416  if ((*lease)->subnet_id_ != cur_id) {
417  if (cur_id > 0) {
418  if (assigned > 0) {
419  rows_.push_back(LeaseStatsRow(cur_id,
421  assigned));
422  assigned = 0;
423  }
424 
425  if (declined > 0) {
426  rows_.push_back(LeaseStatsRow(cur_id,
428  declined));
429  declined = 0;
430  }
431  }
432 
433  // Update current subnet id
434  cur_id = (*lease)->subnet_id_;
435  }
436 
437  // Bump the appropriate accumulator
438  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
439  ++assigned;
440  } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
441  ++declined;
442  }
443  }
444 
445  // Make the rows for last subnet
446  if (assigned > 0) {
447  rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
448  assigned));
449  }
450 
451  if (declined > 0) {
452  rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
453  declined));
454  }
455 
456  // Reset the next row position back to the beginning of the rows.
457  next_pos_ = rows_.begin();
458  }
459 
460 private:
462  Lease4Storage& storage4_;
463 };
464 
465 
476 public:
481  : MemfileLeaseStatsQuery(), storage6_(storage6) {
482  };
483 
488  MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& subnet_id)
489  : MemfileLeaseStatsQuery(subnet_id), storage6_(storage6) {
490  };
491 
497  MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& first_subnet_id,
498  const SubnetID& last_subnet_id)
499  : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage6_(storage6) {
500  };
501 
504 
518  virtual void start() {
519  // Get the subnet_id index
520  const Lease6StorageSubnetIdIndex& idx
521  = storage6_.get<SubnetIdIndexTag>();
522 
523  // Set lower and upper bounds based on select mode
524  Lease6StorageSubnetIdIndex::const_iterator lower;
525  Lease6StorageSubnetIdIndex::const_iterator upper;
526  switch (getSelectMode()) {
527  case ALL_SUBNETS:
528  lower = idx.begin();
529  upper = idx.end();
530  break;
531 
532  case SINGLE_SUBNET:
533  lower = idx.lower_bound(getFirstSubnetID());
534  upper = idx.upper_bound(getFirstSubnetID());
535  break;
536 
537  case SUBNET_RANGE:
538  lower = idx.lower_bound(getFirstSubnetID());
539  upper = idx.upper_bound(getLastSubnetID());
540  break;
541  }
542 
543  // Return an empty set if there are no rows.
544  if (lower == upper) {
545  return;
546  }
547 
548  // Iterate over the leases in order by subnet, accumulating per
549  // subnet counts for each state of interest. As we finish each
550  // subnet, add the appropriate rows to our result set.
551  SubnetID cur_id = 0;
552  int64_t assigned = 0;
553  int64_t declined = 0;
554  int64_t assigned_pds = 0;
555  for (Lease6StorageSubnetIdIndex::const_iterator lease = lower;
556  lease != upper; ++lease) {
557  // If we've hit the next subnet, add rows for the current subnet
558  // and wipe the accumulators
559  if ((*lease)->subnet_id_ != cur_id) {
560  if (cur_id > 0) {
561  if (assigned > 0) {
562  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
564  assigned));
565  assigned = 0;
566  }
567 
568  if (declined > 0) {
569  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
571  declined));
572  declined = 0;
573  }
574 
575  if (assigned_pds > 0) {
576  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
578  assigned_pds));
579  assigned_pds = 0;
580  }
581  }
582 
583  // Update current subnet id
584  cur_id = (*lease)->subnet_id_;
585  }
586 
587  // Bump the appropriate accumulator
588  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
589  switch((*lease)->type_) {
590  case Lease::TYPE_NA:
591  ++assigned;
592  break;
593  case Lease::TYPE_PD:
594  ++assigned_pds;
595  break;
596  default:
597  break;
598  }
599  } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
600  // In theory only NAs can be declined
601  if (((*lease)->type_) == Lease::TYPE_NA) {
602  ++declined;
603  }
604  }
605  }
606 
607  // Make the rows for last subnet, unless there were no rows
608  if (assigned > 0) {
609  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
610  Lease::STATE_DEFAULT, assigned));
611  }
612 
613  if (declined > 0) {
614  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
615  Lease::STATE_DECLINED, declined));
616  }
617 
618  if (assigned_pds > 0) {
619  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
620  Lease::STATE_DEFAULT, assigned_pds));
621  }
622 
623  // Set the next row position to the beginning of the rows.
624  next_pos_ = rows_.begin();
625  }
626 
627 private:
629  Lease6Storage& storage6_;
630 };
631 
632 // Explicit definition of class static constants. Values are given in the
633 // declaration so they're not needed here.
638 
640  : LeaseMgr(), lfc_setup_(), conn_(parameters), mutex_(new std::mutex) {
641  bool conversion_needed = false;
642 
643  // Check if the extended info tables are enabled.
644  setExtendedInfoTablesEnabled(parameters);
645 
646  // Check the universe and use v4 file or v6 file.
647  std::string universe = conn_.getParameter("universe");
648  if (universe == "4") {
649  std::string file4 = initLeaseFilePath(V4);
650  if (!file4.empty()) {
651  conversion_needed = loadLeasesFromFiles<Lease4,
652  CSVLeaseFile4>(file4,
653  lease_file4_,
654  storage4_);
655  }
656  } else {
657  std::string file6 = initLeaseFilePath(V6);
658  if (!file6.empty()) {
659  conversion_needed = loadLeasesFromFiles<Lease6,
660  CSVLeaseFile6>(file6,
661  lease_file6_,
662  storage6_);
663  static_cast<void>(buildExtendedInfoTables6Internal(false, false));
664  }
665  }
666 
667  // If lease persistence have been disabled for both v4 and v6,
668  // issue a warning. It is ok not to write leases to disk when
669  // doing testing, but it should not be done in normal server
670  // operation.
671  if (!persistLeases(V4) && !persistLeases(V6)) {
673  } else {
674  if (conversion_needed) {
675  auto const& version(getVersion());
677  .arg(version.first).arg(version.second);
678  }
679  lfcSetup(conversion_needed);
680  }
681 }
682 
684  if (lease_file4_) {
685  lease_file4_->close();
686  lease_file4_.reset();
687  }
688  if (lease_file6_) {
689  lease_file6_->close();
690  lease_file6_.reset();
691  }
692 }
693 
694 std::string
696  std::stringstream tmp;
697  tmp << "Memfile backend ";
698  if (u == V4) {
699  tmp << MAJOR_VERSION_V4 << "." << MINOR_VERSION_V4;
700  } else if (u == V6) {
701  tmp << MAJOR_VERSION_V6 << "." << MINOR_VERSION_V6;
702  }
703  return tmp.str();
704 }
705 
706 bool
707 Memfile_LeaseMgr::addLeaseInternal(const Lease4Ptr& lease) {
708  if (getLease4Internal(lease->addr_)) {
709  // there is a lease with specified address already
710  return (false);
711  }
712 
713  // Try to write a lease to disk first. If this fails, the lease will
714  // not be inserted to the memory and the disk and in-memory data will
715  // remain consistent.
716  if (persistLeases(V4)) {
717  lease_file4_->append(*lease);
718  }
719 
720  storage4_.insert(lease);
721 
722  // Update lease current expiration time (allows update between the creation
723  // of the Lease up to the point of insertion in the database).
724  lease->updateCurrentExpirationTime();
725 
726  // Increment class lease counters.
727  class_lease_counter_.addLease(lease);
728 
729  return (true);
730 }
731 
732 bool
735  DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
736 
737  if (MultiThreadingMgr::instance().getMode()) {
738  std::lock_guard<std::mutex> lock(*mutex_);
739  return (addLeaseInternal(lease));
740  } else {
741  return (addLeaseInternal(lease));
742  }
743 }
744 
745 bool
746 Memfile_LeaseMgr::addLeaseInternal(const Lease6Ptr& lease) {
747  if (getLease6Internal(lease->type_, lease->addr_)) {
748  // there is a lease with specified address already
749  return (false);
750  }
751 
752  // Try to write a lease to disk first. If this fails, the lease will
753  // not be inserted to the memory and the disk and in-memory data will
754  // remain consistent.
755  if (persistLeases(V6)) {
756  lease_file6_->append(*lease);
757  }
758 
759  lease->extended_info_action_ = Lease::ACTION_IGNORE;
760  storage6_.insert(lease);
761 
762  // Update lease current expiration time (allows update between the creation
763  // of the Lease up to the point of insertion in the database).
764  lease->updateCurrentExpirationTime();
765 
766  // Increment class lease counters.
767  class_lease_counter_.addLease(lease);
768 
770  static_cast<void>(addExtendedInfo6(lease));
771  }
772 
773  return (true);
774 }
775 
776 bool
779  DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
780 
781  if (MultiThreadingMgr::instance().getMode()) {
782  std::lock_guard<std::mutex> lock(*mutex_);
783  return (addLeaseInternal(lease));
784  } else {
785  return (addLeaseInternal(lease));
786  }
787 }
788 
789 Lease4Ptr
790 Memfile_LeaseMgr::getLease4Internal(const isc::asiolink::IOAddress& addr) const {
791  const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
792  Lease4StorageAddressIndex::iterator l = idx.find(addr);
793  if (l == idx.end()) {
794  return (Lease4Ptr());
795  } else {
796  return (Lease4Ptr(new Lease4(**l)));
797  }
798 }
799 
800 Lease4Ptr
803  DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
804 
805  if (MultiThreadingMgr::instance().getMode()) {
806  std::lock_guard<std::mutex> lock(*mutex_);
807  return (getLease4Internal(addr));
808  } else {
809  return (getLease4Internal(addr));
810  }
811 }
812 
813 void
814 Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
815  Lease4Collection& collection) const {
816  // Using composite index by 'hw address' and 'subnet id'. It is
817  // ok to use it for searching by the 'hw address' only.
819  storage4_.get<HWAddressSubnetIdIndexTag>();
820  std::pair<Lease4StorageHWAddressSubnetIdIndex::const_iterator,
821  Lease4StorageHWAddressSubnetIdIndex::const_iterator> l
822  = idx.equal_range(boost::make_tuple(hwaddr.hwaddr_));
823 
824  for (auto lease = l.first; lease != l.second; ++lease) {
825  collection.push_back(Lease4Ptr(new Lease4(**lease)));
826  }
827 }
828 
830 Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr) const {
832  DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.toText());
833 
834  Lease4Collection collection;
835  if (MultiThreadingMgr::instance().getMode()) {
836  std::lock_guard<std::mutex> lock(*mutex_);
837  getLease4Internal(hwaddr, collection);
838  } else {
839  getLease4Internal(hwaddr, collection);
840  }
841 
842  return (collection);
843 }
844 
845 Lease4Ptr
846 Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
847  SubnetID subnet_id) const {
848  // Get the index by HW Address and Subnet Identifier.
850  storage4_.get<HWAddressSubnetIdIndexTag>();
851  // Try to find the lease using HWAddr and subnet id.
852  Lease4StorageHWAddressSubnetIdIndex::const_iterator lease =
853  idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
854  // Lease was not found. Return empty pointer to the caller.
855  if (lease == idx.end()) {
856  return (Lease4Ptr());
857  }
858 
859  // Lease was found. Return it to the caller.
860  return (Lease4Ptr(new Lease4(**lease)));
861 }
862 
863 Lease4Ptr
865  SubnetID subnet_id) const {
867  DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
868  .arg(hwaddr.toText());
869 
870  if (MultiThreadingMgr::instance().getMode()) {
871  std::lock_guard<std::mutex> lock(*mutex_);
872  return (getLease4Internal(hwaddr, subnet_id));
873  } else {
874  return (getLease4Internal(hwaddr, subnet_id));
875  }
876 }
877 
878 void
879 Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
880  Lease4Collection& collection) const {
881  // Using composite index by 'client id' and 'subnet id'. It is ok
882  // to use it to search by 'client id' only.
884  storage4_.get<ClientIdSubnetIdIndexTag>();
885  std::pair<Lease4StorageClientIdSubnetIdIndex::const_iterator,
886  Lease4StorageClientIdSubnetIdIndex::const_iterator> l
887  = idx.equal_range(boost::make_tuple(client_id.getClientId()));
888 
889  for (auto lease = l.first; lease != l.second; ++lease) {
890  collection.push_back(Lease4Ptr(new Lease4(**lease)));
891  }
892 }
893 
895 Memfile_LeaseMgr::getLease4(const ClientId& client_id) const {
897  DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.toText());
898 
899  Lease4Collection collection;
900  if (MultiThreadingMgr::instance().getMode()) {
901  std::lock_guard<std::mutex> lock(*mutex_);
902  getLease4Internal(client_id, collection);
903  } else {
904  getLease4Internal(client_id, collection);
905  }
906 
907  return (collection);
908 }
909 
910 Lease4Ptr
911 Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
912  SubnetID subnet_id) const {
913  // Get the index by client and subnet id.
915  storage4_.get<ClientIdSubnetIdIndexTag>();
916  // Try to get the lease using client id and subnet id.
917  Lease4StorageClientIdSubnetIdIndex::const_iterator lease =
918  idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
919  // Lease was not found. Return empty pointer to the caller.
920  if (lease == idx.end()) {
921  return (Lease4Ptr());
922  }
923  // Lease was found. Return it to the caller.
924  return (Lease4Ptr(new Lease4(**lease)));
925 }
926 
927 Lease4Ptr
929  SubnetID subnet_id) const {
931  DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id)
932  .arg(client_id.toText());
933 
934  if (MultiThreadingMgr::instance().getMode()) {
935  std::lock_guard<std::mutex> lock(*mutex_);
936  return (getLease4Internal(client_id, subnet_id));
937  } else {
938  return (getLease4Internal(client_id, subnet_id));
939  }
940 }
941 
942 void
943 Memfile_LeaseMgr::getLeases4Internal(SubnetID subnet_id,
944  Lease4Collection& collection) const {
945  const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
946  std::pair<Lease4StorageSubnetIdIndex::const_iterator,
947  Lease4StorageSubnetIdIndex::const_iterator> l =
948  idx.equal_range(subnet_id);
949 
950  for (auto lease = l.first; lease != l.second; ++lease) {
951  collection.push_back(Lease4Ptr(new Lease4(**lease)));
952  }
953 }
954 
958  .arg(subnet_id);
959 
960  Lease4Collection collection;
961  if (MultiThreadingMgr::instance().getMode()) {
962  std::lock_guard<std::mutex> lock(*mutex_);
963  getLeases4Internal(subnet_id, collection);
964  } else {
965  getLeases4Internal(subnet_id, collection);
966  }
967 
968  return (collection);
969 }
970 
971 void
972 Memfile_LeaseMgr::getLeases4Internal(const std::string& hostname,
973  Lease4Collection& collection) const {
974  const Lease4StorageHostnameIndex& idx = storage4_.get<HostnameIndexTag>();
975  std::pair<Lease4StorageHostnameIndex::const_iterator,
976  Lease4StorageHostnameIndex::const_iterator> l =
977  idx.equal_range(hostname);
978 
979  for (auto lease = l.first; lease != l.second; ++lease) {
980  collection.push_back(Lease4Ptr(new Lease4(**lease)));
981  }
982 }
983 
985 Memfile_LeaseMgr::getLeases4(const std::string& hostname) const {
987  .arg(hostname);
988 
989  Lease4Collection collection;
990  if (MultiThreadingMgr::instance().getMode()) {
991  std::lock_guard<std::mutex> lock(*mutex_);
992  getLeases4Internal(hostname, collection);
993  } else {
994  getLeases4Internal(hostname, collection);
995  }
996 
997  return (collection);
998 }
999 
1000 void
1001 Memfile_LeaseMgr::getLeases4Internal(Lease4Collection& collection) const {
1002  for (auto lease = storage4_.begin(); lease != storage4_.end(); ++lease) {
1003  collection.push_back(Lease4Ptr(new Lease4(**lease)));
1004  }
1005 }
1006 
1010 
1011  Lease4Collection collection;
1012  if (MultiThreadingMgr::instance().getMode()) {
1013  std::lock_guard<std::mutex> lock(*mutex_);
1014  getLeases4Internal(collection);
1015  } else {
1016  getLeases4Internal(collection);
1017  }
1018 
1019  return (collection);
1020 }
1021 
1022 void
1023 Memfile_LeaseMgr::getLeases4Internal(const asiolink::IOAddress& lower_bound_address,
1024  const LeasePageSize& page_size,
1025  Lease4Collection& collection) const {
1026  const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1027  Lease4StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1028 
1029  // Exclude the lower bound address specified by the caller.
1030  if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1031  ++lb;
1032  }
1033 
1034  // Return all other leases being within the page size.
1035  for (auto lease = lb;
1036  (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1037  ++lease) {
1038  collection.push_back(Lease4Ptr(new Lease4(**lease)));
1039  }
1040 }
1041 
1044  const LeasePageSize& page_size) const {
1045  // Expecting IPv4 address.
1046  if (!lower_bound_address.isV4()) {
1047  isc_throw(InvalidAddressFamily, "expected IPv4 address while "
1048  "retrieving leases from the lease database, got "
1049  << lower_bound_address);
1050  }
1051 
1053  .arg(page_size.page_size_)
1054  .arg(lower_bound_address.toText());
1055 
1056  Lease4Collection collection;
1057  if (MultiThreadingMgr::instance().getMode()) {
1058  std::lock_guard<std::mutex> lock(*mutex_);
1059  getLeases4Internal(lower_bound_address, page_size, collection);
1060  } else {
1061  getLeases4Internal(lower_bound_address, page_size, collection);
1062  }
1063 
1064  return (collection);
1065 }
1066 
1067 Lease6Ptr
1068 Memfile_LeaseMgr::getLease6Internal(Lease::Type type,
1069  const isc::asiolink::IOAddress& addr) const {
1070  Lease6Storage::iterator l = storage6_.find(addr);
1071  if (l == storage6_.end() || !(*l) || ((*l)->type_ != type)) {
1072  return (Lease6Ptr());
1073  } else {
1074  return (Lease6Ptr(new Lease6(**l)));
1075  }
1076 }
1077 
1078 Lease6Ptr
1079 Memfile_LeaseMgr::getAnyLease6Internal(const isc::asiolink::IOAddress& addr) const {
1080  Lease6Storage::iterator l = storage6_.find(addr);
1081  if (l == storage6_.end() || !(*l)) {
1082  return (Lease6Ptr());
1083  } else {
1084  return (Lease6Ptr(new Lease6(**l)));
1085  }
1086 }
1087 
1088 Lease6Ptr
1090  const isc::asiolink::IOAddress& addr) const {
1093  .arg(addr.toText())
1094  .arg(Lease::typeToText(type));
1095 
1096  if (MultiThreadingMgr::instance().getMode()) {
1097  std::lock_guard<std::mutex> lock(*mutex_);
1098  return (getLease6Internal(type, addr));
1099  } else {
1100  return (getLease6Internal(type, addr));
1101  }
1102 }
1103 
1104 void
1105 Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1106  const DUID& duid,
1107  uint32_t iaid,
1108  Lease6Collection& collection) const {
1109  // Get the index by DUID, IAID, lease type.
1110  const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1111  // Try to get the lease using the DUID, IAID and lease type.
1112  std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1113  Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1114  idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1115 
1116  for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1117  l.first; lease != l.second; ++lease) {
1118  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1119  }
1120 }
1121 
1124  const DUID& duid,
1125  uint32_t iaid) const {
1128  .arg(iaid)
1129  .arg(duid.toText())
1130  .arg(Lease::typeToText(type));
1131 
1132  Lease6Collection collection;
1133  if (MultiThreadingMgr::instance().getMode()) {
1134  std::lock_guard<std::mutex> lock(*mutex_);
1135  getLeases6Internal(type, duid, iaid, collection);
1136  } else {
1137  getLeases6Internal(type, duid, iaid, collection);
1138  }
1139 
1140  return (collection);
1141 }
1142 
1143 void
1144 Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1145  const DUID& duid,
1146  uint32_t iaid,
1147  SubnetID subnet_id,
1148  Lease6Collection& collection) const {
1149  // Get the index by DUID, IAID, lease type.
1150  const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1151  // Try to get the lease using the DUID, IAID and lease type.
1152  std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1153  Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1154  idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1155 
1156  for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1157  l.first; lease != l.second; ++lease) {
1158  // Filter out the leases which subnet id doesn't match.
1159  if ((*lease)->subnet_id_ == subnet_id) {
1160  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1161  }
1162  }
1163 }
1164 
1167  const DUID& duid,
1168  uint32_t iaid,
1169  SubnetID subnet_id) const {
1172  .arg(iaid)
1173  .arg(subnet_id)
1174  .arg(duid.toText())
1175  .arg(Lease::typeToText(type));
1176 
1177  Lease6Collection collection;
1178  if (MultiThreadingMgr::instance().getMode()) {
1179  std::lock_guard<std::mutex> lock(*mutex_);
1180  getLeases6Internal(type, duid, iaid, subnet_id, collection);
1181  } else {
1182  getLeases6Internal(type, duid, iaid, subnet_id, collection);
1183  }
1184 
1185  return (collection);
1186 }
1187 
1188 void
1189 Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1190  Lease6Collection& collection) const {
1191  const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1192  std::pair<Lease6StorageSubnetIdIndex::const_iterator,
1193  Lease6StorageSubnetIdIndex::const_iterator> l =
1194  idx.equal_range(subnet_id);
1195 
1196  for (auto lease = l.first; lease != l.second; ++lease) {
1197  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1198  }
1199 }
1200 
1204  .arg(subnet_id);
1205 
1206  Lease6Collection collection;
1207  if (MultiThreadingMgr::instance().getMode()) {
1208  std::lock_guard<std::mutex> lock(*mutex_);
1209  getLeases6Internal(subnet_id, collection);
1210  } else {
1211  getLeases6Internal(subnet_id, collection);
1212  }
1213 
1214  return (collection);
1215 }
1216 
1217 void
1218 Memfile_LeaseMgr::getLeases6Internal(const std::string& hostname,
1219  Lease6Collection& collection) const {
1220  const Lease6StorageHostnameIndex& idx = storage6_.get<HostnameIndexTag>();
1221  std::pair<Lease6StorageHostnameIndex::const_iterator,
1222  Lease6StorageHostnameIndex::const_iterator> l =
1223  idx.equal_range(hostname);
1224 
1225  for (auto lease = l.first; lease != l.second; ++lease) {
1226  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1227  }
1228 }
1229 
1231 Memfile_LeaseMgr::getLeases6(const std::string& hostname) const {
1233  .arg(hostname);
1234 
1235  Lease6Collection collection;
1236  if (MultiThreadingMgr::instance().getMode()) {
1237  std::lock_guard<std::mutex> lock(*mutex_);
1238  getLeases6Internal(hostname, collection);
1239  } else {
1240  getLeases6Internal(hostname, collection);
1241  }
1242 
1243  return (collection);
1244 }
1245 
1246 void
1247 Memfile_LeaseMgr::getLeases6Internal(Lease6Collection& collection) const {
1248  for (auto lease = storage6_.begin(); lease != storage6_.end(); ++lease) {
1249  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1250  }
1251 }
1252 
1256 
1257  Lease6Collection collection;
1258  if (MultiThreadingMgr::instance().getMode()) {
1259  std::lock_guard<std::mutex> lock(*mutex_);
1260  getLeases6Internal(collection);
1261  } else {
1262  getLeases6Internal(collection);
1263  }
1264 
1265  return (collection);
1266 }
1267 
1268 void
1269 Memfile_LeaseMgr::getLeases6Internal(const DUID& duid,
1270  Lease6Collection& collection) const {
1271  const Lease6StorageDuidIndex& idx = storage6_.get<DuidIndexTag>();
1272  std::pair<Lease6StorageDuidIndex::const_iterator,
1273  Lease6StorageDuidIndex::const_iterator> l =
1274  idx.equal_range(duid.getDuid());
1275 
1276  for (auto lease = l.first; lease != l.second; ++lease) {
1277  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1278  }
1279 }
1280 
1284  .arg(duid.toText());
1285 
1286  Lease6Collection collection;
1287  if (MultiThreadingMgr::instance().getMode()) {
1288  std::lock_guard<std::mutex> lock(*mutex_);
1289  getLeases6Internal(duid, collection);
1290  } else {
1291  getLeases6Internal(duid, collection);
1292  }
1293 
1294  return (collection);
1295 }
1296 
1297 void
1298 Memfile_LeaseMgr::getLeases6Internal(const asiolink::IOAddress& lower_bound_address,
1299  const LeasePageSize& page_size,
1300  Lease6Collection& collection) const {
1301  const Lease6StorageAddressIndex& idx = storage6_.get<AddressIndexTag>();
1302  Lease6StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1303 
1304  // Exclude the lower bound address specified by the caller.
1305  if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1306  ++lb;
1307  }
1308 
1309  // Return all other leases being within the page size.
1310  for (auto lease = lb;
1311  (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1312  ++lease) {
1313  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1314  }
1315 }
1316 
1319  const LeasePageSize& page_size) const {
1320  // Expecting IPv6 address.
1321  if (!lower_bound_address.isV6()) {
1322  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1323  "retrieving leases from the lease database, got "
1324  << lower_bound_address);
1325  }
1326 
1328  .arg(page_size.page_size_)
1329  .arg(lower_bound_address.toText());
1330 
1331  Lease6Collection collection;
1332  if (MultiThreadingMgr::instance().getMode()) {
1333  std::lock_guard<std::mutex> lock(*mutex_);
1334  getLeases6Internal(lower_bound_address, page_size, collection);
1335  } else {
1336  getLeases6Internal(lower_bound_address, page_size, collection);
1337  }
1338 
1339  return (collection);
1340 }
1341 
1342 void
1343 Memfile_LeaseMgr::getExpiredLeases4Internal(Lease4Collection& expired_leases,
1344  const size_t max_leases) const {
1345  // Obtain the index which segragates leases by state and time.
1346  const Lease4StorageExpirationIndex& index = storage4_.get<ExpirationIndexTag>();
1347 
1348  // Retrieve leases which are not reclaimed and which haven't expired. The
1349  // 'less-than' operator will be used for both components of the index. So,
1350  // for the 'state' 'false' is less than 'true'. Also the leases with
1351  // expiration time lower than current time will be returned.
1352  Lease4StorageExpirationIndex::const_iterator ub =
1353  index.upper_bound(boost::make_tuple(false, time(0)));
1354 
1355  // Copy only the number of leases indicated by the max_leases parameter.
1356  for (Lease4StorageExpirationIndex::const_iterator lease = index.begin();
1357  (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1358  max_leases));
1359  ++lease) {
1360  expired_leases.push_back(Lease4Ptr(new Lease4(**lease)));
1361  }
1362 }
1363 
1364 void
1366  const size_t max_leases) const {
1368  .arg(max_leases);
1369 
1370  if (MultiThreadingMgr::instance().getMode()) {
1371  std::lock_guard<std::mutex> lock(*mutex_);
1372  getExpiredLeases4Internal(expired_leases, max_leases);
1373  } else {
1374  getExpiredLeases4Internal(expired_leases, max_leases);
1375  }
1376 }
1377 
1378 void
1379 Memfile_LeaseMgr::getExpiredLeases6Internal(Lease6Collection& expired_leases,
1380  const size_t max_leases) const {
1381  // Obtain the index which segragates leases by state and time.
1382  const Lease6StorageExpirationIndex& index = storage6_.get<ExpirationIndexTag>();
1383 
1384  // Retrieve leases which are not reclaimed and which haven't expired. The
1385  // 'less-than' operator will be used for both components of the index. So,
1386  // for the 'state' 'false' is less than 'true'. Also the leases with
1387  // expiration time lower than current time will be returned.
1388  Lease6StorageExpirationIndex::const_iterator ub =
1389  index.upper_bound(boost::make_tuple(false, time(0)));
1390 
1391  // Copy only the number of leases indicated by the max_leases parameter.
1392  for (Lease6StorageExpirationIndex::const_iterator lease = index.begin();
1393  (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1394  max_leases));
1395  ++lease) {
1396  expired_leases.push_back(Lease6Ptr(new Lease6(**lease)));
1397  }
1398 }
1399 
1400 void
1402  const size_t max_leases) const {
1404  .arg(max_leases);
1405 
1406  if (MultiThreadingMgr::instance().getMode()) {
1407  std::lock_guard<std::mutex> lock(*mutex_);
1408  getExpiredLeases6Internal(expired_leases, max_leases);
1409  } else {
1410  getExpiredLeases6Internal(expired_leases, max_leases);
1411  }
1412 }
1413 
1414 void
1415 Memfile_LeaseMgr::updateLease4Internal(const Lease4Ptr& lease) {
1416  // Obtain 'by address' index.
1417  Lease4StorageAddressIndex& index = storage4_.get<AddressIndexTag>();
1418 
1419  bool persist = persistLeases(V4);
1420 
1421  // Lease must exist if it is to be updated.
1422  Lease4StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1423  if (lease_it == index.end()) {
1424  isc_throw(NoSuchLease, "failed to update the lease with address "
1425  << lease->addr_ << " - no such lease");
1426  } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1427  ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1428  // For test purpose only: check that the lease has not changed in
1429  // the database.
1430  isc_throw(NoSuchLease, "failed to update the lease with address "
1431  << lease->addr_ << " - lease has changed in database");
1432  }
1433 
1434  // Try to write a lease to disk first. If this fails, the lease will
1435  // not be inserted to the memory and the disk and in-memory data will
1436  // remain consistent.
1437  if (persist) {
1438  lease_file4_->append(*lease);
1439  }
1440 
1441  // Update lease current expiration time.
1442  lease->updateCurrentExpirationTime();
1443 
1444  // Save a copy of the old lease as lease_it will point to the new
1445  // one after the replacement.
1446  Lease4Ptr old_lease = *lease_it;
1447 
1448  // Use replace() to re-index leases.
1449  index.replace(lease_it, Lease4Ptr(new Lease4(*lease)));
1450 
1451  // Adjust class lease counters.
1452  class_lease_counter_.updateLease(lease, old_lease);
1453 }
1454 
1455 void
1458  DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
1459 
1460  if (MultiThreadingMgr::instance().getMode()) {
1461  std::lock_guard<std::mutex> lock(*mutex_);
1462  updateLease4Internal(lease);
1463  } else {
1464  updateLease4Internal(lease);
1465  }
1466 }
1467 
1468 void
1469 Memfile_LeaseMgr::updateLease6Internal(const Lease6Ptr& lease) {
1470  // Obtain 'by address' index.
1471  Lease6StorageAddressIndex& index = storage6_.get<AddressIndexTag>();
1472 
1473  bool persist = persistLeases(V6);
1474 
1475  // Get the recorded action and reset it.
1476  Lease::ExtendedInfoAction recorded_action = lease->extended_info_action_;
1477  lease->extended_info_action_ = Lease::ACTION_IGNORE;
1478 
1479  // Lease must exist if it is to be updated.
1480  Lease6StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1481  if (lease_it == index.end()) {
1482  isc_throw(NoSuchLease, "failed to update the lease with address "
1483  << lease->addr_ << " - no such lease");
1484  } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1485  ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1486  // For test purpose only: check that the lease has not changed in
1487  // the database.
1488  isc_throw(NoSuchLease, "failed to update the lease with address "
1489  << lease->addr_ << " - lease has changed in database");
1490  }
1491 
1492  // Try to write a lease to disk first. If this fails, the lease will
1493  // not be inserted to the memory and the disk and in-memory data will
1494  // remain consistent.
1495  if (persist) {
1496  lease_file6_->append(*lease);
1497  }
1498 
1499  // Update lease current expiration time.
1500  lease->updateCurrentExpirationTime();
1501 
1502  // Save a copy of the old lease as lease_it will point to the new
1503  // one after the replacement.
1504  Lease6Ptr old_lease = *lease_it;
1505 
1506  // Use replace() to re-index leases.
1507  index.replace(lease_it, Lease6Ptr(new Lease6(*lease)));
1508 
1509  // Adjust class lease counters.
1510  class_lease_counter_.updateLease(lease, old_lease);
1511 
1512  // Update extended info tables.
1514  switch (recorded_action) {
1515  case Lease::ACTION_IGNORE:
1516  break;
1517 
1518  case Lease::ACTION_DELETE:
1519  deleteExtendedInfo6(lease->addr_);
1520  break;
1521 
1522  case Lease::ACTION_UPDATE:
1523  deleteExtendedInfo6(lease->addr_);
1524  static_cast<void>(addExtendedInfo6(lease));
1525  break;
1526  }
1527  }
1528 }
1529 
1530 void
1533  DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
1534 
1535  if (MultiThreadingMgr::instance().getMode()) {
1536  std::lock_guard<std::mutex> lock(*mutex_);
1537  updateLease6Internal(lease);
1538  } else {
1539  updateLease6Internal(lease);
1540  }
1541 }
1542 
1543 bool
1544 Memfile_LeaseMgr::deleteLeaseInternal(const Lease4Ptr& lease) {
1545  const isc::asiolink::IOAddress& addr = lease->addr_;
1546  Lease4Storage::iterator l = storage4_.find(addr);
1547  if (l == storage4_.end()) {
1548  // No such lease
1549  return (false);
1550  } else {
1551  if (persistLeases(V4)) {
1552  // Copy the lease. The valid lifetime needs to be modified and
1553  // we don't modify the original lease.
1554  Lease4 lease_copy = **l;
1555  // Setting valid lifetime to 0 means that lease is being
1556  // removed.
1557  lease_copy.valid_lft_ = 0;
1558  lease_file4_->append(lease_copy);
1559  } else {
1560  // For test purpose only: check that the lease has not changed in
1561  // the database.
1562  if (((*l)->cltt_ != lease->current_cltt_) ||
1563  ((*l)->valid_lft_ != lease->current_valid_lft_)) {
1564  return false;
1565  }
1566  }
1567 
1568  storage4_.erase(l);
1569 
1570  // Decrement class lease counters.
1571  class_lease_counter_.removeLease(lease);
1572 
1573  return (true);
1574  }
1575 }
1576 
1577 bool
1580  DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
1581 
1582  if (MultiThreadingMgr::instance().getMode()) {
1583  std::lock_guard<std::mutex> lock(*mutex_);
1584  return (deleteLeaseInternal(lease));
1585  } else {
1586  return (deleteLeaseInternal(lease));
1587  }
1588 }
1589 
1590 bool
1591 Memfile_LeaseMgr::deleteLeaseInternal(const Lease6Ptr& lease) {
1592  lease->extended_info_action_ = Lease::ACTION_IGNORE;
1593 
1594  const isc::asiolink::IOAddress& addr = lease->addr_;
1595  Lease6Storage::iterator l = storage6_.find(addr);
1596  if (l == storage6_.end()) {
1597  // No such lease
1598  return (false);
1599  } else {
1600  if (persistLeases(V6)) {
1601  // Copy the lease. The lifetimes need to be modified and we
1602  // don't modify the original lease.
1603  Lease6 lease_copy = **l;
1604  // Setting lifetimes to 0 means that lease is being removed.
1605  lease_copy.valid_lft_ = 0;
1606  lease_copy.preferred_lft_ = 0;
1607  lease_file6_->append(lease_copy);
1608  } else {
1609  // For test purpose only: check that the lease has not changed in
1610  // the database.
1611  if (((*l)->cltt_ != lease->current_cltt_) ||
1612  ((*l)->valid_lft_ != lease->current_valid_lft_)) {
1613  return false;
1614  }
1615  }
1616 
1617  storage6_.erase(l);
1618 
1619  // Decrement class lease counters.
1620  class_lease_counter_.removeLease(lease);
1621 
1622  // Delete references from extended info tables.
1624  deleteExtendedInfo6(lease->addr_);
1625  }
1626 
1627  return (true);
1628  }
1629 }
1630 
1631 bool
1634  DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
1635 
1636  if (MultiThreadingMgr::instance().getMode()) {
1637  std::lock_guard<std::mutex> lock(*mutex_);
1638  return (deleteLeaseInternal(lease));
1639  } else {
1640  return (deleteLeaseInternal(lease));
1641  }
1642 }
1643 
1644 uint64_t
1648  .arg(secs);
1649 
1650  if (MultiThreadingMgr::instance().getMode()) {
1651  std::lock_guard<std::mutex> lock(*mutex_);
1652  return (deleteExpiredReclaimedLeases<
1654  >(secs, V4, storage4_, lease_file4_));
1655  } else {
1656  return (deleteExpiredReclaimedLeases<
1658  >(secs, V4, storage4_, lease_file4_));
1659  }
1660 }
1661 
1662 uint64_t
1666  .arg(secs);
1667 
1668  if (MultiThreadingMgr::instance().getMode()) {
1669  std::lock_guard<std::mutex> lock(*mutex_);
1670  return (deleteExpiredReclaimedLeases<
1672  >(secs, V6, storage6_, lease_file6_));
1673  } else {
1674  return (deleteExpiredReclaimedLeases<
1676  >(secs, V6, storage6_, lease_file6_));
1677  }
1678 }
1679 
1680 template<typename IndexType, typename LeaseType, typename StorageType,
1681  typename LeaseFileType>
1682 uint64_t
1683 Memfile_LeaseMgr::deleteExpiredReclaimedLeases(const uint32_t secs,
1684  const Universe& universe,
1685  StorageType& storage,
1686  LeaseFileType& lease_file) {
1687  // Obtain the index which segragates leases by state and time.
1688  IndexType& index = storage.template get<ExpirationIndexTag>();
1689 
1690  // This returns the first element which is greater than the specified
1691  // tuple (true, time(0) - secs). However, the range between the
1692  // beginning of the index and returned element also includes all the
1693  // elements for which the first value is false (lease state is NOT
1694  // reclaimed), because false < true. All elements between the
1695  // beginning of the index and the element returned, for which the
1696  // first value is true, represent the reclaimed leases which should
1697  // be deleted, because their expiration time + secs has occurred earlier
1698  // than current time.
1699  typename IndexType::const_iterator upper_limit =
1700  index.upper_bound(boost::make_tuple(true, time(0) - secs));
1701 
1702  // Now, we have to exclude all elements of the index which represent
1703  // leases in the state other than reclaimed - with the first value
1704  // in the index equal to false. Note that elements in the index are
1705  // ordered from the lower to the higher ones. So, all elements with
1706  // the first value of false are placed before the elements with the
1707  // value of true. Hence, we have to find the first element which
1708  // contains value of true. The time value is the lowest possible.
1709  typename IndexType::const_iterator lower_limit =
1710  index.upper_bound(boost::make_tuple(true, std::numeric_limits<int64_t>::min()));
1711 
1712  // If there are some elements in this range, delete them.
1713  uint64_t num_leases = static_cast<uint64_t>(std::distance(lower_limit, upper_limit));
1714  if (num_leases > 0) {
1715 
1718  .arg(num_leases);
1719 
1720  // If lease persistence is enabled, we also have to mark leases
1721  // as deleted in the lease file. We do this by setting the
1722  // lifetime to 0.
1723  if (persistLeases(universe)) {
1724  for (typename IndexType::const_iterator lease = lower_limit;
1725  lease != upper_limit; ++lease) {
1726  // Copy lease to not affect the lease in the container.
1727  LeaseType lease_copy(**lease);
1728  // Set the valid lifetime to 0 to indicate the removal
1729  // of the lease.
1730  lease_copy.valid_lft_ = 0;
1731  lease_file->append(lease_copy);
1732  }
1733  }
1734 
1735  // Delete references from extended info tables.
1737  // Swap if and for when v4 will be implemented.
1738  if (universe == V6) {
1739  for (typename IndexType::const_iterator lease = lower_limit;
1740  lease != upper_limit; ++lease) {
1741  deleteExtendedInfo6((*lease)->addr_);
1742  }
1743  }
1744  }
1745 
1746  // Erase leases from memory.
1747  index.erase(lower_limit, upper_limit);
1748 
1749  }
1750  // Return number of leases deleted.
1751  return (num_leases);
1752 }
1753 
1754 std::string
1756  return (std::string("In memory database with leases stored in a CSV file."));
1757 }
1758 
1759 std::pair<uint32_t, uint32_t>
1761  std::string const& universe(conn_.getParameter("universe"));
1762  if (universe == "4") {
1763  return std::make_pair(MAJOR_VERSION_V4, MINOR_VERSION_V4);
1764  } else if (universe == "6") {
1765  return std::make_pair(MAJOR_VERSION_V6, MINOR_VERSION_V6);
1766  }
1767  isc_throw(BadValue, "cannot determine version for universe " << universe);
1768 }
1769 
1770 void
1773 }
1774 
1775 void
1779 }
1780 
1781 std::string
1782 Memfile_LeaseMgr::appendSuffix(const std::string& file_name,
1783  const LFCFileType& file_type) {
1784  std::string name(file_name);
1785  switch (file_type) {
1786  case FILE_INPUT:
1787  name += ".1";
1788  break;
1789  case FILE_PREVIOUS:
1790  name += ".2";
1791  break;
1792  case FILE_OUTPUT:
1793  name += ".output";
1794  break;
1795  case FILE_FINISH:
1796  name += ".completed";
1797  break;
1798  case FILE_PID:
1799  name += ".pid";
1800  break;
1801  default:
1802  // Do not append any suffix for the FILE_CURRENT.
1803  ;
1804  }
1805 
1806  return (name);
1807 }
1808 
1809 std::string
1811  std::ostringstream s;
1812  s << CfgMgr::instance().getDataDir() << "/kea-leases";
1813  s << (u == V4 ? "4" : "6");
1814  s << ".csv";
1815  return (s.str());
1816 }
1817 
1818 std::string
1820  if (u == V4) {
1821  return (lease_file4_ ? lease_file4_->getFilename() : "");
1822  }
1823 
1824  return (lease_file6_ ? lease_file6_->getFilename() : "");
1825 }
1826 
1827 bool
1829  // Currently, if the lease file IO is not created, it means that writes to
1830  // disk have been explicitly disabled by the administrator. At some point,
1831  // there may be a dedicated ON/OFF flag implemented to control this.
1832  if (u == V4 && lease_file4_) {
1833  return (true);
1834  }
1835 
1836  return (u == V6 && lease_file6_);
1837 }
1838 
1839 std::string
1840 Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
1841  std::string persist_val;
1842  try {
1843  persist_val = conn_.getParameter("persist");
1844  } catch (const Exception&) {
1845  // If parameter persist hasn't been specified, we use a default value
1846  // 'yes'.
1847  persist_val = "true";
1848  }
1849  // If persist_val is 'false' we will not store leases to disk, so let's
1850  // return empty file name.
1851  if (persist_val == "false") {
1852  return ("");
1853 
1854  } else if (persist_val != "true") {
1855  isc_throw(isc::BadValue, "invalid value 'persist="
1856  << persist_val << "'");
1857  }
1858 
1859  std::string lease_file;
1860  try {
1861  lease_file = conn_.getParameter("name");
1862  } catch (const Exception&) {
1863  lease_file = getDefaultLeaseFilePath(u);
1864  }
1865  return (lease_file);
1866 }
1867 
1868 template<typename LeaseObjectType, typename LeaseFileType, typename StorageType>
1869 bool
1870 Memfile_LeaseMgr::loadLeasesFromFiles(const std::string& filename,
1871  boost::shared_ptr<LeaseFileType>& lease_file,
1872  StorageType& storage) {
1873  // Check if the instance of the LFC is running right now. If it is
1874  // running, we refuse to load leases as the LFC may be writing to the
1875  // lease files right now. When the user retries server configuration
1876  // it should go through.
1879  PIDFile pid_file(appendSuffix(filename, FILE_PID));
1880  if (pid_file.check()) {
1881  isc_throw(DbOpenError, "unable to load leases from files while the "
1882  "lease file cleanup is in progress");
1883  }
1884 
1885  storage.clear();
1886 
1887  std::string max_row_errors_str = "0";
1888  try {
1889  max_row_errors_str = conn_.getParameter("max-row-errors");
1890  } catch (const std::exception&) {
1891  // Ignore and default to 0.
1892  }
1893 
1894  int64_t max_row_errors64;
1895  try {
1896  max_row_errors64 = boost::lexical_cast<int64_t>(max_row_errors_str);
1897  } catch (const boost::bad_lexical_cast&) {
1898  isc_throw(isc::BadValue, "invalid value of the max-row-errors "
1899  << max_row_errors_str << " specified");
1900  }
1901  if ((max_row_errors64 < 0) ||
1902  (max_row_errors64 > std::numeric_limits<uint32_t>::max())) {
1903  isc_throw(isc::BadValue, "invalid value of the max-row-errors "
1904  << max_row_errors_str << " specified");
1905  }
1906  uint32_t max_row_errors = static_cast<uint32_t>(max_row_errors64);
1907 
1908  // Load the leasefile.completed, if exists.
1909  bool conversion_needed = false;
1910  lease_file.reset(new LeaseFileType(std::string(filename + ".completed")));
1911  if (lease_file->exists()) {
1912  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1913  max_row_errors);
1914  conversion_needed = conversion_needed || lease_file->needsConversion();
1915  } else {
1916  // If the leasefile.completed doesn't exist, let's load the leases
1917  // from leasefile.2 and leasefile.1, if they exist.
1918  lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_PREVIOUS)));
1919  if (lease_file->exists()) {
1920  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1921  max_row_errors);
1922  conversion_needed = conversion_needed || lease_file->needsConversion();
1923  }
1924 
1925  lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_INPUT)));
1926  if (lease_file->exists()) {
1927  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1928  max_row_errors);
1929  conversion_needed = conversion_needed || lease_file->needsConversion();
1930  }
1931  }
1932 
1933  // Always load leases from the primary lease file. If the lease file
1934  // doesn't exist it will be created by the LeaseFileLoader. Note
1935  // that the false value passed as the last parameter to load
1936  // function causes the function to leave the file open after
1937  // it is parsed. This file will be used by the backend to record
1938  // future lease updates.
1939  lease_file.reset(new LeaseFileType(filename));
1940  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1941  max_row_errors, false);
1942  conversion_needed = conversion_needed || lease_file->needsConversion();
1943 
1944  return (conversion_needed);
1945 }
1946 
1947 
1948 bool
1950  return (lfc_setup_->isRunning());
1951 }
1952 
1953 int
1955  return (lfc_setup_->getExitStatus());
1956 }
1957 
1958 void
1961 
1962  // Check if we're in the v4 or v6 space and use the appropriate file.
1963  if (lease_file4_) {
1965  lfcExecute(lease_file4_);
1966  } else if (lease_file6_) {
1968  lfcExecute(lease_file6_);
1969  }
1970 }
1971 
1972 void
1973 Memfile_LeaseMgr::lfcSetup(bool conversion_needed) {
1974  std::string lfc_interval_str = "3600";
1975  try {
1976  lfc_interval_str = conn_.getParameter("lfc-interval");
1977  } catch (const std::exception&) {
1978  // Ignore and default to 3600.
1979  }
1980 
1981  uint32_t lfc_interval = 0;
1982  try {
1983  lfc_interval = boost::lexical_cast<uint32_t>(lfc_interval_str);
1984  } catch (const boost::bad_lexical_cast&) {
1985  isc_throw(isc::BadValue, "invalid value of the lfc-interval "
1986  << lfc_interval_str << " specified");
1987  }
1988 
1989  if (lfc_interval > 0 || conversion_needed) {
1990  lfc_setup_.reset(new LFCSetup(std::bind(&Memfile_LeaseMgr::lfcCallback, this)));
1991  lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_, conversion_needed);
1992  }
1993 }
1994 
1995 template<typename LeaseFileType>
1996 void
1997 Memfile_LeaseMgr::lfcExecute(boost::shared_ptr<LeaseFileType>& lease_file) {
1998  bool do_lfc = true;
1999 
2000  // Check the status of the LFC instance.
2001  // If the finish file exists or the copy of the lease file exists it
2002  // is an indication that another LFC instance may be in progress or
2003  // may be stalled. In that case we don't want to rotate the current
2004  // lease file to avoid overriding the contents of the existing file.
2005  CSVFile lease_file_finish(appendSuffix(lease_file->getFilename(), FILE_FINISH));
2006  CSVFile lease_file_copy(appendSuffix(lease_file->getFilename(), FILE_INPUT));
2007  if (!lease_file_finish.exists() && !lease_file_copy.exists()) {
2008  // Close the current file so as we can move it to the copy file.
2009  lease_file->close();
2010  // Move the current file to the copy file. Remember the result
2011  // because we don't want to run LFC if the rename failed.
2012  do_lfc = (rename(lease_file->getFilename().c_str(),
2013  lease_file_copy.getFilename().c_str()) == 0);
2014 
2015  if (!do_lfc) {
2017  .arg(lease_file->getFilename())
2018  .arg(lease_file_copy.getFilename())
2019  .arg(strerror(errno));
2020  }
2021 
2022  // Regardless if we successfully moved the current file or not,
2023  // we need to re-open the current file for the server to write
2024  // new lease updates. If the file has been successfully moved,
2025  // this will result in creation of the new file. Otherwise,
2026  // an existing file will be opened.
2027  try {
2028  lease_file->open(true);
2029 
2030  } catch (const CSVFileError& ex) {
2031  // If we're unable to open the lease file this is a serious
2032  // error because the server will not be able to persist
2033  // leases.
2041  .arg(lease_file->getFilename())
2042  .arg(ex.what());
2043  // Reset the pointer to the file so as the backend doesn't
2044  // try to write leases to disk.
2045  lease_file.reset();
2046  do_lfc = false;
2047  }
2048  }
2049  // Once the files have been rotated, or untouched if another LFC had
2050  // not finished, a new process is started.
2051  if (do_lfc) {
2052  lfc_setup_->execute();
2053  }
2054 }
2055 
2058  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_));
2059  if (MultiThreadingMgr::instance().getMode()) {
2060  std::lock_guard<std::mutex> lock(*mutex_);
2061  query->start();
2062  } else {
2063  query->start();
2064  }
2065 
2066  return(query);
2067 }
2068 
2071  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, subnet_id));
2072  if (MultiThreadingMgr::instance().getMode()) {
2073  std::lock_guard<std::mutex> lock(*mutex_);
2074  query->start();
2075  } else {
2076  query->start();
2077  }
2078 
2079  return(query);
2080 }
2081 
2084  const SubnetID& last_subnet_id) {
2085  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, first_subnet_id,
2086  last_subnet_id));
2087  if (MultiThreadingMgr::instance().getMode()) {
2088  std::lock_guard<std::mutex> lock(*mutex_);
2089  query->start();
2090  } else {
2091  query->start();
2092  }
2093 
2094  return(query);
2095 }
2096 
2099  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_));
2100  if (MultiThreadingMgr::instance().getMode()) {
2101  std::lock_guard<std::mutex> lock(*mutex_);
2102  query->start();
2103  } else {
2104  query->start();
2105  }
2106 
2107  return(query);
2108 }
2109 
2112  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, subnet_id));
2113  if (MultiThreadingMgr::instance().getMode()) {
2114  std::lock_guard<std::mutex> lock(*mutex_);
2115  query->start();
2116  } else {
2117  query->start();
2118  }
2119 
2120  return(query);
2121 }
2122 
2125  const SubnetID& last_subnet_id) {
2126  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, first_subnet_id,
2127  last_subnet_id));
2128  if (MultiThreadingMgr::instance().getMode()) {
2129  std::lock_guard<std::mutex> lock(*mutex_);
2130  query->start();
2131  } else {
2132  query->start();
2133  }
2134 
2135  return(query);
2136 }
2137 
2138 size_t
2141  .arg(subnet_id);
2142 
2143  // Get the index by DUID, IAID, lease type.
2144  const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
2145 
2146  // Try to get the lease using the DUID, IAID and lease type.
2147  std::pair<Lease4StorageSubnetIdIndex::const_iterator,
2148  Lease4StorageSubnetIdIndex::const_iterator> l =
2149  idx.equal_range(subnet_id);
2150 
2151  // Let's collect all leases.
2152  Lease4Collection leases;
2153  for (auto lease = l.first; lease != l.second; ++lease) {
2154  leases.push_back(*lease);
2155  }
2156 
2157  size_t num = leases.size();
2158  for (auto l = leases.begin(); l != leases.end(); ++l) {
2159  deleteLease(*l);
2160  }
2162  .arg(subnet_id).arg(num);
2163 
2164  return (num);
2165 }
2166 
2167 size_t
2170  .arg(subnet_id);
2171 
2172  // Get the index by DUID, IAID, lease type.
2173  const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
2174 
2175  // Try to get the lease using the DUID, IAID and lease type.
2176  std::pair<Lease6StorageSubnetIdIndex::const_iterator,
2177  Lease6StorageSubnetIdIndex::const_iterator> l =
2178  idx.equal_range(subnet_id);
2179 
2180  // Let's collect all leases.
2181  Lease6Collection leases;
2182  for (auto lease = l.first; lease != l.second; ++lease) {
2183  leases.push_back(*lease);
2184  }
2185 
2186  size_t num = leases.size();
2187  for (auto l = leases.begin(); l != leases.end(); ++l) {
2188  deleteLease(*l);
2189  }
2191  .arg(subnet_id).arg(num);
2192 
2193  return (num);
2194 }
2195 
2196 void
2198  class_lease_counter_.clear();
2199  for (auto lease = storage4_.begin(); lease != storage4_.end(); ++lease) {
2200  // Bump the appropriate accumulator
2201  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
2202  class_lease_counter_.addLease(*lease);
2203  }
2204  }
2205 }
2206 
2207 void
2209  class_lease_counter_.clear();
2210  for (auto lease = storage6_.begin(); lease != storage6_.end(); ++lease) {
2211  // Bump the appropriate accumulator
2212  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
2213  class_lease_counter_.addLease(*lease);
2214  }
2215  }
2216 }
2217 
2218 size_t
2220  const Lease::Type& ltype /* = Lease::TYPE_V4*/) const {
2221  if (MultiThreadingMgr::instance().getMode()) {
2222  std::lock_guard<std::mutex> lock(*mutex_);
2223  return(class_lease_counter_.getClassCount(client_class, ltype));
2224  } else {
2225  return(class_lease_counter_.getClassCount(client_class, ltype));
2226  }
2227 }
2228 
2229 void
2231  return(class_lease_counter_.clear());
2232 }
2233 
2234 std::string
2236  if (!user_context) {
2237  return ("");
2238  }
2239 
2240  ConstElementPtr limits = user_context->find("ISC/limits");
2241  if (!limits) {
2242  return ("");
2243  }
2244 
2245  // Iterate of the 'client-classes' list in 'limits'. For each class that specifies
2246  // an "address-limit", check its value against the class's lease count.
2247  ConstElementPtr classes = limits->get("client-classes");
2248  if (classes) {
2249  for (int i = 0; i < classes->size(); ++i) {
2250  ConstElementPtr class_elem = classes->get(i);
2251  // Get class name.
2252  ConstElementPtr name_elem = class_elem->get("name");
2253  if (!name_elem) {
2254  isc_throw(BadValue, "checkLimits4 - client-class.name is missing: "
2255  << prettyPrint(limits));
2256  }
2257 
2258  std::string name = name_elem->stringValue();
2259 
2260  // Now look for an address-limit
2261  size_t limit;
2262  if (!getLeaseLimit(class_elem, Lease::TYPE_V4, limit)) {
2263  // No limit, go to the next class.
2264  continue;
2265  }
2266 
2267  // If the limit is > 0 look up the class lease count. Limit of 0 always
2268  // denies the lease.
2269  size_t lease_count = 0;
2270  if (limit) {
2271  lease_count = getClassLeaseCount(name);
2272  }
2273 
2274  // If we're over the limit, return the error, no need to evaluate any others.
2275  if (lease_count >= limit) {
2276  std::ostringstream ss;
2277  ss << "address limit " << limit << " for client class \""
2278  << name << "\", current lease count " << lease_count;
2279  return (ss.str());
2280  }
2281  }
2282  }
2283 
2284  // If there were class limits we passed them, now look for a subnet limit.
2285  ConstElementPtr subnet_elem = limits->get("subnet");
2286  if (subnet_elem) {
2287  // Get the subnet id.
2288  ConstElementPtr id_elem = subnet_elem->get("id");
2289  if (!id_elem) {
2290  isc_throw(BadValue, "checkLimits4 - subnet.id is missing: "
2291  << prettyPrint(limits));
2292  }
2293 
2294  SubnetID subnet_id = id_elem->intValue();
2295 
2296  // Now look for an address-limit.
2297  size_t limit;
2298  if (getLeaseLimit(subnet_elem, Lease::TYPE_V4, limit)) {
2299  // If the limit is > 0 look up the subnet lease count. Limit of 0 always
2300  // denies the lease.
2301  int64_t lease_count = 0;
2302  if (limit) {
2303  lease_count = getSubnetStat(subnet_id, "assigned-addresses");
2304  }
2305 
2306  // If we're over the limit, return the error.
2307  if (lease_count >= limit) {
2308  std::ostringstream ss;
2309  ss << "address limit " << limit << " for subnet ID " << subnet_id
2310  << ", current lease count " << lease_count;
2311  return (ss.str());
2312  }
2313  }
2314  }
2315 
2316  // No limits exceeded!
2317  return ("");
2318 }
2319 
2320 std::string
2322  if (!user_context) {
2323  return ("");
2324  }
2325 
2326  ConstElementPtr limits = user_context->find("ISC/limits");
2327  if (!limits) {
2328  return ("");
2329  }
2330 
2331  // Iterate over the 'client-classes' list in 'limits'. For each class that specifies
2332  // limit (either "address-limit" or "prefix-limit", check its value against the appropriate
2333  // class lease count.
2334  ConstElementPtr classes = limits->get("client-classes");
2335  if (classes) {
2336  for (int i = 0; i < classes->size(); ++i) {
2337  ConstElementPtr class_elem = classes->get(i);
2338  // Get class name.
2339  ConstElementPtr name_elem = class_elem->get("name");
2340  if (!name_elem) {
2341  isc_throw(BadValue, "checkLimits6 - client-class.name is missing: "
2342  << prettyPrint(limits));
2343  }
2344 
2345  std::string name = name_elem->stringValue();
2346 
2347  // Now look for either address-limit or a prefix=limit.
2348  size_t limit = 0;
2349  Lease::Type ltype = Lease::TYPE_NA;
2350  if (!getLeaseLimit(class_elem, ltype, limit)) {
2351  ltype = Lease::TYPE_PD;
2352  if (!getLeaseLimit(class_elem, ltype, limit)) {
2353  // No limits for this class, skip to the next.
2354  continue;
2355  }
2356  }
2357 
2358  // If the limit is > 0 look up the class lease count. Limit of 0 always
2359  // denies the lease.
2360  size_t lease_count = 0;
2361  if (limit) {
2362  lease_count = getClassLeaseCount(name, ltype);
2363  }
2364 
2365  // If we're over the limit, return the error, no need to evaluate any others.
2366  if (lease_count >= limit) {
2367  std::ostringstream ss;
2368  ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
2369  << " limit " << limit << " for client class \""
2370  << name << "\", current lease count " << lease_count;
2371  return (ss.str());
2372  }
2373  }
2374  }
2375 
2376  // If there were class limits we passed them, now look for a subnet limit.
2377  ConstElementPtr subnet_elem = limits->get("subnet");
2378  if (subnet_elem) {
2379  // Get the subnet id.
2380  ConstElementPtr id_elem = subnet_elem->get("id");
2381  if (!id_elem) {
2382  isc_throw(BadValue, "checkLimits6 - subnet.id is missing: "
2383  << prettyPrint(limits));
2384  }
2385 
2386  SubnetID subnet_id = id_elem->intValue();
2387 
2388  // Now look for either address-limit or a prefix=limit.
2389  size_t limit = 0;
2390  Lease::Type ltype = Lease::TYPE_NA;
2391  if (!getLeaseLimit(subnet_elem, ltype, limit)) {
2392  ltype = Lease::TYPE_PD;
2393  if (!getLeaseLimit(subnet_elem, ltype, limit)) {
2394  // No limits for the subnet so none exceeded!
2395  return ("");
2396  }
2397  }
2398 
2399  // If the limit is > 0 look up the class lease count. Limit of 0 always
2400  // denies the lease.
2401  int64_t lease_count = 0;
2402  if (limit) {
2403  lease_count = getSubnetStat(subnet_id, (ltype == Lease::TYPE_NA ?
2404  "assigned-nas" : "assigned-pds"));
2405  }
2406 
2407  // If we're over the limit, return the error.
2408  if (lease_count >= limit) {
2409  std::ostringstream ss;
2410  ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
2411  << " limit " << limit << " for subnet ID " << subnet_id
2412  << ", current lease count " << lease_count;
2413  return (ss.str());
2414  }
2415  }
2416 
2417  // No limits exceeded!
2418  return ("");
2419 }
2420 
2421 bool
2423  return true;
2424 }
2425 
2426 int64_t
2427 Memfile_LeaseMgr::getSubnetStat(const SubnetID& subnet_id, const std::string& stat_label) const {
2430  std::string stat_name = StatsMgr::generateName("subnet", subnet_id, stat_label);
2431  ConstElementPtr stat = StatsMgr::instance().get(stat_name);
2432  ConstElementPtr samples = stat->get(stat_name);
2433  if (samples && samples->size()) {
2434  auto sample = samples->get(0);
2435  if (sample->size()) {
2436  auto count_elem = sample->get(0);
2437  return (count_elem->intValue());
2438  }
2439  }
2440 
2441  return (0);
2442 }
2443 
2444 bool
2445 Memfile_LeaseMgr::getLeaseLimit(ConstElementPtr parent, Lease::Type ltype, size_t& limit) const {
2446  ConstElementPtr limit_elem = parent->get(ltype == Lease::TYPE_PD ?
2447  "prefix-limit" : "address-limit");
2448  if (limit_elem) {
2449  limit = limit_elem->intValue();
2450  return (true);
2451  }
2452 
2453  return (false);
2454 }
2455 
2456 namespace {
2457 
2458 std::string
2459 idToText(const OptionBuffer& id) {
2460  std::stringstream tmp;
2461  tmp << std::hex;
2462  bool delim = false;
2463  for (std::vector<uint8_t>::const_iterator it = id.begin();
2464  it != id.end(); ++it) {
2465  if (delim) {
2466  tmp << ":";
2467  }
2468  tmp << std::setw(2) << std::setfill('0')
2469  << static_cast<unsigned int>(*it);
2470  delim = true;
2471  }
2472  return (tmp.str());
2473 }
2474 
2475 } // anonymous namespace
2476 
2479  const IOAddress& lower_bound_address,
2480  const LeasePageSize& page_size,
2481  const time_t& qry_start_time /* = 0 */,
2482  const time_t& qry_end_time /* = 0 */) {
2483  // Expecting IPv4 address.
2484  if (!lower_bound_address.isV4()) {
2485  isc_throw(InvalidAddressFamily, "expected IPv4 address while "
2486  "retrieving leases from the lease database, got "
2487  << lower_bound_address);
2488  }
2489 
2492  .arg(page_size.page_size_)
2493  .arg(lower_bound_address.toText())
2494  .arg(idToText(relay_id))
2495  .arg(qry_start_time)
2496  .arg(qry_end_time);
2497 
2498  if (MultiThreadingMgr::instance().getMode()) {
2499  std::lock_guard<std::mutex> lock(*mutex_);
2500  return (getLeases4ByRelayIdInternal(relay_id,
2501  lower_bound_address,
2502  page_size,
2503  qry_start_time,
2504  qry_end_time));
2505  } else {
2506  return (getLeases4ByRelayIdInternal(relay_id,
2507  lower_bound_address,
2508  page_size,
2509  qry_start_time,
2510  qry_end_time));
2511  }
2512 }
2513 
2515 Memfile_LeaseMgr::getLeases4ByRelayIdInternal(const OptionBuffer&,
2516  const IOAddress&,
2517  const LeasePageSize&,
2518  const time_t&,
2519  const time_t&) {
2520  isc_throw(NotImplemented, "Memfile_LeaseMgr::getLeases4ByRelayId not implemented");
2521 }
2522 
2525  const IOAddress& lower_bound_address,
2526  const LeasePageSize& page_size,
2527  const time_t& qry_start_time /* = 0 */,
2528  const time_t& qry_end_time /* = 0 */) {
2529  // Expecting IPv4 address.
2530  if (!lower_bound_address.isV4()) {
2531  isc_throw(InvalidAddressFamily, "expected IPv4 address while "
2532  "retrieving leases from the lease database, got "
2533  << lower_bound_address);
2534  }
2535 
2538  .arg(page_size.page_size_)
2539  .arg(lower_bound_address.toText())
2540  .arg(idToText(remote_id))
2541  .arg(qry_start_time)
2542  .arg(qry_end_time);
2543 
2544  if (MultiThreadingMgr::instance().getMode()) {
2545  std::lock_guard<std::mutex> lock(*mutex_);
2546  return (getLeases4ByRemoteIdInternal(remote_id,
2547  lower_bound_address,
2548  page_size,
2549  qry_start_time,
2550  qry_end_time));
2551  } else {
2552  return (getLeases4ByRemoteIdInternal(remote_id,
2553  lower_bound_address,
2554  page_size,
2555  qry_start_time,
2556  qry_end_time));
2557  }
2558 }
2559 
2561 Memfile_LeaseMgr::getLeases4ByRemoteIdInternal(const OptionBuffer&,
2562  const IOAddress&,
2563  const LeasePageSize&,
2564  const time_t&,
2565  const time_t&) {
2566  isc_throw(NotImplemented, "Memfile_LeaseMgr::getLeases4ByRemoteId not implemented");
2567 }
2568 
2571  const IOAddress& link_addr,
2572  uint8_t link_len,
2573  const IOAddress& lower_bound_address,
2574  const LeasePageSize& page_size) {
2575  // Expecting IPv6 valid prefix and address.
2576  if (!link_addr.isV6()) {
2577  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
2578  "retrieving leases from the lease database, got "
2579  << link_addr);
2580  }
2581  if (link_len > 128) {
2582  isc_throw(OutOfRange, "invalid IPv6 prefix length "
2583  << static_cast<unsigned>(link_len));
2584  }
2585  if (!lower_bound_address.isV6()) {
2586  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
2587  "retrieving leases from the lease database, got "
2588  << lower_bound_address);
2589  }
2590 
2593  .arg(page_size.page_size_)
2594  .arg(lower_bound_address.toText())
2595  .arg(relay_id.toText())
2596  .arg(link_addr.toText())
2597  .arg(static_cast<unsigned>(link_len));
2598 
2599  if (MultiThreadingMgr::instance().getMode()) {
2600  std::lock_guard<std::mutex> lock(*mutex_);
2601  return (getLeases6ByRelayIdInternal(relay_id,
2602  link_addr,
2603  link_len,
2604  lower_bound_address,
2605  page_size));
2606  } else {
2607  return (getLeases6ByRelayIdInternal(relay_id,
2608  link_addr,
2609  link_len,
2610  lower_bound_address,
2611  page_size));
2612  }
2613 }
2614 
2616 Memfile_LeaseMgr::getLeases6ByRelayIdInternal(const DUID& relay_id,
2617  const IOAddress& link_addr,
2618  uint8_t link_len,
2619  const IOAddress& lower_bound_address,
2620  const LeasePageSize& page_size) {
2621  const std::vector<uint8_t>& relay_id_data = relay_id.getDuid();
2622  Lease6Collection collection;
2623  const RelayIdIndex& idx = relay_id6_.get<RelayIdIndexTag>();
2624  if (!link_len) {
2625  RelayIdIndex::const_iterator lb =
2626  idx.lower_bound(boost::make_tuple(relay_id_data,
2627  lower_bound_address));
2628 
2629  // Return all leases being within the page size.
2630  IOAddress last_addr = lower_bound_address;
2631  for (; lb != idx.end(); ++lb) {
2632  if ((*lb)->lease_addr_ == last_addr) {
2633  // Already seen: skip it.
2634  continue;
2635  }
2636  if ((*lb)->id_ != relay_id_data) {
2637  // Gone after the relay id index.
2638  break;
2639  }
2640  last_addr = (*lb)->lease_addr_;
2641  Lease6Ptr lease = getAnyLease6Internal(last_addr);
2642  if (lease) {
2643  collection.push_back(lease);
2644  if (collection.size() >= page_size.page_size_) {
2645  break;
2646  }
2647  }
2648  }
2649  } else {
2650  const IOAddress& first_addr = firstAddrInPrefix(link_addr, link_len);
2651  const IOAddress& last_addr = lastAddrInPrefix(link_addr, link_len);
2652  const IOAddress& start_addr =
2653  (lower_bound_address < first_addr ? first_addr : lower_bound_address);
2654  RelayIdIndex::const_iterator lb =
2655  idx.lower_bound(boost::make_tuple(relay_id_data, start_addr));
2656  RelayIdIndex::const_iterator ub =
2657  idx.upper_bound(boost::make_tuple(relay_id_data, last_addr));
2658 
2659  // Return all leases being within the page size.
2660  IOAddress last_seen_addr = lower_bound_address;
2661  for (auto it = lb; it != ub; ++it) {
2662  if ((*it)->lease_addr_ == last_seen_addr) {
2663  // Already seen: skip it.
2664  continue;
2665  }
2666  last_seen_addr = (*it)->lease_addr_;
2667  Lease6Ptr lease = getAnyLease6Internal(last_seen_addr);
2668  if (lease) {
2669  collection.push_back(lease);
2670  if (collection.size() >= page_size.page_size_) {
2671  break;
2672  }
2673  }
2674  }
2675  }
2676  return (collection);
2677 }
2678 
2681  const IOAddress& link_addr,
2682  uint8_t link_len,
2683  const IOAddress& lower_bound_address,
2684  const LeasePageSize& page_size) {
2685  // Expecting IPv6 valid prefix and address.
2686  if (!link_addr.isV6()) {
2687  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
2688  "retrieving leases from the lease database, got "
2689  << link_addr);
2690  }
2691  if (link_len > 128) {
2692  isc_throw(OutOfRange, "invalid IPv6 prefix length "
2693  << static_cast<unsigned>(link_len));
2694  }
2695  if (!lower_bound_address.isV6()) {
2696  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
2697  "retrieving leases from the lease database, got "
2698  << lower_bound_address);
2699  }
2700 
2703  .arg(page_size.page_size_)
2704  .arg(lower_bound_address.toText())
2705  .arg(idToText(remote_id))
2706  .arg(link_addr.toText())
2707  .arg(static_cast<unsigned>(link_len));
2708 
2709  if (MultiThreadingMgr::instance().getMode()) {
2710  std::lock_guard<std::mutex> lock(*mutex_);
2711  return (getLeases6ByRemoteIdInternal(remote_id,
2712  link_addr,
2713  link_len,
2714  lower_bound_address,
2715  page_size));
2716  } else {
2717  return (getLeases6ByRemoteIdInternal(remote_id,
2718  link_addr,
2719  link_len,
2720  lower_bound_address,
2721  page_size));
2722  }
2723 }
2724 
2726 Memfile_LeaseMgr::getLeases6ByRemoteIdInternal(const OptionBuffer& remote_id,
2727  const IOAddress& link_addr,
2728  uint8_t link_len,
2729  const IOAddress& lower_bound_address,
2730  const LeasePageSize& page_size) {
2731  Lease6Collection collection;
2732  std::set<IOAddress> sorted;
2733  const RemoteIdIndex& idx = remote_id6_.get<RemoteIdIndexTag>();
2734  RemoteIdIndexRange er = idx.equal_range(remote_id);
2735  if (!link_len) {
2736  // Store all addresses greater than lower_bound_address.
2737  for (auto it = er.first; it != er.second; ++it) {
2738  const IOAddress& addr = (*it)->lease_addr_;
2739  if (addr <= lower_bound_address) {
2740  continue;
2741  }
2742  static_cast<void>(sorted.insert(addr));
2743  }
2744 
2745  // Return all leases being within the page size.
2746  for (const IOAddress& addr : sorted) {
2747  Lease6Ptr lease = getAnyLease6Internal(addr);
2748  if (lease) {
2749  collection.push_back(lease);
2750  if (collection.size() >= page_size.page_size_) {
2751  break;
2752  }
2753  }
2754  }
2755  } else {
2756  const IOAddress& first_addr = firstAddrInPrefix(link_addr, link_len);
2757  const IOAddress& last_addr = lastAddrInPrefix(link_addr, link_len);
2758 
2759  // Store all addresses greater than lower_bound_address in the link.
2760  for (auto it = er.first; it != er.second; ++it) {
2761  const IOAddress& addr = (*it)->lease_addr_;
2762  if (addr <= lower_bound_address) {
2763  continue;
2764  }
2765  if ((addr < first_addr) || (last_addr < addr)) {
2766  continue;
2767  }
2768  static_cast<void>(sorted.insert(addr));
2769  }
2770 
2771  // Return all leases being within the page size.
2772  for (const IOAddress& addr : sorted) {
2773  Lease6Ptr lease = getAnyLease6Internal(addr);
2774  if (lease) {
2775  collection.push_back(lease);
2776  if (collection.size() >= page_size.page_size_) {
2777  break;
2778  }
2779  }
2780  }
2781  }
2782  return (collection);
2783 }
2784 
2787  uint8_t link_len,
2788  const IOAddress& lower_bound_address,
2789  const LeasePageSize& page_size) {
2790  // Expecting IPv6 valid prefix and address.
2791  if (!link_addr.isV6()) {
2792  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
2793  "retrieving leases from the lease database, got "
2794  << link_addr);
2795  }
2796  if ((link_len == 0) || (link_len > 128)) {
2797  isc_throw(OutOfRange, "invalid IPv6 prefix length "
2798  << static_cast<unsigned>(link_len));
2799  }
2800  if (!lower_bound_address.isV6()) {
2801  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
2802  "retrieving leases from the lease database, got "
2803  << lower_bound_address);
2804  }
2805 
2808  .arg(page_size.page_size_)
2809  .arg(lower_bound_address.toText())
2810  .arg(link_addr.toText())
2811  .arg(static_cast<unsigned>(link_len));
2812 
2813  if (MultiThreadingMgr::instance().getMode()) {
2814  std::lock_guard<std::mutex> lock(*mutex_);
2815  return (getLeases6ByLinkInternal(link_addr,
2816  link_len,
2817  lower_bound_address,
2818  page_size));
2819  } else {
2820  return (getLeases6ByLinkInternal(link_addr,
2821  link_len,
2822  lower_bound_address,
2823  page_size));
2824  }
2825 }
2826 
2828 Memfile_LeaseMgr::getLeases6ByLinkInternal(const IOAddress& link_addr,
2829  uint8_t link_len,
2830  const IOAddress& lower_bound_address,
2831  const LeasePageSize& page_size) {
2832  const IOAddress& first_addr = firstAddrInPrefix(link_addr, link_len);
2833  const IOAddress& last_addr = lastAddrInPrefix(link_addr, link_len);
2834  const IOAddress& start_addr =
2835  (lower_bound_address < first_addr ? first_addr : lower_bound_address);
2836  Lease6Collection collection;
2837  const Lease6StorageAddressIndex& idx = storage6_.get<AddressIndexTag>();
2838  Lease6StorageAddressIndex::const_iterator lb = idx.lower_bound(start_addr);
2839  Lease6StorageAddressIndex::const_iterator eb = idx.upper_bound(last_addr);
2840 
2841  // Return all leases being within the page size.
2842  IOAddress last_seen_addr = lower_bound_address;
2843  for (auto it = lb; it != eb; ++it) {
2844  if ((*it)->addr_ == last_seen_addr) {
2845  // Already seen: skip it.
2846  continue;
2847  }
2848  last_seen_addr = (*it)->addr_;
2849  Lease6Ptr lease = getAnyLease6Internal(last_seen_addr);
2850  if (lease) {
2851  collection.push_back(lease);
2852  if (collection.size() >= page_size.page_size_) {
2853  break;
2854  }
2855  }
2856  }
2857  return (collection);
2858 }
2859 
2860 size_t
2861 Memfile_LeaseMgr::buildExtendedInfoTables6Internal(bool update, bool current) {
2862  CfgConsistencyPtr cfg;
2863  if (current) {
2864  cfg = CfgMgr::instance().getCurrentCfg()->getConsistency();
2865  } else {
2866  cfg = CfgMgr::instance().getStagingCfg()->getConsistency();
2867  }
2868  if (!cfg) {
2869  isc_throw(Unexpected, "the " << (current ? "current" : "staging")
2870  << " consistency configuration is null");
2871  }
2872  auto check = cfg->getExtendedInfoSanityCheck();
2873  bool enabled = getExtendedInfoTablesEnabled();
2874 
2878  .arg(update ? " updating in file" : "")
2879  .arg(enabled ? "enabled" : "disabled");
2880 
2881  // Clear tables when enabled.
2882  if (enabled) {
2883  relay_id6_.clear();
2884  remote_id6_.clear();
2885  }
2886 
2887  size_t leases = 0;
2888  size_t modified = 0;
2889  size_t updated = 0;
2890  size_t processed = 0;
2891 
2892  for (auto lease : storage6_) {
2893  ++leases;
2894  try {
2895  if (upgradeLease6ExtendedInfo(lease, check)) {
2896  ++modified;
2897  if (update && persistLeases(V6)) {
2898  lease_file6_->append(*lease);
2899  ++updated;
2900  }
2901  }
2902  if (enabled && addExtendedInfo6(lease)) {
2903  ++processed;
2904  }
2905  } catch (const std::exception& ex) {
2908  .arg(lease->addr_.toText())
2909  .arg(ex.what());
2910  }
2911  }
2912 
2914  .arg(leases)
2915  .arg(modified)
2916  .arg(updated)
2917  .arg(processed);
2918 
2919  return (updated);
2920 }
2921 
2922 size_t
2924  if (MultiThreadingMgr::instance().getMode()) {
2925  std::lock_guard<std::mutex> lock(*mutex_);
2926  return (buildExtendedInfoTables6Internal(update, current));
2927  } else {
2928  return (buildExtendedInfoTables6Internal(update, current));
2929  }
2930 }
2931 
2932 void
2934  LeaseAddressRelayIdIndex& relay_id_idx =
2936  static_cast<void>(relay_id_idx.erase(addr));
2937  LeaseAddressRemoteIdIndex& remote_id_idx =
2939  static_cast<void>(remote_id_idx.erase(addr));
2940 }
2941 
2942 void
2944  const std::vector<uint8_t>& relay_id) {
2945  Lease6ExtendedInfoPtr ex_info;
2946  ex_info.reset(new Lease6ExtendedInfo(lease_addr, relay_id));
2947  relay_id6_.insert(ex_info);
2948 }
2949 
2950 void
2952  const std::vector<uint8_t>& remote_id) {
2953  Lease6ExtendedInfoPtr ex_info;
2954  ex_info.reset(new Lease6ExtendedInfo(lease_addr, remote_id));
2955  remote_id6_.insert(ex_info);
2956 }
2957 
2958 void
2959 Memfile_LeaseMgr::writeLeases4(const std::string& filename) {
2960  if (MultiThreadingMgr::instance().getMode()) {
2961  std::lock_guard<std::mutex> lock(*mutex_);
2962  writeLeases4Internal(filename);
2963  } else {
2964  writeLeases4Internal(filename);
2965  }
2966 }
2967 
2968 void
2969 Memfile_LeaseMgr::writeLeases4Internal(const std::string& filename) {
2970  bool overwrite = (lease_file4_ && lease_file4_->getFilename() == filename);
2971  try {
2972  if (overwrite) {
2973  lease_file4_->close();
2974  }
2975  std::ostringstream old;
2976  old << filename << ".bak" << getpid();
2977  ::rename(filename.c_str(), old.str().c_str());
2978  CSVLeaseFile4 backup(filename);
2979  backup.open();
2980  for (const auto& lease : storage4_) {
2981  backup.append(*lease);
2982  }
2983  backup.close();
2984  if (overwrite) {
2985  lease_file4_->open(true);
2986  }
2987  } catch (const std::exception&) {
2988  if (overwrite) {
2989  lease_file4_->open(true);
2990  }
2991  throw;
2992  }
2993 }
2994 
2995 void
2996 Memfile_LeaseMgr::writeLeases6(const std::string& filename) {
2997  if (MultiThreadingMgr::instance().getMode()) {
2998  std::lock_guard<std::mutex> lock(*mutex_);
2999  writeLeases6Internal(filename);
3000  } else {
3001  writeLeases6Internal(filename);
3002  }
3003 }
3004 
3005 void
3006 Memfile_LeaseMgr::writeLeases6Internal(const std::string& filename) {
3007  bool overwrite = (lease_file6_ && lease_file6_->getFilename() == filename);
3008  try {
3009  if (overwrite) {
3010  lease_file6_->close();
3011  }
3012  std::ostringstream old;
3013  old << filename << ".bak" << getpid();
3014  ::rename(filename.c_str(), old.str().c_str());
3015  CSVLeaseFile6 backup(filename);
3016  backup.open();
3017  for (const auto& lease : storage6_) {
3018  backup.append(*lease);
3019  }
3020  backup.close();
3021  if (overwrite) {
3022  lease_file6_->open(true);
3023  }
3024  } catch (const std::exception&) {
3025  if (overwrite) {
3026  lease_file6_->open(true);
3027  }
3028  throw;
3029  }
3030 }
3031 
3032 } // namespace dhcp
3033 } // namespace isc
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.
RAII class creating a critical section.
Represents a configuration for Lease File Cleanup.
Tag for indexes by DUID, IAID, lease type tuple.
virtual ~MemfileLeaseStatsQuery4()
Destructor.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HWADDR
bool exists() const
Checks if the CSV file exists and can be opened for reading.
Definition: csv_file.cc:133
boost::shared_ptr< TimerMgr > TimerMgrPtr
Type definition of the shared pointer to TimerMgr.
Definition: timer_mgr.h:24
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv4 leases.
virtual ~Memfile_LeaseMgr()
Destructor (closes file)
virtual void recountClassLeases4() override
Recount the leases per class for V4 leases.
MemfileLeaseStatsQuery(const SubnetID &subnet_id)
Constructor for single subnet query.
boost::shared_ptr< LeaseStatsQuery > LeaseStatsQueryPtr
Defines a pointer to a LeaseStatsQuery.
Definition: lease_mgr.h:210
Lease6ExtendedInfoRemoteIdTable::index< LeaseAddressIndexTag >::type LeaseAddressRemoteIdIndex
Lease6 extended information by lease address index of by remote id table.
util::Optional< std::string > getDataDir() const
returns path do the data directory
Definition: cfgmgr.cc:31
virtual Lease6Collection getLeases6() const override
Returns all IPv6 leases.
A generic exception that is thrown when a function is not implemented.
const isc::log::MessageID DHCPSRV_MEMFILE_UPDATE_ADDR6
void removeLease(LeasePtr lease)
Decrement the counts for all of a lease&#39;s classes by one.
const std::vector< uint8_t > & getClientId() const
Returns reference to the client-id data.
Definition: duid.cc:117
Structure that holds a lease for IPv4 address.
Definition: lease.h:305
virtual void setExtendedInfoTablesEnabled(const bool enabled)
Extended information / Bulk Lease Query shared interface.
Definition: lease_mgr.h:983
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES4
boost::shared_ptr< Lease6ExtendedInfo > Lease6ExtendedInfoPtr
Pointer to a Lease6ExtendedInfo object.
Abstract Lease Manager.
Definition: lease_mgr.h:225
void setup(const uint32_t lfc_interval, const boost::shared_ptr< CSVLeaseFile4 > &lease_file4, const boost::shared_ptr< CSVLeaseFile6 > &lease_file6, bool run_once_now=false)
Sets the new configuration for the Lease File Cleanup.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
std::pair< RemoteIdIndex::const_iterator, RemoteIdIndex::const_iterator > RemoteIdIndexRange
Lease6 extended information by remote id range.
int getExitStatus() const
Returns exit code of the last completed cleanup.
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_START
virtual std::string checkLimits4(isc::data::ConstElementPtr const &user_context) const override
Checks if the IPv4 lease limits set in the given user context are exceeded.
std::vector< LeaseStatsRow >::iterator next_pos_
An iterator for accessing the next row within the result set.
virtual size_t getClassLeaseCount(const ClientClass &client_class, const Lease::Type &ltype=Lease::TYPE_V4) const override
Returns the class lease count for a given class and lease type.
static std::string typeToText(Type type)
returns text representation of a lease type
Definition: lease.cc:53
virtual Lease4Collection getLeases4() const override
Returns all IPv4 leases.
const isc::log::MessageID DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6_ERROR
virtual Lease4Collection getLeases4ByRemoteId(const OptionBuffer &remote_id, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size, const time_t &qry_start_time=0, const time_t &qry_end_time=0) override
Returns existing IPv4 leases with a given remote-id.
void prettyPrint(ConstElementPtr element, std::ostream &out, unsigned indent, unsigned step)
Pretty prints the data into stream.
Definition: data.cc:1487
Tag for index using relay-id.
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES6
Memfile derivation of the IPv6 statistical lease data query.
const isc::log::MessageID DHCPSRV_MEMFILE_GET6_DUID
virtual void addRelayId6(const isc::asiolink::IOAddress &lease_addr, const std::vector< uint8_t > &relay_id) override
Add lease6 extended info into by-relay-id table.
void updateLease(LeasePtr new_lease, LeasePtr old_lease)
Adjust class lease counts given a new and old version of a lease.
virtual void updateLease4(const Lease4Ptr &lease4) override
Updates IPv4 lease.
MemfileLeaseStatsQuery(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for subnet range query.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
uint32_t preferred_lft_
Preferred lifetime.
Definition: lease.h:556
Manages a pool of asynchronous interval timers.
Definition: timer_mgr.h:62
Attempt to update lease that was not there.
Lease6ExtendedInfoRelayIdTable::index< LeaseAddressIndexTag >::type LeaseAddressRelayIdIndex
Lease6 extended information by lease address index of by relay id table.
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition: lease.h:514
Lease4Storage::index< HostnameIndexTag >::type Lease4StorageHostnameIndex
DHCPv4 lease storage index by hostname.
Lease6Storage::index< DuidIaidTypeIndexTag >::type Lease6StorageDuidIaidTypeIndex
DHCPv6 lease storage index by DUID, IAID, lease type.
Universe
Specifies universe (V4, V6)
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
the lease contains IPv6 prefix (for prefix delegation)
Definition: lease.h:49
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED4
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition: cfgmgr.cc:161
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID_HWADDR
Tag for indexes by expiration time.
std::vector< uint8_t > hwaddr_
Definition: hwaddr.h:98
bool isRunning() const
Checks if the lease file cleanup is in progress.
STL namespace.
boost::shared_ptr< CSVLeaseFile4 > lease_file4_
Holds the pointer to the DHCPv4 lease file IO.
const isc::log::MessageID DHCPSRV_MEMFILE_CONVERTING_LEASE_FILES
virtual void writeLeases4(const std::string &filename) override
Write V4 leases to a file.
Lease4Storage::index< HWAddressSubnetIdIndexTag >::type Lease4StorageHWAddressSubnetIdIndex
DHCPv4 lease storage index by HW address and subnet identifier.
Base class for fulfilling a statistical lease data query.
Definition: lease_mgr.h:131
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_SETUP
std::string getFilename() const
Returns the path to the CSV file.
Definition: csv_file.h:408
void start()
Creates the IPv4 lease statistical data result set.
Class to help with processing PID files.
Definition: pid_file.h:40
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv4 leases.
Memfile_LeaseMgr(const db::DatabaseConnection::ParameterMap &parameters)
The sole lease manager constructor.
virtual Lease6Collection getLeases6ByLink(const asiolink::IOAddress &link_addr, uint8_t link_len, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size) override
Returns existing IPv6 leases with on a given link.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID
virtual std::pair< uint32_t, uint32_t > getVersion() const override
Returns backend version.
boost::shared_ptr< CfgConsistency > CfgConsistencyPtr
Type used to for pointing to CfgConsistency structure.
ignore extended info,
Definition: lease.h:189
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv6 leases.
virtual void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv6 leases.
Lease6ExtendedInfoRemoteIdTable::index< RemoteIdIndexTag >::type RemoteIdIndex
Lease6 extended information by remote id index.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_PAGE6
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_RELAYID4
const isc::log::MessageID DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6
LFCFileType
Types of the lease files used by the Lease File Cleanup.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
size_t getClassCount(const ClientClass &client_class, const Lease::Type &ltype=Lease::TYPE_V4) const
Fetches the lease count for the given class and lease type.
Holds DUID (DHCPv6 Unique Identifier)
Definition: duid.h:27
const isc::log::MessageID DHCPSRV_MEMFILE_UPDATE_ADDR4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID4
Tag for index using hostname.
Exception thrown on failure to open database.
Provides methods to access CSV file with DHCPv4 leases.
static isc::asiolink::IOServicePtr & getIOService()
Returns pointer to the IO service.
Definition: lease_mgr.h:793
MemfileLeaseStatsQuery6(Lease6Storage &storage6, const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for a subnet range query.
const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR6
const isc::log::MessageID DHCPSRV_MEMFILE_GET6
virtual Lease4Collection getLeases4ByRelayId(const OptionBuffer &relay_id, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size, const time_t &qry_start_time=0, const time_t &qry_end_time=0) override
The following queries are used to fulfill Bulk Lease Query queries.
Lease6Storage::index< AddressIndexTag >::type Lease6StorageAddressIndex
DHCPv6 lease storage index by address.
MemfileLeaseStatsQuery6(Lease6Storage &storage6, const SubnetID &subnet_id)
Constructor for a single subnet query.
static std::string getDBVersion()
Class method to return extended version info This class method must be redeclared and redefined in de...
Definition: lease_mgr.cc:360
static bool upgradeLease6ExtendedInfo(const Lease6Ptr &lease, CfgConsistency::ExtendedInfoSanity check=CfgConsistency::EXTENDED_INFO_CHECK_FIX)
Upgrade a V6 lease user context to the new extended info entry.
Definition: lease_mgr.cc:612
const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR4
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
virtual Lease6Collection getLeases6ByRemoteId(const OptionBuffer &remote_id, const asiolink::IOAddress &link_addr, uint8_t link_len, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size) override
Returns existing IPv6 leases with a given remote-id.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES6_FINISHED
virtual void lfcCallback()
A callback function triggering Lease File Cleanup (LFC).
Lease6Storage::index< DuidIndexTag >::type Lease6StorageDuidIndex
DHCPv6 lease storage index by DUID.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_CLIENTID
Lease4Storage::index< AddressIndexTag >::type Lease4StorageAddressIndex
DHCPv4 lease storage index by address.
Definition: edns.h:19
const isc::log::MessageID DHCPSRV_MEMFILE_GET_IAID_DUID
virtual void commit() override
Commit Transactions.
virtual bool getNextRow(LeaseStatsRow &row)
Fetches the next row in the result set.
Lease4Storage::index< SubnetIdIndexTag >::type Lease4StorageSubnetIdIndex
DHCPv4 lease storage index subnet identifier.
const size_t page_size_
Holds page size.
Definition: lease_mgr.h:56
boost::multi_index_container< Lease6Ptr, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< AddressIndexTag >, boost::multi_index::member< Lease, isc::asiolink::IOAddress, &Lease::addr_ > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< DuidIaidTypeIndexTag >, boost::multi_index::composite_key< Lease6, boost::multi_index::const_mem_fun< Lease6, const std::vector< uint8_t > &, &Lease6::getDuidVector >, boost::multi_index::member< Lease6, uint32_t, &Lease6::iaid_ >, boost::multi_index::member< Lease6, Lease::Type, &Lease6::type_ > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< ExpirationIndexTag >, boost::multi_index::composite_key< Lease6, boost::multi_index::const_mem_fun< Lease, bool, &Lease::stateExpiredReclaimed >, boost::multi_index::const_mem_fun< Lease, int64_t, &Lease::getExpirationTime > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetIdIndexTag >, boost::multi_index::member< Lease, isc::dhcp::SubnetID, &Lease::subnet_id_ > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< DuidIndexTag >, boost::multi_index::const_mem_fun< Lease6, const std::vector< uint8_t > &, &Lease6::getDuidVector > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< HostnameIndexTag >, boost::multi_index::member< Lease, std::string, &Lease::hostname_ > > >> Lease6Storage
A multi index container holding DHCPv6 leases.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_RELAYID6
bool isLFCRunning() const
Checks if the process performing lease file cleanup is running.
Tag for index using remote-id.
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:294
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition: dhcpsrv_log.h:38
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery4(const SubnetID &subnet_id) override
Creates and runs the IPv4 lease stats query for a single subnet.
Lease4Storage::index< ExpirationIndexTag >::type Lease4StorageExpirationIndex
DHCPv4 lease storage index by expiration time.
virtual bool addExtendedInfo6(const Lease6Ptr &lease)
Extract extended info from a lease6 and add it into tables.
Definition: lease_mgr.cc:965
static const int MINOR_VERSION_V4
the minor version of the v4 memfile backend
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_EXECUTE
const isc::log::MessageID DHCPSRV_MEMFILE_ROLLBACK
Lease6 extended informations for Bulk Lease Query.
Lease6ExtendedInfoRelayIdTable relay_id6_
stores IPv6 by-relay-id cross-reference table
const isc::log::MessageID DHCPSRV_MEMFILE_GET_ADDR4
A generic exception that is thrown when an unexpected error condition occurs.
virtual std::string getDescription() const override
Returns description of the backend.
IPv4 lease.
Definition: lease.h:50
virtual std::string checkLimits6(isc::data::ConstElementPtr const &user_context) const override
Checks if the IPv6 lease limits set in the given user context are exceeded.
virtual size_t buildExtendedInfoTables6(bool update, bool current) override
Build extended info v6 tables.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED6
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HOSTNAME4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID6
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HOSTNAME6
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:530
int version()
returns Kea hooks version.
virtual LeaseStatsQueryPtr startLeaseStatsQuery6() override
Creates and runs the IPv6 lease stats query.
const isc::log::MessageID DHCPSRV_MEMFILE_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.
Lease6Storage::index< HostnameIndexTag >::type Lease6StorageHostnameIndex
DHCPv6 lease storage index by hostname.
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_UNREGISTER_TIMER_FAILED
std::string getParameter(const std::string &name) const
Returns value of a connection parameter.
virtual LeaseStatsQueryPtr startLeaseStatsQuery4() override
Creates and runs the IPv4 lease stats query.
virtual void writeLeases6(const std::string &filename) override
Write V6 leases to a file.
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:677
virtual bool isJsonSupported() const override
Checks if JSON support is enabled in the database.
Tag for index using DUID.
bool getExtendedInfoTablesEnabled() const
Returns the setting indicating if lease extended info tables are enabled.
Definition: lease_mgr.h:960
void addLease(LeasePtr lease)
Increment the counts for all of a lease&#39;s classes by one.
virtual size_t wipeLeases6(const SubnetID &subnet_id) override
Removed specified IPv6 leases.
MemfileLeaseStatsQuery()
Constructor for all subnets query.
MemfileLeaseStatsQuery4(Lease4Storage &storage4, const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for a subnet range query.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED6
Tag for indexes by HW address, subnet identifier tuple.
virtual void updateLease6(const Lease6Ptr &lease6) override
Updates IPv6 lease.
const std::vector< uint8_t > & getDuid() const
Returns a const reference to the actual DUID value.
Definition: duid.cc:46
the lease contains non-temporary IPv6 address
Definition: lease.h:47
Memfile derivation of the IPv4 statistical lease data query.
virtual void deleteExtendedInfo6(const isc::asiolink::IOAddress &addr) override
Extended information / Bulk Lease Query shared interface.
const isc::log::MessageID DHCPSRV_MEMFILE_GET4
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const override
Returns existing IPv6 lease for a given IPv6 address.
virtual Lease6Collection getLeases6ByRelayId(const DUID &relay_id, const asiolink::IOAddress &link_addr, uint8_t link_len, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size) override
Returns existing IPv6 leases with a given relay-id.
Invalid address family used as input to Lease Manager.
Definition: db_exceptions.h:59
std::string getLeaseFilePath(Universe u) const
Returns an absolute path to the lease file.
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-lfc.
bool persistLeases(Universe u) const
Specifies whether or not leases are written to disk.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const override
Returns existing IPv4 lease for specified IPv4 address.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_ADDR6
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_RENAME_FAIL
void clear()
Remove all entries.
update extended info tables.
Definition: lease.h:191
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START
static std::string sanityCheckToText(LeaseSanity check_type)
Converts lease sanity check value to printable text.
Tag for indexes by address.
Tag for indexes by lease address.
const isc::log::MessageID DHCPSRV_MEMFILE_COMMIT
Lease6ExtendedInfoRelayIdTable::index< RelayIdIndexTag >::type RelayIdIndex
Lease6 extended information by relay id index.
std::string getDefaultLeaseFilePath(Universe u) const
Returns default path to the lease file.
virtual ~MemfileLeaseStatsQuery6()
Destructor.
virtual void recountClassLeases6() override
Recount the leases per class for V6 leases.
virtual size_t wipeLeases4(const SubnetID &subnet_id) override
Removes specified IPv4 leases.
Type
Type of lease or pool.
Definition: lease.h:46
Lease6Storage::index< ExpirationIndexTag >::type Lease6StorageExpirationIndex
DHCPv6 lease storage index by expiration time.
Holds Client identifier or client IPv4 address.
Definition: duid.h:111
static const int MAJOR_VERSION_V4
A generic exception that is thrown if a function is called in a prohibited way.
Provides input/output access to CSV files.
Definition: csv_file.h:358
MemfileLeaseStatsQuery6(Lease6Storage &storage6)
Constructor.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
const isc::log::MessageID DHCPSRV_MEMFILE_BEGIN_BUILD_EXTENDED_INFO_TABLES6
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_SPAWN_FAIL
Hardware type that represents information from DHCPv4 packet.
Definition: hwaddr.h:20
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition: dhcpsrv_log.h:26
Base Memfile derivation of the statistical lease data query.
static const uint32_t STATE_DEFAULT
A lease in the default state.
Definition: lease.h:69
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_MEMFILE_GET_PAGE4
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES4_FINISHED
Lease6ExtendedInfoRemoteIdTable remote_id6_
stores IPv6 by-remote-id cross-reference table
const isc::log::MessageID DHCPSRV_MEMFILE_GET_REMOTEID6
Tag for indexes by client and subnet identifiers.
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:72
Contains a single row of lease statistical data.
Definition: lease_mgr.h:64
std::vector< LeaseStatsRow > rows_
A vector containing the "result set".
void execute()
Spawns a new process.
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
Definition: duid.cc:75
MemfileLeaseStatsQuery4(Lease4Storage &storage4, const SubnetID &subnet_id)
Constructor for a single subnet query.
Wraps value holding size of the page with leases.
Definition: lease_mgr.h:46
const isc::log::MessageID DHCPSRV_MEMFILE_NO_STORAGE
ExtendedInfoAction
Action on extended info tables.
Definition: lease.h:188
uint32_t valid_lft_
Valid lifetime.
Definition: lease.h:125
std::string ClientClass
Defines a single class name.
Definition: classify.h:42
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Tag for indexes by subnet-id.
virtual ~MemfileLeaseStatsQuery()
Destructor.
Lease4Storage::index< ClientIdSubnetIdIndexTag >::type Lease4StorageClientIdSubnetIdIndex
DHCPv4 lease storage index by client and subnet identifier.
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_REOPEN_FAIL
virtual bool addLease(const Lease4Ptr &lease) override
Adds an IPv4 lease.
boost::shared_ptr< CSVLeaseFile6 > lease_file6_
Holds the pointer to the DHCPv6 lease file IO.
virtual void start()
Creates the IPv6 lease statistical data result set.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery6(const SubnetID &subnet_id) override
Creates and runs the IPv6 lease stats query for a single subnet.
int getLFCExitStatus() const
Returns the status code returned by the last executed LFC process.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED4
virtual void clearClassLeaseCounts() override
Clears the class-lease count map.
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:519
static const int MINOR_VERSION_V6
the minor version of the v6 memfile backend
Provides methods to access CSV file with DHCPv6 leases.
delete reference to the lease
Definition: lease.h:190
static std::string appendSuffix(const std::string &file_name, const LFCFileType &file_type)
Appends appropriate suffix to the file name.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID_CLIENTID
const isc::log::MessageID DHCPSRV_MEMFILE_GET_REMOTEID4
MemfileLeaseStatsQuery4(Lease4Storage &storage4)
Constructor for an all subnets query.
int getRowCount() const
Returns the number of rows in the result set.
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
Definition: duid.cc:122
virtual void addRemoteId6(const isc::asiolink::IOAddress &lease_addr, const std::vector< uint8_t > &remote_id) override
Add lease6 extended info into by-remote-id table.
std::string toText(bool include_htype=true) const
Returns textual representation of a hardware address (e.g.
Definition: hwaddr.cc:51
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:25
virtual bool deleteLease(const Lease4Ptr &lease) override
Deletes an IPv4 lease.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_LINKADDR6
Lease6Storage::index< SubnetIdIndexTag >::type Lease6StorageSubnetIdIndex
DHCPv6 lease storage index by Subnet-id.
virtual void rollback() override
Rollback Transactions.
Exception thrown when an error occurs during CSV file processing.
Definition: csv_file.h:22
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition: cfgmgr.cc:167
int check() const
Read the PID in from the file and check it.
Definition: pid_file.cc:26
boost::multi_index_container< Lease4Ptr, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< AddressIndexTag >, boost::multi_index::member< Lease, isc::asiolink::IOAddress, &Lease::addr_ > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< HWAddressSubnetIdIndexTag >, boost::multi_index::composite_key< Lease4, boost::multi_index::const_mem_fun< Lease, const std::vector< uint8_t > &, &Lease::getHWAddrVector >, boost::multi_index::member< Lease, SubnetID, &Lease::subnet_id_ > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< ClientIdSubnetIdIndexTag >, boost::multi_index::composite_key< Lease4, boost::multi_index::const_mem_fun< Lease4, const std::vector< uint8_t > &, &Lease4::getClientIdVector >, boost::multi_index::member< Lease, uint32_t, &Lease::subnet_id_ > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< ExpirationIndexTag >, boost::multi_index::composite_key< Lease4, boost::multi_index::const_mem_fun< Lease, bool, &Lease::stateExpiredReclaimed >, boost::multi_index::const_mem_fun< Lease, int64_t, &Lease::getExpirationTime > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetIdIndexTag >, boost::multi_index::member< Lease, isc::dhcp::SubnetID, &Lease::subnet_id_ > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< HostnameIndexTag >, boost::multi_index::member< Lease, std::string, &Lease::hostname_ > >, boost::multi_index::hashed_non_unique< boost::multi_index::tag< RemoteIdIndexTag >, boost::multi_index::member< Lease4, std::vector< uint8_t >, &Lease4::remote_id_ > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< RelayIdIndexTag >, boost::multi_index::composite_key< Lease4, boost::multi_index::member< Lease4, std::vector< uint8_t >, &Lease4::relay_id_ >, boost::multi_index::member< Lease, isc::asiolink::IOAddress, &Lease::addr_ > > > >> Lease4Storage
A multi index container holding DHCPv4 leases.