Kea  2.3.1-git
memfile_lease_mgr.cc
Go to the documentation of this file.
1 // Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
10 #include <dhcpsrv/cfgmgr.h>
12 #include <dhcpsrv/dhcpsrv_log.h>
15 #include <dhcpsrv/timer_mgr.h>
16 #include <exceptions/exceptions.h>
17 #include <stats/stats_mgr.h>
19 #include <util/pid_file.h>
20 
21 #include <cstdio>
22 #include <cstring>
23 #include <errno.h>
24 #include <iostream>
25 #include <limits>
26 #include <sstream>
27 
28 namespace {
29 
37 const char* KEA_LFC_EXECUTABLE_ENV_NAME = "KEA_LFC_EXECUTABLE";
38 
39 } // namespace
40 
41 using namespace isc::asiolink;
42 using namespace isc::data;
43 using namespace isc::db;
44 using namespace isc::util;
45 using namespace isc::stats;
46 
47 namespace isc {
48 namespace dhcp {
49 
64 class LFCSetup {
65 public:
66 
75 
79  ~LFCSetup();
80 
92  void setup(const uint32_t lfc_interval,
93  const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
94  const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
95  bool run_once_now = false);
96 
98  void execute();
99 
103  bool isRunning() const;
104 
106  int getExitStatus() const;
107 
108 private:
109 
112  boost::scoped_ptr<ProcessSpawn> process_;
113 
116 
118  pid_t pid_;
119 
124  TimerMgrPtr timer_mgr_;
125 };
126 
127 LFCSetup::LFCSetup(asiolink::IntervalTimer::Callback callback)
128  : process_(), callback_(callback), pid_(0),
129  timer_mgr_(TimerMgr::instance()) {
130 }
131 
133  try {
134  // Remove the timer. This will throw an exception if the timer does not
135  // exist. There are several possible reasons for this:
136  // a) It hasn't been registered (although if the LFC Setup instance
137  // exists it means that the timer must have been registered or that
138  // such registration has been attempted).
139  // b) The registration may fail if the duplicate timer exists or if the
140  // TimerMgr's worker thread is running but if this happens it is a
141  // programming error.
142  // c) The program is shutting down and the timer has been removed by
143  // another component.
144  timer_mgr_->unregisterTimer("memfile-lfc");
145 
146  } catch (const std::exception& ex) {
147  // We don't want exceptions being thrown from the destructor so we just
148  // log a message here. The message is logged at debug severity as
149  // we don't want an error message output during shutdown.
152  }
153 }
154 
155 void
156 LFCSetup::setup(const uint32_t lfc_interval,
157  const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
158  const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
159  bool run_once_now) {
160 
161  // If to nothing to do, punt
162  if (lfc_interval == 0 && !run_once_now) {
163  return;
164  }
165 
166  // Start preparing the command line for kea-lfc.
167  std::string executable;
168  char* c_executable = getenv(KEA_LFC_EXECUTABLE_ENV_NAME);
169  if (c_executable == NULL) {
170  executable = KEA_LFC_EXECUTABLE;
171  } else {
172  executable = c_executable;
173  }
174 
175  // Gather the base file name.
176  std::string lease_file = lease_file4 ? lease_file4->getFilename() :
177  lease_file6->getFilename();
178 
179  // Create the other names by appending suffixes to the base name.
180  ProcessArgs args;
181  // Universe: v4 or v6.
182  args.push_back(lease_file4 ? "-4" : "-6");
183 
184  // Previous file.
185  args.push_back("-x");
186  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
188  // Input file.
189  args.push_back("-i");
190  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
192  // Output file.
193  args.push_back("-o");
194  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
196  // Finish file.
197  args.push_back("-f");
198  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
200  // PID file.
201  args.push_back("-p");
202  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
204 
205  // The configuration file is currently unused.
206  args.push_back("-c");
207  args.push_back("ignored-path");
208 
209  // Create the process (do not start it yet).
210  process_.reset(new ProcessSpawn(LeaseMgr::getIOService(), executable, args));
211 
212  // If we've been told to run it once now, invoke the callback directly.
213  if (run_once_now) {
214  callback_();
215  }
216 
217  // If it's supposed to run periodically, setup that now.
218  if (lfc_interval > 0) {
219  // Set the timer to call callback function periodically.
221 
222  // Multiple the lfc_interval value by 1000 as this value specifies
223  // a timeout in seconds, whereas the setup() method expects the
224  // timeout in milliseconds.
225  timer_mgr_->registerTimer("memfile-lfc", callback_, lfc_interval * 1000,
227  timer_mgr_->setup("memfile-lfc");
228  }
229 }
230 
231 void
233  try {
235  .arg(process_->getCommandLine());
236  pid_ = process_->spawn();
237 
238  } catch (const ProcessSpawnError&) {
240  }
241 }
242 
243 bool
245  return (process_ && process_->isRunning(pid_));
246 }
247 
248 int
250  if (!process_) {
251  isc_throw(InvalidOperation, "unable to obtain LFC process exit code: "
252  " the process is NULL");
253  }
254  return (process_->getExitStatus(pid_));
255 }
256 
257 
264 public:
268  : rows_(0), next_pos_(rows_.end()) {
269  };
270 
275  : LeaseStatsQuery(subnet_id), rows_(0), next_pos_(rows_.end()) {
276  };
277 
282  MemfileLeaseStatsQuery(const SubnetID& first_subnet_id, const SubnetID& last_subnet_id)
283  : LeaseStatsQuery(first_subnet_id, last_subnet_id), rows_(0), next_pos_(rows_.end()) {
284  };
285 
288 
299  virtual bool getNextRow(LeaseStatsRow& row) {
300  if (next_pos_ == rows_.end()) {
301  return (false);
302  }
303 
304  row = *next_pos_;
305  ++next_pos_;
306  return (true);
307  }
308 
310  int getRowCount() const {
311  return (rows_.size());
312  }
313 
314 protected:
316  std::vector<LeaseStatsRow> rows_;
317 
319  std::vector<LeaseStatsRow>::iterator next_pos_;
320 };
321 
332 public:
337  : MemfileLeaseStatsQuery(), storage4_(storage4) {
338  };
339 
344  MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& subnet_id)
345  : MemfileLeaseStatsQuery(subnet_id), storage4_(storage4) {
346  };
347 
353  MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& first_subnet_id,
354  const SubnetID& last_subnet_id)
355  : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage4_(storage4) {
356  };
357 
360 
375  void start() {
376  const Lease4StorageSubnetIdIndex& idx
377  = storage4_.get<SubnetIdIndexTag>();
378 
379  // Set lower and upper bounds based on select mode
380  Lease4StorageSubnetIdIndex::const_iterator lower;
381  Lease4StorageSubnetIdIndex::const_iterator upper;
382  switch (getSelectMode()) {
383  case ALL_SUBNETS:
384  lower = idx.begin();
385  upper = idx.end();
386  break;
387 
388  case SINGLE_SUBNET:
389  lower = idx.lower_bound(getFirstSubnetID());
390  upper = idx.upper_bound(getFirstSubnetID());
391  break;
392 
393  case SUBNET_RANGE:
394  lower = idx.lower_bound(getFirstSubnetID());
395  upper = idx.upper_bound(getLastSubnetID());
396  break;
397  }
398 
399  // Return an empty set if there are no rows.
400  if (lower == upper) {
401  return;
402  }
403 
404  // Iterate over the leases in order by subnet, accumulating per
405  // subnet counts for each state of interest. As we finish each
406  // subnet, add the appropriate rows to our result set.
407  SubnetID cur_id = 0;
408  int64_t assigned = 0;
409  int64_t declined = 0;
410  for (Lease4StorageSubnetIdIndex::const_iterator lease = lower;
411  lease != upper; ++lease) {
412  // If we've hit the next subnet, add rows for the current subnet
413  // and wipe the accumulators
414  if ((*lease)->subnet_id_ != cur_id) {
415  if (cur_id > 0) {
416  if (assigned > 0) {
417  rows_.push_back(LeaseStatsRow(cur_id,
419  assigned));
420  assigned = 0;
421  }
422 
423  if (declined > 0) {
424  rows_.push_back(LeaseStatsRow(cur_id,
426  declined));
427  declined = 0;
428  }
429  }
430 
431  // Update current subnet id
432  cur_id = (*lease)->subnet_id_;
433  }
434 
435  // Bump the appropriate accumulator
436  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
437  ++assigned;
438  } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
439  ++declined;
440  }
441  }
442 
443  // Make the rows for last subnet
444  if (assigned > 0) {
445  rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
446  assigned));
447  }
448 
449  if (declined > 0) {
450  rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
451  declined));
452  }
453 
454  // Reset the next row position back to the beginning of the rows.
455  next_pos_ = rows_.begin();
456  }
457 
458 private:
460  Lease4Storage& storage4_;
461 };
462 
463 
474 public:
479  : MemfileLeaseStatsQuery(), storage6_(storage6) {
480  };
481 
486  MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& subnet_id)
487  : MemfileLeaseStatsQuery(subnet_id), storage6_(storage6) {
488  };
489 
495  MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& first_subnet_id,
496  const SubnetID& last_subnet_id)
497  : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage6_(storage6) {
498  };
499 
502 
516  virtual void start() {
517  // Get the subnet_id index
518  const Lease6StorageSubnetIdIndex& idx
519  = storage6_.get<SubnetIdIndexTag>();
520 
521  // Set lower and upper bounds based on select mode
522  Lease6StorageSubnetIdIndex::const_iterator lower;
523  Lease6StorageSubnetIdIndex::const_iterator upper;
524  switch (getSelectMode()) {
525  case ALL_SUBNETS:
526  lower = idx.begin();
527  upper = idx.end();
528  break;
529 
530  case SINGLE_SUBNET:
531  lower = idx.lower_bound(getFirstSubnetID());
532  upper = idx.upper_bound(getFirstSubnetID());
533  break;
534 
535  case SUBNET_RANGE:
536  lower = idx.lower_bound(getFirstSubnetID());
537  upper = idx.upper_bound(getLastSubnetID());
538  break;
539  }
540 
541  // Return an empty set if there are no rows.
542  if (lower == upper) {
543  return;
544  }
545 
546  // Iterate over the leases in order by subnet, accumulating per
547  // subnet counts for each state of interest. As we finish each
548  // subnet, add the appropriate rows to our result set.
549  SubnetID cur_id = 0;
550  int64_t assigned = 0;
551  int64_t declined = 0;
552  int64_t assigned_pds = 0;
553  for (Lease6StorageSubnetIdIndex::const_iterator lease = lower;
554  lease != upper; ++lease) {
555  // If we've hit the next subnet, add rows for the current subnet
556  // and wipe the accumulators
557  if ((*lease)->subnet_id_ != cur_id) {
558  if (cur_id > 0) {
559  if (assigned > 0) {
560  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
562  assigned));
563  assigned = 0;
564  }
565 
566  if (declined > 0) {
567  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
569  declined));
570  declined = 0;
571  }
572 
573  if (assigned_pds > 0) {
574  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
576  assigned_pds));
577  assigned_pds = 0;
578  }
579  }
580 
581  // Update current subnet id
582  cur_id = (*lease)->subnet_id_;
583  }
584 
585  // Bump the appropriate accumulator
586  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
587  switch((*lease)->type_) {
588  case Lease::TYPE_NA:
589  ++assigned;
590  break;
591  case Lease::TYPE_PD:
592  ++assigned_pds;
593  break;
594  default:
595  break;
596  }
597  } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
598  // In theory only NAs can be declined
599  if (((*lease)->type_) == Lease::TYPE_NA) {
600  ++declined;
601  }
602  }
603  }
604 
605  // Make the rows for last subnet, unless there were no rows
606  if (assigned > 0) {
607  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
608  Lease::STATE_DEFAULT, assigned));
609  }
610 
611  if (declined > 0) {
612  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
613  Lease::STATE_DECLINED, declined));
614  }
615 
616  if (assigned_pds > 0) {
617  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
618  Lease::STATE_DEFAULT, assigned_pds));
619  }
620 
621  // Set the next row position to the beginning of the rows.
622  next_pos_ = rows_.begin();
623  }
624 
625 private:
627  Lease6Storage& storage6_;
628 };
629 
630 // Explicit definition of class static constants. Values are given in the
631 // declaration so they're not needed here.
636 
638  : LeaseMgr(), lfc_setup_(), conn_(parameters), mutex_(new std::mutex) {
639  bool conversion_needed = false;
640 
641  // Check the universe and use v4 file or v6 file.
642  std::string universe = conn_.getParameter("universe");
643  if (universe == "4") {
644  std::string file4 = initLeaseFilePath(V4);
645  if (!file4.empty()) {
646  conversion_needed = loadLeasesFromFiles<Lease4,
647  CSVLeaseFile4>(file4,
648  lease_file4_,
649  storage4_);
650  }
651  } else {
652  std::string file6 = initLeaseFilePath(V6);
653  if (!file6.empty()) {
654  conversion_needed = loadLeasesFromFiles<Lease6,
655  CSVLeaseFile6>(file6,
656  lease_file6_,
657  storage6_);
658  }
659  }
660 
661  // If lease persistence have been disabled for both v4 and v6,
662  // issue a warning. It is ok not to write leases to disk when
663  // doing testing, but it should not be done in normal server
664  // operation.
665  if (!persistLeases(V4) && !persistLeases(V6)) {
667  } else {
668  if (conversion_needed) {
669  auto const& version(getVersion());
671  .arg(version.first).arg(version.second);
672  }
673  lfcSetup(conversion_needed);
674  }
675 }
676 
678  if (lease_file4_) {
679  lease_file4_->close();
680  lease_file4_.reset();
681  }
682  if (lease_file6_) {
683  lease_file6_->close();
684  lease_file6_.reset();
685  }
686 }
687 
688 std::string
690  std::stringstream tmp;
691  tmp << "Memfile backend ";
692  if (u == V4) {
693  tmp << MAJOR_VERSION_V4 << "." << MINOR_VERSION_V4;
694  } else if (u == V6) {
695  tmp << MAJOR_VERSION_V6 << "." << MINOR_VERSION_V6;
696  }
697  return tmp.str();
698 }
699 
700 bool
701 Memfile_LeaseMgr::addLeaseInternal(const Lease4Ptr& lease) {
702  if (getLease4Internal(lease->addr_)) {
703  // there is a lease with specified address already
704  return (false);
705  }
706 
707  // Try to write a lease to disk first. If this fails, the lease will
708  // not be inserted to the memory and the disk and in-memory data will
709  // remain consistent.
710  if (persistLeases(V4)) {
711  lease_file4_->append(*lease);
712  }
713 
714  storage4_.insert(lease);
715 
716  // Update lease current expiration time (allows update between the creation
717  // of the Lease up to the point of insertion in the database).
718  lease->updateCurrentExpirationTime();
719 
720  // Increment class lease counters.
721  class_lease_counter_.addLease(lease);
722 
723  return (true);
724 }
725 
726 bool
729  DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
730 
731  if (MultiThreadingMgr::instance().getMode()) {
732  std::lock_guard<std::mutex> lock(*mutex_);
733  return (addLeaseInternal(lease));
734  } else {
735  return (addLeaseInternal(lease));
736  }
737 }
738 
739 bool
740 Memfile_LeaseMgr::addLeaseInternal(const Lease6Ptr& lease) {
741  if (getLease6Internal(lease->type_, lease->addr_)) {
742  // there is a lease with specified address already
743  return (false);
744  }
745 
746  // Try to write a lease to disk first. If this fails, the lease will
747  // not be inserted to the memory and the disk and in-memory data will
748  // remain consistent.
749  if (persistLeases(V6)) {
750  lease_file6_->append(*lease);
751  }
752 
753  storage6_.insert(lease);
754 
755  // Update lease current expiration time (allows update between the creation
756  // of the Lease up to the point of insertion in the database).
757  lease->updateCurrentExpirationTime();
758 
759  // Increment class lease counters.
760  class_lease_counter_.addLease(lease);
761 
762  return (true);
763 }
764 
765 bool
768  DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
769 
770  if (MultiThreadingMgr::instance().getMode()) {
771  std::lock_guard<std::mutex> lock(*mutex_);
772  return (addLeaseInternal(lease));
773  } else {
774  return (addLeaseInternal(lease));
775  }
776 }
777 
778 Lease4Ptr
779 Memfile_LeaseMgr::getLease4Internal(const isc::asiolink::IOAddress& addr) const {
780  const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
781  Lease4StorageAddressIndex::iterator l = idx.find(addr);
782  if (l == idx.end()) {
783  return (Lease4Ptr());
784  } else {
785  return (Lease4Ptr(new Lease4(**l)));
786  }
787 }
788 
789 Lease4Ptr
792  DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
793 
794  if (MultiThreadingMgr::instance().getMode()) {
795  std::lock_guard<std::mutex> lock(*mutex_);
796  return (getLease4Internal(addr));
797  } else {
798  return (getLease4Internal(addr));
799  }
800 }
801 
802 void
803 Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
804  Lease4Collection& collection) const {
805  // Using composite index by 'hw address' and 'subnet id'. It is
806  // ok to use it for searching by the 'hw address' only.
808  storage4_.get<HWAddressSubnetIdIndexTag>();
809  std::pair<Lease4StorageHWAddressSubnetIdIndex::const_iterator,
810  Lease4StorageHWAddressSubnetIdIndex::const_iterator> l
811  = idx.equal_range(boost::make_tuple(hwaddr.hwaddr_));
812 
813  for (auto lease = l.first; lease != l.second; ++lease) {
814  collection.push_back(Lease4Ptr(new Lease4(**lease)));
815  }
816 }
817 
819 Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr) const {
821  DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.toText());
822 
823  Lease4Collection collection;
824  if (MultiThreadingMgr::instance().getMode()) {
825  std::lock_guard<std::mutex> lock(*mutex_);
826  getLease4Internal(hwaddr, collection);
827  } else {
828  getLease4Internal(hwaddr, collection);
829  }
830 
831  return (collection);
832 }
833 
834 Lease4Ptr
835 Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
836  SubnetID subnet_id) const {
837  // Get the index by HW Address and Subnet Identifier.
839  storage4_.get<HWAddressSubnetIdIndexTag>();
840  // Try to find the lease using HWAddr and subnet id.
841  Lease4StorageHWAddressSubnetIdIndex::const_iterator lease =
842  idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
843  // Lease was not found. Return empty pointer to the caller.
844  if (lease == idx.end()) {
845  return (Lease4Ptr());
846  }
847 
848  // Lease was found. Return it to the caller.
849  return (Lease4Ptr(new Lease4(**lease)));
850 }
851 
852 Lease4Ptr
854  SubnetID subnet_id) const {
856  DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
857  .arg(hwaddr.toText());
858 
859  if (MultiThreadingMgr::instance().getMode()) {
860  std::lock_guard<std::mutex> lock(*mutex_);
861  return (getLease4Internal(hwaddr, subnet_id));
862  } else {
863  return (getLease4Internal(hwaddr, subnet_id));
864  }
865 }
866 
867 void
868 Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
869  Lease4Collection& collection) const {
870  // Using composite index by 'client id' and 'subnet id'. It is ok
871  // to use it to search by 'client id' only.
873  storage4_.get<ClientIdSubnetIdIndexTag>();
874  std::pair<Lease4StorageClientIdSubnetIdIndex::const_iterator,
875  Lease4StorageClientIdSubnetIdIndex::const_iterator> l
876  = idx.equal_range(boost::make_tuple(client_id.getClientId()));
877 
878  for (auto lease = l.first; lease != l.second; ++lease) {
879  collection.push_back(Lease4Ptr(new Lease4(**lease)));
880  }
881 }
882 
884 Memfile_LeaseMgr::getLease4(const ClientId& client_id) const {
886  DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.toText());
887 
888  Lease4Collection collection;
889  if (MultiThreadingMgr::instance().getMode()) {
890  std::lock_guard<std::mutex> lock(*mutex_);
891  getLease4Internal(client_id, collection);
892  } else {
893  getLease4Internal(client_id, collection);
894  }
895 
896  return (collection);
897 }
898 
899 Lease4Ptr
900 Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
901  SubnetID subnet_id) const {
902  // Get the index by client and subnet id.
904  storage4_.get<ClientIdSubnetIdIndexTag>();
905  // Try to get the lease using client id and subnet id.
906  Lease4StorageClientIdSubnetIdIndex::const_iterator lease =
907  idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
908  // Lease was not found. Return empty pointer to the caller.
909  if (lease == idx.end()) {
910  return (Lease4Ptr());
911  }
912  // Lease was found. Return it to the caller.
913  return (Lease4Ptr(new Lease4(**lease)));
914 }
915 
916 Lease4Ptr
918  SubnetID subnet_id) const {
920  DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id)
921  .arg(client_id.toText());
922 
923  if (MultiThreadingMgr::instance().getMode()) {
924  std::lock_guard<std::mutex> lock(*mutex_);
925  return (getLease4Internal(client_id, subnet_id));
926  } else {
927  return (getLease4Internal(client_id, subnet_id));
928  }
929 }
930 
931 void
932 Memfile_LeaseMgr::getLeases4Internal(SubnetID subnet_id,
933  Lease4Collection& collection) const {
934  const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
935  std::pair<Lease4StorageSubnetIdIndex::const_iterator,
936  Lease4StorageSubnetIdIndex::const_iterator> l =
937  idx.equal_range(subnet_id);
938 
939  for (auto lease = l.first; lease != l.second; ++lease) {
940  collection.push_back(Lease4Ptr(new Lease4(**lease)));
941  }
942 }
943 
947  .arg(subnet_id);
948 
949  Lease4Collection collection;
950  if (MultiThreadingMgr::instance().getMode()) {
951  std::lock_guard<std::mutex> lock(*mutex_);
952  getLeases4Internal(subnet_id, collection);
953  } else {
954  getLeases4Internal(subnet_id, collection);
955  }
956 
957  return (collection);
958 }
959 
960 void
961 Memfile_LeaseMgr::getLeases4Internal(const std::string& hostname,
962  Lease4Collection& collection) const {
963  const Lease4StorageHostnameIndex& idx = storage4_.get<HostnameIndexTag>();
964  std::pair<Lease4StorageHostnameIndex::const_iterator,
965  Lease4StorageHostnameIndex::const_iterator> l =
966  idx.equal_range(hostname);
967 
968  for (auto lease = l.first; lease != l.second; ++lease) {
969  collection.push_back(Lease4Ptr(new Lease4(**lease)));
970  }
971 }
972 
974 Memfile_LeaseMgr::getLeases4(const std::string& hostname) const {
976  .arg(hostname);
977 
978  Lease4Collection collection;
979  if (MultiThreadingMgr::instance().getMode()) {
980  std::lock_guard<std::mutex> lock(*mutex_);
981  getLeases4Internal(hostname, collection);
982  } else {
983  getLeases4Internal(hostname, collection);
984  }
985 
986  return (collection);
987 }
988 
989 void
990 Memfile_LeaseMgr::getLeases4Internal(Lease4Collection& collection) const {
991  for (auto lease = storage4_.begin(); lease != storage4_.end(); ++lease) {
992  collection.push_back(Lease4Ptr(new Lease4(**lease)));
993  }
994 }
995 
999 
1000  Lease4Collection collection;
1001  if (MultiThreadingMgr::instance().getMode()) {
1002  std::lock_guard<std::mutex> lock(*mutex_);
1003  getLeases4Internal(collection);
1004  } else {
1005  getLeases4Internal(collection);
1006  }
1007 
1008  return (collection);
1009 }
1010 
1011 void
1012 Memfile_LeaseMgr::getLeases4Internal(const asiolink::IOAddress& lower_bound_address,
1013  const LeasePageSize& page_size,
1014  Lease4Collection& collection) const {
1015  const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1016  Lease4StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1017 
1018  // Exclude the lower bound address specified by the caller.
1019  if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1020  ++lb;
1021  }
1022 
1023  // Return all other leases being within the page size.
1024  for (auto lease = lb;
1025  (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1026  ++lease) {
1027  collection.push_back(Lease4Ptr(new Lease4(**lease)));
1028  }
1029 }
1030 
1033  const LeasePageSize& page_size) const {
1034  // Expecting IPv4 address.
1035  if (!lower_bound_address.isV4()) {
1036  isc_throw(InvalidAddressFamily, "expected IPv4 address while "
1037  "retrieving leases from the lease database, got "
1038  << lower_bound_address);
1039  }
1040 
1042  .arg(page_size.page_size_)
1043  .arg(lower_bound_address.toText());
1044 
1045  Lease4Collection collection;
1046  if (MultiThreadingMgr::instance().getMode()) {
1047  std::lock_guard<std::mutex> lock(*mutex_);
1048  getLeases4Internal(lower_bound_address, page_size, collection);
1049  } else {
1050  getLeases4Internal(lower_bound_address, page_size, collection);
1051  }
1052 
1053  return (collection);
1054 }
1055 
1056 Lease6Ptr
1057 Memfile_LeaseMgr::getLease6Internal(Lease::Type type,
1058  const isc::asiolink::IOAddress& addr) const {
1059  Lease6Storage::iterator l = storage6_.find(addr);
1060  if (l == storage6_.end() || !(*l) || ((*l)->type_ != type)) {
1061  return (Lease6Ptr());
1062  } else {
1063  return (Lease6Ptr(new Lease6(**l)));
1064  }
1065 }
1066 
1067 Lease6Ptr
1069  const isc::asiolink::IOAddress& addr) const {
1072  .arg(addr.toText())
1073  .arg(Lease::typeToText(type));
1074 
1075  if (MultiThreadingMgr::instance().getMode()) {
1076  std::lock_guard<std::mutex> lock(*mutex_);
1077  return (getLease6Internal(type, addr));
1078  } else {
1079  return (getLease6Internal(type, addr));
1080  }
1081 }
1082 
1083 void
1084 Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1085  const DUID& duid,
1086  uint32_t iaid,
1087  Lease6Collection& collection) const {
1088  // Get the index by DUID, IAID, lease type.
1089  const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1090  // Try to get the lease using the DUID, IAID and lease type.
1091  std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1092  Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1093  idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1094 
1095  for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1096  l.first; lease != l.second; ++lease) {
1097  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1098  }
1099 }
1100 
1103  const DUID& duid,
1104  uint32_t iaid) const {
1107  .arg(iaid)
1108  .arg(duid.toText())
1109  .arg(Lease::typeToText(type));
1110 
1111  Lease6Collection collection;
1112  if (MultiThreadingMgr::instance().getMode()) {
1113  std::lock_guard<std::mutex> lock(*mutex_);
1114  getLeases6Internal(type, duid, iaid, collection);
1115  } else {
1116  getLeases6Internal(type, duid, iaid, collection);
1117  }
1118 
1119  return (collection);
1120 }
1121 
1122 void
1123 Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1124  const DUID& duid,
1125  uint32_t iaid,
1126  SubnetID subnet_id,
1127  Lease6Collection& collection) const {
1128  // Get the index by DUID, IAID, lease type.
1129  const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1130  // Try to get the lease using the DUID, IAID and lease type.
1131  std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1132  Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1133  idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1134 
1135  for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1136  l.first; lease != l.second; ++lease) {
1137  // Filter out the leases which subnet id doesn't match.
1138  if ((*lease)->subnet_id_ == subnet_id) {
1139  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1140  }
1141  }
1142 }
1143 
1146  const DUID& duid,
1147  uint32_t iaid,
1148  SubnetID subnet_id) const {
1151  .arg(iaid)
1152  .arg(subnet_id)
1153  .arg(duid.toText())
1154  .arg(Lease::typeToText(type));
1155 
1156  Lease6Collection collection;
1157  if (MultiThreadingMgr::instance().getMode()) {
1158  std::lock_guard<std::mutex> lock(*mutex_);
1159  getLeases6Internal(type, duid, iaid, subnet_id, collection);
1160  } else {
1161  getLeases6Internal(type, duid, iaid, subnet_id, collection);
1162  }
1163 
1164  return (collection);
1165 }
1166 
1167 void
1168 Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1169  Lease6Collection& collection) const {
1170  const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1171  std::pair<Lease6StorageSubnetIdIndex::const_iterator,
1172  Lease6StorageSubnetIdIndex::const_iterator> l =
1173  idx.equal_range(subnet_id);
1174 
1175  for (auto lease = l.first; lease != l.second; ++lease) {
1176  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1177  }
1178 }
1179 
1183  .arg(subnet_id);
1184 
1185  Lease6Collection collection;
1186  if (MultiThreadingMgr::instance().getMode()) {
1187  std::lock_guard<std::mutex> lock(*mutex_);
1188  getLeases6Internal(subnet_id, collection);
1189  } else {
1190  getLeases6Internal(subnet_id, collection);
1191  }
1192 
1193  return (collection);
1194 }
1195 
1196 void
1197 Memfile_LeaseMgr::getLeases6Internal(const std::string& hostname,
1198  Lease6Collection& collection) const {
1199  const Lease6StorageHostnameIndex& idx = storage6_.get<HostnameIndexTag>();
1200  std::pair<Lease6StorageHostnameIndex::const_iterator,
1201  Lease6StorageHostnameIndex::const_iterator> l =
1202  idx.equal_range(hostname);
1203 
1204  for (auto lease = l.first; lease != l.second; ++lease) {
1205  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1206  }
1207 }
1208 
1210 Memfile_LeaseMgr::getLeases6(const std::string& hostname) const {
1212  .arg(hostname);
1213 
1214  Lease6Collection collection;
1215  if (MultiThreadingMgr::instance().getMode()) {
1216  std::lock_guard<std::mutex> lock(*mutex_);
1217  getLeases6Internal(hostname, collection);
1218  } else {
1219  getLeases6Internal(hostname, collection);
1220  }
1221 
1222  return (collection);
1223 }
1224 
1225 void
1226 Memfile_LeaseMgr::getLeases6Internal(Lease6Collection& collection) const {
1227  for (auto lease = storage6_.begin(); lease != storage6_.end(); ++lease) {
1228  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1229  }
1230 }
1231 
1235 
1236  Lease6Collection collection;
1237  if (MultiThreadingMgr::instance().getMode()) {
1238  std::lock_guard<std::mutex> lock(*mutex_);
1239  getLeases6Internal(collection);
1240  } else {
1241  getLeases6Internal(collection);
1242  }
1243 
1244  return (collection);
1245 }
1246 
1247 void
1248 Memfile_LeaseMgr::getLeases6Internal(const DUID& duid,
1249  Lease6Collection& collection) const {
1250  const Lease6StorageDuidIndex& idx = storage6_.get<DuidIndexTag>();
1251  std::pair<Lease6StorageDuidIndex::const_iterator,
1252  Lease6StorageDuidIndex::const_iterator> l =
1253  idx.equal_range(duid.getDuid());
1254 
1255  for (auto lease = l.first; lease != l.second; ++lease) {
1256  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1257  }
1258 }
1259 
1263  .arg(duid.toText());
1264 
1265  Lease6Collection collection;
1266  if (MultiThreadingMgr::instance().getMode()) {
1267  std::lock_guard<std::mutex> lock(*mutex_);
1268  getLeases6Internal(duid, collection);
1269  } else {
1270  getLeases6Internal(duid, collection);
1271  }
1272 
1273  return (collection);
1274 }
1275 
1276 void
1277 Memfile_LeaseMgr::getLeases6Internal(const asiolink::IOAddress& lower_bound_address,
1278  const LeasePageSize& page_size,
1279  Lease6Collection& collection) const {
1280  const Lease6StorageAddressIndex& idx = storage6_.get<AddressIndexTag>();
1281  Lease6StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1282 
1283  // Exclude the lower bound address specified by the caller.
1284  if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1285  ++lb;
1286  }
1287 
1288  // Return all other leases being within the page size.
1289  for (auto lease = lb;
1290  (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1291  ++lease) {
1292  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1293  }
1294 }
1295 
1298  const LeasePageSize& page_size) const {
1299  // Expecting IPv6 address.
1300  if (!lower_bound_address.isV6()) {
1301  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1302  "retrieving leases from the lease database, got "
1303  << lower_bound_address);
1304  }
1305 
1307  .arg(page_size.page_size_)
1308  .arg(lower_bound_address.toText());
1309 
1310  Lease6Collection collection;
1311  if (MultiThreadingMgr::instance().getMode()) {
1312  std::lock_guard<std::mutex> lock(*mutex_);
1313  getLeases6Internal(lower_bound_address, page_size, collection);
1314  } else {
1315  getLeases6Internal(lower_bound_address, page_size, collection);
1316  }
1317 
1318  return (collection);
1319 }
1320 
1321 void
1322 Memfile_LeaseMgr::getExpiredLeases4Internal(Lease4Collection& expired_leases,
1323  const size_t max_leases) const {
1324  // Obtain the index which segragates leases by state and time.
1325  const Lease4StorageExpirationIndex& index = storage4_.get<ExpirationIndexTag>();
1326 
1327  // Retrieve leases which are not reclaimed and which haven't expired. The
1328  // 'less-than' operator will be used for both components of the index. So,
1329  // for the 'state' 'false' is less than 'true'. Also the leases with
1330  // expiration time lower than current time will be returned.
1331  Lease4StorageExpirationIndex::const_iterator ub =
1332  index.upper_bound(boost::make_tuple(false, time(NULL)));
1333 
1334  // Copy only the number of leases indicated by the max_leases parameter.
1335  for (Lease4StorageExpirationIndex::const_iterator lease = index.begin();
1336  (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1337  max_leases));
1338  ++lease) {
1339  expired_leases.push_back(Lease4Ptr(new Lease4(**lease)));
1340  }
1341 }
1342 
1343 void
1345  const size_t max_leases) const {
1347  .arg(max_leases);
1348 
1349  if (MultiThreadingMgr::instance().getMode()) {
1350  std::lock_guard<std::mutex> lock(*mutex_);
1351  getExpiredLeases4Internal(expired_leases, max_leases);
1352  } else {
1353  getExpiredLeases4Internal(expired_leases, max_leases);
1354  }
1355 }
1356 
1357 void
1358 Memfile_LeaseMgr::getExpiredLeases6Internal(Lease6Collection& expired_leases,
1359  const size_t max_leases) const {
1360  // Obtain the index which segragates leases by state and time.
1361  const Lease6StorageExpirationIndex& index = storage6_.get<ExpirationIndexTag>();
1362 
1363  // Retrieve leases which are not reclaimed and which haven't expired. The
1364  // 'less-than' operator will be used for both components of the index. So,
1365  // for the 'state' 'false' is less than 'true'. Also the leases with
1366  // expiration time lower than current time will be returned.
1367  Lease6StorageExpirationIndex::const_iterator ub =
1368  index.upper_bound(boost::make_tuple(false, time(NULL)));
1369 
1370  // Copy only the number of leases indicated by the max_leases parameter.
1371  for (Lease6StorageExpirationIndex::const_iterator lease = index.begin();
1372  (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1373  max_leases));
1374  ++lease) {
1375  expired_leases.push_back(Lease6Ptr(new Lease6(**lease)));
1376  }
1377 }
1378 
1379 void
1381  const size_t max_leases) const {
1383  .arg(max_leases);
1384 
1385  if (MultiThreadingMgr::instance().getMode()) {
1386  std::lock_guard<std::mutex> lock(*mutex_);
1387  getExpiredLeases6Internal(expired_leases, max_leases);
1388  } else {
1389  getExpiredLeases6Internal(expired_leases, max_leases);
1390  }
1391 }
1392 
1393 void
1394 Memfile_LeaseMgr::updateLease4Internal(const Lease4Ptr& lease) {
1395  // Obtain 'by address' index.
1396  Lease4StorageAddressIndex& index = storage4_.get<AddressIndexTag>();
1397 
1398  bool persist = persistLeases(V4);
1399 
1400  // Lease must exist if it is to be updated.
1401  Lease4StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1402  if (lease_it == index.end()) {
1403  isc_throw(NoSuchLease, "failed to update the lease with address "
1404  << lease->addr_ << " - no such lease");
1405  } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1406  ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1407  // For test purpose only: check that the lease has not changed in
1408  // the database.
1409  isc_throw(NoSuchLease, "failed to update the lease with address "
1410  << lease->addr_ << " - lease has changed in database");
1411  }
1412 
1413  // Try to write a lease to disk first. If this fails, the lease will
1414  // not be inserted to the memory and the disk and in-memory data will
1415  // remain consistent.
1416  if (persist) {
1417  lease_file4_->append(*lease);
1418  }
1419 
1420  // Update lease current expiration time.
1421  lease->updateCurrentExpirationTime();
1422 
1423  // Save a copy of the old lease as lease_it will point to the new
1424  // one after the replacement.
1425  Lease4Ptr old_lease = *lease_it;
1426 
1427  // Use replace() to re-index leases.
1428  index.replace(lease_it, Lease4Ptr(new Lease4(*lease)));
1429 
1430  // Adjust class lease counters.
1431  class_lease_counter_.updateLease(lease, old_lease);
1432 }
1433 
1434 void
1437  DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
1438 
1439  if (MultiThreadingMgr::instance().getMode()) {
1440  std::lock_guard<std::mutex> lock(*mutex_);
1441  updateLease4Internal(lease);
1442  } else {
1443  updateLease4Internal(lease);
1444  }
1445 }
1446 
1447 void
1448 Memfile_LeaseMgr::updateLease6Internal(const Lease6Ptr& lease) {
1449  // Obtain 'by address' index.
1450  Lease6StorageAddressIndex& index = storage6_.get<AddressIndexTag>();
1451 
1452  bool persist = persistLeases(V6);
1453 
1454  // Lease must exist if it is to be updated.
1455  Lease6StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1456  if (lease_it == index.end()) {
1457  isc_throw(NoSuchLease, "failed to update the lease with address "
1458  << lease->addr_ << " - no such lease");
1459  } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1460  ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1461  // For test purpose only: check that the lease has not changed in
1462  // the database.
1463  isc_throw(NoSuchLease, "failed to update the lease with address "
1464  << lease->addr_ << " - lease has changed in database");
1465  }
1466 
1467  // Try to write a lease to disk first. If this fails, the lease will
1468  // not be inserted to the memory and the disk and in-memory data will
1469  // remain consistent.
1470  if (persist) {
1471  lease_file6_->append(*lease);
1472  }
1473 
1474  // Update lease current expiration time.
1475  lease->updateCurrentExpirationTime();
1476 
1477  // Save a copy of the old lease as lease_it will point to the new
1478  // one after the replacement.
1479  Lease6Ptr old_lease = *lease_it;
1480 
1481  // Use replace() to re-index leases.
1482  index.replace(lease_it, Lease6Ptr(new Lease6(*lease)));
1483 
1484  // Adjust class lease counters.
1485  class_lease_counter_.updateLease(lease, old_lease);
1486 }
1487 
1488 void
1491  DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
1492 
1493  if (MultiThreadingMgr::instance().getMode()) {
1494  std::lock_guard<std::mutex> lock(*mutex_);
1495  updateLease6Internal(lease);
1496  } else {
1497  updateLease6Internal(lease);
1498  }
1499 }
1500 
1501 bool
1502 Memfile_LeaseMgr::deleteLeaseInternal(const Lease4Ptr& lease) {
1503  const isc::asiolink::IOAddress& addr = lease->addr_;
1504  Lease4Storage::iterator l = storage4_.find(addr);
1505  if (l == storage4_.end()) {
1506  // No such lease
1507  return (false);
1508  } else {
1509  if (persistLeases(V4)) {
1510  // Copy the lease. The valid lifetime needs to be modified and
1511  // we don't modify the original lease.
1512  Lease4 lease_copy = **l;
1513  // Setting valid lifetime to 0 means that lease is being
1514  // removed.
1515  lease_copy.valid_lft_ = 0;
1516  lease_file4_->append(lease_copy);
1517  } else {
1518  // For test purpose only: check that the lease has not changed in
1519  // the database.
1520  if (((*l)->cltt_ != lease->current_cltt_) ||
1521  ((*l)->valid_lft_ != lease->current_valid_lft_)) {
1522  return false;
1523  }
1524  }
1525 
1526  storage4_.erase(l);
1527 
1528  // Decrement class lease counters.
1529  class_lease_counter_.removeLease(lease);
1530 
1531  return (true);
1532  }
1533 }
1534 
1535 bool
1538  DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
1539 
1540  if (MultiThreadingMgr::instance().getMode()) {
1541  std::lock_guard<std::mutex> lock(*mutex_);
1542  return (deleteLeaseInternal(lease));
1543  } else {
1544  return (deleteLeaseInternal(lease));
1545  }
1546 }
1547 
1548 bool
1549 Memfile_LeaseMgr::deleteLeaseInternal(const Lease6Ptr& lease) {
1550  const isc::asiolink::IOAddress& addr = lease->addr_;
1551  Lease6Storage::iterator l = storage6_.find(addr);
1552  if (l == storage6_.end()) {
1553  // No such lease
1554  return (false);
1555  } else {
1556  if (persistLeases(V6)) {
1557  // Copy the lease. The lifetimes need to be modified and we
1558  // don't modify the original lease.
1559  Lease6 lease_copy = **l;
1560  // Setting lifetimes to 0 means that lease is being removed.
1561  lease_copy.valid_lft_ = 0;
1562  lease_copy.preferred_lft_ = 0;
1563  lease_file6_->append(lease_copy);
1564  } else {
1565  // For test purpose only: check that the lease has not changed in
1566  // the database.
1567  if (((*l)->cltt_ != lease->current_cltt_) ||
1568  ((*l)->valid_lft_ != lease->current_valid_lft_)) {
1569  return false;
1570  }
1571  }
1572 
1573  storage6_.erase(l);
1574 
1575  // Decrement class lease counters.
1576  class_lease_counter_.removeLease(lease);
1577 
1578  return (true);
1579  }
1580 }
1581 
1582 bool
1585  DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
1586 
1587  if (MultiThreadingMgr::instance().getMode()) {
1588  std::lock_guard<std::mutex> lock(*mutex_);
1589  return (deleteLeaseInternal(lease));
1590  } else {
1591  return (deleteLeaseInternal(lease));
1592  }
1593 }
1594 
1595 uint64_t
1599  .arg(secs);
1600 
1601  if (MultiThreadingMgr::instance().getMode()) {
1602  std::lock_guard<std::mutex> lock(*mutex_);
1603  return (deleteExpiredReclaimedLeases<
1605  >(secs, V4, storage4_, lease_file4_));
1606  } else {
1607  return (deleteExpiredReclaimedLeases<
1609  >(secs, V4, storage4_, lease_file4_));
1610  }
1611 }
1612 
1613 uint64_t
1617  .arg(secs);
1618 
1619  if (MultiThreadingMgr::instance().getMode()) {
1620  std::lock_guard<std::mutex> lock(*mutex_);
1621  return (deleteExpiredReclaimedLeases<
1623  >(secs, V6, storage6_, lease_file6_));
1624  } else {
1625  return (deleteExpiredReclaimedLeases<
1627  >(secs, V6, storage6_, lease_file6_));
1628  }
1629 }
1630 
1631 template<typename IndexType, typename LeaseType, typename StorageType,
1632  typename LeaseFileType>
1633 uint64_t
1634 Memfile_LeaseMgr::deleteExpiredReclaimedLeases(const uint32_t secs,
1635  const Universe& universe,
1636  StorageType& storage,
1637  LeaseFileType& lease_file) const {
1638  // Obtain the index which segragates leases by state and time.
1639  IndexType& index = storage.template get<ExpirationIndexTag>();
1640 
1641  // This returns the first element which is greater than the specified
1642  // tuple (true, time(NULL) - secs). However, the range between the
1643  // beginning of the index and returned element also includes all the
1644  // elements for which the first value is false (lease state is NOT
1645  // reclaimed), because false < true. All elements between the
1646  // beginning of the index and the element returned, for which the
1647  // first value is true, represent the reclaimed leases which should
1648  // be deleted, because their expiration time + secs has occurred earlier
1649  // than current time.
1650  typename IndexType::const_iterator upper_limit =
1651  index.upper_bound(boost::make_tuple(true, time(NULL) - secs));
1652 
1653  // Now, we have to exclude all elements of the index which represent
1654  // leases in the state other than reclaimed - with the first value
1655  // in the index equal to false. Note that elements in the index are
1656  // ordered from the lower to the higher ones. So, all elements with
1657  // the first value of false are placed before the elements with the
1658  // value of true. Hence, we have to find the first element which
1659  // contains value of true. The time value is the lowest possible.
1660  typename IndexType::const_iterator lower_limit =
1661  index.upper_bound(boost::make_tuple(true, std::numeric_limits<int64_t>::min()));
1662 
1663  // If there are some elements in this range, delete them.
1664  uint64_t num_leases = static_cast<uint64_t>(std::distance(lower_limit, upper_limit));
1665  if (num_leases > 0) {
1666 
1669  .arg(num_leases);
1670 
1671  // If lease persistence is enabled, we also have to mark leases
1672  // as deleted in the lease file. We do this by setting the
1673  // lifetime to 0.
1674  if (persistLeases(universe)) {
1675  for (typename IndexType::const_iterator lease = lower_limit;
1676  lease != upper_limit; ++lease) {
1677  // Copy lease to not affect the lease in the container.
1678  LeaseType lease_copy(**lease);
1679  // Set the valid lifetime to 0 to indicate the removal
1680  // of the lease.
1681  lease_copy.valid_lft_ = 0;
1682  lease_file->append(lease_copy);
1683  }
1684  }
1685 
1686  // Erase leases from memory.
1687  index.erase(lower_limit, upper_limit);
1688  }
1689  // Return number of leases deleted.
1690  return (num_leases);
1691 }
1692 
1693 
1694 std::string
1696  return (std::string("In memory database with leases stored in a CSV file."));
1697 }
1698 
1699 std::pair<uint32_t, uint32_t>
1701  std::string const& universe(conn_.getParameter("universe"));
1702  if (universe == "4") {
1703  return std::make_pair(MAJOR_VERSION_V4, MINOR_VERSION_V4);
1704  } else if (universe == "6") {
1705  return std::make_pair(MAJOR_VERSION_V6, MINOR_VERSION_V6);
1706  }
1707  isc_throw(BadValue, "cannot determine version for universe " << universe);
1708 }
1709 
1710 void
1713 }
1714 
1715 void
1719 }
1720 
1721 std::string
1722 Memfile_LeaseMgr::appendSuffix(const std::string& file_name,
1723  const LFCFileType& file_type) {
1724  std::string name(file_name);
1725  switch (file_type) {
1726  case FILE_INPUT:
1727  name += ".1";
1728  break;
1729  case FILE_PREVIOUS:
1730  name += ".2";
1731  break;
1732  case FILE_OUTPUT:
1733  name += ".output";
1734  break;
1735  case FILE_FINISH:
1736  name += ".completed";
1737  break;
1738  case FILE_PID:
1739  name += ".pid";
1740  break;
1741  default:
1742  // Do not append any suffix for the FILE_CURRENT.
1743  ;
1744  }
1745 
1746  return (name);
1747 }
1748 
1749 std::string
1751  std::ostringstream s;
1752  s << CfgMgr::instance().getDataDir() << "/kea-leases";
1753  s << (u == V4 ? "4" : "6");
1754  s << ".csv";
1755  return (s.str());
1756 }
1757 
1758 std::string
1760  if (u == V4) {
1761  return (lease_file4_ ? lease_file4_->getFilename() : "");
1762  }
1763 
1764  return (lease_file6_ ? lease_file6_->getFilename() : "");
1765 }
1766 
1767 bool
1769  // Currently, if the lease file IO is not created, it means that writes to
1770  // disk have been explicitly disabled by the administrator. At some point,
1771  // there may be a dedicated ON/OFF flag implemented to control this.
1772  if (u == V4 && lease_file4_) {
1773  return (true);
1774  }
1775 
1776  return (u == V6 && lease_file6_);
1777 }
1778 
1779 std::string
1780 Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
1781  std::string persist_val;
1782  try {
1783  persist_val = conn_.getParameter("persist");
1784  } catch (const Exception&) {
1785  // If parameter persist hasn't been specified, we use a default value
1786  // 'yes'.
1787  persist_val = "true";
1788  }
1789  // If persist_val is 'false' we will not store leases to disk, so let's
1790  // return empty file name.
1791  if (persist_val == "false") {
1792  return ("");
1793 
1794  } else if (persist_val != "true") {
1795  isc_throw(isc::BadValue, "invalid value 'persist="
1796  << persist_val << "'");
1797  }
1798 
1799  std::string lease_file;
1800  try {
1801  lease_file = conn_.getParameter("name");
1802  } catch (const Exception&) {
1803  lease_file = getDefaultLeaseFilePath(u);
1804  }
1805  return (lease_file);
1806 }
1807 
1808 template<typename LeaseObjectType, typename LeaseFileType, typename StorageType>
1809 bool
1810 Memfile_LeaseMgr::loadLeasesFromFiles(const std::string& filename,
1811  boost::shared_ptr<LeaseFileType>& lease_file,
1812  StorageType& storage) {
1813  // Check if the instance of the LFC is running right now. If it is
1814  // running, we refuse to load leases as the LFC may be writing to the
1815  // lease files right now. When the user retries server configuration
1816  // it should go through.
1819  PIDFile pid_file(appendSuffix(filename, FILE_PID));
1820  if (pid_file.check()) {
1821  isc_throw(DbOpenError, "unable to load leases from files while the "
1822  "lease file cleanup is in progress");
1823  }
1824 
1825  storage.clear();
1826 
1827  std::string max_row_errors_str = "0";
1828  try {
1829  max_row_errors_str = conn_.getParameter("max-row-errors");
1830  } catch (const std::exception&) {
1831  // Ignore and default to 0.
1832  }
1833 
1834  uint32_t max_row_errors = 0;
1835  try {
1836  max_row_errors = boost::lexical_cast<uint32_t>(max_row_errors_str);
1837  } catch (const boost::bad_lexical_cast&) {
1838  isc_throw(isc::BadValue, "invalid value of the max-row-errors "
1839  << max_row_errors_str << " specified");
1840  }
1841 
1842  // Load the leasefile.completed, if exists.
1843  bool conversion_needed = false;
1844  lease_file.reset(new LeaseFileType(std::string(filename + ".completed")));
1845  if (lease_file->exists()) {
1846  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1847  max_row_errors);
1848  conversion_needed = conversion_needed || lease_file->needsConversion();
1849  } else {
1850  // If the leasefile.completed doesn't exist, let's load the leases
1851  // from leasefile.2 and leasefile.1, if they exist.
1852  lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_PREVIOUS)));
1853  if (lease_file->exists()) {
1854  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1855  max_row_errors);
1856  conversion_needed = conversion_needed || lease_file->needsConversion();
1857  }
1858 
1859  lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_INPUT)));
1860  if (lease_file->exists()) {
1861  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1862  max_row_errors);
1863  conversion_needed = conversion_needed || lease_file->needsConversion();
1864  }
1865  }
1866 
1867  // Always load leases from the primary lease file. If the lease file
1868  // doesn't exist it will be created by the LeaseFileLoader. Note
1869  // that the false value passed as the last parameter to load
1870  // function causes the function to leave the file open after
1871  // it is parsed. This file will be used by the backend to record
1872  // future lease updates.
1873  lease_file.reset(new LeaseFileType(filename));
1874  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1875  max_row_errors, false);
1876  conversion_needed = conversion_needed || lease_file->needsConversion();
1877 
1878  return (conversion_needed);
1879 }
1880 
1881 
1882 bool
1884  return (lfc_setup_->isRunning());
1885 }
1886 
1887 int
1889  return (lfc_setup_->getExitStatus());
1890 }
1891 
1892 void
1895 
1896  // Check if we're in the v4 or v6 space and use the appropriate file.
1897  if (lease_file4_) {
1899  lfcExecute(lease_file4_);
1900  } else if (lease_file6_) {
1902  lfcExecute(lease_file6_);
1903  }
1904 }
1905 
1906 void
1907 Memfile_LeaseMgr::lfcSetup(bool conversion_needed) {
1908  std::string lfc_interval_str = "3600";
1909  try {
1910  lfc_interval_str = conn_.getParameter("lfc-interval");
1911  } catch (const std::exception&) {
1912  // Ignore and default to 3600.
1913  }
1914 
1915  uint32_t lfc_interval = 0;
1916  try {
1917  lfc_interval = boost::lexical_cast<uint32_t>(lfc_interval_str);
1918  } catch (const boost::bad_lexical_cast&) {
1919  isc_throw(isc::BadValue, "invalid value of the lfc-interval "
1920  << lfc_interval_str << " specified");
1921  }
1922 
1923  if (lfc_interval > 0 || conversion_needed) {
1924  lfc_setup_.reset(new LFCSetup(std::bind(&Memfile_LeaseMgr::lfcCallback, this)));
1925  lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_, conversion_needed);
1926  }
1927 }
1928 
1929 template<typename LeaseFileType>
1930 void
1931 Memfile_LeaseMgr::lfcExecute(boost::shared_ptr<LeaseFileType>& lease_file) {
1932  bool do_lfc = true;
1933 
1934  // Check the status of the LFC instance.
1935  // If the finish file exists or the copy of the lease file exists it
1936  // is an indication that another LFC instance may be in progress or
1937  // may be stalled. In that case we don't want to rotate the current
1938  // lease file to avoid overriding the contents of the existing file.
1939  CSVFile lease_file_finish(appendSuffix(lease_file->getFilename(), FILE_FINISH));
1940  CSVFile lease_file_copy(appendSuffix(lease_file->getFilename(), FILE_INPUT));
1941  if (!lease_file_finish.exists() && !lease_file_copy.exists()) {
1942  // Close the current file so as we can move it to the copy file.
1943  lease_file->close();
1944  // Move the current file to the copy file. Remember the result
1945  // because we don't want to run LFC if the rename failed.
1946  do_lfc = (rename(lease_file->getFilename().c_str(),
1947  lease_file_copy.getFilename().c_str()) == 0);
1948 
1949  if (!do_lfc) {
1951  .arg(lease_file->getFilename())
1952  .arg(lease_file_copy.getFilename())
1953  .arg(strerror(errno));
1954  }
1955 
1956  // Regardless if we successfully moved the current file or not,
1957  // we need to re-open the current file for the server to write
1958  // new lease updates. If the file has been successfully moved,
1959  // this will result in creation of the new file. Otherwise,
1960  // an existing file will be opened.
1961  try {
1962  lease_file->open(true);
1963 
1964  } catch (const CSVFileError& ex) {
1965  // If we're unable to open the lease file this is a serious
1966  // error because the server will not be able to persist
1967  // leases.
1975  .arg(lease_file->getFilename())
1976  .arg(ex.what());
1977  // Reset the pointer to the file so as the backend doesn't
1978  // try to write leases to disk.
1979  lease_file.reset();
1980  do_lfc = false;
1981  }
1982  }
1983  // Once the files have been rotated, or untouched if another LFC had
1984  // not finished, a new process is started.
1985  if (do_lfc) {
1986  lfc_setup_->execute();
1987  }
1988 }
1989 
1992  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_));
1993  if (MultiThreadingMgr::instance().getMode()) {
1994  std::lock_guard<std::mutex> lock(*mutex_);
1995  query->start();
1996  } else {
1997  query->start();
1998  }
1999 
2000  return(query);
2001 }
2002 
2005  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, subnet_id));
2006  if (MultiThreadingMgr::instance().getMode()) {
2007  std::lock_guard<std::mutex> lock(*mutex_);
2008  query->start();
2009  } else {
2010  query->start();
2011  }
2012 
2013  return(query);
2014 }
2015 
2018  const SubnetID& last_subnet_id) {
2019  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, first_subnet_id,
2020  last_subnet_id));
2021  if (MultiThreadingMgr::instance().getMode()) {
2022  std::lock_guard<std::mutex> lock(*mutex_);
2023  query->start();
2024  } else {
2025  query->start();
2026  }
2027 
2028  return(query);
2029 }
2030 
2033  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_));
2034  if (MultiThreadingMgr::instance().getMode()) {
2035  std::lock_guard<std::mutex> lock(*mutex_);
2036  query->start();
2037  } else {
2038  query->start();
2039  }
2040 
2041  return(query);
2042 }
2043 
2046  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, subnet_id));
2047  if (MultiThreadingMgr::instance().getMode()) {
2048  std::lock_guard<std::mutex> lock(*mutex_);
2049  query->start();
2050  } else {
2051  query->start();
2052  }
2053 
2054  return(query);
2055 }
2056 
2059  const SubnetID& last_subnet_id) {
2060  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, first_subnet_id,
2061  last_subnet_id));
2062  if (MultiThreadingMgr::instance().getMode()) {
2063  std::lock_guard<std::mutex> lock(*mutex_);
2064  query->start();
2065  } else {
2066  query->start();
2067  }
2068 
2069  return(query);
2070 }
2071 
2072 size_t
2075  .arg(subnet_id);
2076 
2077  // Get the index by DUID, IAID, lease type.
2078  const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
2079 
2080  // Try to get the lease using the DUID, IAID and lease type.
2081  std::pair<Lease4StorageSubnetIdIndex::const_iterator,
2082  Lease4StorageSubnetIdIndex::const_iterator> l =
2083  idx.equal_range(subnet_id);
2084 
2085  // Let's collect all leases.
2086  Lease4Collection leases;
2087  for (auto lease = l.first; lease != l.second; ++lease) {
2088  leases.push_back(*lease);
2089  }
2090 
2091  size_t num = leases.size();
2092  for (auto l = leases.begin(); l != leases.end(); ++l) {
2093  deleteLease(*l);
2094  }
2096  .arg(subnet_id).arg(num);
2097 
2098  return (num);
2099 }
2100 
2101 size_t
2104  .arg(subnet_id);
2105 
2106  // Get the index by DUID, IAID, lease type.
2107  const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
2108 
2109  // Try to get the lease using the DUID, IAID and lease type.
2110  std::pair<Lease6StorageSubnetIdIndex::const_iterator,
2111  Lease6StorageSubnetIdIndex::const_iterator> l =
2112  idx.equal_range(subnet_id);
2113 
2114  // Let's collect all leases.
2115  Lease6Collection leases;
2116  for (auto lease = l.first; lease != l.second; ++lease) {
2117  leases.push_back(*lease);
2118  }
2119 
2120  size_t num = leases.size();
2121  for (auto l = leases.begin(); l != leases.end(); ++l) {
2122  deleteLease(*l);
2123  }
2125  .arg(subnet_id).arg(num);
2126 
2127  return (num);
2128 }
2129 
2130 void
2132  class_lease_counter_.clear();
2133  for (auto lease = storage4_.begin(); lease != storage4_.end(); ++lease) {
2134  // Bump the appropriate accumulator
2135  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
2136  class_lease_counter_.addLease(*lease);
2137  }
2138  }
2139 }
2140 
2141 void
2143  class_lease_counter_.clear();
2144  for (auto lease = storage6_.begin(); lease != storage6_.end(); ++lease) {
2145  // Bump the appropriate accumulator
2146  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
2147  class_lease_counter_.addLease(*lease);
2148  }
2149  }
2150 }
2151 
2152 size_t
2154  const Lease::Type& ltype /* = Lease::TYPE_V4*/) const {
2155  if (MultiThreadingMgr::instance().getMode()) {
2156  std::lock_guard<std::mutex> lock(*mutex_);
2157  return(class_lease_counter_.getClassCount(client_class, ltype));
2158  } else {
2159  return(class_lease_counter_.getClassCount(client_class, ltype));
2160  }
2161 }
2162 
2163 void
2165  return(class_lease_counter_.clear());
2166 }
2167 
2168 std::string
2170  if (!user_context) {
2171  return ("");
2172  }
2173 
2174  ConstElementPtr limits = user_context->find("ISC/limits");
2175  if (!limits) {
2176  return ("");
2177  }
2178 
2179  // Iterate of the 'client-classes' list in 'limits'. For each class that specifies
2180  // an "address-limit", check its value against the class's lease count.
2181  ConstElementPtr classes = limits->get("client-classes");
2182  if (classes) {
2183  for (int i = 0; i < classes->size(); ++i) {
2184  ConstElementPtr class_elem = classes->get(i);
2185  // Get class name.
2186  ConstElementPtr name_elem = class_elem->get("name");
2187  if (!name_elem) {
2188  isc_throw(BadValue, "checkLimits4 - client-class.name is missing: "
2189  << prettyPrint(limits));
2190  }
2191 
2192  std::string name = name_elem->stringValue();
2193 
2194  // Now look for an address-limit
2195  size_t limit;
2196  if (!getLeaseLimit(class_elem, Lease::TYPE_V4, limit)) {
2197  // No limit, go to the next class.
2198  continue;
2199  }
2200 
2201  // If the limit is > 0 look up the class lease count. Limit of 0 always
2202  // denies the lease.
2203  size_t lease_count = 0;
2204  if (limit) {
2205  lease_count = getClassLeaseCount(name);
2206  }
2207 
2208  // If we're over the limit, return the error, no need to evaluate any others.
2209  if (lease_count >= limit) {
2210  std::ostringstream ss;
2211  ss << "address limit " << limit << " for client class \""
2212  << name << "\", current lease count " << lease_count;
2213  return (ss.str());
2214  }
2215  }
2216  }
2217 
2218  // If there were class limits we passed them, now look for a subnet limit.
2219  ConstElementPtr subnet_elem = limits->get("subnet");
2220  if (subnet_elem) {
2221  // Get the subnet id.
2222  ConstElementPtr id_elem = subnet_elem->get("id");
2223  if (!id_elem) {
2224  isc_throw(BadValue, "checkLimits4 - subnet.id is missing: "
2225  << prettyPrint(limits));
2226  }
2227 
2228  SubnetID subnet_id = id_elem->intValue();
2229 
2230  // Now look for an address-limit.
2231  size_t limit;
2232  if (getLeaseLimit(subnet_elem, Lease::TYPE_V4, limit)) {
2233  // If the limit is > 0 look up the subnet lease count. Limit of 0 always
2234  // denies the lease.
2235  int64_t lease_count = 0;
2236  if (limit) {
2237  lease_count = getSubnetStat(subnet_id, "assigned-addresses");
2238  }
2239 
2240  // If we're over the limit, return the error.
2241  if (lease_count >= limit) {
2242  std::ostringstream ss;
2243  ss << "address limit " << limit << " for subnet ID " << subnet_id
2244  << ", current lease count " << lease_count;
2245  return (ss.str());
2246  }
2247  }
2248  }
2249 
2250  // No limits exceeded!
2251  return ("");
2252 }
2253 
2254 std::string
2256  if (!user_context) {
2257  return ("");
2258  }
2259 
2260  ConstElementPtr limits = user_context->find("ISC/limits");
2261  if (!limits) {
2262  return ("");
2263  }
2264 
2265  // Iterate over the 'client-classes' list in 'limits'. For each class that specifies
2266  // limit (either "address-limit" or "prefix-limit", check its value against the appropriate
2267  // class lease count.
2268  ConstElementPtr classes = limits->get("client-classes");
2269  if (classes) {
2270  for (int i = 0; i < classes->size(); ++i) {
2271  ConstElementPtr class_elem = classes->get(i);
2272  // Get class name.
2273  ConstElementPtr name_elem = class_elem->get("name");
2274  if (!name_elem) {
2275  isc_throw(BadValue, "checkLimits6 - client-class.name is missing: "
2276  << prettyPrint(limits));
2277  }
2278 
2279  std::string name = name_elem->stringValue();
2280 
2281  // Now look for either address-limit or a prefix=limit.
2282  size_t limit = 0;
2283  Lease::Type ltype = Lease::TYPE_NA;
2284  if (!getLeaseLimit(class_elem, ltype, limit)) {
2285  ltype = Lease::TYPE_PD;
2286  if (!getLeaseLimit(class_elem, ltype, limit)) {
2287  // No limits for this class, skip to the next.
2288  continue;
2289  }
2290  }
2291 
2292  // If the limit is > 0 look up the class lease count. Limit of 0 always
2293  // denies the lease.
2294  size_t lease_count = 0;
2295  if (limit) {
2296  lease_count = getClassLeaseCount(name, ltype);
2297  }
2298 
2299  // If we're over the limit, return the error, no need to evaluate any others.
2300  if (lease_count >= limit) {
2301  std::ostringstream ss;
2302  ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
2303  << " limit " << limit << " for client class \""
2304  << name << "\", current lease count " << lease_count;
2305  return (ss.str());
2306  }
2307  }
2308  }
2309 
2310  // If there were class limits we passed them, now look for a subnet limit.
2311  ConstElementPtr subnet_elem = limits->get("subnet");
2312  if (subnet_elem) {
2313  // Get the subnet id.
2314  ConstElementPtr id_elem = subnet_elem->get("id");
2315  if (!id_elem) {
2316  isc_throw(BadValue, "checkLimits6 - subnet.id is missing: "
2317  << prettyPrint(limits));
2318  }
2319 
2320  SubnetID subnet_id = id_elem->intValue();
2321 
2322  // Now look for either address-limit or a prefix=limit.
2323  size_t limit = 0;
2324  Lease::Type ltype = Lease::TYPE_NA;
2325  if (!getLeaseLimit(subnet_elem, ltype, limit)) {
2326  ltype = Lease::TYPE_PD;
2327  if (!getLeaseLimit(subnet_elem, ltype, limit)) {
2328  // No limits for the subnet so none exceeded!
2329  return ("");
2330  }
2331  }
2332 
2333  // If the limit is > 0 look up the class lease count. Limit of 0 always
2334  // denies the lease.
2335  int64_t lease_count = 0;
2336  if (limit) {
2337  lease_count = getSubnetStat(subnet_id, (ltype == Lease::TYPE_NA ?
2338  "assigned-nas" : "assigned-pds"));
2339  }
2340 
2341  // If we're over the limit, return the error.
2342  if (lease_count >= limit) {
2343  std::ostringstream ss;
2344  ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
2345  << " limit " << limit << " for subnet ID " << subnet_id
2346  << ", current lease count " << lease_count;
2347  return (ss.str());
2348  }
2349  }
2350 
2351  // No limits exceeded!
2352  return ("");
2353 }
2354 
2355 bool
2357  return true;
2358 }
2359 
2360 int64_t
2361 Memfile_LeaseMgr::getSubnetStat(const SubnetID& subnet_id, const std::string& stat_label) const {
2364  std::string stat_name = StatsMgr::generateName("subnet", subnet_id, stat_label);
2365  ConstElementPtr stat = StatsMgr::instance().get(stat_name);
2366  ConstElementPtr samples = stat->get(stat_name);
2367  if (samples && samples->size()) {
2368  auto sample = samples->get(0);
2369  if (sample->size()) {
2370  auto count_elem = sample->get(0);
2371  return (count_elem->intValue());
2372  }
2373  }
2374 
2375  return (0);
2376 }
2377 
2378 bool
2379 Memfile_LeaseMgr::getLeaseLimit(ConstElementPtr parent, Lease::Type ltype, size_t& limit) const {
2380  ConstElementPtr limit_elem = parent->get(ltype == Lease::TYPE_PD ?
2381  "prefix-limit" : "address-limit");
2382  if (limit_elem) {
2383  limit = limit_elem->intValue();
2384  return (true);
2385  }
2386 
2387  return (false);
2388 }
2389 
2392  const IOAddress& /* lower_bound_address */,
2393  const LeasePageSize& /* page_size */,
2394  const time_t& /* qry_start_time = 0 */,
2395  const time_t& /* qry_end_time = 0 */) {
2396  isc_throw(NotImplemented, "Memfile_LeaseMgr::getLeases4ByRelayId not implemented");
2397 }
2398 
2401  const IOAddress& /* lower_bound_address */,
2402  const LeasePageSize& /* page_size */,
2403  const time_t& /* qry_start_time = 0 */,
2404  const time_t& /* qry_end_time = 0 */) {
2405  isc_throw(NotImplemented, "Memfile_LeaseMgr::getLeases4ByRemoteId not implemented");
2406 }
2407 
2410  const IOAddress& /* link_addr */,
2411  const IOAddress& /* lower_bound_address */,
2412  const LeasePageSize& /* page_size */) {
2413  isc_throw(NotImplemented, "Memfile_LeaseMgr::getLeases6ByRelayId not implemented");
2414 }
2415 
2418  const IOAddress& /* link_addr */,
2419  const IOAddress& /* lower_bound_address */,
2420  const LeasePageSize& /* page_size*/) {
2421  isc_throw(NotImplemented, "Memfile_LeaseMgr::getLeases6ByRemoteId not implemented");
2422 }
2423 
2426  const IOAddress& /* lower_bound_address */,
2427  const LeasePageSize& /* page_size */) {
2428  isc_throw(NotImplemented, "Memfile_LeaseMgr::getLeases6ByLink not implemented");
2429 }
2430 
2431 void
2432 Memfile_LeaseMgr::writeLeases4(const std::string& filename) {
2433  if (MultiThreadingMgr::instance().getMode()) {
2434  std::lock_guard<std::mutex> lock(*mutex_);
2435  writeLeases4Internal(filename);
2436  } else {
2437  writeLeases4Internal(filename);
2438  }
2439 }
2440 
2441 void
2442 Memfile_LeaseMgr::writeLeases4Internal(const std::string& filename) {
2443  bool overwrite = (lease_file4_ && lease_file4_->getFilename() == filename);
2444  try {
2445  if (overwrite) {
2446  lease_file4_->close();
2447  }
2448  std::ostringstream old;
2449  old << filename << ".bak" << getpid();
2450  ::rename(filename.c_str(), old.str().c_str());
2451  CSVLeaseFile4 backup(filename);
2452  backup.open();
2453  for (const auto& lease : storage4_) {
2454  backup.append(*lease);
2455  }
2456  backup.close();
2457  if (overwrite) {
2458  lease_file4_->open(true);
2459  }
2460  } catch (const std::exception&) {
2461  if (overwrite) {
2462  lease_file4_->open(true);
2463  }
2464  throw;
2465  }
2466 }
2467 
2468 void
2469 Memfile_LeaseMgr::writeLeases6(const std::string& filename) {
2470  if (MultiThreadingMgr::instance().getMode()) {
2471  std::lock_guard<std::mutex> lock(*mutex_);
2472  writeLeases6Internal(filename);
2473  } else {
2474  writeLeases6Internal(filename);
2475  }
2476 }
2477 
2478 void
2479 Memfile_LeaseMgr::writeLeases6Internal(const std::string& filename) {
2480  bool overwrite = (lease_file6_ && lease_file6_->getFilename() == filename);
2481  try {
2482  if (overwrite) {
2483  lease_file6_->close();
2484  }
2485  std::ostringstream old;
2486  old << filename << ".bak" << getpid();
2487  ::rename(filename.c_str(), old.str().c_str());
2488  CSVLeaseFile6 backup(filename);
2489  backup.open();
2490  for (const auto& lease : storage6_) {
2491  backup.append(*lease);
2492  }
2493  backup.close();
2494  if (overwrite) {
2495  lease_file6_->open(true);
2496  }
2497  } catch (const std::exception&) {
2498  if (overwrite) {
2499  lease_file6_->open(true);
2500  }
2501  throw;
2502  }
2503 }
2504 
2505 } // namespace dhcp
2506 } // namespace isc
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery6(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id) override
Creates and runs the IPv6 lease stats query for a single subnet.
RAII class creating a critical section.
Represents a configuration for Lease File Cleanup.
Tag for indexes by DUID, IAID, lease type tuple.
virtual ~MemfileLeaseStatsQuery4()
Destructor.
virtual Lease6Collection getLeases6ByLink(const asiolink::IOAddress &link_addr, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size) override
Returns existing IPv6 leases with on a given link.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HWADDR
bool exists() const
Checks if the CSV file exists and can be opened for reading.
Definition: csv_file.cc:133
boost::shared_ptr< TimerMgr > TimerMgrPtr
Type definition of the shared pointer to TimerMgr.
Definition: timer_mgr.h:24
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv4 leases.
virtual ~Memfile_LeaseMgr()
Destructor (closes file)
virtual void recountClassLeases4() override
Recount the leases per class for V4 leases.
MemfileLeaseStatsQuery(const SubnetID &subnet_id)
Constructor for single subnet query.
boost::shared_ptr< LeaseStatsQuery > LeaseStatsQueryPtr
Defines a pointer to a LeaseStatsQuery.
Definition: lease_mgr.h:208
util::Optional< std::string > getDataDir() const
returns path do the data directory
Definition: cfgmgr.cc:31
virtual Lease6Collection getLeases6() const override
Returns all IPv6 leases.
A generic exception that is thrown when a function is not implemented.
const isc::log::MessageID DHCPSRV_MEMFILE_UPDATE_ADDR6
void removeLease(LeasePtr lease)
Decrement the counts for all of a lease&#39;s classes by one.
const std::vector< uint8_t > & getClientId() const
Returns reference to the client-id data.
Definition: duid.cc:117
Structure that holds a lease for IPv4 address.
Definition: lease.h:295
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES4
Abstract Lease Manager.
Definition: lease_mgr.h:223
void setup(const uint32_t lfc_interval, const boost::shared_ptr< CSVLeaseFile4 > &lease_file4, const boost::shared_ptr< CSVLeaseFile6 > &lease_file6, bool run_once_now=false)
Sets the new configuration for the Lease File Cleanup.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
int getExitStatus() const
Returns exit code of the last completed cleanup.
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_START
virtual std::string checkLimits4(isc::data::ConstElementPtr const &user_context) const override
Checks if the IPv4 lease limits set in the given user context are exceeded.
std::vector< LeaseStatsRow >::iterator next_pos_
An iterator for accessing the next row within the result set.
virtual Lease6Collection getLeases6ByRemoteId(const OptionBuffer &remote_id, const asiolink::IOAddress &link_addr, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size) override
Returns existing IPv6 leases with a given remote-id.
virtual size_t getClassLeaseCount(const ClientClass &client_class, const Lease::Type &ltype=Lease::TYPE_V4) const override
Returns the class lease count for a given class and lease type.
static std::string typeToText(Type type)
returns text representation of a lease type
Definition: lease.cc:52
virtual Lease4Collection getLeases4() const override
Returns all IPv4 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.
void prettyPrint(ConstElementPtr element, std::ostream &out, unsigned indent, unsigned step)
Pretty prints the data into stream.
Definition: data.cc:1487
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES6
Memfile derivation of the IPv6 statistical lease data query.
const isc::log::MessageID DHCPSRV_MEMFILE_GET6_DUID
void updateLease(LeasePtr new_lease, LeasePtr old_lease)
Adjust class lease counts given a new and old version of a lease.
virtual void updateLease4(const Lease4Ptr &lease4) override
Updates IPv4 lease.
MemfileLeaseStatsQuery(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for subnet range query.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
uint32_t preferred_lft_
Preferred lifetime.
Definition: lease.h:540
Manages a pool of asynchronous interval timers.
Definition: timer_mgr.h:62
Attempt to update lease that was not there.
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition: lease.h:498
Lease4Storage::index< HostnameIndexTag >::type Lease4StorageHostnameIndex
DHCPv4 lease storage index by hostname.
Lease6Storage::index< DuidIaidTypeIndexTag >::type Lease6StorageDuidIaidTypeIndex
DHCPv6 lease storage index by DUID, IAID, lease type.
Universe
Specifies universe (V4, V6)
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
the lease contains IPv6 prefix (for prefix delegation)
Definition: lease.h:49
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID_HWADDR
Tag for indexes by expiration time.
std::vector< uint8_t > hwaddr_
Definition: hwaddr.h:98
bool isRunning() const
Checks if the lease file cleanup is in progress.
STL namespace.
boost::shared_ptr< CSVLeaseFile4 > lease_file4_
Holds the pointer to the DHCPv4 lease file IO.
const isc::log::MessageID DHCPSRV_MEMFILE_CONVERTING_LEASE_FILES
virtual void writeLeases4(const std::string &filename) override
Write V4 leases to a file.
Lease4Storage::index< HWAddressSubnetIdIndexTag >::type Lease4StorageHWAddressSubnetIdIndex
DHCPv4 lease storage index by HW address and subnet identifier.
Base class for fulfilling a statistical lease data query.
Definition: lease_mgr.h:129
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_SETUP
std::string getFilename() const
Returns the path to the CSV file.
Definition: csv_file.h:408
void start()
Creates the IPv4 lease statistical data result set.
Class to help with processing PID files.
Definition: pid_file.h:40
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv4 leases.
Memfile_LeaseMgr(const db::DatabaseConnection::ParameterMap &parameters)
The sole lease manager constructor.
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_ > > >> Lease4Storage
A multi index container holding DHCPv4 leases.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID
virtual std::pair< uint32_t, uint32_t > getVersion() const override
Returns backend version.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv6 leases.
virtual void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv6 leases.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_PAGE6
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
LFCFileType
Types of the lease files used by the Lease File Cleanup.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
size_t getClassCount(const ClientClass &client_class, const Lease::Type &ltype=Lease::TYPE_V4) const
Fetches the lease count for the given class and lease type.
Holds DUID (DHCPv6 Unique Identifier)
Definition: duid.h:27
const isc::log::MessageID DHCPSRV_MEMFILE_UPDATE_ADDR4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID4
Tag for index using hostname.
Exception thrown on failure to open database.
Provides methods to access CSV file with DHCPv4 leases.
static isc::asiolink::IOServicePtr & getIOService()
Returns pointer to the IO service.
Definition: lease_mgr.h:791
MemfileLeaseStatsQuery6(Lease6Storage &storage6, const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for a subnet range query.
const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR6
const isc::log::MessageID DHCPSRV_MEMFILE_GET6
virtual Lease4Collection getLeases4ByRelayId(const OptionBuffer &relay_id, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size, const time_t &qry_start_time=0, const time_t &qry_end_time=0) override
The following queries are used to fulfill Bulk LeaseQuery queries.
Lease6Storage::index< AddressIndexTag >::type Lease6StorageAddressIndex
DHCPv6 lease storage index by address.
MemfileLeaseStatsQuery6(Lease6Storage &storage6, const SubnetID &subnet_id)
Constructor for a single subnet query.
static std::string getDBVersion()
Class method to return extended version info This class method must be redeclared and redefined in de...
Definition: lease_mgr.cc:354
const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR4
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES6_FINISHED
virtual void lfcCallback()
A callback function triggering Lease File Cleanup (LFC).
Lease6Storage::index< DuidIndexTag >::type Lease6StorageDuidIndex
DHCPv6 lease storage index by DUID.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_CLIENTID
Lease4Storage::index< AddressIndexTag >::type Lease4StorageAddressIndex
DHCPv4 lease storage index by address.
Definition: edns.h:19
const isc::log::MessageID DHCPSRV_MEMFILE_GET_IAID_DUID
virtual void commit() override
Commit Transactions.
virtual bool getNextRow(LeaseStatsRow &row)
Fetches the next row in the result set.
Lease4Storage::index< SubnetIdIndexTag >::type Lease4StorageSubnetIdIndex
DHCPv4 lease storage index subnet identifier.
const size_t page_size_
Holds page size.
Definition: lease_mgr.h:54
boost::multi_index_container< Lease6Ptr, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< AddressIndexTag >, boost::multi_index::member< Lease, isc::asiolink::IOAddress, &Lease::addr_ > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< DuidIaidTypeIndexTag >, boost::multi_index::composite_key< Lease6, boost::multi_index::const_mem_fun< Lease6, const std::vector< uint8_t > &, &Lease6::getDuidVector >, boost::multi_index::member< Lease6, uint32_t, &Lease6::iaid_ >, boost::multi_index::member< Lease6, Lease::Type, &Lease6::type_ > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< ExpirationIndexTag >, boost::multi_index::composite_key< Lease6, boost::multi_index::const_mem_fun< Lease, bool, &Lease::stateExpiredReclaimed >, boost::multi_index::const_mem_fun< Lease, int64_t, &Lease::getExpirationTime > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetIdIndexTag >, boost::multi_index::member< Lease, isc::dhcp::SubnetID, &Lease::subnet_id_ > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< DuidIndexTag >, boost::multi_index::const_mem_fun< Lease6, const std::vector< uint8_t > &, &Lease6::getDuidVector > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< HostnameIndexTag >, boost::multi_index::member< Lease, std::string, &Lease::hostname_ > > >> Lease6Storage
A multi index container holding DHCPv6 leases.
bool isLFCRunning() const
Checks if the process performing lease file cleanup is running.
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:284
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition: dhcpsrv_log.h:38
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery4(const SubnetID &subnet_id) override
Creates and runs the IPv4 lease stats query for a single subnet.
Lease4Storage::index< ExpirationIndexTag >::type Lease4StorageExpirationIndex
DHCPv4 lease storage index by expiration time.
static const int MINOR_VERSION_V4
the minor version of the v4 memfile backend
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_EXECUTE
const isc::log::MessageID DHCPSRV_MEMFILE_ROLLBACK
const isc::log::MessageID DHCPSRV_MEMFILE_GET_ADDR4
virtual std::string getDescription() const override
Returns description of the backend.
IPv4 lease.
Definition: lease.h:50
virtual std::string checkLimits6(isc::data::ConstElementPtr const &user_context) const override
Checks if the IPv6 lease limits set in the given user context are exceeded.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED6
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HOSTNAME4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID6
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HOSTNAME6
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:514
int version()
returns Kea hooks version.
virtual LeaseStatsQueryPtr startLeaseStatsQuery6() override
Creates and runs the IPv6 lease stats query.
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_ADDR
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery4(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id) override
Creates and runs the IPv4 lease stats query for a single subnet.
Lease6Storage::index< HostnameIndexTag >::type Lease6StorageHostnameIndex
DHCPv6 lease storage index by hostname.
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_UNREGISTER_TIMER_FAILED
std::string getParameter(const std::string &name) const
Returns value of a connection parameter.
virtual LeaseStatsQueryPtr startLeaseStatsQuery4() override
Creates and runs the IPv4 lease stats query.
virtual void writeLeases6(const std::string &filename) override
Write V6 leases to a file.
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:661
virtual bool isJsonSupported() const override
Checks if JSON support is enabled in the database.
Tag for index using DUID.
void addLease(LeasePtr lease)
Increment the counts for all of a lease&#39;s classes by one.
virtual size_t wipeLeases6(const SubnetID &subnet_id) override
Removed specified IPv6 leases.
MemfileLeaseStatsQuery()
Constructor for all subnets query.
virtual Lease6Collection getLeases6ByRelayId(const DUID &relay_id, const asiolink::IOAddress &link_addr, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size) override
Returns existing IPv6 leases with a given relay-id.
MemfileLeaseStatsQuery4(Lease4Storage &storage4, const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for a subnet range query.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED6
Tag for indexes by HW address, subnet identifier tuple.
virtual void updateLease6(const Lease6Ptr &lease6) override
Updates IPv6 lease.
const std::vector< uint8_t > & getDuid() const
Returns a const reference to the actual DUID value.
Definition: duid.cc:46
the lease contains non-temporary IPv6 address
Definition: lease.h:47
Memfile derivation of the IPv4 statistical lease data query.
const isc::log::MessageID DHCPSRV_MEMFILE_GET4
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const override
Returns existing IPv6 lease for a given IPv6 address.
Invalid address family used as input to Lease Manager.
Definition: db_exceptions.h:59
std::string getLeaseFilePath(Universe u) const
Returns an absolute path to the lease file.
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-lfc.
bool persistLeases(Universe u) const
Specifies whether or not leases are written to disk.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const override
Returns existing IPv4 lease for specified IPv4 address.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_ADDR6
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_RENAME_FAIL
void clear()
Remove all entries.
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START
Tag for indexes by address.
const isc::log::MessageID DHCPSRV_MEMFILE_COMMIT
std::string getDefaultLeaseFilePath(Universe u) const
Returns default path to the lease file.
virtual ~MemfileLeaseStatsQuery6()
Destructor.
virtual void recountClassLeases6() override
Recount the leases per class for V6 leases.
virtual size_t wipeLeases4(const SubnetID &subnet_id) override
Removes specified IPv4 leases.
Type
Type of lease or pool.
Definition: lease.h:46
Lease6Storage::index< ExpirationIndexTag >::type Lease6StorageExpirationIndex
DHCPv6 lease storage index by expiration time.
Holds Client identifier or client IPv4 address.
Definition: duid.h:111
static const int MAJOR_VERSION_V4
A generic exception that is thrown if a function is called in a prohibited way.
Provides input/output access to CSV files.
Definition: csv_file.h:358
MemfileLeaseStatsQuery6(Lease6Storage &storage6)
Constructor.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_SPAWN_FAIL
Hardware type that represents information from DHCPv4 packet.
Definition: hwaddr.h:20
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition: dhcpsrv_log.h:26
Base Memfile derivation of the statistical lease data query.
static const uint32_t STATE_DEFAULT
A lease in the default state.
Definition: lease.h:69
const isc::log::MessageID DHCPSRV_MEMFILE_GET_PAGE4
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES4_FINISHED
Tag for indexes by client and subnet identifiers.
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
static const uint32_t STATE_DECLINED
Declined lease.
Definition: lease.h:72
Contains a single row of lease statistical data.
Definition: lease_mgr.h:62
std::vector< LeaseStatsRow > rows_
A vector containing the "result set".
void execute()
Spawns a new process.
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
Definition: duid.cc:75
MemfileLeaseStatsQuery4(Lease4Storage &storage4, const SubnetID &subnet_id)
Constructor for a single subnet query.
Wraps value holding size of the page with leases.
Definition: lease_mgr.h:44
const isc::log::MessageID DHCPSRV_MEMFILE_NO_STORAGE
uint32_t valid_lft_
Valid lifetime.
Definition: lease.h:125
std::string ClientClass
Defines a single class name.
Definition: classify.h:42
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Tag for indexes by subnet-id.
virtual ~MemfileLeaseStatsQuery()
Destructor.
Lease4Storage::index< ClientIdSubnetIdIndexTag >::type Lease4StorageClientIdSubnetIdIndex
DHCPv4 lease storage index by client and subnet identifier.
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_REOPEN_FAIL
virtual bool addLease(const Lease4Ptr &lease) override
Adds an IPv4 lease.
boost::shared_ptr< CSVLeaseFile6 > lease_file6_
Holds the pointer to the DHCPv6 lease file IO.
virtual void start()
Creates the IPv6 lease statistical data result set.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery6(const SubnetID &subnet_id) override
Creates and runs the IPv6 lease stats query for a single subnet.
int getLFCExitStatus() const
Returns the status code returned by the last executed LFC process.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED4
virtual void clearClassLeaseCounts() override
Clears the class-lease count map.
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:503
static const int MINOR_VERSION_V6
the minor version of the v6 memfile backend
Provides methods to access CSV file with DHCPv6 leases.
static std::string appendSuffix(const std::string &file_name, const LFCFileType &file_type)
Appends appropriate suffix to the file name.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID_CLIENTID
MemfileLeaseStatsQuery4(Lease4Storage &storage4)
Constructor for an all subnets query.
int getRowCount() const
Returns the number of rows in the result set.
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
Definition: duid.cc:122
std::string toText(bool include_htype=true) const
Returns textual representation of a hardware address (e.g.
Definition: hwaddr.cc:51
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:24
virtual bool deleteLease(const Lease4Ptr &lease) override
Deletes an IPv4 lease.
Lease6Storage::index< SubnetIdIndexTag >::type Lease6StorageSubnetIdIndex
DHCPv6 lease storage index by Subnet-id.
virtual void rollback() override
Rollback Transactions.
Exception thrown when an error occurs during CSV file processing.
Definition: csv_file.h:22
int check() const
Read the PID in from the file and check it.
Definition: pid_file.cc:26