Kea  2.5.3
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:
272  : LeaseStatsQuery(select_mode), rows_(0), next_pos_(rows_.end()) {
273  };
274 
279  : LeaseStatsQuery(subnet_id), rows_(0), next_pos_(rows_.end()) {
280  };
281 
286  MemfileLeaseStatsQuery(const SubnetID& first_subnet_id, const SubnetID& last_subnet_id)
287  : LeaseStatsQuery(first_subnet_id, last_subnet_id), rows_(0), next_pos_(rows_.end()) {
288  };
289 
292 
303  virtual bool getNextRow(LeaseStatsRow& row) {
304  if (next_pos_ == rows_.end()) {
305  return (false);
306  }
307 
308  row = *next_pos_;
309  ++next_pos_;
310  return (true);
311  }
312 
314  int getRowCount() const {
315  return (rows_.size());
316  }
317 
318 protected:
320  std::vector<LeaseStatsRow> rows_;
321 
323  std::vector<LeaseStatsRow>::iterator next_pos_;
324 };
325 
336 public:
343  const SelectMode& select_mode = ALL_SUBNETS)
344  : MemfileLeaseStatsQuery(select_mode), storage4_(storage4) {
345  };
346 
351  MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& subnet_id)
352  : MemfileLeaseStatsQuery(subnet_id), storage4_(storage4) {
353  };
354 
360  MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& first_subnet_id,
361  const SubnetID& last_subnet_id)
362  : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage4_(storage4) {
363  };
364 
367 
382  void start() {
383  switch (getSelectMode()) {
384  case ALL_SUBNETS:
385  case SINGLE_SUBNET:
386  case SUBNET_RANGE:
387  startSubnets();
388  break;
389 
390  case ALL_SUBNET_POOLS:
391  startSubnetPools();
392  break;
393  }
394  }
395 
396 private:
411  void startSubnets() {
412  const Lease4StorageSubnetIdIndex& idx
413  = storage4_.get<SubnetIdIndexTag>();
414 
415  // Set lower and upper bounds based on select mode
416  Lease4StorageSubnetIdIndex::const_iterator lower;
417  Lease4StorageSubnetIdIndex::const_iterator upper;
418 
419  switch (getSelectMode()) {
420  case ALL_SUBNETS:
421  lower = idx.begin();
422  upper = idx.end();
423  break;
424 
425  case SINGLE_SUBNET:
426  lower = idx.lower_bound(getFirstSubnetID());
427  upper = idx.upper_bound(getFirstSubnetID());
428  break;
429 
430  case SUBNET_RANGE:
431  lower = idx.lower_bound(getFirstSubnetID());
432  upper = idx.upper_bound(getLastSubnetID());
433  break;
434 
435  default:
436  return;
437  }
438 
439  // Return an empty set if there are no rows.
440  if (lower == upper) {
441  return;
442  }
443 
444  // Iterate over the leases in order by subnet, accumulating per
445  // subnet counts for each state of interest. As we finish each
446  // subnet, add the appropriate rows to our result set.
447  SubnetID cur_id = 0;
448  int64_t assigned = 0;
449  int64_t declined = 0;
450  for (Lease4StorageSubnetIdIndex::const_iterator lease = lower;
451  lease != upper; ++lease) {
452  // If we've hit the next subnet, add rows for the current subnet
453  // and wipe the accumulators
454  if ((*lease)->subnet_id_ != cur_id) {
455  if (cur_id > 0) {
456  if (assigned > 0) {
457  rows_.push_back(LeaseStatsRow(cur_id,
459  assigned));
460  assigned = 0;
461  }
462 
463  if (declined > 0) {
464  rows_.push_back(LeaseStatsRow(cur_id,
466  declined));
467  declined = 0;
468  }
469  }
470 
471  // Update current subnet id
472  cur_id = (*lease)->subnet_id_;
473  }
474 
475  // Bump the appropriate accumulator
476  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
477  ++assigned;
478  } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
479  ++declined;
480  }
481  }
482 
483  // Make the rows for last subnet
484  if (assigned > 0) {
485  rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
486  assigned));
487  }
488 
489  if (declined > 0) {
490  rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
491  declined));
492  }
493 
494  // Reset the next row position back to the beginning of the rows.
495  next_pos_ = rows_.begin();
496  }
497 
512  void startSubnetPools() {
514  = storage4_.get<SubnetIdPoolIdIndexTag>();
515 
516  // Set lower and upper bounds based on select mode
517  Lease4StorageSubnetIdPoolIdIndex::const_iterator lower;
518  Lease4StorageSubnetIdPoolIdIndex::const_iterator upper;
519  switch (getSelectMode()) {
520  case ALL_SUBNET_POOLS:
521  lower = idx.begin();
522  upper = idx.end();
523  break;
524 
525  default:
526  return;
527  }
528 
529  // Return an empty set if there are no rows.
530  if (lower == upper) {
531  return;
532  }
533 
534  // Iterate over the leases in order by subnet and pool, accumulating per
535  // subnet and pool counts for each state of interest. As we finish each
536  // subnet or pool, add the appropriate rows to our result set.
537  SubnetID cur_id = 0;
538  uint32_t cur_pool_id = 0;
539  int64_t assigned = 0;
540  int64_t declined = 0;
541  for (Lease4StorageSubnetIdPoolIdIndex::const_iterator lease = lower;
542  lease != upper; ++lease) {
543  // If we've hit the next pool, add rows for the current subnet and
544  // pool and wipe the accumulators
545  if ((*lease)->pool_id_ != cur_pool_id) {
546  if (assigned > 0) {
547  rows_.push_back(LeaseStatsRow(cur_id,
549  assigned, cur_pool_id));
550  assigned = 0;
551  }
552 
553  if (declined > 0) {
554  rows_.push_back(LeaseStatsRow(cur_id,
556  declined, cur_pool_id));
557  declined = 0;
558  }
559 
560  // Update current pool id
561  cur_pool_id = (*lease)->pool_id_;
562  }
563 
564  // If we've hit the next subnet, add rows for the current subnet
565  // and wipe the accumulators
566  if ((*lease)->subnet_id_ != cur_id) {
567  if (cur_id > 0) {
568  if (assigned > 0) {
569  rows_.push_back(LeaseStatsRow(cur_id,
571  assigned, cur_pool_id));
572  assigned = 0;
573  }
574 
575  if (declined > 0) {
576  rows_.push_back(LeaseStatsRow(cur_id,
578  declined, cur_pool_id));
579  declined = 0;
580  }
581  }
582 
583  // Update current subnet id
584  cur_id = (*lease)->subnet_id_;
585 
586  // Reset pool id
587  cur_pool_id = 0;
588  }
589 
590  // Bump the appropriate accumulator
591  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
592  ++assigned;
593  } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
594  ++declined;
595  }
596  }
597 
598  // Make the rows for last subnet
599  if (assigned > 0) {
600  rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
601  assigned, cur_pool_id));
602  }
603 
604  if (declined > 0) {
605  rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
606  declined, cur_pool_id));
607  }
608 
609  // Reset the next row position back to the beginning of the rows.
610  next_pos_ = rows_.begin();
611  }
612 
614  Lease4Storage& storage4_;
615 };
616 
617 
628 public:
635  const SelectMode& select_mode = ALL_SUBNETS)
636  : MemfileLeaseStatsQuery(select_mode), storage6_(storage6) {
637  };
638 
643  MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& subnet_id)
644  : MemfileLeaseStatsQuery(subnet_id), storage6_(storage6) {
645  };
646 
652  MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& first_subnet_id,
653  const SubnetID& last_subnet_id)
654  : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage6_(storage6) {
655  };
656 
659 
674  void start() {
675  switch (getSelectMode()) {
676  case ALL_SUBNETS:
677  case SINGLE_SUBNET:
678  case SUBNET_RANGE:
679  startSubnets();
680  break;
681 
682  case ALL_SUBNET_POOLS:
683  startSubnetPools();
684  break;
685  }
686  }
687 
688 private:
703  virtual void startSubnets() {
704  const Lease6StorageSubnetIdIndex& idx
705  = storage6_.get<SubnetIdIndexTag>();
706 
707  // Set lower and upper bounds based on select mode
708  Lease6StorageSubnetIdIndex::const_iterator lower;
709  Lease6StorageSubnetIdIndex::const_iterator upper;
710  switch (getSelectMode()) {
711  case ALL_SUBNETS:
712  lower = idx.begin();
713  upper = idx.end();
714  break;
715 
716  case SINGLE_SUBNET:
717  lower = idx.lower_bound(getFirstSubnetID());
718  upper = idx.upper_bound(getFirstSubnetID());
719  break;
720 
721  case SUBNET_RANGE:
722  lower = idx.lower_bound(getFirstSubnetID());
723  upper = idx.upper_bound(getLastSubnetID());
724  break;
725 
726  default:
727  return;
728  }
729 
730  // Return an empty set if there are no rows.
731  if (lower == upper) {
732  return;
733  }
734 
735  // Iterate over the leases in order by subnet, accumulating per
736  // subnet counts for each state of interest. As we finish each
737  // subnet, add the appropriate rows to our result set.
738  SubnetID cur_id = 0;
739  int64_t assigned = 0;
740  int64_t declined = 0;
741  int64_t assigned_pds = 0;
742  for (Lease6StorageSubnetIdIndex::const_iterator lease = lower;
743  lease != upper; ++lease) {
744  // If we've hit the next subnet, add rows for the current subnet
745  // and wipe the accumulators
746  if ((*lease)->subnet_id_ != cur_id) {
747  if (cur_id > 0) {
748  if (assigned > 0) {
749  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
751  assigned));
752  assigned = 0;
753  }
754 
755  if (declined > 0) {
756  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
758  declined));
759  declined = 0;
760  }
761 
762  if (assigned_pds > 0) {
763  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
765  assigned_pds));
766  assigned_pds = 0;
767  }
768  }
769 
770  // Update current subnet id
771  cur_id = (*lease)->subnet_id_;
772  }
773 
774  // Bump the appropriate accumulator
775  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
776  switch((*lease)->type_) {
777  case Lease::TYPE_NA:
778  ++assigned;
779  break;
780  case Lease::TYPE_PD:
781  ++assigned_pds;
782  break;
783  default:
784  break;
785  }
786  } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
787  // In theory only NAs can be declined
788  if (((*lease)->type_) == Lease::TYPE_NA) {
789  ++declined;
790  }
791  }
792  }
793 
794  // Make the rows for last subnet, unless there were no rows
795  if (assigned > 0) {
796  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
797  Lease::STATE_DEFAULT, assigned));
798  }
799 
800  if (declined > 0) {
801  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
802  Lease::STATE_DECLINED, declined));
803  }
804 
805  if (assigned_pds > 0) {
806  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
807  Lease::STATE_DEFAULT, assigned_pds));
808  }
809 
810  // Set the next row position to the beginning of the rows.
811  next_pos_ = rows_.begin();
812  }
813 
828  virtual void startSubnetPools() {
830  = storage6_.get<SubnetIdPoolIdIndexTag>();
831 
832  // Set lower and upper bounds based on select mode
833  Lease6StorageSubnetIdPoolIdIndex::const_iterator lower;
834  Lease6StorageSubnetIdPoolIdIndex::const_iterator upper;
835  switch (getSelectMode()) {
836  case ALL_SUBNET_POOLS:
837  lower = idx.begin();
838  upper = idx.end();
839  break;
840 
841  default:
842  return;
843  }
844 
845  // Return an empty set if there are no rows.
846  if (lower == upper) {
847  return;
848  }
849 
850  // Iterate over the leases in order by subnet, accumulating per
851  // subnet counts for each state of interest. As we finish each
852  // subnet, add the appropriate rows to our result set.
853  SubnetID cur_id = 0;
854  uint32_t cur_pool_id = 0;
855  int64_t assigned = 0;
856  int64_t declined = 0;
857  int64_t assigned_pds = 0;
858  for (Lease6StorageSubnetIdPoolIdIndex::const_iterator lease = lower;
859  lease != upper; ++lease) {
860  // If we've hit the next pool, add rows for the current subnet and
861  // pool and wipe the accumulators
862  if ((*lease)->pool_id_ != cur_pool_id) {
863  if (assigned > 0) {
864  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
866  assigned, cur_pool_id));
867  assigned = 0;
868  }
869 
870  if (declined > 0) {
871  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
873  declined, cur_pool_id));
874  declined = 0;
875  }
876 
877  if (assigned_pds > 0) {
878  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
880  assigned_pds, cur_pool_id));
881  assigned_pds = 0;
882  }
883 
884  // Update current pool id
885  cur_pool_id = (*lease)->pool_id_;
886  }
887 
888  // If we've hit the next subnet, add rows for the current subnet
889  // and wipe the accumulators
890  if ((*lease)->subnet_id_ != cur_id) {
891  if (cur_id > 0) {
892  if (assigned > 0) {
893  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
895  assigned, cur_pool_id));
896  assigned = 0;
897  }
898 
899  if (declined > 0) {
900  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
902  declined, cur_pool_id));
903  declined = 0;
904  }
905 
906  if (assigned_pds > 0) {
907  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
909  assigned_pds, cur_pool_id));
910  assigned_pds = 0;
911  }
912  }
913 
914  // Update current subnet id
915  cur_id = (*lease)->subnet_id_;
916 
917  // Reset pool id
918  cur_pool_id = 0;
919  }
920 
921  // Bump the appropriate accumulator
922  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
923  switch((*lease)->type_) {
924  case Lease::TYPE_NA:
925  ++assigned;
926  break;
927  case Lease::TYPE_PD:
928  ++assigned_pds;
929  break;
930  default:
931  break;
932  }
933  } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
934  // In theory only NAs can be declined
935  if (((*lease)->type_) == Lease::TYPE_NA) {
936  ++declined;
937  }
938  }
939  }
940 
941  // Make the rows for last subnet, unless there were no rows
942  if (assigned > 0) {
943  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
944  Lease::STATE_DEFAULT, assigned,
945  cur_pool_id));
946  }
947 
948  if (declined > 0) {
949  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
950  Lease::STATE_DECLINED, declined,
951  cur_pool_id));
952  }
953 
954  if (assigned_pds > 0) {
955  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
956  Lease::STATE_DEFAULT, assigned_pds,
957  cur_pool_id));
958  }
959 
960  // Set the next row position to the beginning of the rows.
961  next_pos_ = rows_.begin();
962  }
963 
965  Lease6Storage& storage6_;
966 };
967 
968 // Explicit definition of class static constants. Values are given in the
969 // declaration so they're not needed here.
974 
976  : TrackingLeaseMgr(), lfc_setup_(), conn_(parameters), mutex_(new std::mutex) {
977  bool conversion_needed = false;
978 
979  // Check if the extended info tables are enabled.
980  setExtendedInfoTablesEnabled(parameters);
981 
982  // Check the universe and use v4 file or v6 file.
983  std::string universe = conn_.getParameter("universe");
984  if (universe == "4") {
985  std::string file4 = initLeaseFilePath(V4);
986  if (!file4.empty()) {
987  conversion_needed = loadLeasesFromFiles<Lease4,
988  CSVLeaseFile4>(file4,
989  lease_file4_,
990  storage4_);
991  static_cast<void>(extractExtendedInfo4(false, false));
992  }
993  } else {
994  std::string file6 = initLeaseFilePath(V6);
995  if (!file6.empty()) {
996  conversion_needed = loadLeasesFromFiles<Lease6,
997  CSVLeaseFile6>(file6,
998  lease_file6_,
999  storage6_);
1001  }
1002  }
1003 
1004  // If lease persistence have been disabled for both v4 and v6,
1005  // issue a warning. It is ok not to write leases to disk when
1006  // doing testing, but it should not be done in normal server
1007  // operation.
1008  if (!persistLeases(V4) && !persistLeases(V6)) {
1010  } else {
1011  if (conversion_needed) {
1012  auto const& version(getVersion());
1014  .arg(version.first).arg(version.second);
1015  }
1016  lfcSetup(conversion_needed);
1017  }
1018 }
1019 
1021  if (lease_file4_) {
1022  lease_file4_->close();
1023  lease_file4_.reset();
1024  }
1025  if (lease_file6_) {
1026  lease_file6_->close();
1027  lease_file6_.reset();
1028  }
1029 }
1030 
1031 std::string
1033  std::stringstream tmp;
1034  tmp << "Memfile backend ";
1035  if (u == V4) {
1036  tmp << MAJOR_VERSION_V4 << "." << MINOR_VERSION_V4;
1037  } else if (u == V6) {
1038  tmp << MAJOR_VERSION_V6 << "." << MINOR_VERSION_V6;
1039  }
1040  return tmp.str();
1041 }
1042 
1043 bool
1044 Memfile_LeaseMgr::addLeaseInternal(const Lease4Ptr& lease) {
1045  if (getLease4Internal(lease->addr_)) {
1046  // there is a lease with specified address already
1047  return (false);
1048  }
1049 
1050  // Try to write a lease to disk first. If this fails, the lease will
1051  // not be inserted to the memory and the disk and in-memory data will
1052  // remain consistent.
1053  if (persistLeases(V4)) {
1054  lease_file4_->append(*lease);
1055  }
1056 
1057  storage4_.insert(lease);
1058 
1059  // Update lease current expiration time (allows update between the creation
1060  // of the Lease up to the point of insertion in the database).
1061  lease->updateCurrentExpirationTime();
1062 
1063  // Increment class lease counters.
1064  class_lease_counter_.addLease(lease);
1065 
1066  // Run installed callbacks.
1067  if (hasCallbacks()) {
1068  trackAddLease(lease, true);
1069  }
1070 
1071  return (true);
1072 }
1073 
1074 bool
1077  DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
1078 
1079  if (MultiThreadingMgr::instance().getMode()) {
1080  std::lock_guard<std::mutex> lock(*mutex_);
1081  return (addLeaseInternal(lease));
1082  } else {
1083  return (addLeaseInternal(lease));
1084  }
1085 }
1086 
1087 bool
1088 Memfile_LeaseMgr::addLeaseInternal(const Lease6Ptr& lease) {
1089  if (getLease6Internal(lease->type_, lease->addr_)) {
1090  // there is a lease with specified address already
1091  return (false);
1092  }
1093 
1094  // Try to write a lease to disk first. If this fails, the lease will
1095  // not be inserted to the memory and the disk and in-memory data will
1096  // remain consistent.
1097  if (persistLeases(V6)) {
1098  lease_file6_->append(*lease);
1099  }
1100 
1101  lease->extended_info_action_ = Lease6::ACTION_IGNORE;
1102  storage6_.insert(lease);
1103 
1104  // Update lease current expiration time (allows update between the creation
1105  // of the Lease up to the point of insertion in the database).
1106  lease->updateCurrentExpirationTime();
1107 
1108  // Increment class lease counters.
1109  class_lease_counter_.addLease(lease);
1110 
1112  static_cast<void>(addExtendedInfo6(lease));
1113  }
1114 
1115  // Run installed callbacks.
1116  if (hasCallbacks()) {
1117  trackAddLease(lease, true);
1118  }
1119 
1120  return (true);
1121 }
1122 
1123 bool
1126  DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
1127 
1128  if (MultiThreadingMgr::instance().getMode()) {
1129  std::lock_guard<std::mutex> lock(*mutex_);
1130  return (addLeaseInternal(lease));
1131  } else {
1132  return (addLeaseInternal(lease));
1133  }
1134 }
1135 
1136 Lease4Ptr
1137 Memfile_LeaseMgr::getLease4Internal(const isc::asiolink::IOAddress& addr) const {
1138  const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1139  Lease4StorageAddressIndex::iterator l = idx.find(addr);
1140  if (l == idx.end()) {
1141  return (Lease4Ptr());
1142  } else {
1143  return (Lease4Ptr(new Lease4(**l)));
1144  }
1145 }
1146 
1147 Lease4Ptr
1150  DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
1151 
1152  if (MultiThreadingMgr::instance().getMode()) {
1153  std::lock_guard<std::mutex> lock(*mutex_);
1154  return (getLease4Internal(addr));
1155  } else {
1156  return (getLease4Internal(addr));
1157  }
1158 }
1159 
1160 void
1161 Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
1162  Lease4Collection& collection) const {
1163  // Using composite index by 'hw address' and 'subnet id'. It is
1164  // ok to use it for searching by the 'hw address' only.
1166  storage4_.get<HWAddressSubnetIdIndexTag>();
1167  std::pair<Lease4StorageHWAddressSubnetIdIndex::const_iterator,
1168  Lease4StorageHWAddressSubnetIdIndex::const_iterator> l
1169  = idx.equal_range(boost::make_tuple(hwaddr.hwaddr_));
1170 
1171  for (auto lease = l.first; lease != l.second; ++lease) {
1172  collection.push_back(Lease4Ptr(new Lease4(**lease)));
1173  }
1174 }
1175 
1177 Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr) const {
1179  DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.toText());
1180 
1181  Lease4Collection collection;
1182  if (MultiThreadingMgr::instance().getMode()) {
1183  std::lock_guard<std::mutex> lock(*mutex_);
1184  getLease4Internal(hwaddr, collection);
1185  } else {
1186  getLease4Internal(hwaddr, collection);
1187  }
1188 
1189  return (collection);
1190 }
1191 
1192 Lease4Ptr
1193 Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
1194  SubnetID subnet_id) const {
1195  // Get the index by HW Address and Subnet Identifier.
1197  storage4_.get<HWAddressSubnetIdIndexTag>();
1198  // Try to find the lease using HWAddr and subnet id.
1199  Lease4StorageHWAddressSubnetIdIndex::const_iterator lease =
1200  idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
1201  // Lease was not found. Return empty pointer to the caller.
1202  if (lease == idx.end()) {
1203  return (Lease4Ptr());
1204  }
1205 
1206  // Lease was found. Return it to the caller.
1207  return (Lease4Ptr(new Lease4(**lease)));
1208 }
1209 
1210 Lease4Ptr
1212  SubnetID subnet_id) const {
1214  DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
1215  .arg(hwaddr.toText());
1216 
1217  if (MultiThreadingMgr::instance().getMode()) {
1218  std::lock_guard<std::mutex> lock(*mutex_);
1219  return (getLease4Internal(hwaddr, subnet_id));
1220  } else {
1221  return (getLease4Internal(hwaddr, subnet_id));
1222  }
1223 }
1224 
1225 void
1226 Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
1227  Lease4Collection& collection) const {
1228  // Using composite index by 'client id' and 'subnet id'. It is ok
1229  // to use it to search by 'client id' only.
1231  storage4_.get<ClientIdSubnetIdIndexTag>();
1232  std::pair<Lease4StorageClientIdSubnetIdIndex::const_iterator,
1233  Lease4StorageClientIdSubnetIdIndex::const_iterator> l
1234  = idx.equal_range(boost::make_tuple(client_id.getClientId()));
1235 
1236  for (auto lease = l.first; lease != l.second; ++lease) {
1237  collection.push_back(Lease4Ptr(new Lease4(**lease)));
1238  }
1239 }
1240 
1242 Memfile_LeaseMgr::getLease4(const ClientId& client_id) const {
1244  DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.toText());
1245 
1246  Lease4Collection collection;
1247  if (MultiThreadingMgr::instance().getMode()) {
1248  std::lock_guard<std::mutex> lock(*mutex_);
1249  getLease4Internal(client_id, collection);
1250  } else {
1251  getLease4Internal(client_id, collection);
1252  }
1253 
1254  return (collection);
1255 }
1256 
1257 Lease4Ptr
1258 Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
1259  SubnetID subnet_id) const {
1260  // Get the index by client and subnet id.
1262  storage4_.get<ClientIdSubnetIdIndexTag>();
1263  // Try to get the lease using client id and subnet id.
1264  Lease4StorageClientIdSubnetIdIndex::const_iterator lease =
1265  idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
1266  // Lease was not found. Return empty pointer to the caller.
1267  if (lease == idx.end()) {
1268  return (Lease4Ptr());
1269  }
1270  // Lease was found. Return it to the caller.
1271  return (Lease4Ptr(new Lease4(**lease)));
1272 }
1273 
1274 Lease4Ptr
1276  SubnetID subnet_id) const {
1278  DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id)
1279  .arg(client_id.toText());
1280 
1281  if (MultiThreadingMgr::instance().getMode()) {
1282  std::lock_guard<std::mutex> lock(*mutex_);
1283  return (getLease4Internal(client_id, subnet_id));
1284  } else {
1285  return (getLease4Internal(client_id, subnet_id));
1286  }
1287 }
1288 
1289 void
1290 Memfile_LeaseMgr::getLeases4Internal(SubnetID subnet_id,
1291  Lease4Collection& collection) const {
1292  const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
1293  std::pair<Lease4StorageSubnetIdIndex::const_iterator,
1294  Lease4StorageSubnetIdIndex::const_iterator> l =
1295  idx.equal_range(subnet_id);
1296 
1297  for (auto lease = l.first; lease != l.second; ++lease) {
1298  collection.push_back(Lease4Ptr(new Lease4(**lease)));
1299  }
1300 }
1301 
1305  .arg(subnet_id);
1306 
1307  Lease4Collection collection;
1308  if (MultiThreadingMgr::instance().getMode()) {
1309  std::lock_guard<std::mutex> lock(*mutex_);
1310  getLeases4Internal(subnet_id, collection);
1311  } else {
1312  getLeases4Internal(subnet_id, collection);
1313  }
1314 
1315  return (collection);
1316 }
1317 
1318 void
1319 Memfile_LeaseMgr::getLeases4Internal(const std::string& hostname,
1320  Lease4Collection& collection) const {
1321  const Lease4StorageHostnameIndex& idx = storage4_.get<HostnameIndexTag>();
1322  std::pair<Lease4StorageHostnameIndex::const_iterator,
1323  Lease4StorageHostnameIndex::const_iterator> l =
1324  idx.equal_range(hostname);
1325 
1326  for (auto lease = l.first; lease != l.second; ++lease) {
1327  collection.push_back(Lease4Ptr(new Lease4(**lease)));
1328  }
1329 }
1330 
1332 Memfile_LeaseMgr::getLeases4(const std::string& hostname) const {
1334  .arg(hostname);
1335 
1336  Lease4Collection collection;
1337  if (MultiThreadingMgr::instance().getMode()) {
1338  std::lock_guard<std::mutex> lock(*mutex_);
1339  getLeases4Internal(hostname, collection);
1340  } else {
1341  getLeases4Internal(hostname, collection);
1342  }
1343 
1344  return (collection);
1345 }
1346 
1347 void
1348 Memfile_LeaseMgr::getLeases4Internal(Lease4Collection& collection) const {
1349  for (auto lease = storage4_.begin(); lease != storage4_.end(); ++lease) {
1350  collection.push_back(Lease4Ptr(new Lease4(**lease)));
1351  }
1352 }
1353 
1357 
1358  Lease4Collection collection;
1359  if (MultiThreadingMgr::instance().getMode()) {
1360  std::lock_guard<std::mutex> lock(*mutex_);
1361  getLeases4Internal(collection);
1362  } else {
1363  getLeases4Internal(collection);
1364  }
1365 
1366  return (collection);
1367 }
1368 
1369 void
1370 Memfile_LeaseMgr::getLeases4Internal(const asiolink::IOAddress& lower_bound_address,
1371  const LeasePageSize& page_size,
1372  Lease4Collection& collection) const {
1373  const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1374  Lease4StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1375 
1376  // Exclude the lower bound address specified by the caller.
1377  if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1378  ++lb;
1379  }
1380 
1381  // Return all other leases being within the page size.
1382  for (auto lease = lb;
1383  (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1384  ++lease) {
1385  collection.push_back(Lease4Ptr(new Lease4(**lease)));
1386  }
1387 }
1388 
1391  const LeasePageSize& page_size) const {
1392  // Expecting IPv4 address.
1393  if (!lower_bound_address.isV4()) {
1394  isc_throw(InvalidAddressFamily, "expected IPv4 address while "
1395  "retrieving leases from the lease database, got "
1396  << lower_bound_address);
1397  }
1398 
1400  .arg(page_size.page_size_)
1401  .arg(lower_bound_address.toText());
1402 
1403  Lease4Collection collection;
1404  if (MultiThreadingMgr::instance().getMode()) {
1405  std::lock_guard<std::mutex> lock(*mutex_);
1406  getLeases4Internal(lower_bound_address, page_size, collection);
1407  } else {
1408  getLeases4Internal(lower_bound_address, page_size, collection);
1409  }
1410 
1411  return (collection);
1412 }
1413 
1414 Lease6Ptr
1415 Memfile_LeaseMgr::getLease6Internal(Lease::Type type,
1416  const isc::asiolink::IOAddress& addr) const {
1417  Lease6Storage::iterator l = storage6_.find(addr);
1418  if (l == storage6_.end() || !(*l) || ((*l)->type_ != type)) {
1419  return (Lease6Ptr());
1420  } else {
1421  return (Lease6Ptr(new Lease6(**l)));
1422  }
1423 }
1424 
1425 Lease6Ptr
1426 Memfile_LeaseMgr::getAnyLease6Internal(const isc::asiolink::IOAddress& addr) const {
1427  Lease6Storage::iterator l = storage6_.find(addr);
1428  if (l == storage6_.end() || !(*l)) {
1429  return (Lease6Ptr());
1430  } else {
1431  return (Lease6Ptr(new Lease6(**l)));
1432  }
1433 }
1434 
1435 Lease6Ptr
1437  const isc::asiolink::IOAddress& addr) const {
1440  .arg(addr.toText())
1441  .arg(Lease::typeToText(type));
1442 
1443  if (MultiThreadingMgr::instance().getMode()) {
1444  std::lock_guard<std::mutex> lock(*mutex_);
1445  return (getLease6Internal(type, addr));
1446  } else {
1447  return (getLease6Internal(type, addr));
1448  }
1449 }
1450 
1451 void
1452 Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1453  const DUID& duid,
1454  uint32_t iaid,
1455  Lease6Collection& collection) const {
1456  // Get the index by DUID, IAID, lease type.
1457  const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1458  // Try to get the lease using the DUID, IAID and lease type.
1459  std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1460  Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1461  idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1462 
1463  for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1464  l.first; lease != l.second; ++lease) {
1465  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1466  }
1467 }
1468 
1471  const DUID& duid,
1472  uint32_t iaid) const {
1475  .arg(iaid)
1476  .arg(duid.toText())
1477  .arg(Lease::typeToText(type));
1478 
1479  Lease6Collection collection;
1480  if (MultiThreadingMgr::instance().getMode()) {
1481  std::lock_guard<std::mutex> lock(*mutex_);
1482  getLeases6Internal(type, duid, iaid, collection);
1483  } else {
1484  getLeases6Internal(type, duid, iaid, collection);
1485  }
1486 
1487  return (collection);
1488 }
1489 
1490 void
1491 Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1492  const DUID& duid,
1493  uint32_t iaid,
1494  SubnetID subnet_id,
1495  Lease6Collection& collection) const {
1496  // Get the index by DUID, IAID, lease type.
1497  const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1498  // Try to get the lease using the DUID, IAID and lease type.
1499  std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1500  Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1501  idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1502 
1503  for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1504  l.first; lease != l.second; ++lease) {
1505  // Filter out the leases which subnet id doesn't match.
1506  if ((*lease)->subnet_id_ == subnet_id) {
1507  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1508  }
1509  }
1510 }
1511 
1514  const DUID& duid,
1515  uint32_t iaid,
1516  SubnetID subnet_id) const {
1519  .arg(iaid)
1520  .arg(subnet_id)
1521  .arg(duid.toText())
1522  .arg(Lease::typeToText(type));
1523 
1524  Lease6Collection collection;
1525  if (MultiThreadingMgr::instance().getMode()) {
1526  std::lock_guard<std::mutex> lock(*mutex_);
1527  getLeases6Internal(type, duid, iaid, subnet_id, collection);
1528  } else {
1529  getLeases6Internal(type, duid, iaid, subnet_id, collection);
1530  }
1531 
1532  return (collection);
1533 }
1534 
1535 void
1536 Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1537  Lease6Collection& collection) const {
1538  const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1539  std::pair<Lease6StorageSubnetIdIndex::const_iterator,
1540  Lease6StorageSubnetIdIndex::const_iterator> l =
1541  idx.equal_range(subnet_id);
1542 
1543  for (auto lease = l.first; lease != l.second; ++lease) {
1544  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1545  }
1546 }
1547 
1551  .arg(subnet_id);
1552 
1553  Lease6Collection collection;
1554  if (MultiThreadingMgr::instance().getMode()) {
1555  std::lock_guard<std::mutex> lock(*mutex_);
1556  getLeases6Internal(subnet_id, collection);
1557  } else {
1558  getLeases6Internal(subnet_id, collection);
1559  }
1560 
1561  return (collection);
1562 }
1563 
1564 void
1565 Memfile_LeaseMgr::getLeases6Internal(const std::string& hostname,
1566  Lease6Collection& collection) const {
1567  const Lease6StorageHostnameIndex& idx = storage6_.get<HostnameIndexTag>();
1568  std::pair<Lease6StorageHostnameIndex::const_iterator,
1569  Lease6StorageHostnameIndex::const_iterator> l =
1570  idx.equal_range(hostname);
1571 
1572  for (auto lease = l.first; lease != l.second; ++lease) {
1573  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1574  }
1575 }
1576 
1578 Memfile_LeaseMgr::getLeases6(const std::string& hostname) const {
1580  .arg(hostname);
1581 
1582  Lease6Collection collection;
1583  if (MultiThreadingMgr::instance().getMode()) {
1584  std::lock_guard<std::mutex> lock(*mutex_);
1585  getLeases6Internal(hostname, collection);
1586  } else {
1587  getLeases6Internal(hostname, collection);
1588  }
1589 
1590  return (collection);
1591 }
1592 
1593 void
1594 Memfile_LeaseMgr::getLeases6Internal(Lease6Collection& collection) const {
1595  for (auto lease = storage6_.begin(); lease != storage6_.end(); ++lease) {
1596  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1597  }
1598 }
1599 
1603 
1604  Lease6Collection collection;
1605  if (MultiThreadingMgr::instance().getMode()) {
1606  std::lock_guard<std::mutex> lock(*mutex_);
1607  getLeases6Internal(collection);
1608  } else {
1609  getLeases6Internal(collection);
1610  }
1611 
1612  return (collection);
1613 }
1614 
1615 void
1616 Memfile_LeaseMgr::getLeases6Internal(const DUID& duid,
1617  Lease6Collection& collection) const {
1618  const Lease6StorageDuidIndex& idx = storage6_.get<DuidIndexTag>();
1619  std::pair<Lease6StorageDuidIndex::const_iterator,
1620  Lease6StorageDuidIndex::const_iterator> l =
1621  idx.equal_range(duid.getDuid());
1622 
1623  for (auto lease = l.first; lease != l.second; ++lease) {
1624  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1625  }
1626 }
1627 
1631  .arg(duid.toText());
1632 
1633  Lease6Collection collection;
1634  if (MultiThreadingMgr::instance().getMode()) {
1635  std::lock_guard<std::mutex> lock(*mutex_);
1636  getLeases6Internal(duid, collection);
1637  } else {
1638  getLeases6Internal(duid, collection);
1639  }
1640 
1641  return (collection);
1642 }
1643 
1644 void
1645 Memfile_LeaseMgr::getLeases6Internal(const asiolink::IOAddress& lower_bound_address,
1646  const LeasePageSize& page_size,
1647  Lease6Collection& collection) const {
1648  const Lease6StorageAddressIndex& idx = storage6_.get<AddressIndexTag>();
1649  Lease6StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1650 
1651  // Exclude the lower bound address specified by the caller.
1652  if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1653  ++lb;
1654  }
1655 
1656  // Return all other leases being within the page size.
1657  for (auto lease = lb;
1658  (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1659  ++lease) {
1660  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1661  }
1662 }
1663 
1666  const LeasePageSize& page_size) const {
1667  // Expecting IPv6 address.
1668  if (!lower_bound_address.isV6()) {
1669  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1670  "retrieving leases from the lease database, got "
1671  << lower_bound_address);
1672  }
1673 
1675  .arg(page_size.page_size_)
1676  .arg(lower_bound_address.toText());
1677 
1678  Lease6Collection collection;
1679  if (MultiThreadingMgr::instance().getMode()) {
1680  std::lock_guard<std::mutex> lock(*mutex_);
1681  getLeases6Internal(lower_bound_address, page_size, collection);
1682  } else {
1683  getLeases6Internal(lower_bound_address, page_size, collection);
1684  }
1685 
1686  return (collection);
1687 }
1688 
1689 void
1690 Memfile_LeaseMgr::getExpiredLeases4Internal(Lease4Collection& expired_leases,
1691  const size_t max_leases) const {
1692  // Obtain the index which segragates leases by state and time.
1693  const Lease4StorageExpirationIndex& index = storage4_.get<ExpirationIndexTag>();
1694 
1695  // Retrieve leases which are not reclaimed and which haven't expired. The
1696  // 'less-than' operator will be used for both components of the index. So,
1697  // for the 'state' 'false' is less than 'true'. Also the leases with
1698  // expiration time lower than current time will be returned.
1699  Lease4StorageExpirationIndex::const_iterator ub =
1700  index.upper_bound(boost::make_tuple(false, time(0)));
1701 
1702  // Copy only the number of leases indicated by the max_leases parameter.
1703  for (Lease4StorageExpirationIndex::const_iterator lease = index.begin();
1704  (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1705  max_leases));
1706  ++lease) {
1707  expired_leases.push_back(Lease4Ptr(new Lease4(**lease)));
1708  }
1709 }
1710 
1711 void
1713  const size_t max_leases) const {
1715  .arg(max_leases);
1716 
1717  if (MultiThreadingMgr::instance().getMode()) {
1718  std::lock_guard<std::mutex> lock(*mutex_);
1719  getExpiredLeases4Internal(expired_leases, max_leases);
1720  } else {
1721  getExpiredLeases4Internal(expired_leases, max_leases);
1722  }
1723 }
1724 
1725 void
1726 Memfile_LeaseMgr::getExpiredLeases6Internal(Lease6Collection& expired_leases,
1727  const size_t max_leases) const {
1728  // Obtain the index which segragates leases by state and time.
1729  const Lease6StorageExpirationIndex& index = storage6_.get<ExpirationIndexTag>();
1730 
1731  // Retrieve leases which are not reclaimed and which haven't expired. The
1732  // 'less-than' operator will be used for both components of the index. So,
1733  // for the 'state' 'false' is less than 'true'. Also the leases with
1734  // expiration time lower than current time will be returned.
1735  Lease6StorageExpirationIndex::const_iterator ub =
1736  index.upper_bound(boost::make_tuple(false, time(0)));
1737 
1738  // Copy only the number of leases indicated by the max_leases parameter.
1739  for (Lease6StorageExpirationIndex::const_iterator lease = index.begin();
1740  (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1741  max_leases));
1742  ++lease) {
1743  expired_leases.push_back(Lease6Ptr(new Lease6(**lease)));
1744  }
1745 }
1746 
1747 void
1749  const size_t max_leases) const {
1751  .arg(max_leases);
1752 
1753  if (MultiThreadingMgr::instance().getMode()) {
1754  std::lock_guard<std::mutex> lock(*mutex_);
1755  getExpiredLeases6Internal(expired_leases, max_leases);
1756  } else {
1757  getExpiredLeases6Internal(expired_leases, max_leases);
1758  }
1759 }
1760 
1761 void
1762 Memfile_LeaseMgr::updateLease4Internal(const Lease4Ptr& lease) {
1763  // Obtain 'by address' index.
1764  Lease4StorageAddressIndex& index = storage4_.get<AddressIndexTag>();
1765 
1766  bool persist = persistLeases(V4);
1767 
1768  // Lease must exist if it is to be updated.
1769  Lease4StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1770  if (lease_it == index.end()) {
1771  isc_throw(NoSuchLease, "failed to update the lease with address "
1772  << lease->addr_ << " - no such lease");
1773  } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1774  ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1775  // For test purpose only: check that the lease has not changed in
1776  // the database.
1777  isc_throw(NoSuchLease, "failed to update the lease with address "
1778  << lease->addr_ << " - lease has changed in database");
1779  }
1780 
1781  // Try to write a lease to disk first. If this fails, the lease will
1782  // not be inserted to the memory and the disk and in-memory data will
1783  // remain consistent.
1784  if (persist) {
1785  lease_file4_->append(*lease);
1786  }
1787 
1788  // Update lease current expiration time.
1789  lease->updateCurrentExpirationTime();
1790 
1791  // Save a copy of the old lease as lease_it will point to the new
1792  // one after the replacement.
1793  Lease4Ptr old_lease = *lease_it;
1794 
1795  // Use replace() to re-index leases.
1796  index.replace(lease_it, Lease4Ptr(new Lease4(*lease)));
1797 
1798  // Adjust class lease counters.
1799  class_lease_counter_.updateLease(lease, old_lease);
1800 
1801  // Run installed callbacks.
1802  if (hasCallbacks()) {
1803  trackUpdateLease(lease, true);
1804  }
1805 }
1806 
1807 void
1810  DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
1811 
1812  if (MultiThreadingMgr::instance().getMode()) {
1813  std::lock_guard<std::mutex> lock(*mutex_);
1814  updateLease4Internal(lease);
1815  } else {
1816  updateLease4Internal(lease);
1817  }
1818 }
1819 
1820 void
1821 Memfile_LeaseMgr::updateLease6Internal(const Lease6Ptr& lease) {
1822  // Obtain 'by address' index.
1823  Lease6StorageAddressIndex& index = storage6_.get<AddressIndexTag>();
1824 
1825  bool persist = persistLeases(V6);
1826 
1827  // Get the recorded action and reset it.
1828  Lease6::ExtendedInfoAction recorded_action = lease->extended_info_action_;
1829  lease->extended_info_action_ = Lease6::ACTION_IGNORE;
1830 
1831  // Lease must exist if it is to be updated.
1832  Lease6StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1833  if (lease_it == index.end()) {
1834  isc_throw(NoSuchLease, "failed to update the lease with address "
1835  << lease->addr_ << " - no such lease");
1836  } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1837  ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1838  // For test purpose only: check that the lease has not changed in
1839  // the database.
1840  isc_throw(NoSuchLease, "failed to update the lease with address "
1841  << lease->addr_ << " - lease has changed in database");
1842  }
1843 
1844  // Try to write a lease to disk first. If this fails, the lease will
1845  // not be inserted to the memory and the disk and in-memory data will
1846  // remain consistent.
1847  if (persist) {
1848  lease_file6_->append(*lease);
1849  }
1850 
1851  // Update lease current expiration time.
1852  lease->updateCurrentExpirationTime();
1853 
1854  // Save a copy of the old lease as lease_it will point to the new
1855  // one after the replacement.
1856  Lease6Ptr old_lease = *lease_it;
1857 
1858  // Use replace() to re-index leases.
1859  index.replace(lease_it, Lease6Ptr(new Lease6(*lease)));
1860 
1861  // Adjust class lease counters.
1862  class_lease_counter_.updateLease(lease, old_lease);
1863 
1864  // Update extended info tables.
1866  switch (recorded_action) {
1867  case Lease6::ACTION_IGNORE:
1868  break;
1869 
1870  case Lease6::ACTION_DELETE:
1871  deleteExtendedInfo6(lease->addr_);
1872  break;
1873 
1874  case Lease6::ACTION_UPDATE:
1875  deleteExtendedInfo6(lease->addr_);
1876  static_cast<void>(addExtendedInfo6(lease));
1877  break;
1878  }
1879  }
1880 
1881  // Run installed callbacks.
1882  if (hasCallbacks()) {
1883  trackUpdateLease(lease, true);
1884  }
1885 }
1886 
1887 void
1890  DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
1891 
1892  if (MultiThreadingMgr::instance().getMode()) {
1893  std::lock_guard<std::mutex> lock(*mutex_);
1894  updateLease6Internal(lease);
1895  } else {
1896  updateLease6Internal(lease);
1897  }
1898 }
1899 
1900 bool
1901 Memfile_LeaseMgr::deleteLeaseInternal(const Lease4Ptr& lease) {
1902  const isc::asiolink::IOAddress& addr = lease->addr_;
1903  Lease4Storage::iterator l = storage4_.find(addr);
1904  if (l == storage4_.end()) {
1905  // No such lease
1906  return (false);
1907  } else {
1908  if (persistLeases(V4)) {
1909  // Copy the lease. The valid lifetime needs to be modified and
1910  // we don't modify the original lease.
1911  Lease4 lease_copy = **l;
1912  // Setting valid lifetime to 0 means that lease is being
1913  // removed.
1914  lease_copy.valid_lft_ = 0;
1915  lease_file4_->append(lease_copy);
1916  } else {
1917  // For test purpose only: check that the lease has not changed in
1918  // the database.
1919  if (((*l)->cltt_ != lease->current_cltt_) ||
1920  ((*l)->valid_lft_ != lease->current_valid_lft_)) {
1921  return false;
1922  }
1923  }
1924 
1925  storage4_.erase(l);
1926 
1927  // Decrement class lease counters.
1928  class_lease_counter_.removeLease(lease);
1929 
1930  // Run installed callbacks.
1931  if (hasCallbacks()) {
1932  trackDeleteLease(lease, true);
1933  }
1934 
1935  return (true);
1936  }
1937 }
1938 
1939 bool
1942  DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
1943 
1944  if (MultiThreadingMgr::instance().getMode()) {
1945  std::lock_guard<std::mutex> lock(*mutex_);
1946  return (deleteLeaseInternal(lease));
1947  } else {
1948  return (deleteLeaseInternal(lease));
1949  }
1950 }
1951 
1952 bool
1953 Memfile_LeaseMgr::deleteLeaseInternal(const Lease6Ptr& lease) {
1954  lease->extended_info_action_ = Lease6::ACTION_IGNORE;
1955 
1956  const isc::asiolink::IOAddress& addr = lease->addr_;
1957  Lease6Storage::iterator l = storage6_.find(addr);
1958  if (l == storage6_.end()) {
1959  // No such lease
1960  return (false);
1961  } else {
1962  if (persistLeases(V6)) {
1963  // Copy the lease. The lifetimes need to be modified and we
1964  // don't modify the original lease.
1965  Lease6 lease_copy = **l;
1966  // Setting lifetimes to 0 means that lease is being removed.
1967  lease_copy.valid_lft_ = 0;
1968  lease_copy.preferred_lft_ = 0;
1969  lease_file6_->append(lease_copy);
1970  } else {
1971  // For test purpose only: check that the lease has not changed in
1972  // the database.
1973  if (((*l)->cltt_ != lease->current_cltt_) ||
1974  ((*l)->valid_lft_ != lease->current_valid_lft_)) {
1975  return false;
1976  }
1977  }
1978 
1979  storage6_.erase(l);
1980 
1981  // Decrement class lease counters.
1982  class_lease_counter_.removeLease(lease);
1983 
1984  // Delete references from extended info tables.
1986  deleteExtendedInfo6(lease->addr_);
1987  }
1988 
1989  // Run installed callbacks.
1990  if (hasCallbacks()) {
1991  trackDeleteLease(lease, true);
1992  }
1993 
1994  return (true);
1995  }
1996 }
1997 
1998 bool
2001  DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
2002 
2003  if (MultiThreadingMgr::instance().getMode()) {
2004  std::lock_guard<std::mutex> lock(*mutex_);
2005  return (deleteLeaseInternal(lease));
2006  } else {
2007  return (deleteLeaseInternal(lease));
2008  }
2009 }
2010 
2011 uint64_t
2015  .arg(secs);
2016 
2017  if (MultiThreadingMgr::instance().getMode()) {
2018  std::lock_guard<std::mutex> lock(*mutex_);
2019  return (deleteExpiredReclaimedLeases<
2021  >(secs, V4, storage4_, lease_file4_));
2022  } else {
2023  return (deleteExpiredReclaimedLeases<
2025  >(secs, V4, storage4_, lease_file4_));
2026  }
2027 }
2028 
2029 uint64_t
2033  .arg(secs);
2034 
2035  if (MultiThreadingMgr::instance().getMode()) {
2036  std::lock_guard<std::mutex> lock(*mutex_);
2037  return (deleteExpiredReclaimedLeases<
2039  >(secs, V6, storage6_, lease_file6_));
2040  } else {
2041  return (deleteExpiredReclaimedLeases<
2043  >(secs, V6, storage6_, lease_file6_));
2044  }
2045 }
2046 
2047 template<typename IndexType, typename LeaseType, typename StorageType,
2048  typename LeaseFileType>
2049 uint64_t
2050 Memfile_LeaseMgr::deleteExpiredReclaimedLeases(const uint32_t secs,
2051  const Universe& universe,
2052  StorageType& storage,
2053  LeaseFileType& lease_file) {
2054  // Obtain the index which segragates leases by state and time.
2055  IndexType& index = storage.template get<ExpirationIndexTag>();
2056 
2057  // This returns the first element which is greater than the specified
2058  // tuple (true, time(0) - secs). However, the range between the
2059  // beginning of the index and returned element also includes all the
2060  // elements for which the first value is false (lease state is NOT
2061  // reclaimed), because false < true. All elements between the
2062  // beginning of the index and the element returned, for which the
2063  // first value is true, represent the reclaimed leases which should
2064  // be deleted, because their expiration time + secs has occurred earlier
2065  // than current time.
2066  typename IndexType::const_iterator upper_limit =
2067  index.upper_bound(boost::make_tuple(true, time(0) - secs));
2068 
2069  // Now, we have to exclude all elements of the index which represent
2070  // leases in the state other than reclaimed - with the first value
2071  // in the index equal to false. Note that elements in the index are
2072  // ordered from the lower to the higher ones. So, all elements with
2073  // the first value of false are placed before the elements with the
2074  // value of true. Hence, we have to find the first element which
2075  // contains value of true. The time value is the lowest possible.
2076  typename IndexType::const_iterator lower_limit =
2077  index.upper_bound(boost::make_tuple(true, std::numeric_limits<int64_t>::min()));
2078 
2079  // If there are some elements in this range, delete them.
2080  uint64_t num_leases = static_cast<uint64_t>(std::distance(lower_limit, upper_limit));
2081  if (num_leases > 0) {
2082 
2085  .arg(num_leases);
2086 
2087  // If lease persistence is enabled, we also have to mark leases
2088  // as deleted in the lease file. We do this by setting the
2089  // lifetime to 0.
2090  if (persistLeases(universe)) {
2091  for (typename IndexType::const_iterator lease = lower_limit;
2092  lease != upper_limit; ++lease) {
2093  // Copy lease to not affect the lease in the container.
2094  LeaseType lease_copy(**lease);
2095  // Set the valid lifetime to 0 to indicate the removal
2096  // of the lease.
2097  lease_copy.valid_lft_ = 0;
2098  lease_file->append(lease_copy);
2099  }
2100  }
2101 
2102  // Erase leases from memory.
2103  index.erase(lower_limit, upper_limit);
2104 
2105  }
2106  // Return number of leases deleted.
2107  return (num_leases);
2108 }
2109 
2110 std::string
2112  return (std::string("In memory database with leases stored in a CSV file."));
2113 }
2114 
2115 std::pair<uint32_t, uint32_t>
2117  std::string const& universe(conn_.getParameter("universe"));
2118  if (universe == "4") {
2119  return std::make_pair(MAJOR_VERSION_V4, MINOR_VERSION_V4);
2120  } else if (universe == "6") {
2121  return std::make_pair(MAJOR_VERSION_V6, MINOR_VERSION_V6);
2122  }
2123  isc_throw(BadValue, "cannot determine version for universe " << universe);
2124 }
2125 
2126 void
2129 }
2130 
2131 void
2135 }
2136 
2137 std::string
2138 Memfile_LeaseMgr::appendSuffix(const std::string& file_name,
2139  const LFCFileType& file_type) {
2140  std::string name(file_name);
2141  switch (file_type) {
2142  case FILE_INPUT:
2143  name += ".1";
2144  break;
2145  case FILE_PREVIOUS:
2146  name += ".2";
2147  break;
2148  case FILE_OUTPUT:
2149  name += ".output";
2150  break;
2151  case FILE_FINISH:
2152  name += ".completed";
2153  break;
2154  case FILE_PID:
2155  name += ".pid";
2156  break;
2157  default:
2158  // Do not append any suffix for the FILE_CURRENT.
2159  ;
2160  }
2161 
2162  return (name);
2163 }
2164 
2165 std::string
2167  std::ostringstream s;
2168  s << CfgMgr::instance().getDataDir() << "/kea-leases";
2169  s << (u == V4 ? "4" : "6");
2170  s << ".csv";
2171  return (s.str());
2172 }
2173 
2174 std::string
2176  if (u == V4) {
2177  return (lease_file4_ ? lease_file4_->getFilename() : "");
2178  }
2179 
2180  return (lease_file6_ ? lease_file6_->getFilename() : "");
2181 }
2182 
2183 bool
2185  // Currently, if the lease file IO is not created, it means that writes to
2186  // disk have been explicitly disabled by the administrator. At some point,
2187  // there may be a dedicated ON/OFF flag implemented to control this.
2188  if (u == V4 && lease_file4_) {
2189  return (true);
2190  }
2191 
2192  return (u == V6 && lease_file6_);
2193 }
2194 
2195 std::string
2196 Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
2197  std::string persist_val;
2198  try {
2199  persist_val = conn_.getParameter("persist");
2200  } catch (const Exception&) {
2201  // If parameter persist hasn't been specified, we use a default value
2202  // 'yes'.
2203  persist_val = "true";
2204  }
2205  // If persist_val is 'false' we will not store leases to disk, so let's
2206  // return empty file name.
2207  if (persist_val == "false") {
2208  return ("");
2209 
2210  } else if (persist_val != "true") {
2211  isc_throw(isc::BadValue, "invalid value 'persist="
2212  << persist_val << "'");
2213  }
2214 
2215  std::string lease_file;
2216  try {
2217  lease_file = conn_.getParameter("name");
2218  } catch (const Exception&) {
2219  lease_file = getDefaultLeaseFilePath(u);
2220  }
2221  return (lease_file);
2222 }
2223 
2224 template<typename LeaseObjectType, typename LeaseFileType, typename StorageType>
2225 bool
2226 Memfile_LeaseMgr::loadLeasesFromFiles(const std::string& filename,
2227  boost::shared_ptr<LeaseFileType>& lease_file,
2228  StorageType& storage) {
2229  // Check if the instance of the LFC is running right now. If it is
2230  // running, we refuse to load leases as the LFC may be writing to the
2231  // lease files right now. When the user retries server configuration
2232  // it should go through.
2235  PIDFile pid_file(appendSuffix(filename, FILE_PID));
2236  if (pid_file.check()) {
2237  isc_throw(DbOpenError, "unable to load leases from files while the "
2238  "lease file cleanup is in progress");
2239  }
2240 
2241  storage.clear();
2242 
2243  std::string max_row_errors_str = "0";
2244  try {
2245  max_row_errors_str = conn_.getParameter("max-row-errors");
2246  } catch (const std::exception&) {
2247  // Ignore and default to 0.
2248  }
2249 
2250  int64_t max_row_errors64;
2251  try {
2252  max_row_errors64 = boost::lexical_cast<int64_t>(max_row_errors_str);
2253  } catch (const boost::bad_lexical_cast&) {
2254  isc_throw(isc::BadValue, "invalid value of the max-row-errors "
2255  << max_row_errors_str << " specified");
2256  }
2257  if ((max_row_errors64 < 0) ||
2258  (max_row_errors64 > std::numeric_limits<uint32_t>::max())) {
2259  isc_throw(isc::BadValue, "invalid value of the max-row-errors "
2260  << max_row_errors_str << " specified");
2261  }
2262  uint32_t max_row_errors = static_cast<uint32_t>(max_row_errors64);
2263 
2264  // Load the leasefile.completed, if exists.
2265  bool conversion_needed = false;
2266  lease_file.reset(new LeaseFileType(std::string(filename + ".completed")));
2267  if (lease_file->exists()) {
2268  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2269  max_row_errors);
2270  conversion_needed = conversion_needed || lease_file->needsConversion();
2271  } else {
2272  // If the leasefile.completed doesn't exist, let's load the leases
2273  // from leasefile.2 and leasefile.1, if they exist.
2274  lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_PREVIOUS)));
2275  if (lease_file->exists()) {
2276  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2277  max_row_errors);
2278  conversion_needed = conversion_needed || lease_file->needsConversion();
2279  }
2280 
2281  lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_INPUT)));
2282  if (lease_file->exists()) {
2283  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2284  max_row_errors);
2285  conversion_needed = conversion_needed || lease_file->needsConversion();
2286  }
2287  }
2288 
2289  // Always load leases from the primary lease file. If the lease file
2290  // doesn't exist it will be created by the LeaseFileLoader. Note
2291  // that the false value passed as the last parameter to load
2292  // function causes the function to leave the file open after
2293  // it is parsed. This file will be used by the backend to record
2294  // future lease updates.
2295  lease_file.reset(new LeaseFileType(filename));
2296  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2297  max_row_errors, false);
2298  conversion_needed = conversion_needed || lease_file->needsConversion();
2299 
2300  return (conversion_needed);
2301 }
2302 
2303 
2304 bool
2306  return (lfc_setup_->isRunning());
2307 }
2308 
2309 int
2311  return (lfc_setup_->getExitStatus());
2312 }
2313 
2314 void
2317 
2318  // Check if we're in the v4 or v6 space and use the appropriate file.
2319  if (lease_file4_) {
2321  lfcExecute(lease_file4_);
2322  } else if (lease_file6_) {
2324  lfcExecute(lease_file6_);
2325  }
2326 }
2327 
2328 void
2329 Memfile_LeaseMgr::lfcSetup(bool conversion_needed) {
2330  std::string lfc_interval_str = "3600";
2331  try {
2332  lfc_interval_str = conn_.getParameter("lfc-interval");
2333  } catch (const std::exception&) {
2334  // Ignore and default to 3600.
2335  }
2336 
2337  uint32_t lfc_interval = 0;
2338  try {
2339  lfc_interval = boost::lexical_cast<uint32_t>(lfc_interval_str);
2340  } catch (const boost::bad_lexical_cast&) {
2341  isc_throw(isc::BadValue, "invalid value of the lfc-interval "
2342  << lfc_interval_str << " specified");
2343  }
2344 
2345  if (lfc_interval > 0 || conversion_needed) {
2346  lfc_setup_.reset(new LFCSetup(std::bind(&Memfile_LeaseMgr::lfcCallback, this)));
2347  lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_, conversion_needed);
2348  }
2349 }
2350 
2351 template<typename LeaseFileType>
2352 void
2353 Memfile_LeaseMgr::lfcExecute(boost::shared_ptr<LeaseFileType>& lease_file) {
2354  bool do_lfc = true;
2355 
2356  // Check the status of the LFC instance.
2357  // If the finish file exists or the copy of the lease file exists it
2358  // is an indication that another LFC instance may be in progress or
2359  // may be stalled. In that case we don't want to rotate the current
2360  // lease file to avoid overriding the contents of the existing file.
2361  CSVFile lease_file_finish(appendSuffix(lease_file->getFilename(), FILE_FINISH));
2362  CSVFile lease_file_copy(appendSuffix(lease_file->getFilename(), FILE_INPUT));
2363  if (!lease_file_finish.exists() && !lease_file_copy.exists()) {
2364  // Close the current file so as we can move it to the copy file.
2365  lease_file->close();
2366  // Move the current file to the copy file. Remember the result
2367  // because we don't want to run LFC if the rename failed.
2368  do_lfc = (rename(lease_file->getFilename().c_str(),
2369  lease_file_copy.getFilename().c_str()) == 0);
2370 
2371  if (!do_lfc) {
2373  .arg(lease_file->getFilename())
2374  .arg(lease_file_copy.getFilename())
2375  .arg(strerror(errno));
2376  }
2377 
2378  // Regardless if we successfully moved the current file or not,
2379  // we need to re-open the current file for the server to write
2380  // new lease updates. If the file has been successfully moved,
2381  // this will result in creation of the new file. Otherwise,
2382  // an existing file will be opened.
2383  try {
2384  lease_file->open(true);
2385 
2386  } catch (const CSVFileError& ex) {
2387  // If we're unable to open the lease file this is a serious
2388  // error because the server will not be able to persist
2389  // leases.
2397  .arg(lease_file->getFilename())
2398  .arg(ex.what());
2399  // Reset the pointer to the file so as the backend doesn't
2400  // try to write leases to disk.
2401  lease_file.reset();
2402  do_lfc = false;
2403  }
2404  }
2405  // Once the files have been rotated, or untouched if another LFC had
2406  // not finished, a new process is started.
2407  if (do_lfc) {
2408  lfc_setup_->execute();
2409  }
2410 }
2411 
2414  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_));
2415  if (MultiThreadingMgr::instance().getMode()) {
2416  std::lock_guard<std::mutex> lock(*mutex_);
2417  query->start();
2418  } else {
2419  query->start();
2420  }
2421 
2422  return(query);
2423 }
2424 
2428  if (MultiThreadingMgr::instance().getMode()) {
2429  std::lock_guard<std::mutex> lock(*mutex_);
2430  query->start();
2431  } else {
2432  query->start();
2433  }
2434 
2435  return(query);
2436 }
2437 
2440  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, subnet_id));
2441  if (MultiThreadingMgr::instance().getMode()) {
2442  std::lock_guard<std::mutex> lock(*mutex_);
2443  query->start();
2444  } else {
2445  query->start();
2446  }
2447 
2448  return(query);
2449 }
2450 
2453  const SubnetID& last_subnet_id) {
2454  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, first_subnet_id,
2455  last_subnet_id));
2456  if (MultiThreadingMgr::instance().getMode()) {
2457  std::lock_guard<std::mutex> lock(*mutex_);
2458  query->start();
2459  } else {
2460  query->start();
2461  }
2462 
2463  return(query);
2464 }
2465 
2468  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_));
2469  if (MultiThreadingMgr::instance().getMode()) {
2470  std::lock_guard<std::mutex> lock(*mutex_);
2471  query->start();
2472  } else {
2473  query->start();
2474  }
2475 
2476  return(query);
2477 }
2478 
2482  if (MultiThreadingMgr::instance().getMode()) {
2483  std::lock_guard<std::mutex> lock(*mutex_);
2484  query->start();
2485  } else {
2486  query->start();
2487  }
2488 
2489  return(query);
2490 }
2491 
2494  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, subnet_id));
2495  if (MultiThreadingMgr::instance().getMode()) {
2496  std::lock_guard<std::mutex> lock(*mutex_);
2497  query->start();
2498  } else {
2499  query->start();
2500  }
2501 
2502  return(query);
2503 }
2504 
2507  const SubnetID& last_subnet_id) {
2508  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, first_subnet_id,
2509  last_subnet_id));
2510  if (MultiThreadingMgr::instance().getMode()) {
2511  std::lock_guard<std::mutex> lock(*mutex_);
2512  query->start();
2513  } else {
2514  query->start();
2515  }
2516 
2517  return(query);
2518 }
2519 
2520 size_t
2523  .arg(subnet_id);
2524 
2525  // Get the index by DUID, IAID, lease type.
2526  const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
2527 
2528  // Try to get the lease using the DUID, IAID and lease type.
2529  std::pair<Lease4StorageSubnetIdIndex::const_iterator,
2530  Lease4StorageSubnetIdIndex::const_iterator> l =
2531  idx.equal_range(subnet_id);
2532 
2533  // Let's collect all leases.
2534  Lease4Collection leases;
2535  for (auto lease = l.first; lease != l.second; ++lease) {
2536  leases.push_back(*lease);
2537  }
2538 
2539  size_t num = leases.size();
2540  for (auto l = leases.begin(); l != leases.end(); ++l) {
2541  deleteLease(*l);
2542  }
2544  .arg(subnet_id).arg(num);
2545 
2546  return (num);
2547 }
2548 
2549 size_t
2552  .arg(subnet_id);
2553 
2554  // Get the index by DUID, IAID, lease type.
2555  const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
2556 
2557  // Try to get the lease using the DUID, IAID and lease type.
2558  std::pair<Lease6StorageSubnetIdIndex::const_iterator,
2559  Lease6StorageSubnetIdIndex::const_iterator> l =
2560  idx.equal_range(subnet_id);
2561 
2562  // Let's collect all leases.
2563  Lease6Collection leases;
2564  for (auto lease = l.first; lease != l.second; ++lease) {
2565  leases.push_back(*lease);
2566  }
2567 
2568  size_t num = leases.size();
2569  for (auto l = leases.begin(); l != leases.end(); ++l) {
2570  deleteLease(*l);
2571  }
2573  .arg(subnet_id).arg(num);
2574 
2575  return (num);
2576 }
2577 
2578 void
2580  class_lease_counter_.clear();
2581  for (auto lease = storage4_.begin(); lease != storage4_.end(); ++lease) {
2582  // Bump the appropriate accumulator
2583  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
2584  class_lease_counter_.addLease(*lease);
2585  }
2586  }
2587 }
2588 
2589 void
2591  class_lease_counter_.clear();
2592  for (auto lease = storage6_.begin(); lease != storage6_.end(); ++lease) {
2593  // Bump the appropriate accumulator
2594  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
2595  class_lease_counter_.addLease(*lease);
2596  }
2597  }
2598 }
2599 
2600 size_t
2602  const Lease::Type& ltype /* = Lease::TYPE_V4*/) const {
2603  if (MultiThreadingMgr::instance().getMode()) {
2604  std::lock_guard<std::mutex> lock(*mutex_);
2605  return(class_lease_counter_.getClassCount(client_class, ltype));
2606  } else {
2607  return(class_lease_counter_.getClassCount(client_class, ltype));
2608  }
2609 }
2610 
2611 void
2613  return(class_lease_counter_.clear());
2614 }
2615 
2616 std::string
2618  if (!user_context) {
2619  return ("");
2620  }
2621 
2622  ConstElementPtr limits = user_context->find("ISC/limits");
2623  if (!limits) {
2624  return ("");
2625  }
2626 
2627  // Iterate of the 'client-classes' list in 'limits'. For each class that specifies
2628  // an "address-limit", check its value against the class's lease count.
2629  ConstElementPtr classes = limits->get("client-classes");
2630  if (classes) {
2631  for (int i = 0; i < classes->size(); ++i) {
2632  ConstElementPtr class_elem = classes->get(i);
2633  // Get class name.
2634  ConstElementPtr name_elem = class_elem->get("name");
2635  if (!name_elem) {
2636  isc_throw(BadValue, "checkLimits4 - client-class.name is missing: "
2637  << prettyPrint(limits));
2638  }
2639 
2640  std::string name = name_elem->stringValue();
2641 
2642  // Now look for an address-limit
2643  size_t limit;
2644  if (!getLeaseLimit(class_elem, Lease::TYPE_V4, limit)) {
2645  // No limit, go to the next class.
2646  continue;
2647  }
2648 
2649  // If the limit is > 0 look up the class lease count. Limit of 0 always
2650  // denies the lease.
2651  size_t lease_count = 0;
2652  if (limit) {
2653  lease_count = getClassLeaseCount(name);
2654  }
2655 
2656  // If we're over the limit, return the error, no need to evaluate any others.
2657  if (lease_count >= limit) {
2658  std::ostringstream ss;
2659  ss << "address limit " << limit << " for client class \""
2660  << name << "\", current lease count " << lease_count;
2661  return (ss.str());
2662  }
2663  }
2664  }
2665 
2666  // If there were class limits we passed them, now look for a subnet limit.
2667  ConstElementPtr subnet_elem = limits->get("subnet");
2668  if (subnet_elem) {
2669  // Get the subnet id.
2670  ConstElementPtr id_elem = subnet_elem->get("id");
2671  if (!id_elem) {
2672  isc_throw(BadValue, "checkLimits4 - subnet.id is missing: "
2673  << prettyPrint(limits));
2674  }
2675 
2676  SubnetID subnet_id = id_elem->intValue();
2677 
2678  // Now look for an address-limit.
2679  size_t limit;
2680  if (getLeaseLimit(subnet_elem, Lease::TYPE_V4, limit)) {
2681  // If the limit is > 0 look up the subnet lease count. Limit of 0 always
2682  // denies the lease.
2683  int64_t lease_count = 0;
2684  if (limit) {
2685  lease_count = getSubnetStat(subnet_id, "assigned-addresses");
2686  }
2687 
2688  // If we're over the limit, return the error.
2689  if (lease_count >= limit) {
2690  std::ostringstream ss;
2691  ss << "address limit " << limit << " for subnet ID " << subnet_id
2692  << ", current lease count " << lease_count;
2693  return (ss.str());
2694  }
2695  }
2696  }
2697 
2698  // No limits exceeded!
2699  return ("");
2700 }
2701 
2702 std::string
2704  if (!user_context) {
2705  return ("");
2706  }
2707 
2708  ConstElementPtr limits = user_context->find("ISC/limits");
2709  if (!limits) {
2710  return ("");
2711  }
2712 
2713  // Iterate over the 'client-classes' list in 'limits'. For each class that specifies
2714  // limit (either "address-limit" or "prefix-limit", check its value against the appropriate
2715  // class lease count.
2716  ConstElementPtr classes = limits->get("client-classes");
2717  if (classes) {
2718  for (int i = 0; i < classes->size(); ++i) {
2719  ConstElementPtr class_elem = classes->get(i);
2720  // Get class name.
2721  ConstElementPtr name_elem = class_elem->get("name");
2722  if (!name_elem) {
2723  isc_throw(BadValue, "checkLimits6 - client-class.name is missing: "
2724  << prettyPrint(limits));
2725  }
2726 
2727  std::string name = name_elem->stringValue();
2728 
2729  // Now look for either address-limit or a prefix=limit.
2730  size_t limit = 0;
2731  Lease::Type ltype = Lease::TYPE_NA;
2732  if (!getLeaseLimit(class_elem, ltype, limit)) {
2733  ltype = Lease::TYPE_PD;
2734  if (!getLeaseLimit(class_elem, ltype, limit)) {
2735  // No limits for this class, skip to the next.
2736  continue;
2737  }
2738  }
2739 
2740  // If the limit is > 0 look up the class lease count. Limit of 0 always
2741  // denies the lease.
2742  size_t lease_count = 0;
2743  if (limit) {
2744  lease_count = getClassLeaseCount(name, ltype);
2745  }
2746 
2747  // If we're over the limit, return the error, no need to evaluate any others.
2748  if (lease_count >= limit) {
2749  std::ostringstream ss;
2750  ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
2751  << " limit " << limit << " for client class \""
2752  << name << "\", current lease count " << lease_count;
2753  return (ss.str());
2754  }
2755  }
2756  }
2757 
2758  // If there were class limits we passed them, now look for a subnet limit.
2759  ConstElementPtr subnet_elem = limits->get("subnet");
2760  if (subnet_elem) {
2761  // Get the subnet id.
2762  ConstElementPtr id_elem = subnet_elem->get("id");
2763  if (!id_elem) {
2764  isc_throw(BadValue, "checkLimits6 - subnet.id is missing: "
2765  << prettyPrint(limits));
2766  }
2767 
2768  SubnetID subnet_id = id_elem->intValue();
2769 
2770  // Now look for either address-limit or a prefix=limit.
2771  size_t limit = 0;
2772  Lease::Type ltype = Lease::TYPE_NA;
2773  if (!getLeaseLimit(subnet_elem, ltype, limit)) {
2774  ltype = Lease::TYPE_PD;
2775  if (!getLeaseLimit(subnet_elem, ltype, limit)) {
2776  // No limits for the subnet so none exceeded!
2777  return ("");
2778  }
2779  }
2780 
2781  // If the limit is > 0 look up the class lease count. Limit of 0 always
2782  // denies the lease.
2783  int64_t lease_count = 0;
2784  if (limit) {
2785  lease_count = getSubnetStat(subnet_id, (ltype == Lease::TYPE_NA ?
2786  "assigned-nas" : "assigned-pds"));
2787  }
2788 
2789  // If we're over the limit, return the error.
2790  if (lease_count >= limit) {
2791  std::ostringstream ss;
2792  ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
2793  << " limit " << limit << " for subnet ID " << subnet_id
2794  << ", current lease count " << lease_count;
2795  return (ss.str());
2796  }
2797  }
2798 
2799  // No limits exceeded!
2800  return ("");
2801 }
2802 
2803 bool
2805  return true;
2806 }
2807 
2808 int64_t
2809 Memfile_LeaseMgr::getSubnetStat(const SubnetID& subnet_id, const std::string& stat_label) const {
2812  std::string stat_name = StatsMgr::generateName("subnet", subnet_id, stat_label);
2813  ConstElementPtr stat = StatsMgr::instance().get(stat_name);
2814  ConstElementPtr samples = stat->get(stat_name);
2815  if (samples && samples->size()) {
2816  auto sample = samples->get(0);
2817  if (sample->size()) {
2818  auto count_elem = sample->get(0);
2819  return (count_elem->intValue());
2820  }
2821  }
2822 
2823  return (0);
2824 }
2825 
2826 bool
2827 Memfile_LeaseMgr::getLeaseLimit(ConstElementPtr parent, Lease::Type ltype, size_t& limit) const {
2828  ConstElementPtr limit_elem = parent->get(ltype == Lease::TYPE_PD ?
2829  "prefix-limit" : "address-limit");
2830  if (limit_elem) {
2831  limit = limit_elem->intValue();
2832  return (true);
2833  }
2834 
2835  return (false);
2836 }
2837 
2838 namespace {
2839 
2840 std::string
2841 idToText(const OptionBuffer& id) {
2842  std::stringstream tmp;
2843  tmp << std::hex;
2844  bool delim = false;
2845  for (std::vector<uint8_t>::const_iterator it = id.begin();
2846  it != id.end(); ++it) {
2847  if (delim) {
2848  tmp << ":";
2849  }
2850  tmp << std::setw(2) << std::setfill('0')
2851  << static_cast<unsigned int>(*it);
2852  delim = true;
2853  }
2854  return (tmp.str());
2855 }
2856 
2857 } // anonymous namespace
2858 
2861  const IOAddress& lower_bound_address,
2862  const LeasePageSize& page_size,
2863  const time_t& qry_start_time /* = 0 */,
2864  const time_t& qry_end_time /* = 0 */) {
2867  .arg(page_size.page_size_)
2868  .arg(lower_bound_address.toText())
2869  .arg(idToText(relay_id))
2870  .arg(qry_start_time)
2871  .arg(qry_end_time);
2872 
2873  // Expecting IPv4 address.
2874  if (!lower_bound_address.isV4()) {
2875  isc_throw(InvalidAddressFamily, "expected IPv4 address while "
2876  "retrieving leases from the lease database, got "
2877  << lower_bound_address);
2878  }
2879 
2880  // Catch 2038 bug with 32 bit time_t.
2881  if ((qry_start_time < 0) || (qry_end_time < 0)) {
2882  isc_throw(BadValue, "negative time value");
2883  }
2884 
2885  // Start time must be before end time.
2886  if ((qry_start_time > 0) && (qry_end_time > 0) &&
2887  (qry_start_time > qry_end_time)) {
2888  isc_throw(BadValue, "start time must be before end time");
2889  }
2890 
2891  if (MultiThreadingMgr::instance().getMode()) {
2892  std::lock_guard<std::mutex> lock(*mutex_);
2893  return (getLeases4ByRelayIdInternal(relay_id,
2894  lower_bound_address,
2895  page_size,
2896  qry_start_time,
2897  qry_end_time));
2898  } else {
2899  return (getLeases4ByRelayIdInternal(relay_id,
2900  lower_bound_address,
2901  page_size,
2902  qry_start_time,
2903  qry_end_time));
2904  }
2905 }
2906 
2908 Memfile_LeaseMgr::getLeases4ByRelayIdInternal(const OptionBuffer& relay_id,
2909  const IOAddress& lower_bound_address,
2910  const LeasePageSize& page_size,
2911  const time_t& qry_start_time,
2912  const time_t& qry_end_time) {
2913  Lease4Collection collection;
2914  const Lease4StorageRelayIdIndex& idx = storage4_.get<RelayIdIndexTag>();
2915  Lease4StorageRelayIdIndex::const_iterator lb =
2916  idx.lower_bound(boost::make_tuple(relay_id, lower_bound_address));
2917  // Return all convenient leases being within the page size.
2918  IOAddress last_addr = lower_bound_address;
2919  for (; lb != idx.end(); ++lb) {
2920  if ((*lb)->addr_ == last_addr) {
2921  // Already seen: skip it.
2922  continue;
2923  }
2924  if ((*lb)->relay_id_ != relay_id) {
2925  // Gone after the relay id index.
2926  break;
2927  }
2928  last_addr = (*lb)->addr_;
2929  if ((qry_start_time > 0) && ((*lb)->cltt_ < qry_start_time)) {
2930  // Too old.
2931  continue;
2932  }
2933  if ((qry_end_time > 0) && ((*lb)->cltt_ > qry_end_time)) {
2934  // Too young.
2935  continue;
2936  }
2937  collection.push_back(Lease4Ptr(new Lease4(**lb)));
2938  if (collection.size() >= page_size.page_size_) {
2939  break;
2940  }
2941  }
2942  return (collection);
2943 }
2944 
2947  const IOAddress& lower_bound_address,
2948  const LeasePageSize& page_size,
2949  const time_t& qry_start_time /* = 0 */,
2950  const time_t& qry_end_time /* = 0 */) {
2953  .arg(page_size.page_size_)
2954  .arg(lower_bound_address.toText())
2955  .arg(idToText(remote_id))
2956  .arg(qry_start_time)
2957  .arg(qry_end_time);
2958 
2959  // Expecting IPv4 address.
2960  if (!lower_bound_address.isV4()) {
2961  isc_throw(InvalidAddressFamily, "expected IPv4 address while "
2962  "retrieving leases from the lease database, got "
2963  << lower_bound_address);
2964  }
2965 
2966  // Catch 2038 bug with 32 bit time_t.
2967  if ((qry_start_time < 0) || (qry_end_time < 0)) {
2968  isc_throw(BadValue, "negative time value");
2969  }
2970 
2971  // Start time must be before end time.
2972  if ((qry_start_time > 0) && (qry_end_time > 0) &&
2973  (qry_start_time > qry_end_time)) {
2974  isc_throw(BadValue, "start time must be before end time");
2975  }
2976 
2977  if (MultiThreadingMgr::instance().getMode()) {
2978  std::lock_guard<std::mutex> lock(*mutex_);
2979  return (getLeases4ByRemoteIdInternal(remote_id,
2980  lower_bound_address,
2981  page_size,
2982  qry_start_time,
2983  qry_end_time));
2984  } else {
2985  return (getLeases4ByRemoteIdInternal(remote_id,
2986  lower_bound_address,
2987  page_size,
2988  qry_start_time,
2989  qry_end_time));
2990  }
2991 }
2992 
2994 Memfile_LeaseMgr::getLeases4ByRemoteIdInternal(const OptionBuffer& remote_id,
2995  const IOAddress& lower_bound_address,
2996  const LeasePageSize& page_size,
2997  const time_t& qry_start_time,
2998  const time_t& qry_end_time) {
2999  Lease4Collection collection;
3000  std::map<IOAddress, Lease4Ptr> sorted;
3001  const Lease4StorageRemoteIdIndex& idx = storage4_.get<RemoteIdIndexTag>();
3002  Lease4StorageRemoteIdRange er = idx.equal_range(remote_id);
3003  // Store all convenient leases being within the page size.
3004  for (auto it = er.first; it != er.second; ++it) {
3005  const IOAddress& addr = (*it)->addr_;
3006  if (addr <= lower_bound_address) {
3007  // Not greater than lower_bound_address.
3008  continue;
3009  }
3010  if ((qry_start_time > 0) && ((*it)->cltt_ < qry_start_time)) {
3011  // Too old.
3012  continue;
3013  }
3014  if ((qry_end_time > 0) && ((*it)->cltt_ > qry_end_time)) {
3015  // Too young.
3016  continue;
3017  }
3018  sorted[addr] = *it;
3019  }
3020 
3021  // Return all leases being within the page size.
3022  for (auto it : sorted) {
3023  collection.push_back(Lease4Ptr(new Lease4(*it.second)));
3024  if (collection.size() >= page_size.page_size_) {
3025  break;
3026  }
3027  }
3028  return (collection);
3029 }
3030 
3031 void
3033  if (MultiThreadingMgr::instance().getMode()) {
3034  std::lock_guard<std::mutex> lock(*mutex_);
3035  relay_id6_.clear();
3036  remote_id6_.clear();
3037  } else {
3038  relay_id6_.clear();
3039  remote_id6_.clear();
3040  }
3041 }
3042 
3043 size_t
3045  return (relay_id6_.size());
3046 }
3047 
3048 size_t
3050  return (remote_id6_.size());
3051 }
3052 
3055  const IOAddress& link_addr,
3056  uint8_t link_len,
3057  const IOAddress& lower_bound_address,
3058  const LeasePageSize& page_size) {
3061  .arg(page_size.page_size_)
3062  .arg(lower_bound_address.toText())
3063  .arg(relay_id.toText())
3064  .arg(link_addr.toText())
3065  .arg(static_cast<unsigned>(link_len));
3066 
3067  // Expecting IPv6 valid prefix and address.
3068  if (!link_addr.isV6()) {
3069  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3070  "retrieving leases from the lease database, got "
3071  << link_addr);
3072  }
3073  if (link_len > 128) {
3074  isc_throw(OutOfRange, "invalid IPv6 prefix length "
3075  << static_cast<unsigned>(link_len));
3076  }
3077  if (!lower_bound_address.isV6()) {
3078  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3079  "retrieving leases from the lease database, got "
3080  << lower_bound_address);
3081  }
3082 
3083  if (MultiThreadingMgr::instance().getMode()) {
3084  std::lock_guard<std::mutex> lock(*mutex_);
3085  return (getLeases6ByRelayIdInternal(relay_id,
3086  link_addr,
3087  link_len,
3088  lower_bound_address,
3089  page_size));
3090  } else {
3091  return (getLeases6ByRelayIdInternal(relay_id,
3092  link_addr,
3093  link_len,
3094  lower_bound_address,
3095  page_size));
3096  }
3097 }
3098 
3100 Memfile_LeaseMgr::getLeases6ByRelayIdInternal(const DUID& relay_id,
3101  const IOAddress& link_addr,
3102  uint8_t link_len,
3103  const IOAddress& lower_bound_address,
3104  const LeasePageSize& page_size) {
3105  const std::vector<uint8_t>& relay_id_data = relay_id.getDuid();
3106  Lease6Collection collection;
3107  const RelayIdIndex& idx = relay_id6_.get<RelayIdIndexTag>();
3108  if (!link_len) {
3109  RelayIdIndex::const_iterator lb =
3110  idx.lower_bound(boost::make_tuple(relay_id_data,
3111  lower_bound_address));
3112 
3113  // Return all leases being within the page size.
3114  IOAddress last_addr = lower_bound_address;
3115  for (; lb != idx.end(); ++lb) {
3116  if ((*lb)->lease_addr_ == last_addr) {
3117  // Already seen: skip it.
3118  continue;
3119  }
3120  if ((*lb)->id_ != relay_id_data) {
3121  // Gone after the relay id index.
3122  break;
3123  }
3124  last_addr = (*lb)->lease_addr_;
3125  Lease6Ptr lease = getAnyLease6Internal(last_addr);
3126  if (lease) {
3127  collection.push_back(lease);
3128  if (collection.size() >= page_size.page_size_) {
3129  break;
3130  }
3131  }
3132  }
3133  } else {
3134  const IOAddress& first_addr = firstAddrInPrefix(link_addr, link_len);
3135  const IOAddress& last_addr = lastAddrInPrefix(link_addr, link_len);
3136  const IOAddress& start_addr =
3137  (lower_bound_address < first_addr ? first_addr : lower_bound_address);
3138  RelayIdIndex::const_iterator lb =
3139  idx.lower_bound(boost::make_tuple(relay_id_data, start_addr));
3140  RelayIdIndex::const_iterator ub =
3141  idx.upper_bound(boost::make_tuple(relay_id_data, last_addr));
3142 
3143  // Return all leases being within the page size.
3144  IOAddress last_seen_addr = lower_bound_address;
3145  for (auto it = lb; it != ub; ++it) {
3146  if ((*it)->lease_addr_ == last_seen_addr) {
3147  // Already seen: skip it.
3148  continue;
3149  }
3150  last_seen_addr = (*it)->lease_addr_;
3151  Lease6Ptr lease = getAnyLease6Internal(last_seen_addr);
3152  if (lease) {
3153  collection.push_back(lease);
3154  if (collection.size() >= page_size.page_size_) {
3155  break;
3156  }
3157  }
3158  }
3159  }
3160  return (collection);
3161 }
3162 
3165  const IOAddress& link_addr,
3166  uint8_t link_len,
3167  const IOAddress& lower_bound_address,
3168  const LeasePageSize& page_size) {
3171  .arg(page_size.page_size_)
3172  .arg(lower_bound_address.toText())
3173  .arg(idToText(remote_id))
3174  .arg(link_addr.toText())
3175  .arg(static_cast<unsigned>(link_len));
3176 
3177  // Expecting IPv6 valid prefix and address.
3178  if (!link_addr.isV6()) {
3179  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3180  "retrieving leases from the lease database, got "
3181  << link_addr);
3182  }
3183  if (link_len > 128) {
3184  isc_throw(OutOfRange, "invalid IPv6 prefix length "
3185  << static_cast<unsigned>(link_len));
3186  }
3187  if (!lower_bound_address.isV6()) {
3188  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3189  "retrieving leases from the lease database, got "
3190  << lower_bound_address);
3191  }
3192 
3193  if (MultiThreadingMgr::instance().getMode()) {
3194  std::lock_guard<std::mutex> lock(*mutex_);
3195  return (getLeases6ByRemoteIdInternal(remote_id,
3196  link_addr,
3197  link_len,
3198  lower_bound_address,
3199  page_size));
3200  } else {
3201  return (getLeases6ByRemoteIdInternal(remote_id,
3202  link_addr,
3203  link_len,
3204  lower_bound_address,
3205  page_size));
3206  }
3207 }
3208 
3210 Memfile_LeaseMgr::getLeases6ByRemoteIdInternal(const OptionBuffer& remote_id,
3211  const IOAddress& link_addr,
3212  uint8_t link_len,
3213  const IOAddress& lower_bound_address,
3214  const LeasePageSize& page_size) {
3215  Lease6Collection collection;
3216  std::set<IOAddress> sorted;
3217  const RemoteIdIndex& idx = remote_id6_.get<RemoteIdIndexTag>();
3218  RemoteIdIndexRange er = idx.equal_range(remote_id);
3219  if (!link_len) {
3220  // Store all addresses greater than lower_bound_address.
3221  for (auto it = er.first; it != er.second; ++it) {
3222  const IOAddress& addr = (*it)->lease_addr_;
3223  if (addr <= lower_bound_address) {
3224  continue;
3225  }
3226  static_cast<void>(sorted.insert(addr));
3227  }
3228 
3229  // Return all leases being within the page size.
3230  for (const IOAddress& addr : sorted) {
3231  Lease6Ptr lease = getAnyLease6Internal(addr);
3232  if (lease) {
3233  collection.push_back(lease);
3234  if (collection.size() >= page_size.page_size_) {
3235  break;
3236  }
3237  }
3238  }
3239  } else {
3240  const IOAddress& first_addr = firstAddrInPrefix(link_addr, link_len);
3241  const IOAddress& last_addr = lastAddrInPrefix(link_addr, link_len);
3242 
3243  // Store all addresses greater than lower_bound_address in the link.
3244  for (auto it = er.first; it != er.second; ++it) {
3245  const IOAddress& addr = (*it)->lease_addr_;
3246  if (addr <= lower_bound_address) {
3247  continue;
3248  }
3249  if ((addr < first_addr) || (last_addr < addr)) {
3250  continue;
3251  }
3252  static_cast<void>(sorted.insert(addr));
3253  }
3254 
3255  // Return all leases being within the page size.
3256  for (const IOAddress& addr : sorted) {
3257  Lease6Ptr lease = getAnyLease6Internal(addr);
3258  if (lease) {
3259  collection.push_back(lease);
3260  if (collection.size() >= page_size.page_size_) {
3261  break;
3262  }
3263  }
3264  }
3265  }
3266  return (collection);
3267 }
3268 
3271  uint8_t link_len,
3272  const IOAddress& lower_bound_address,
3273  const LeasePageSize& page_size) {
3276  .arg(page_size.page_size_)
3277  .arg(lower_bound_address.toText())
3278  .arg(link_addr.toText())
3279  .arg(static_cast<unsigned>(link_len));
3280 
3281  // Expecting IPv6 valid prefix and address.
3282  if (!link_addr.isV6()) {
3283  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3284  "retrieving leases from the lease database, got "
3285  << link_addr);
3286  }
3287  if ((link_len == 0) || (link_len > 128)) {
3288  isc_throw(OutOfRange, "invalid IPv6 prefix length "
3289  << static_cast<unsigned>(link_len));
3290  }
3291  if (!lower_bound_address.isV6()) {
3292  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3293  "retrieving leases from the lease database, got "
3294  << lower_bound_address);
3295  }
3296 
3297  if (MultiThreadingMgr::instance().getMode()) {
3298  std::lock_guard<std::mutex> lock(*mutex_);
3299  return (getLeases6ByLinkInternal(link_addr,
3300  link_len,
3301  lower_bound_address,
3302  page_size));
3303  } else {
3304  return (getLeases6ByLinkInternal(link_addr,
3305  link_len,
3306  lower_bound_address,
3307  page_size));
3308  }
3309 }
3310 
3312 Memfile_LeaseMgr::getLeases6ByLinkInternal(const IOAddress& link_addr,
3313  uint8_t link_len,
3314  const IOAddress& lower_bound_address,
3315  const LeasePageSize& page_size) {
3316  const IOAddress& first_addr = firstAddrInPrefix(link_addr, link_len);
3317  const IOAddress& last_addr = lastAddrInPrefix(link_addr, link_len);
3318  const IOAddress& start_addr =
3319  (lower_bound_address < first_addr ? first_addr : lower_bound_address);
3320  Lease6Collection collection;
3321  const Lease6StorageAddressIndex& idx = storage6_.get<AddressIndexTag>();
3322  Lease6StorageAddressIndex::const_iterator lb = idx.lower_bound(start_addr);
3323  Lease6StorageAddressIndex::const_iterator eb = idx.upper_bound(last_addr);
3324 
3325  // Return all leases being within the page size.
3326  IOAddress last_seen_addr = lower_bound_address;
3327  for (auto it = lb; it != eb; ++it) {
3328  if ((*it)->addr_ == last_seen_addr) {
3329  // Already seen: skip it.
3330  continue;
3331  }
3332  last_seen_addr = (*it)->addr_;
3333  Lease6Ptr lease = getAnyLease6Internal(last_seen_addr);
3334  if (lease) {
3335  collection.push_back(lease);
3336  if (collection.size() >= page_size.page_size_) {
3337  break;
3338  }
3339  }
3340  }
3341  return (collection);
3342 }
3343 
3344 size_t
3345 Memfile_LeaseMgr::extractExtendedInfo4(bool update, bool current) {
3346  CfgConsistencyPtr cfg;
3347  if (current) {
3348  cfg = CfgMgr::instance().getCurrentCfg()->getConsistency();
3349  } else {
3350  cfg = CfgMgr::instance().getStagingCfg()->getConsistency();
3351  }
3352  if (!cfg) {
3353  isc_throw(Unexpected, "the " << (current ? "current" : "staging")
3354  << " consistency configuration is null");
3355  }
3356  auto check = cfg->getExtendedInfoSanityCheck();
3357 
3361  .arg(update ? " updating in file" : "");
3362 
3363  size_t leases = 0;
3364  size_t modified = 0;
3365  size_t updated = 0;
3366  size_t processed = 0;
3367  auto& index = storage4_.get<AddressIndexTag>();
3368  auto lease_it = index.begin();
3369  auto next_it = index.end();
3370 
3371  for (; lease_it != index.end(); lease_it = next_it) {
3372  next_it = std::next(lease_it);
3373  Lease4Ptr lease = *lease_it;
3374  ++leases;
3375  try {
3376  if (upgradeLease4ExtendedInfo(lease, check)) {
3377  ++modified;
3378  if (update && persistLeases(V4)) {
3379  lease_file4_->append(*lease);
3380  ++updated;
3381  }
3382  }
3383  // Work on a copy as the multi-index requires fields used
3384  // as indexes to be read-only.
3385  Lease4Ptr copy(new Lease4(*lease));
3387  if (!copy->relay_id_.empty() || !copy->remote_id_.empty()) {
3388  index.replace(lease_it, copy);
3389  ++processed;
3390  }
3391  } catch (const std::exception& ex) {
3394  .arg(lease->addr_.toText())
3395  .arg(ex.what());
3396  }
3397  }
3398 
3400  .arg(leases)
3401  .arg(modified)
3402  .arg(updated)
3403  .arg(processed);
3404 
3405  return (updated);
3406 }
3407 
3408 size_t
3410  return (0);
3411 }
3412 
3413 void
3415  CfgConsistencyPtr cfg = CfgMgr::instance().getStagingCfg()->getConsistency();
3416  if (!cfg) {
3417  isc_throw(Unexpected, "the staging consistency configuration is null");
3418  }
3419  auto check = cfg->getExtendedInfoSanityCheck();
3420  bool enabled = getExtendedInfoTablesEnabled();
3421 
3425  .arg(enabled ? "enabled" : "disabled");
3426 
3427  // Clear tables when enabled.
3428  if (enabled) {
3429  relay_id6_.clear();
3430  remote_id6_.clear();
3431  }
3432 
3433  size_t leases = 0;
3434  size_t modified = 0;
3435  size_t processed = 0;
3436 
3437  for (auto lease : storage6_) {
3438  ++leases;
3439  try {
3440  if (upgradeLease6ExtendedInfo(lease, check)) {
3441  ++modified;
3442  }
3443  if (enabled && addExtendedInfo6(lease)) {
3444  ++processed;
3445  }
3446  } catch (const std::exception& ex) {
3449  .arg(lease->addr_.toText())
3450  .arg(ex.what());
3451  }
3452  }
3453 
3455  .arg(leases)
3456  .arg(modified)
3457  .arg(processed);
3458 }
3459 
3460 size_t
3462  return (0);
3463 }
3464 
3465 void
3467  LeaseAddressRelayIdIndex& relay_id_idx =
3469  static_cast<void>(relay_id_idx.erase(addr));
3470  LeaseAddressRemoteIdIndex& remote_id_idx =
3472  static_cast<void>(remote_id_idx.erase(addr));
3473 }
3474 
3475 void
3477  const std::vector<uint8_t>& relay_id) {
3478  Lease6ExtendedInfoPtr ex_info;
3479  ex_info.reset(new Lease6ExtendedInfo(lease_addr, relay_id));
3480  relay_id6_.insert(ex_info);
3481 }
3482 
3483 void
3485  const std::vector<uint8_t>& remote_id) {
3486  Lease6ExtendedInfoPtr ex_info;
3487  ex_info.reset(new Lease6ExtendedInfo(lease_addr, remote_id));
3488  remote_id6_.insert(ex_info);
3489 }
3490 
3491 void
3492 Memfile_LeaseMgr::writeLeases4(const std::string& filename) {
3493  if (MultiThreadingMgr::instance().getMode()) {
3494  std::lock_guard<std::mutex> lock(*mutex_);
3495  writeLeases4Internal(filename);
3496  } else {
3497  writeLeases4Internal(filename);
3498  }
3499 }
3500 
3501 void
3502 Memfile_LeaseMgr::writeLeases4Internal(const std::string& filename) {
3503  bool overwrite = (lease_file4_ && lease_file4_->getFilename() == filename);
3504  try {
3505  if (overwrite) {
3506  lease_file4_->close();
3507  }
3508  std::ostringstream old;
3509  old << filename << ".bak" << getpid();
3510  ::rename(filename.c_str(), old.str().c_str());
3511  CSVLeaseFile4 backup(filename);
3512  backup.open();
3513  for (const auto& lease : storage4_) {
3514  backup.append(*lease);
3515  }
3516  backup.close();
3517  if (overwrite) {
3518  lease_file4_->open(true);
3519  }
3520  } catch (const std::exception&) {
3521  if (overwrite) {
3522  lease_file4_->open(true);
3523  }
3524  throw;
3525  }
3526 }
3527 
3528 void
3529 Memfile_LeaseMgr::writeLeases6(const std::string& filename) {
3530  if (MultiThreadingMgr::instance().getMode()) {
3531  std::lock_guard<std::mutex> lock(*mutex_);
3532  writeLeases6Internal(filename);
3533  } else {
3534  writeLeases6Internal(filename);
3535  }
3536 }
3537 
3538 void
3539 Memfile_LeaseMgr::writeLeases6Internal(const std::string& filename) {
3540  bool overwrite = (lease_file6_ && lease_file6_->getFilename() == filename);
3541  try {
3542  if (overwrite) {
3543  lease_file6_->close();
3544  }
3545  std::ostringstream old;
3546  old << filename << ".bak" << getpid();
3547  ::rename(filename.c_str(), old.str().c_str());
3548  CSVLeaseFile6 backup(filename);
3549  backup.open();
3550  for (const auto& lease : storage6_) {
3551  backup.append(*lease);
3552  }
3553  backup.close();
3554  if (overwrite) {
3555  lease_file6_->open(true);
3556  }
3557  } catch (const std::exception&) {
3558  if (overwrite) {
3559  lease_file6_->open(true);
3560  }
3561  throw;
3562  }
3563 }
3564 
3565 } // namespace dhcp
3566 } // namespace isc
int version()
returns Kea hooks version.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
A generic exception that is thrown when an unexpected error condition occurs.
std::string getParameter(const std::string &name) const
Returns value of a connection parameter.
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Exception thrown on failure to open database.
Invalid address family used as input to Lease Manager.
Definition: db_exceptions.h:59
Provides methods to access CSV file with DHCPv4 leases.
Provides methods to access CSV file with DHCPv6 leases.
static std::string sanityCheckToText(LeaseSanity check_type)
Converts lease sanity check value to printable text.
util::Optional< std::string > getDataDir() const
returns path do the data directory
Definition: cfgmgr.cc:31
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition: cfgmgr.cc:167
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition: cfgmgr.cc:161
void addLease(LeasePtr lease)
Increment the counts for all of a lease's classes by one.
void clear()
Remove all entries.
void removeLease(LeasePtr lease)
Decrement the counts for all of a lease's classes by one.
void updateLease(LeasePtr new_lease, LeasePtr old_lease)
Adjust class lease counts given a new and old version of a lease.
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 Client identifier or client IPv4 address.
Definition: duid.h:218
const std::vector< uint8_t > & getClientId() const
Returns reference to the client-id data.
Definition: duid.cc:70
Holds DUID (DHCPv6 Unique Identifier)
Definition: duid.h:138
const std::vector< uint8_t > & getDuid() const
Returns a const reference to the actual DUID value.
Definition: duid.cc:34
std::string toText() const
Returns textual representation of the identifier (e.g.
Definition: duid.h:84
Represents a configuration for Lease File Cleanup.
void execute()
Spawns a new process.
int getExitStatus() const
Returns exit code of the last completed cleanup.
bool isRunning() const
Checks if the lease file cleanup is in progress.
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.
Lease6 extended informations for Bulk Lease Query.
void setExtendedInfoTablesEnabled(const bool enabled)
Modifies the setting whether the lease6 extended info tables are enabled.
Definition: lease_mgr.h:1039
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:771
bool getExtendedInfoTablesEnabled() const
Returns the setting indicating if lease6 extended info tables are enabled.
Definition: lease_mgr.h:1031
static isc::asiolink::IOServicePtr & getIOService()
Returns pointer to the IO service.
Definition: lease_mgr.h:842
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:520
static void extractLease4ExtendedInfo(const Lease4Ptr &lease, bool ignore_errors=true)
Extract relay and remote identifiers from the extended info.
Definition: lease_mgr.cc:1123
static bool upgradeLease4ExtendedInfo(const Lease4Ptr &lease, CfgConsistency::ExtendedInfoSanity check=CfgConsistency::EXTENDED_INFO_CHECK_FIX)
The following queries are used to fulfill Bulk Lease Query queries.
Definition: lease_mgr.cc:539
virtual bool addExtendedInfo6(const Lease6Ptr &lease)
Extract extended info from a lease6 and add it into tables.
Definition: lease_mgr.cc:1209
Wraps value holding size of the page with leases.
Definition: lease_mgr.h:46
const size_t page_size_
Holds page size.
Definition: lease_mgr.h:56
Base class for fulfilling a statistical lease data query.
Definition: lease_mgr.h:149
SubnetID getLastSubnetID() const
Returns the value of last subnet ID specified (or zero)
Definition: lease_mgr.h:209
SubnetID getFirstSubnetID() const
Returns the value of first subnet ID specified (or zero)
Definition: lease_mgr.h:204
SelectMode getSelectMode() const
Returns the selection criteria mode The value returned is based upon the constructor variant used and...
Definition: lease_mgr.h:216
SelectMode
Defines the types of selection criteria supported.
Definition: lease_mgr.h:152
Memfile derivation of the IPv4 statistical lease data query.
MemfileLeaseStatsQuery4(Lease4Storage &storage4, const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for a subnet range query.
MemfileLeaseStatsQuery4(Lease4Storage &storage4, const SelectMode &select_mode=ALL_SUBNETS)
Constructor for an all subnets query.
virtual ~MemfileLeaseStatsQuery4()
Destructor.
void start()
Creates the IPv4 lease statistical data result set.
MemfileLeaseStatsQuery4(Lease4Storage &storage4, const SubnetID &subnet_id)
Constructor for a single subnet query.
Memfile derivation of the IPv6 statistical lease data query.
void start()
Creates the IPv6 lease statistical data result set.
virtual ~MemfileLeaseStatsQuery6()
Destructor.
MemfileLeaseStatsQuery6(Lease6Storage &storage6, const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for a subnet range query.
MemfileLeaseStatsQuery6(Lease6Storage &storage6, const SelectMode &select_mode=ALL_SUBNETS)
Constructor.
MemfileLeaseStatsQuery6(Lease6Storage &storage6, const SubnetID &subnet_id)
Constructor for a single subnet query.
Base Memfile derivation of the statistical lease data query.
std::vector< LeaseStatsRow >::iterator next_pos_
An iterator for accessing the next row within the result set.
MemfileLeaseStatsQuery(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for subnet range query.
virtual bool getNextRow(LeaseStatsRow &row)
Fetches the next row in the result set.
std::vector< LeaseStatsRow > rows_
A vector containing the "result set".
MemfileLeaseStatsQuery(const SelectMode &select_mode=ALL_SUBNETS)
Constructor for all subnets query.
virtual ~MemfileLeaseStatsQuery()
Destructor.
int getRowCount() const
Returns the number of rows in the result set.
MemfileLeaseStatsQuery(const SubnetID &subnet_id)
Constructor for single subnet query.
Lease6ExtendedInfoRemoteIdTable remote_id6_
stores IPv6 by-remote-id cross-reference table
virtual void rollback() override
Rollback Transactions.
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.
size_t extractExtendedInfo4(bool update, bool current)
Extract extended info for v4 leases.
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery6(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id) override
Creates and runs the IPv6 lease stats query for a single subnet.
virtual 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.
virtual void clearClassLeaseCounts() override
Clears the class-lease count map.
virtual size_t byRelayId6size() const override
Return the by-relay-id table size.
virtual Lease4Collection getLeases4ByRelayId(const OptionBuffer &relay_id, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size, const time_t &qry_start_time=0, const time_t &qry_end_time=0) override
The following queries are used to fulfill Bulk Lease Query queries.
Memfile_LeaseMgr(const db::DatabaseConnection::ParameterMap &parameters)
The sole lease manager constructor.
bool isLFCRunning() const
Checks if the process performing lease file cleanup is running.
virtual void writeLeases4(const std::string &filename) override
Write V4 leases to a file.
virtual void updateLease4(const Lease4Ptr &lease4) override
Updates IPv4 lease.
virtual size_t wipeLeases4(const SubnetID &subnet_id) override
Removes specified IPv4 leases.
virtual void deleteExtendedInfo6(const isc::asiolink::IOAddress &addr) override
Delete lease6 extended info from tables.
virtual bool isJsonSupported() const override
Checks if JSON support is enabled in the database.
Universe
Specifies universe (V4, V6)
LFCFileType
Types of the lease files used by the Lease File Cleanup.
@ FILE_PREVIOUS
Previous Lease File.
virtual bool deleteLease(const Lease4Ptr &lease) override
Deletes an IPv4 lease.
virtual void commit() override
Commit Transactions.
virtual size_t wipeLeases6(const SubnetID &subnet_id) override
Removed specified IPv6 leases.
int getLFCExitStatus() const
Returns the status code returned by the last executed LFC process.
virtual LeaseStatsQueryPtr startPoolLeaseStatsQuery6() override
Creates and runs the IPv6 lease stats query for all subnets and pools.
bool persistLeases(Universe u) const
Specifies whether or not leases are written to disk.
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.
virtual Lease4Collection getLeases4() const override
Returns all IPv4 leases.
virtual size_t getClassLeaseCount(const ClientClass &client_class, const Lease::Type &ltype=Lease::TYPE_V4) const override
Returns the class lease count for a given class and lease type.
virtual void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv6 leases.
void buildExtendedInfoTables6()
Extended information / Bulk Lease Query shared interface.
virtual bool addLease(const Lease4Ptr &lease) override
Adds an IPv4 lease.
virtual size_t byRemoteId6size() const override
Return the by-remote-id table size.
virtual void writeLeases6(const std::string &filename) override
Write V6 leases to a file.
Lease6ExtendedInfoRelayIdTable relay_id6_
stores IPv6 by-relay-id cross-reference table
virtual void recountClassLeases6() override
Recount the leases per class for V6 leases.
virtual Lease4Collection getLeases4ByRemoteId(const OptionBuffer &remote_id, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size, const time_t &qry_start_time=0, const time_t &qry_end_time=0) override
Returns existing IPv4 leases with a given remote-id.
virtual void wipeExtendedInfoTables6() override
Wipe extended info table (v6).
virtual std::pair< uint32_t, uint32_t > getVersion() const override
Returns backend version.
boost::shared_ptr< CSVLeaseFile4 > lease_file4_
Holds the pointer to the DHCPv4 lease file IO.
std::string getLeaseFilePath(Universe u) const
Returns an absolute path to the lease file.
virtual Lease6Collection getLeases6() const override
Returns all IPv6 leases.
virtual void lfcCallback()
A callback function triggering Lease File Cleanup (LFC).
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery4(const SubnetID &subnet_id) override
Creates and runs the IPv4 lease stats query for a single subnet.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery6(const SubnetID &subnet_id) override
Creates and runs the IPv6 lease stats query for a single subnet.
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.
virtual std::string getDescription() const override
Returns description of the backend.
static std::string appendSuffix(const std::string &file_name, const LFCFileType &file_type)
Appends appropriate suffix to the file name.
virtual void addRelayId6(const isc::asiolink::IOAddress &lease_addr, const std::vector< uint8_t > &relay_id) override
Add lease6 extended info into by-relay-id table.
virtual size_t upgradeExtendedInfo6(const LeasePageSize &page_size) override
Upgrade extended info (v6).
virtual LeaseStatsQueryPtr startLeaseStatsQuery4() override
Creates and runs the IPv4 lease stats query.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const override
Returns existing IPv6 lease for a given IPv6 address.
virtual void recountClassLeases4() override
Recount the leases per class for V4 leases.
virtual void updateLease6(const Lease6Ptr &lease6) override
Updates IPv6 lease.
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery4(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id) override
Creates and runs the IPv4 lease stats query for a single subnet.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv4 leases.
virtual LeaseStatsQueryPtr startPoolLeaseStatsQuery4() override
Creates and runs the IPv4 lease stats query for all subnets and pools.
virtual std::string checkLimits6(isc::data::ConstElementPtr const &user_context) const override
Checks if the IPv6 lease limits set in the given user context are exceeded.
virtual LeaseStatsQueryPtr startLeaseStatsQuery6() override
Creates and runs the IPv6 lease stats query.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const override
Returns existing IPv4 lease for specified IPv4 address.
virtual ~Memfile_LeaseMgr()
Destructor (closes file)
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.
boost::shared_ptr< CSVLeaseFile6 > lease_file6_
Holds the pointer to the DHCPv6 lease file IO.
std::string getDefaultLeaseFilePath(Universe u) const
Returns default path to the lease file.
virtual size_t upgradeExtendedInfo4(const LeasePageSize &page_size) override
Upgrade extended info (v4).
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv6 leases.
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv4 leases.
Attempt to update lease that was not there.
Manages a pool of asynchronous interval timers.
Definition: timer_mgr.h:62
Introduces callbacks into the LeaseMgr.
void trackUpdateLease(const LeasePtr &lease, bool mt_safe)
Invokes the callbacks when a lease is updated.
void trackAddLease(const LeasePtr &lease, bool mt_safe)
Invokes the callbacks when a new lease is added.
void trackDeleteLease(const LeasePtr &lease, bool mt_safe)
Invokes the callbacks when a lease is deleted.
bool hasCallbacks() const
Checks if any callbacks have been registered.
Exception thrown when an error occurs during CSV file processing.
Definition: csv_file.h:22
Provides input/output access to CSV files.
Definition: csv_file.h:358
RAII class creating a critical section.
Class to help with processing PID files.
Definition: pid_file.h:40
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
static const int MAJOR_VERSION_V4
static const int MINOR_VERSION_V4
the minor version of the v4 memfile backend
static const int MINOR_VERSION_V6
the minor version of the v6 memfile backend
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
Definition: data.cc:1395
void prettyPrint(ConstElementPtr element, std::ostream &out, unsigned indent, unsigned step)
Pretty prints the data into stream.
Definition: data.cc:1522
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:29
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_START
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID_CLIENTID
const isc::log::MessageID DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4
std::string ClientClass
Defines a single class name.
Definition: classify.h:42
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_ > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetIdPoolIdIndexTag >, boost::multi_index::composite_key< Lease4, boost::multi_index::member< Lease, SubnetID, &Lease::subnet_id_ >, boost::multi_index::member< Lease, uint32_t, &Lease::pool_id_ > > > >> Lease4Storage
A multi index container holding DHCPv4 leases.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID_HWADDR
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES6
const isc::log::MessageID DHCPSRV_MEMFILE_GET4
const isc::log::MessageID DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6_ERROR
const isc::log::MessageID DHCPSRV_MEMFILE_GET_REMOTEID6
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_UNREGISTER_TIMER_FAILED
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_SPAWN_FAIL
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_ > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetIdPoolIdIndexTag >, boost::multi_index::composite_key< Lease6, boost::multi_index::member< Lease, SubnetID, &Lease::subnet_id_ >, boost::multi_index::member< Lease, uint32_t, &Lease::pool_id_ > > > >> Lease6Storage
A multi index container holding DHCPv6 leases.
Lease6Storage::index< ExpirationIndexTag >::type Lease6StorageExpirationIndex
DHCPv6 lease storage index by expiration time.
const isc::log::MessageID DHCPSRV_MEMFILE_CONVERTING_LEASE_FILES
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_SETUP
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES6_FINISHED
Lease6Storage::index< DuidIndexTag >::type Lease6StorageDuidIndex
DHCPv6 lease storage index by DUID.
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:502
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:670
boost::shared_ptr< LeaseStatsQuery > LeaseStatsQueryPtr
Defines a pointer to a LeaseStatsQuery.
Definition: lease_mgr.h:233
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES4
Lease6Storage::index< SubnetIdPoolIdIndexTag >::type Lease6StorageSubnetIdPoolIdIndex
DHCPv6 lease storage index subnet-id and pool-id.
Lease6Storage::index< DuidIaidTypeIndexTag >::type Lease6StorageDuidIaidTypeIndex
DHCPv6 lease storage index by DUID, IAID, lease type.
boost::shared_ptr< TimerMgr > TimerMgrPtr
Type definition of the shared pointer to TimerMgr.
Definition: timer_mgr.h:24
const isc::log::MessageID DHCPSRV_MEMFILE_GET_RELAYID4
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_RENAME_FAIL
const isc::log::MessageID DHCPSRV_MEMFILE_UPDATE_ADDR4
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_ADDR
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID6
Lease4Storage::index< ExpirationIndexTag >::type Lease4StorageExpirationIndex
DHCPv4 lease storage index by expiration time.
Lease6Storage::index< AddressIndexTag >::type Lease6StorageAddressIndex
DHCPv6 lease storage index by address.
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition: dhcpsrv_log.h:38
const isc::log::MessageID DHCPSRV_MEMFILE_GET_ADDR4
const isc::log::MessageID DHCPSRV_MEMFILE_ROLLBACK
const isc::log::MessageID DHCPSRV_MEMFILE_UPDATE_ADDR6
Lease4Storage::index< HostnameIndexTag >::type Lease4StorageHostnameIndex
DHCPv4 lease storage index by hostname.
std::pair< Lease4StorageRemoteIdIndex::const_iterator, Lease4StorageRemoteIdIndex::const_iterator > Lease4StorageRemoteIdRange
DHCPv4 lease storage range by remote-id.
Lease6Storage::index< HostnameIndexTag >::type Lease6StorageHostnameIndex
DHCPv6 lease storage index by hostname.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED6
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HOSTNAME4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_LINKADDR6
Lease4Storage::index< ClientIdSubnetIdIndexTag >::type Lease4StorageClientIdSubnetIdIndex
DHCPv4 lease storage index by client-id and subnet-id.
Lease4Storage::index< HWAddressSubnetIdIndexTag >::type Lease4StorageHWAddressSubnetIdIndex
DHCPv4 lease storage index by HW address and subnet-id.
const isc::log::MessageID DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4_ERROR
const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR6
Lease6ExtendedInfoRelayIdTable::index< LeaseAddressIndexTag >::type LeaseAddressRelayIdIndex
Lease6 extended information by lease address index of by relay id table.
Lease6ExtendedInfoRelayIdTable::index< RelayIdIndexTag >::type RelayIdIndex
Lease6 extended information by relay id index.
Lease4Storage::index< RemoteIdIndexTag >::type Lease4StorageRemoteIdIndex
DHCPv4 lease storage index by remote-id.
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:25
const isc::log::MessageID DHCPSRV_MEMFILE_BEGIN_EXTRACT_EXTENDED_INFO4
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES4_FINISHED
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID4
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_REOPEN_FAIL
const isc::log::MessageID DHCPSRV_MEMFILE_COMMIT
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED4
boost::shared_ptr< CfgConsistency > CfgConsistencyPtr
Type used to for pointing to CfgConsistency structure.
const isc::log::MessageID DHCPSRV_MEMFILE_BEGIN_BUILD_EXTENDED_INFO_TABLES6
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HOSTNAME6
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED6
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_EXECUTE
std::pair< RemoteIdIndex::const_iterator, RemoteIdIndex::const_iterator > RemoteIdIndexRange
Lease6 extended information by remote id range.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_RELAYID6
const isc::log::MessageID DHCPSRV_MEMFILE_NO_STORAGE
const isc::log::MessageID DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6
const isc::log::MessageID DHCPSRV_MEMFILE_GET_PAGE4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HWADDR
const isc::log::MessageID DHCPSRV_MEMFILE_GET6_DUID
Lease4Storage::index< SubnetIdIndexTag >::type Lease4StorageSubnetIdIndex
DHCPv4 lease storage index subnet-id.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition: lease.h:497
const isc::log::MessageID DHCPSRV_MEMFILE_GET_ADDR6
const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_CLIENTID
Lease4Storage::index< AddressIndexTag >::type Lease4StorageAddressIndex
DHCPv4 lease storage index by address.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_IAID_DUID
const isc::log::MessageID DHCPSRV_MEMFILE_GET6
const isc::log::MessageID DHCPSRV_MEMFILE_GET_REMOTEID4
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:289
Lease6ExtendedInfoRemoteIdTable::index< LeaseAddressIndexTag >::type LeaseAddressRemoteIdIndex
Lease6 extended information by lease address index of by remote id table.
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition: dhcpsrv_log.h:26
Lease6Storage::index< SubnetIdIndexTag >::type Lease6StorageSubnetIdIndex
DHCPv6 lease storage index by subnet-id.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID
boost::shared_ptr< Lease6ExtendedInfo > Lease6ExtendedInfoPtr
Pointer to a Lease6ExtendedInfo object.
Lease6ExtendedInfoRemoteIdTable::index< RemoteIdIndexTag >::type RemoteIdIndex
Lease6 extended information by remote id index.
Lease4Storage::index< SubnetIdPoolIdIndexTag >::type Lease4StorageSubnetIdPoolIdIndex
DHCPv4 lease storage index subnet-id and pool-id.
Lease4Storage::index< RelayIdIndexTag >::type Lease4StorageRelayIdIndex
DHCPv4 lease storage index by relay-id.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_PAGE6
Definition: edns.h:19
Defines the logger used by the top-level component of kea-lfc.
Tag for indexes by address.
Tag for indexes by client-id, subnet-id tuple.
Tag for indexes by DUID, IAID, lease type tuple.
Tag for index using DUID.
Tag for indexes by expiration time.
Hardware type that represents information from DHCPv4 packet.
Definition: hwaddr.h:20
std::vector< uint8_t > hwaddr_
Definition: hwaddr.h:98
std::string toText(bool include_htype=true) const
Returns textual representation of a hardware address (e.g.
Definition: hwaddr.cc:51
Tag for indexes by HW address, subnet-id tuple.
Tag for index using hostname.
Structure that holds a lease for IPv4 address.
Definition: lease.h:300
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:513
ExtendedInfoAction
Action on extended info tables.
Definition: lease.h:550
@ ACTION_UPDATE
update extended info tables.
Definition: lease.h:553
@ ACTION_DELETE
delete reference to the lease
Definition: lease.h:552
@ ACTION_IGNORE
ignore extended info,
Definition: lease.h:551
Tag for indexes by lease address.
Contains a single row of lease statistical data.
Definition: lease_mgr.h:64
static const uint32_t STATE_DEFAULT
A lease in the default state.
Definition: lease.h:69
static const uint32_t STATE_DECLINED
Declined lease.
Definition: lease.h:72
Type
Type of lease or pool.
Definition: lease.h:46
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
Definition: lease.h:49
@ TYPE_V4
IPv4 lease.
Definition: lease.h:50
@ TYPE_NA
the lease contains non-temporary IPv6 address
Definition: lease.h:47
static std::string typeToText(Type type)
returns text representation of a lease type
Definition: lease.cc:54
Tag for index using relay-id.
Tag for index using remote-id.
Tag for indexes by subnet-id.