Kea  2.1.7-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>
18 #include <util/pid_file.h>
19 #include <cstdio>
20 #include <cstring>
21 #include <errno.h>
22 #include <iostream>
23 #include <limits>
24 #include <sstream>
25 
26 namespace {
27 
35 const char* KEA_LFC_EXECUTABLE_ENV_NAME = "KEA_LFC_EXECUTABLE";
36 
37 } // namespace
38 
39 using namespace isc::asiolink;
40 using namespace isc::db;
41 using namespace isc::util;
42 
44 
45 namespace isc {
46 namespace dhcp {
47 
62 class LFCSetup {
63 public:
64 
73 
77  ~LFCSetup();
78 
90  void setup(const uint32_t lfc_interval,
91  const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
92  const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
93  bool run_once_now = false);
94 
96  void execute();
97 
101  bool isRunning() const;
102 
104  int getExitStatus() const;
105 
106 private:
107 
110  boost::scoped_ptr<ProcessSpawn> process_;
111 
114 
116  pid_t pid_;
117 
122  TimerMgrPtr timer_mgr_;
123 };
124 
125 LFCSetup::LFCSetup(asiolink::IntervalTimer::Callback callback)
126  : process_(), callback_(callback), pid_(0),
127  timer_mgr_(TimerMgr::instance()) {
128 }
129 
131  try {
132  // Remove the timer. This will throw an exception if the timer does not
133  // exist. There are several possible reasons for this:
134  // a) It hasn't been registered (although if the LFC Setup instance
135  // exists it means that the timer must have been registered or that
136  // such registration has been attempted).
137  // b) The registration may fail if the duplicate timer exists or if the
138  // TimerMgr's worker thread is running but if this happens it is a
139  // programming error.
140  // c) The program is shutting down and the timer has been removed by
141  // another component.
142  timer_mgr_->unregisterTimer("memfile-lfc");
143 
144  } catch (const std::exception& ex) {
145  // We don't want exceptions being thrown from the destructor so we just
146  // log a message here. The message is logged at debug severity as
147  // we don't want an error message output during shutdown.
150  }
151 }
152 
153 void
154 LFCSetup::setup(const uint32_t lfc_interval,
155  const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
156  const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
157  bool run_once_now) {
158 
159  // If to nothing to do, punt
160  if (lfc_interval == 0 && !run_once_now) {
161  return;
162  }
163 
164  // Start preparing the command line for kea-lfc.
165  std::string executable;
166  char* c_executable = getenv(KEA_LFC_EXECUTABLE_ENV_NAME);
167  if (c_executable == NULL) {
168  executable = KEA_LFC_EXECUTABLE;
169  } else {
170  executable = c_executable;
171  }
172 
173  // Gather the base file name.
174  std::string lease_file = lease_file4 ? lease_file4->getFilename() :
175  lease_file6->getFilename();
176 
177  // Create the other names by appending suffixes to the base name.
178  ProcessArgs args;
179  // Universe: v4 or v6.
180  args.push_back(lease_file4 ? "-4" : "-6");
181 
182  // Previous file.
183  args.push_back("-x");
184  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
186  // Input file.
187  args.push_back("-i");
188  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
190  // Output file.
191  args.push_back("-o");
192  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
194  // Finish file.
195  args.push_back("-f");
196  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
198  // PID file.
199  args.push_back("-p");
200  args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
202 
203  // The configuration file is currently unused.
204  args.push_back("-c");
205  args.push_back("ignored-path");
206 
207  // Create the process (do not start it yet).
208  process_.reset(new ProcessSpawn(LeaseMgr::getIOService(), executable, args));
209 
210  // If we've been told to run it once now, invoke the callback directly.
211  if (run_once_now) {
212  callback_();
213  }
214 
215  // If it's supposed to run periodically, setup that now.
216  if (lfc_interval > 0) {
217  // Set the timer to call callback function periodically.
219 
220  // Multiple the lfc_interval value by 1000 as this value specifies
221  // a timeout in seconds, whereas the setup() method expects the
222  // timeout in milliseconds.
223  timer_mgr_->registerTimer("memfile-lfc", callback_, lfc_interval * 1000,
225  timer_mgr_->setup("memfile-lfc");
226  }
227 }
228 
229 void
231  try {
233  .arg(process_->getCommandLine());
234  pid_ = process_->spawn();
235 
236  } catch (const ProcessSpawnError&) {
238  }
239 }
240 
241 bool
243  return (process_ && process_->isRunning(pid_));
244 }
245 
246 int
248  if (!process_) {
249  isc_throw(InvalidOperation, "unable to obtain LFC process exit code: "
250  " the process is NULL");
251  }
252  return (process_->getExitStatus(pid_));
253 }
254 
255 
262 public:
266  : rows_(0), next_pos_(rows_.end()) {
267  };
268 
273  : LeaseStatsQuery(subnet_id), rows_(0), next_pos_(rows_.end()) {
274  };
275 
280  MemfileLeaseStatsQuery(const SubnetID& first_subnet_id, const SubnetID& last_subnet_id)
281  : LeaseStatsQuery(first_subnet_id, last_subnet_id), rows_(0), next_pos_(rows_.end()) {
282  };
283 
286 
297  virtual bool getNextRow(LeaseStatsRow& row) {
298  if (next_pos_ == rows_.end()) {
299  return (false);
300  }
301 
302  row = *next_pos_;
303  ++next_pos_;
304  return (true);
305  }
306 
308  int getRowCount() const {
309  return (rows_.size());
310  }
311 
312 protected:
314  std::vector<LeaseStatsRow> rows_;
315 
317  std::vector<LeaseStatsRow>::iterator next_pos_;
318 };
319 
330 public:
335  : MemfileLeaseStatsQuery(), storage4_(storage4) {
336  };
337 
342  MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& subnet_id)
343  : MemfileLeaseStatsQuery(subnet_id), storage4_(storage4) {
344  };
345 
351  MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& first_subnet_id,
352  const SubnetID& last_subnet_id)
353  : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage4_(storage4) {
354  };
355 
358 
373  void start() {
374  const Lease4StorageSubnetIdIndex& idx
375  = storage4_.get<SubnetIdIndexTag>();
376 
377  // Set lower and upper bounds based on select mode
378  Lease4StorageSubnetIdIndex::const_iterator lower;
379  Lease4StorageSubnetIdIndex::const_iterator upper;
380  switch (getSelectMode()) {
381  case ALL_SUBNETS:
382  lower = idx.begin();
383  upper = idx.end();
384  break;
385 
386  case SINGLE_SUBNET:
387  lower = idx.lower_bound(getFirstSubnetID());
388  upper = idx.upper_bound(getFirstSubnetID());
389  break;
390 
391  case SUBNET_RANGE:
392  lower = idx.lower_bound(getFirstSubnetID());
393  upper = idx.upper_bound(getLastSubnetID());
394  break;
395  }
396 
397  // Return an empty set if there are no rows.
398  if (lower == upper) {
399  return;
400  }
401 
402  // Iterate over the leases in order by subnet, accumulating per
403  // subnet counts for each state of interest. As we finish each
404  // subnet, add the appropriate rows to our result set.
405  SubnetID cur_id = 0;
406  int64_t assigned = 0;
407  int64_t declined = 0;
408  for (Lease4StorageSubnetIdIndex::const_iterator lease = lower;
409  lease != upper; ++lease) {
410  // If we've hit the next subnet, add rows for the current subnet
411  // and wipe the accumulators
412  if ((*lease)->subnet_id_ != cur_id) {
413  if (cur_id > 0) {
414  if (assigned > 0) {
415  rows_.push_back(LeaseStatsRow(cur_id,
417  assigned));
418  assigned = 0;
419  }
420 
421  if (declined > 0) {
422  rows_.push_back(LeaseStatsRow(cur_id,
424  declined));
425  declined = 0;
426  }
427  }
428 
429  // Update current subnet id
430  cur_id = (*lease)->subnet_id_;
431  }
432 
433  // Bump the appropriate accumulator
434  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
435  ++assigned;
436  } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
437  ++declined;
438  }
439  }
440 
441  // Make the rows for last subnet
442  if (assigned > 0) {
443  rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
444  assigned));
445  }
446 
447  if (declined > 0) {
448  rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
449  declined));
450  }
451 
452  // Reset the next row position back to the beginning of the rows.
453  next_pos_ = rows_.begin();
454  }
455 
456 private:
458  Lease4Storage& storage4_;
459 };
460 
461 
472 public:
477  : MemfileLeaseStatsQuery(), storage6_(storage6) {
478  };
479 
484  MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& subnet_id)
485  : MemfileLeaseStatsQuery(subnet_id), storage6_(storage6) {
486  };
487 
493  MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& first_subnet_id,
494  const SubnetID& last_subnet_id)
495  : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage6_(storage6) {
496  };
497 
500 
514  virtual void start() {
515  // Get the subnet_id index
516  const Lease6StorageSubnetIdIndex& idx
517  = storage6_.get<SubnetIdIndexTag>();
518 
519  // Set lower and upper bounds based on select mode
520  Lease6StorageSubnetIdIndex::const_iterator lower;
521  Lease6StorageSubnetIdIndex::const_iterator upper;
522  switch (getSelectMode()) {
523  case ALL_SUBNETS:
524  lower = idx.begin();
525  upper = idx.end();
526  break;
527 
528  case SINGLE_SUBNET:
529  lower = idx.lower_bound(getFirstSubnetID());
530  upper = idx.upper_bound(getFirstSubnetID());
531  break;
532 
533  case SUBNET_RANGE:
534  lower = idx.lower_bound(getFirstSubnetID());
535  upper = idx.upper_bound(getLastSubnetID());
536  break;
537  }
538 
539  // Return an empty set if there are no rows.
540  if (lower == upper) {
541  return;
542  }
543 
544  // Iterate over the leases in order by subnet, accumulating per
545  // subnet counts for each state of interest. As we finish each
546  // subnet, add the appropriate rows to our result set.
547  SubnetID cur_id = 0;
548  int64_t assigned = 0;
549  int64_t declined = 0;
550  int64_t assigned_pds = 0;
551  for (Lease6StorageSubnetIdIndex::const_iterator lease = lower;
552  lease != upper; ++lease) {
553  // If we've hit the next subnet, add rows for the current subnet
554  // and wipe the accumulators
555  if ((*lease)->subnet_id_ != cur_id) {
556  if (cur_id > 0) {
557  if (assigned > 0) {
558  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
560  assigned));
561  assigned = 0;
562  }
563 
564  if (declined > 0) {
565  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
567  declined));
568  declined = 0;
569  }
570 
571  if (assigned_pds > 0) {
572  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
574  assigned_pds));
575  assigned_pds = 0;
576  }
577  }
578 
579  // Update current subnet id
580  cur_id = (*lease)->subnet_id_;
581  }
582 
583  // Bump the appropriate accumulator
584  if ((*lease)->state_ == Lease::STATE_DEFAULT) {
585  switch((*lease)->type_) {
586  case Lease::TYPE_NA:
587  ++assigned;
588  break;
589  case Lease::TYPE_PD:
590  ++assigned_pds;
591  break;
592  default:
593  break;
594  }
595  } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
596  // In theory only NAs can be declined
597  if (((*lease)->type_) == Lease::TYPE_NA) {
598  ++declined;
599  }
600  }
601  }
602 
603  // Make the rows for last subnet, unless there were no rows
604  if (assigned > 0) {
605  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
606  Lease::STATE_DEFAULT, assigned));
607  }
608 
609  if (declined > 0) {
610  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
611  Lease::STATE_DECLINED, declined));
612  }
613 
614  if (assigned_pds > 0) {
615  rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
616  Lease::STATE_DEFAULT, assigned_pds));
617  }
618 
619  // Set the next row position to the beginning of the rows.
620  next_pos_ = rows_.begin();
621  }
622 
623 private:
625  Lease6Storage& storage6_;
626 };
627 
628 // Explicit definition of class static constants. Values are given in the
629 // declaration so they're not needed here.
634 
636  : LeaseMgr(), lfc_setup_(), conn_(parameters), mutex_(new std::mutex) {
637  bool conversion_needed = false;
638 
639  // Check the universe and use v4 file or v6 file.
640  std::string universe = conn_.getParameter("universe");
641  if (universe == "4") {
642  std::string file4 = initLeaseFilePath(V4);
643  if (!file4.empty()) {
644  conversion_needed = loadLeasesFromFiles<Lease4,
645  CSVLeaseFile4>(file4,
646  lease_file4_,
647  storage4_);
648  }
649  } else {
650  std::string file6 = initLeaseFilePath(V6);
651  if (!file6.empty()) {
652  conversion_needed = loadLeasesFromFiles<Lease6,
653  CSVLeaseFile6>(file6,
654  lease_file6_,
655  storage6_);
656  }
657  }
658 
659  // If lease persistence have been disabled for both v4 and v6,
660  // issue a warning. It is ok not to write leases to disk when
661  // doing testing, but it should not be done in normal server
662  // operation.
663  if (!persistLeases(V4) && !persistLeases(V6)) {
665  } else {
666  if (conversion_needed) {
667  auto const& version(getVersion());
669  .arg(version.first).arg(version.second);
670  }
671  lfcSetup(conversion_needed);
672  }
673 }
674 
676  if (lease_file4_) {
677  lease_file4_->close();
678  lease_file4_.reset();
679  }
680  if (lease_file6_) {
681  lease_file6_->close();
682  lease_file6_.reset();
683  }
684 }
685 
686 std::string
688  std::stringstream tmp;
689  tmp << "Memfile backend ";
690  if (u == V4) {
691  tmp << MAJOR_VERSION_V4 << "." << MINOR_VERSION_V4;
692  } else if (u == V6) {
693  tmp << MAJOR_VERSION_V6 << "." << MINOR_VERSION_V6;
694  }
695  return tmp.str();
696 }
697 
698 bool
699 Memfile_LeaseMgr::addLeaseInternal(const Lease4Ptr& lease) {
700  if (getLease4Internal(lease->addr_)) {
701  // there is a lease with specified address already
702  return (false);
703  }
704 
705  // Try to write a lease to disk first. If this fails, the lease will
706  // not be inserted to the memory and the disk and in-memory data will
707  // remain consistent.
708  if (persistLeases(V4)) {
709  lease_file4_->append(*lease);
710  }
711 
712  storage4_.insert(lease);
713 
714  // Update lease current expiration time (allows update between the creation
715  // of the Lease up to the point of insertion in the database).
716  lease->updateCurrentExpirationTime();
717 
718  return (true);
719 }
720 
721 bool
724  DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
725 
726  if (MultiThreadingMgr::instance().getMode()) {
727  std::lock_guard<std::mutex> lock(*mutex_);
728  return (addLeaseInternal(lease));
729  } else {
730  return (addLeaseInternal(lease));
731  }
732 }
733 
734 bool
735 Memfile_LeaseMgr::addLeaseInternal(const Lease6Ptr& lease) {
736  if (getLease6Internal(lease->type_, lease->addr_)) {
737  // there is a lease with specified address already
738  return (false);
739  }
740 
741  // Try to write a lease to disk first. If this fails, the lease will
742  // not be inserted to the memory and the disk and in-memory data will
743  // remain consistent.
744  if (persistLeases(V6)) {
745  lease_file6_->append(*lease);
746  }
747 
748  storage6_.insert(lease);
749 
750  // Update lease current expiration time (allows update between the creation
751  // of the Lease up to the point of insertion in the database).
752  lease->updateCurrentExpirationTime();
753 
754  return (true);
755 }
756 
757 bool
760  DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
761 
762  if (MultiThreadingMgr::instance().getMode()) {
763  std::lock_guard<std::mutex> lock(*mutex_);
764  return (addLeaseInternal(lease));
765  } else {
766  return (addLeaseInternal(lease));
767  }
768 }
769 
770 Lease4Ptr
771 Memfile_LeaseMgr::getLease4Internal(const isc::asiolink::IOAddress& addr) const {
772  const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
773  Lease4StorageAddressIndex::iterator l = idx.find(addr);
774  if (l == idx.end()) {
775  return (Lease4Ptr());
776  } else {
777  return (Lease4Ptr(new Lease4(**l)));
778  }
779 }
780 
781 Lease4Ptr
784  DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
785 
786  if (MultiThreadingMgr::instance().getMode()) {
787  std::lock_guard<std::mutex> lock(*mutex_);
788  return (getLease4Internal(addr));
789  } else {
790  return (getLease4Internal(addr));
791  }
792 }
793 
794 void
795 Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
796  Lease4Collection& collection) const {
797  // Using composite index by 'hw address' and 'subnet id'. It is
798  // ok to use it for searching by the 'hw address' only.
800  storage4_.get<HWAddressSubnetIdIndexTag>();
801  std::pair<Lease4StorageHWAddressSubnetIdIndex::const_iterator,
802  Lease4StorageHWAddressSubnetIdIndex::const_iterator> l
803  = idx.equal_range(boost::make_tuple(hwaddr.hwaddr_));
804 
805  for (auto lease = l.first; lease != l.second; ++lease) {
806  collection.push_back(Lease4Ptr(new Lease4(**lease)));
807  }
808 }
809 
811 Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr) const {
813  DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.toText());
814 
815  Lease4Collection collection;
816  if (MultiThreadingMgr::instance().getMode()) {
817  std::lock_guard<std::mutex> lock(*mutex_);
818  getLease4Internal(hwaddr, collection);
819  } else {
820  getLease4Internal(hwaddr, collection);
821  }
822 
823  return (collection);
824 }
825 
826 Lease4Ptr
827 Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
828  SubnetID subnet_id) const {
829  // Get the index by HW Address and Subnet Identifier.
831  storage4_.get<HWAddressSubnetIdIndexTag>();
832  // Try to find the lease using HWAddr and subnet id.
833  Lease4StorageHWAddressSubnetIdIndex::const_iterator lease =
834  idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
835  // Lease was not found. Return empty pointer to the caller.
836  if (lease == idx.end()) {
837  return (Lease4Ptr());
838  }
839 
840  // Lease was found. Return it to the caller.
841  return (Lease4Ptr(new Lease4(**lease)));
842 }
843 
844 Lease4Ptr
846  SubnetID subnet_id) const {
848  DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
849  .arg(hwaddr.toText());
850 
851  if (MultiThreadingMgr::instance().getMode()) {
852  std::lock_guard<std::mutex> lock(*mutex_);
853  return (getLease4Internal(hwaddr, subnet_id));
854  } else {
855  return (getLease4Internal(hwaddr, subnet_id));
856  }
857 }
858 
859 void
860 Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
861  Lease4Collection& collection) const {
862  // Using composite index by 'client id' and 'subnet id'. It is ok
863  // to use it to search by 'client id' only.
865  storage4_.get<ClientIdSubnetIdIndexTag>();
866  std::pair<Lease4StorageClientIdSubnetIdIndex::const_iterator,
867  Lease4StorageClientIdSubnetIdIndex::const_iterator> l
868  = idx.equal_range(boost::make_tuple(client_id.getClientId()));
869 
870  for (auto lease = l.first; lease != l.second; ++lease) {
871  collection.push_back(Lease4Ptr(new Lease4(**lease)));
872  }
873 }
874 
876 Memfile_LeaseMgr::getLease4(const ClientId& client_id) const {
878  DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.toText());
879 
880  Lease4Collection collection;
881  if (MultiThreadingMgr::instance().getMode()) {
882  std::lock_guard<std::mutex> lock(*mutex_);
883  getLease4Internal(client_id, collection);
884  } else {
885  getLease4Internal(client_id, collection);
886  }
887 
888  return (collection);
889 }
890 
891 Lease4Ptr
892 Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
893  SubnetID subnet_id) const {
894  // Get the index by client and subnet id.
896  storage4_.get<ClientIdSubnetIdIndexTag>();
897  // Try to get the lease using client id and subnet id.
898  Lease4StorageClientIdSubnetIdIndex::const_iterator lease =
899  idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
900  // Lease was not found. Return empty pointer to the caller.
901  if (lease == idx.end()) {
902  return (Lease4Ptr());
903  }
904  // Lease was found. Return it to the caller.
905  return (Lease4Ptr(new Lease4(**lease)));
906 }
907 
908 Lease4Ptr
910  SubnetID subnet_id) const {
912  DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id)
913  .arg(client_id.toText());
914 
915  if (MultiThreadingMgr::instance().getMode()) {
916  std::lock_guard<std::mutex> lock(*mutex_);
917  return (getLease4Internal(client_id, subnet_id));
918  } else {
919  return (getLease4Internal(client_id, subnet_id));
920  }
921 }
922 
923 void
924 Memfile_LeaseMgr::getLeases4Internal(SubnetID subnet_id,
925  Lease4Collection& collection) const {
926  const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
927  std::pair<Lease4StorageSubnetIdIndex::const_iterator,
928  Lease4StorageSubnetIdIndex::const_iterator> l =
929  idx.equal_range(subnet_id);
930 
931  for (auto lease = l.first; lease != l.second; ++lease) {
932  collection.push_back(Lease4Ptr(new Lease4(**lease)));
933  }
934 }
935 
939  .arg(subnet_id);
940 
941  Lease4Collection collection;
942  if (MultiThreadingMgr::instance().getMode()) {
943  std::lock_guard<std::mutex> lock(*mutex_);
944  getLeases4Internal(subnet_id, collection);
945  } else {
946  getLeases4Internal(subnet_id, collection);
947  }
948 
949  return (collection);
950 }
951 
952 void
953 Memfile_LeaseMgr::getLeases4Internal(const std::string& hostname,
954  Lease4Collection& collection) const {
955  const Lease4StorageHostnameIndex& idx = storage4_.get<HostnameIndexTag>();
956  std::pair<Lease4StorageHostnameIndex::const_iterator,
957  Lease4StorageHostnameIndex::const_iterator> l =
958  idx.equal_range(hostname);
959 
960  for (auto lease = l.first; lease != l.second; ++lease) {
961  collection.push_back(Lease4Ptr(new Lease4(**lease)));
962  }
963 }
964 
966 Memfile_LeaseMgr::getLeases4(const std::string& hostname) const {
968  .arg(hostname);
969 
970  Lease4Collection collection;
971  if (MultiThreadingMgr::instance().getMode()) {
972  std::lock_guard<std::mutex> lock(*mutex_);
973  getLeases4Internal(hostname, collection);
974  } else {
975  getLeases4Internal(hostname, collection);
976  }
977 
978  return (collection);
979 }
980 
981 void
982 Memfile_LeaseMgr::getLeases4Internal(Lease4Collection& collection) const {
983  for (auto lease = storage4_.begin(); lease != storage4_.end(); ++lease) {
984  collection.push_back(Lease4Ptr(new Lease4(**lease)));
985  }
986 }
987 
991 
992  Lease4Collection collection;
993  if (MultiThreadingMgr::instance().getMode()) {
994  std::lock_guard<std::mutex> lock(*mutex_);
995  getLeases4Internal(collection);
996  } else {
997  getLeases4Internal(collection);
998  }
999 
1000  return (collection);
1001 }
1002 
1003 void
1004 Memfile_LeaseMgr::getLeases4Internal(const asiolink::IOAddress& lower_bound_address,
1005  const LeasePageSize& page_size,
1006  Lease4Collection& collection) const {
1007  const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1008  Lease4StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1009 
1010  // Exclude the lower bound address specified by the caller.
1011  if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1012  ++lb;
1013  }
1014 
1015  // Return all other leases being within the page size.
1016  for (auto lease = lb;
1017  (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1018  ++lease) {
1019  collection.push_back(Lease4Ptr(new Lease4(**lease)));
1020  }
1021 }
1022 
1025  const LeasePageSize& page_size) const {
1026  // Expecting IPv4 address.
1027  if (!lower_bound_address.isV4()) {
1028  isc_throw(InvalidAddressFamily, "expected IPv4 address while "
1029  "retrieving leases from the lease database, got "
1030  << lower_bound_address);
1031  }
1032 
1034  .arg(page_size.page_size_)
1035  .arg(lower_bound_address.toText());
1036 
1037  Lease4Collection collection;
1038  if (MultiThreadingMgr::instance().getMode()) {
1039  std::lock_guard<std::mutex> lock(*mutex_);
1040  getLeases4Internal(lower_bound_address, page_size, collection);
1041  } else {
1042  getLeases4Internal(lower_bound_address, page_size, collection);
1043  }
1044 
1045  return (collection);
1046 }
1047 
1048 Lease6Ptr
1049 Memfile_LeaseMgr::getLease6Internal(Lease::Type type,
1050  const isc::asiolink::IOAddress& addr) const {
1051  Lease6Storage::iterator l = storage6_.find(addr);
1052  if (l == storage6_.end() || !(*l) || ((*l)->type_ != type)) {
1053  return (Lease6Ptr());
1054  } else {
1055  return (Lease6Ptr(new Lease6(**l)));
1056  }
1057 }
1058 
1059 Lease6Ptr
1061  const isc::asiolink::IOAddress& addr) const {
1064  .arg(addr.toText())
1065  .arg(Lease::typeToText(type));
1066 
1067  if (MultiThreadingMgr::instance().getMode()) {
1068  std::lock_guard<std::mutex> lock(*mutex_);
1069  return (getLease6Internal(type, addr));
1070  } else {
1071  return (getLease6Internal(type, addr));
1072  }
1073 }
1074 
1075 void
1076 Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1077  const DUID& duid,
1078  uint32_t iaid,
1079  Lease6Collection& collection) const {
1080  // Get the index by DUID, IAID, lease type.
1081  const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1082  // Try to get the lease using the DUID, IAID and lease type.
1083  std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1084  Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1085  idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1086 
1087  for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1088  l.first; lease != l.second; ++lease) {
1089  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1090  }
1091 }
1092 
1095  const DUID& duid,
1096  uint32_t iaid) const {
1099  .arg(iaid)
1100  .arg(duid.toText())
1101  .arg(Lease::typeToText(type));
1102 
1103  Lease6Collection collection;
1104  if (MultiThreadingMgr::instance().getMode()) {
1105  std::lock_guard<std::mutex> lock(*mutex_);
1106  getLeases6Internal(type, duid, iaid, collection);
1107  } else {
1108  getLeases6Internal(type, duid, iaid, collection);
1109  }
1110 
1111  return (collection);
1112 }
1113 
1114 void
1115 Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1116  const DUID& duid,
1117  uint32_t iaid,
1118  SubnetID subnet_id,
1119  Lease6Collection& collection) const {
1120  // Get the index by DUID, IAID, lease type.
1121  const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1122  // Try to get the lease using the DUID, IAID and lease type.
1123  std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1124  Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1125  idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1126 
1127  for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1128  l.first; lease != l.second; ++lease) {
1129  // Filter out the leases which subnet id doesn't match.
1130  if ((*lease)->subnet_id_ == subnet_id) {
1131  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1132  }
1133  }
1134 }
1135 
1138  const DUID& duid,
1139  uint32_t iaid,
1140  SubnetID subnet_id) const {
1143  .arg(iaid)
1144  .arg(subnet_id)
1145  .arg(duid.toText())
1146  .arg(Lease::typeToText(type));
1147 
1148  Lease6Collection collection;
1149  if (MultiThreadingMgr::instance().getMode()) {
1150  std::lock_guard<std::mutex> lock(*mutex_);
1151  getLeases6Internal(type, duid, iaid, subnet_id, collection);
1152  } else {
1153  getLeases6Internal(type, duid, iaid, subnet_id, collection);
1154  }
1155 
1156  return (collection);
1157 }
1158 
1159 void
1160 Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1161  Lease6Collection& collection) const {
1162  const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1163  std::pair<Lease6StorageSubnetIdIndex::const_iterator,
1164  Lease6StorageSubnetIdIndex::const_iterator> l =
1165  idx.equal_range(subnet_id);
1166 
1167  for (auto lease = l.first; lease != l.second; ++lease) {
1168  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1169  }
1170 }
1171 
1175  .arg(subnet_id);
1176 
1177  Lease6Collection collection;
1178  if (MultiThreadingMgr::instance().getMode()) {
1179  std::lock_guard<std::mutex> lock(*mutex_);
1180  getLeases6Internal(subnet_id, collection);
1181  } else {
1182  getLeases6Internal(subnet_id, collection);
1183  }
1184 
1185  return (collection);
1186 }
1187 
1188 void
1189 Memfile_LeaseMgr::getLeases6Internal(const std::string& hostname,
1190  Lease6Collection& collection) const {
1191  const Lease6StorageHostnameIndex& idx = storage6_.get<HostnameIndexTag>();
1192  std::pair<Lease6StorageHostnameIndex::const_iterator,
1193  Lease6StorageHostnameIndex::const_iterator> l =
1194  idx.equal_range(hostname);
1195 
1196  for (auto lease = l.first; lease != l.second; ++lease) {
1197  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1198  }
1199 }
1200 
1202 Memfile_LeaseMgr::getLeases6(const std::string& hostname) const {
1204  .arg(hostname);
1205 
1206  Lease6Collection collection;
1207  if (MultiThreadingMgr::instance().getMode()) {
1208  std::lock_guard<std::mutex> lock(*mutex_);
1209  getLeases6Internal(hostname, collection);
1210  } else {
1211  getLeases6Internal(hostname, collection);
1212  }
1213 
1214  return (collection);
1215 }
1216 
1217 void
1218 Memfile_LeaseMgr::getLeases6Internal(Lease6Collection& collection) const {
1219  for (auto lease = storage6_.begin(); lease != storage6_.end(); ++lease) {
1220  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1221  }
1222 }
1223 
1227 
1228  Lease6Collection collection;
1229  if (MultiThreadingMgr::instance().getMode()) {
1230  std::lock_guard<std::mutex> lock(*mutex_);
1231  getLeases6Internal(collection);
1232  } else {
1233  getLeases6Internal(collection);
1234  }
1235 
1236  return (collection);
1237 }
1238 
1239 void
1240 Memfile_LeaseMgr::getLeases6Internal(const DUID& duid,
1241  Lease6Collection& collection) const {
1242  const Lease6StorageDuidIndex& idx = storage6_.get<DuidIndexTag>();
1243  std::pair<Lease6StorageDuidIndex::const_iterator,
1244  Lease6StorageDuidIndex::const_iterator> l =
1245  idx.equal_range(duid.getDuid());
1246 
1247  for (auto lease = l.first; lease != l.second; ++lease) {
1248  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1249  }
1250 }
1251 
1255  .arg(duid.toText());
1256 
1257  Lease6Collection collection;
1258  if (MultiThreadingMgr::instance().getMode()) {
1259  std::lock_guard<std::mutex> lock(*mutex_);
1260  getLeases6Internal(duid, collection);
1261  } else {
1262  getLeases6Internal(duid, collection);
1263  }
1264 
1265  return (collection);
1266 }
1267 
1268 void
1269 Memfile_LeaseMgr::getLeases6Internal(const asiolink::IOAddress& lower_bound_address,
1270  const LeasePageSize& page_size,
1271  Lease6Collection& collection) const {
1272  const Lease6StorageAddressIndex& idx = storage6_.get<AddressIndexTag>();
1273  Lease6StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1274 
1275  // Exclude the lower bound address specified by the caller.
1276  if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1277  ++lb;
1278  }
1279 
1280  // Return all other leases being within the page size.
1281  for (auto lease = lb;
1282  (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1283  ++lease) {
1284  collection.push_back(Lease6Ptr(new Lease6(**lease)));
1285  }
1286 }
1287 
1290  const LeasePageSize& page_size) const {
1291  // Expecting IPv6 address.
1292  if (!lower_bound_address.isV6()) {
1293  isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1294  "retrieving leases from the lease database, got "
1295  << lower_bound_address);
1296  }
1297 
1299  .arg(page_size.page_size_)
1300  .arg(lower_bound_address.toText());
1301 
1302  Lease6Collection collection;
1303  if (MultiThreadingMgr::instance().getMode()) {
1304  std::lock_guard<std::mutex> lock(*mutex_);
1305  getLeases6Internal(lower_bound_address, page_size, collection);
1306  } else {
1307  getLeases6Internal(lower_bound_address, page_size, collection);
1308  }
1309 
1310  return (collection);
1311 }
1312 
1313 void
1314 Memfile_LeaseMgr::getExpiredLeases4Internal(Lease4Collection& expired_leases,
1315  const size_t max_leases) const {
1316  // Obtain the index which segragates leases by state and time.
1317  const Lease4StorageExpirationIndex& index = storage4_.get<ExpirationIndexTag>();
1318 
1319  // Retrieve leases which are not reclaimed and which haven't expired. The
1320  // 'less-than' operator will be used for both components of the index. So,
1321  // for the 'state' 'false' is less than 'true'. Also the leases with
1322  // expiration time lower than current time will be returned.
1323  Lease4StorageExpirationIndex::const_iterator ub =
1324  index.upper_bound(boost::make_tuple(false, time(NULL)));
1325 
1326  // Copy only the number of leases indicated by the max_leases parameter.
1327  for (Lease4StorageExpirationIndex::const_iterator lease = index.begin();
1328  (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1329  max_leases));
1330  ++lease) {
1331  expired_leases.push_back(Lease4Ptr(new Lease4(**lease)));
1332  }
1333 }
1334 
1335 void
1337  const size_t max_leases) const {
1339  .arg(max_leases);
1340 
1341  if (MultiThreadingMgr::instance().getMode()) {
1342  std::lock_guard<std::mutex> lock(*mutex_);
1343  getExpiredLeases4Internal(expired_leases, max_leases);
1344  } else {
1345  getExpiredLeases4Internal(expired_leases, max_leases);
1346  }
1347 }
1348 
1349 void
1350 Memfile_LeaseMgr::getExpiredLeases6Internal(Lease6Collection& expired_leases,
1351  const size_t max_leases) const {
1352  // Obtain the index which segragates leases by state and time.
1353  const Lease6StorageExpirationIndex& index = storage6_.get<ExpirationIndexTag>();
1354 
1355  // Retrieve leases which are not reclaimed and which haven't expired. The
1356  // 'less-than' operator will be used for both components of the index. So,
1357  // for the 'state' 'false' is less than 'true'. Also the leases with
1358  // expiration time lower than current time will be returned.
1359  Lease6StorageExpirationIndex::const_iterator ub =
1360  index.upper_bound(boost::make_tuple(false, time(NULL)));
1361 
1362  // Copy only the number of leases indicated by the max_leases parameter.
1363  for (Lease6StorageExpirationIndex::const_iterator lease = index.begin();
1364  (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1365  max_leases));
1366  ++lease) {
1367  expired_leases.push_back(Lease6Ptr(new Lease6(**lease)));
1368  }
1369 }
1370 
1371 void
1373  const size_t max_leases) const {
1375  .arg(max_leases);
1376 
1377  if (MultiThreadingMgr::instance().getMode()) {
1378  std::lock_guard<std::mutex> lock(*mutex_);
1379  getExpiredLeases6Internal(expired_leases, max_leases);
1380  } else {
1381  getExpiredLeases6Internal(expired_leases, max_leases);
1382  }
1383 }
1384 
1385 void
1386 Memfile_LeaseMgr::updateLease4Internal(const Lease4Ptr& lease) {
1387  // Obtain 'by address' index.
1388  Lease4StorageAddressIndex& index = storage4_.get<AddressIndexTag>();
1389 
1390  bool persist = persistLeases(V4);
1391 
1392  // Lease must exist if it is to be updated.
1393  Lease4StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1394  if (lease_it == index.end()) {
1395  isc_throw(NoSuchLease, "failed to update the lease with address "
1396  << lease->addr_ << " - no such lease");
1397  } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1398  ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1399  // For test purpose only: check that the lease has not changed in
1400  // the database.
1401  isc_throw(NoSuchLease, "failed to update the lease with address "
1402  << lease->addr_ << " - lease has changed in database");
1403  }
1404 
1405  // Try to write a lease to disk first. If this fails, the lease will
1406  // not be inserted to the memory and the disk and in-memory data will
1407  // remain consistent.
1408  if (persist) {
1409  lease_file4_->append(*lease);
1410  }
1411 
1412  // Update lease current expiration time.
1413  lease->updateCurrentExpirationTime();
1414 
1415  // Use replace() to re-index leases.
1416  index.replace(lease_it, Lease4Ptr(new Lease4(*lease)));
1417 }
1418 
1419 void
1422  DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
1423 
1424  if (MultiThreadingMgr::instance().getMode()) {
1425  std::lock_guard<std::mutex> lock(*mutex_);
1426  updateLease4Internal(lease);
1427  } else {
1428  updateLease4Internal(lease);
1429  }
1430 }
1431 
1432 void
1433 Memfile_LeaseMgr::updateLease6Internal(const Lease6Ptr& lease) {
1434  // Obtain 'by address' index.
1435  Lease6StorageAddressIndex& index = storage6_.get<AddressIndexTag>();
1436 
1437  bool persist = persistLeases(V6);
1438 
1439  // Lease must exist if it is to be updated.
1440  Lease6StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1441  if (lease_it == index.end()) {
1442  isc_throw(NoSuchLease, "failed to update the lease with address "
1443  << lease->addr_ << " - no such lease");
1444  } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1445  ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1446  // For test purpose only: check that the lease has not changed in
1447  // the database.
1448  isc_throw(NoSuchLease, "failed to update the lease with address "
1449  << lease->addr_ << " - lease has changed in database");
1450  }
1451 
1452  // Try to write a lease to disk first. If this fails, the lease will
1453  // not be inserted to the memory and the disk and in-memory data will
1454  // remain consistent.
1455  if (persist) {
1456  lease_file6_->append(*lease);
1457  }
1458 
1459  // Update lease current expiration time.
1460  lease->updateCurrentExpirationTime();
1461 
1462  // Use replace() to re-index leases.
1463  index.replace(lease_it, Lease6Ptr(new Lease6(*lease)));
1464 }
1465 
1466 void
1469  DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
1470 
1471  if (MultiThreadingMgr::instance().getMode()) {
1472  std::lock_guard<std::mutex> lock(*mutex_);
1473  updateLease6Internal(lease);
1474  } else {
1475  updateLease6Internal(lease);
1476  }
1477 }
1478 
1479 bool
1480 Memfile_LeaseMgr::deleteLeaseInternal(const Lease4Ptr& lease) {
1481  const isc::asiolink::IOAddress& addr = lease->addr_;
1482  Lease4Storage::iterator l = storage4_.find(addr);
1483  if (l == storage4_.end()) {
1484  // No such lease
1485  return (false);
1486  } else {
1487  if (persistLeases(V4)) {
1488  // Copy the lease. The valid lifetime needs to be modified and
1489  // we don't modify the original lease.
1490  Lease4 lease_copy = **l;
1491  // Setting valid lifetime to 0 means that lease is being
1492  // removed.
1493  lease_copy.valid_lft_ = 0;
1494  lease_file4_->append(lease_copy);
1495  } else {
1496  // For test purpose only: check that the lease has not changed in
1497  // the database.
1498  if (((*l)->cltt_ != lease->current_cltt_) ||
1499  ((*l)->valid_lft_ != lease->current_valid_lft_)) {
1500  return false;
1501  }
1502  }
1503  storage4_.erase(l);
1504  return (true);
1505  }
1506 }
1507 
1508 bool
1511  DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
1512 
1513  if (MultiThreadingMgr::instance().getMode()) {
1514  std::lock_guard<std::mutex> lock(*mutex_);
1515  return (deleteLeaseInternal(lease));
1516  } else {
1517  return (deleteLeaseInternal(lease));
1518  }
1519 }
1520 
1521 bool
1522 Memfile_LeaseMgr::deleteLeaseInternal(const Lease6Ptr& lease) {
1523  const isc::asiolink::IOAddress& addr = lease->addr_;
1524  Lease6Storage::iterator l = storage6_.find(addr);
1525  if (l == storage6_.end()) {
1526  // No such lease
1527  return (false);
1528  } else {
1529  if (persistLeases(V6)) {
1530  // Copy the lease. The lifetimes need to be modified and we
1531  // don't modify the original lease.
1532  Lease6 lease_copy = **l;
1533  // Setting lifetimes to 0 means that lease is being removed.
1534  lease_copy.valid_lft_ = 0;
1535  lease_copy.preferred_lft_ = 0;
1536  lease_file6_->append(lease_copy);
1537  } else {
1538  // For test purpose only: check that the lease has not changed in
1539  // the database.
1540  if (((*l)->cltt_ != lease->current_cltt_) ||
1541  ((*l)->valid_lft_ != lease->current_valid_lft_)) {
1542  return false;
1543  }
1544  }
1545  storage6_.erase(l);
1546  return (true);
1547  }
1548 }
1549 
1550 bool
1553  DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
1554 
1555  if (MultiThreadingMgr::instance().getMode()) {
1556  std::lock_guard<std::mutex> lock(*mutex_);
1557  return (deleteLeaseInternal(lease));
1558  } else {
1559  return (deleteLeaseInternal(lease));
1560  }
1561 }
1562 
1563 uint64_t
1567  .arg(secs);
1568 
1569  if (MultiThreadingMgr::instance().getMode()) {
1570  std::lock_guard<std::mutex> lock(*mutex_);
1571  return (deleteExpiredReclaimedLeases<
1573  >(secs, V4, storage4_, lease_file4_));
1574  } else {
1575  return (deleteExpiredReclaimedLeases<
1577  >(secs, V4, storage4_, lease_file4_));
1578  }
1579 }
1580 
1581 uint64_t
1585  .arg(secs);
1586 
1587  if (MultiThreadingMgr::instance().getMode()) {
1588  std::lock_guard<std::mutex> lock(*mutex_);
1589  return (deleteExpiredReclaimedLeases<
1591  >(secs, V6, storage6_, lease_file6_));
1592  } else {
1593  return (deleteExpiredReclaimedLeases<
1595  >(secs, V6, storage6_, lease_file6_));
1596  }
1597 }
1598 
1599 template<typename IndexType, typename LeaseType, typename StorageType,
1600  typename LeaseFileType>
1601 uint64_t
1602 Memfile_LeaseMgr::deleteExpiredReclaimedLeases(const uint32_t secs,
1603  const Universe& universe,
1604  StorageType& storage,
1605  LeaseFileType& lease_file) const {
1606  // Obtain the index which segragates leases by state and time.
1607  IndexType& index = storage.template get<ExpirationIndexTag>();
1608 
1609  // This returns the first element which is greater than the specified
1610  // tuple (true, time(NULL) - secs). However, the range between the
1611  // beginning of the index and returned element also includes all the
1612  // elements for which the first value is false (lease state is NOT
1613  // reclaimed), because false < true. All elements between the
1614  // beginning of the index and the element returned, for which the
1615  // first value is true, represent the reclaimed leases which should
1616  // be deleted, because their expiration time + secs has occurred earlier
1617  // than current time.
1618  typename IndexType::const_iterator upper_limit =
1619  index.upper_bound(boost::make_tuple(true, time(NULL) - secs));
1620 
1621  // Now, we have to exclude all elements of the index which represent
1622  // leases in the state other than reclaimed - with the first value
1623  // in the index equal to false. Note that elements in the index are
1624  // ordered from the lower to the higher ones. So, all elements with
1625  // the first value of false are placed before the elements with the
1626  // value of true. Hence, we have to find the first element which
1627  // contains value of true. The time value is the lowest possible.
1628  typename IndexType::const_iterator lower_limit =
1629  index.upper_bound(boost::make_tuple(true, std::numeric_limits<int64_t>::min()));
1630 
1631  // If there are some elements in this range, delete them.
1632  uint64_t num_leases = static_cast<uint64_t>(std::distance(lower_limit, upper_limit));
1633  if (num_leases > 0) {
1634 
1637  .arg(num_leases);
1638 
1639  // If lease persistence is enabled, we also have to mark leases
1640  // as deleted in the lease file. We do this by setting the
1641  // lifetime to 0.
1642  if (persistLeases(universe)) {
1643  for (typename IndexType::const_iterator lease = lower_limit;
1644  lease != upper_limit; ++lease) {
1645  // Copy lease to not affect the lease in the container.
1646  LeaseType lease_copy(**lease);
1647  // Set the valid lifetime to 0 to indicate the removal
1648  // of the lease.
1649  lease_copy.valid_lft_ = 0;
1650  lease_file->append(lease_copy);
1651  }
1652  }
1653 
1654  // Erase leases from memory.
1655  index.erase(lower_limit, upper_limit);
1656  }
1657  // Return number of leases deleted.
1658  return (num_leases);
1659 }
1660 
1661 
1662 std::string
1664  return (std::string("In memory database with leases stored in a CSV file."));
1665 }
1666 
1667 std::pair<uint32_t, uint32_t>
1669  std::string const& universe(conn_.getParameter("universe"));
1670  if (universe == "4") {
1671  return std::make_pair(MAJOR_VERSION_V4, MINOR_VERSION_V4);
1672  } else if (universe == "6") {
1673  return std::make_pair(MAJOR_VERSION_V6, MINOR_VERSION_V6);
1674  }
1675  isc_throw(BadValue, "cannot determine version for universe " << universe);
1676 }
1677 
1678 void
1681 }
1682 
1683 void
1687 }
1688 
1689 std::string
1690 Memfile_LeaseMgr::appendSuffix(const std::string& file_name,
1691  const LFCFileType& file_type) {
1692  std::string name(file_name);
1693  switch (file_type) {
1694  case FILE_INPUT:
1695  name += ".1";
1696  break;
1697  case FILE_PREVIOUS:
1698  name += ".2";
1699  break;
1700  case FILE_OUTPUT:
1701  name += ".output";
1702  break;
1703  case FILE_FINISH:
1704  name += ".completed";
1705  break;
1706  case FILE_PID:
1707  name += ".pid";
1708  break;
1709  default:
1710  // Do not append any suffix for the FILE_CURRENT.
1711  ;
1712  }
1713 
1714  return (name);
1715 }
1716 
1717 std::string
1719  std::ostringstream s;
1720  s << CfgMgr::instance().getDataDir() << "/kea-leases";
1721  s << (u == V4 ? "4" : "6");
1722  s << ".csv";
1723  return (s.str());
1724 }
1725 
1726 std::string
1728  if (u == V4) {
1729  return (lease_file4_ ? lease_file4_->getFilename() : "");
1730  }
1731 
1732  return (lease_file6_ ? lease_file6_->getFilename() : "");
1733 }
1734 
1735 bool
1737  // Currently, if the lease file IO is not created, it means that writes to
1738  // disk have been explicitly disabled by the administrator. At some point,
1739  // there may be a dedicated ON/OFF flag implemented to control this.
1740  if (u == V4 && lease_file4_) {
1741  return (true);
1742  }
1743 
1744  return (u == V6 && lease_file6_);
1745 }
1746 
1747 std::string
1748 Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
1749  std::string persist_val;
1750  try {
1751  persist_val = conn_.getParameter("persist");
1752  } catch (const Exception&) {
1753  // If parameter persist hasn't been specified, we use a default value
1754  // 'yes'.
1755  persist_val = "true";
1756  }
1757  // If persist_val is 'false' we will not store leases to disk, so let's
1758  // return empty file name.
1759  if (persist_val == "false") {
1760  return ("");
1761 
1762  } else if (persist_val != "true") {
1763  isc_throw(isc::BadValue, "invalid value 'persist="
1764  << persist_val << "'");
1765  }
1766 
1767  std::string lease_file;
1768  try {
1769  lease_file = conn_.getParameter("name");
1770  } catch (const Exception&) {
1771  lease_file = getDefaultLeaseFilePath(u);
1772  }
1773  return (lease_file);
1774 }
1775 
1776 template<typename LeaseObjectType, typename LeaseFileType, typename StorageType>
1777 bool
1778 Memfile_LeaseMgr::loadLeasesFromFiles(const std::string& filename,
1779  boost::shared_ptr<LeaseFileType>& lease_file,
1780  StorageType& storage) {
1781  // Check if the instance of the LFC is running right now. If it is
1782  // running, we refuse to load leases as the LFC may be writing to the
1783  // lease files right now. When the user retries server configuration
1784  // it should go through.
1787  PIDFile pid_file(appendSuffix(filename, FILE_PID));
1788  if (pid_file.check()) {
1789  isc_throw(DbOpenError, "unable to load leases from files while the "
1790  "lease file cleanup is in progress");
1791  }
1792 
1793  storage.clear();
1794 
1795  std::string max_row_errors_str = "0";
1796  try {
1797  max_row_errors_str = conn_.getParameter("max-row-errors");
1798  } catch (const std::exception&) {
1799  // Ignore and default to 0.
1800  }
1801 
1802  uint32_t max_row_errors = 0;
1803  try {
1804  max_row_errors = boost::lexical_cast<uint32_t>(max_row_errors_str);
1805  } catch (const boost::bad_lexical_cast&) {
1806  isc_throw(isc::BadValue, "invalid value of the max-row-errors "
1807  << max_row_errors_str << " specified");
1808  }
1809 
1810  // Load the leasefile.completed, if exists.
1811  bool conversion_needed = false;
1812  lease_file.reset(new LeaseFileType(std::string(filename + ".completed")));
1813  if (lease_file->exists()) {
1814  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1815  max_row_errors);
1816  conversion_needed = conversion_needed || lease_file->needsConversion();
1817  } else {
1818  // If the leasefile.completed doesn't exist, let's load the leases
1819  // from leasefile.2 and leasefile.1, if they exist.
1820  lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_PREVIOUS)));
1821  if (lease_file->exists()) {
1822  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1823  max_row_errors);
1824  conversion_needed = conversion_needed || lease_file->needsConversion();
1825  }
1826 
1827  lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_INPUT)));
1828  if (lease_file->exists()) {
1829  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1830  max_row_errors);
1831  conversion_needed = conversion_needed || lease_file->needsConversion();
1832  }
1833  }
1834 
1835  // Always load leases from the primary lease file. If the lease file
1836  // doesn't exist it will be created by the LeaseFileLoader. Note
1837  // that the false value passed as the last parameter to load
1838  // function causes the function to leave the file open after
1839  // it is parsed. This file will be used by the backend to record
1840  // future lease updates.
1841  lease_file.reset(new LeaseFileType(filename));
1842  LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1843  max_row_errors, false);
1844  conversion_needed = conversion_needed || lease_file->needsConversion();
1845 
1846  return (conversion_needed);
1847 }
1848 
1849 
1850 bool
1852  return (lfc_setup_->isRunning());
1853 }
1854 
1855 int
1857  return (lfc_setup_->getExitStatus());
1858 }
1859 
1860 void
1863 
1864  // Check if we're in the v4 or v6 space and use the appropriate file.
1865  if (lease_file4_) {
1867  lfcExecute(lease_file4_);
1868  } else if (lease_file6_) {
1870  lfcExecute(lease_file6_);
1871  }
1872 }
1873 
1874 void
1875 Memfile_LeaseMgr::lfcSetup(bool conversion_needed) {
1876  std::string lfc_interval_str = "3600";
1877  try {
1878  lfc_interval_str = conn_.getParameter("lfc-interval");
1879  } catch (const std::exception&) {
1880  // Ignore and default to 3600.
1881  }
1882 
1883  uint32_t lfc_interval = 0;
1884  try {
1885  lfc_interval = boost::lexical_cast<uint32_t>(lfc_interval_str);
1886  } catch (const boost::bad_lexical_cast&) {
1887  isc_throw(isc::BadValue, "invalid value of the lfc-interval "
1888  << lfc_interval_str << " specified");
1889  }
1890 
1891  if (lfc_interval > 0 || conversion_needed) {
1892  lfc_setup_.reset(new LFCSetup(std::bind(&Memfile_LeaseMgr::lfcCallback, this)));
1893  lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_, conversion_needed);
1894  }
1895 }
1896 
1897 template<typename LeaseFileType>
1898 void
1899 Memfile_LeaseMgr::lfcExecute(boost::shared_ptr<LeaseFileType>& lease_file) {
1900  bool do_lfc = true;
1901 
1902  // Check the status of the LFC instance.
1903  // If the finish file exists or the copy of the lease file exists it
1904  // is an indication that another LFC instance may be in progress or
1905  // may be stalled. In that case we don't want to rotate the current
1906  // lease file to avoid overriding the contents of the existing file.
1907  CSVFile lease_file_finish(appendSuffix(lease_file->getFilename(), FILE_FINISH));
1908  CSVFile lease_file_copy(appendSuffix(lease_file->getFilename(), FILE_INPUT));
1909  if (!lease_file_finish.exists() && !lease_file_copy.exists()) {
1910  // Close the current file so as we can move it to the copy file.
1911  lease_file->close();
1912  // Move the current file to the copy file. Remember the result
1913  // because we don't want to run LFC if the rename failed.
1914  do_lfc = (rename(lease_file->getFilename().c_str(),
1915  lease_file_copy.getFilename().c_str()) == 0);
1916 
1917  if (!do_lfc) {
1919  .arg(lease_file->getFilename())
1920  .arg(lease_file_copy.getFilename())
1921  .arg(strerror(errno));
1922  }
1923 
1924  // Regardless if we successfully moved the current file or not,
1925  // we need to re-open the current file for the server to write
1926  // new lease updates. If the file has been successfully moved,
1927  // this will result in creation of the new file. Otherwise,
1928  // an existing file will be opened.
1929  try {
1930  lease_file->open(true);
1931 
1932  } catch (const CSVFileError& ex) {
1933  // If we're unable to open the lease file this is a serious
1934  // error because the server will not be able to persist
1935  // leases.
1943  .arg(lease_file->getFilename())
1944  .arg(ex.what());
1945  // Reset the pointer to the file so as the backend doesn't
1946  // try to write leases to disk.
1947  lease_file.reset();
1948  do_lfc = false;
1949  }
1950  }
1951  // Once the files have been rotated, or untouched if another LFC had
1952  // not finished, a new process is started.
1953  if (do_lfc) {
1954  lfc_setup_->execute();
1955  }
1956 }
1957 
1960  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_));
1961  query->start();
1962  return(query);
1963 }
1964 
1967  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, subnet_id));
1968  query->start();
1969  return(query);
1970 }
1971 
1974  const SubnetID& last_subnet_id) {
1975  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, first_subnet_id,
1976  last_subnet_id));
1977  query->start();
1978  return(query);
1979 }
1980 
1983  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_));
1984  query->start();
1985  return(query);
1986 }
1987 
1990  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, subnet_id));
1991  query->start();
1992  return(query);
1993 }
1994 
1997  const SubnetID& last_subnet_id) {
1998  LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, first_subnet_id,
1999  last_subnet_id));
2000  query->start();
2001  return(query);
2002 }
2003 
2004 size_t
2007  .arg(subnet_id);
2008 
2009  // Get the index by DUID, IAID, lease type.
2010  const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
2011 
2012  // Try to get the lease using the DUID, IAID and lease type.
2013  std::pair<Lease4StorageSubnetIdIndex::const_iterator,
2014  Lease4StorageSubnetIdIndex::const_iterator> l =
2015  idx.equal_range(subnet_id);
2016 
2017  // Let's collect all leases.
2018  Lease4Collection leases;
2019  for (auto lease = l.first; lease != l.second; ++lease) {
2020  leases.push_back(*lease);
2021  }
2022 
2023  size_t num = leases.size();
2024  for (auto l = leases.begin(); l != leases.end(); ++l) {
2025  deleteLease(*l);
2026  }
2028  .arg(subnet_id).arg(num);
2029 
2030  return (num);
2031 }
2032 
2033 size_t
2036  .arg(subnet_id);
2037 
2038  // Get the index by DUID, IAID, lease type.
2039  const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
2040 
2041  // Try to get the lease using the DUID, IAID and lease type.
2042  std::pair<Lease6StorageSubnetIdIndex::const_iterator,
2043  Lease6StorageSubnetIdIndex::const_iterator> l =
2044  idx.equal_range(subnet_id);
2045 
2046  // Let's collect all leases.
2047  Lease6Collection leases;
2048  for (auto lease = l.first; lease != l.second; ++lease) {
2049  leases.push_back(*lease);
2050  }
2051 
2052  size_t num = leases.size();
2053  for (auto l = leases.begin(); l != leases.end(); ++l) {
2054  deleteLease(*l);
2055  }
2057  .arg(subnet_id).arg(num);
2058 
2059  return (num);
2060 }
2061 
2062 std::string
2063 Memfile_LeaseMgr::checkLimits4(ConstElementPtr const& /* user_context */) const {
2064  isc_throw(NotImplemented, "Memfile_LeaseMgr::checkLimits4() not implemented");
2065 }
2066 
2067 std::string
2068 Memfile_LeaseMgr::checkLimits6(ConstElementPtr const& /* user_context */) const {
2069  isc_throw(NotImplemented, "Memfile_LeaseMgr::checkLimits6() not implemented");
2070 }
2071 
2072 bool
2074  return true;
2075 }
2076 
2077 } // namespace dhcp
2078 } // namespace isc
RAII class creating a critical section.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery6(const SubnetID &subnet_id)
Creates and runs the IPv6 lease stats query for a single subnet.
Represents a configuration for Lease File Cleanup.
virtual void rollback()
Rollback Transactions.
Tag for indexes by DUID, IAID, lease type tuple.
virtual ~MemfileLeaseStatsQuery4()
Destructor.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HWADDR
bool exists() const
Checks if the CSV file exists and can be opened for reading.
Definition: csv_file.cc:133
boost::shared_ptr< TimerMgr > TimerMgrPtr
Type definition of the shared pointer to TimerMgr.
Definition: timer_mgr.h:24
virtual ~Memfile_LeaseMgr()
Destructor (closes file)
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
A generic exception that is thrown when a function is not implemented.
const isc::log::MessageID DHCPSRV_MEMFILE_UPDATE_ADDR6
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:289
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES4
virtual std::string getDescription() const
Returns description of the backend.
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
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.
static std::string typeToText(Type type)
returns text representation of a lease type
Definition: lease.cc:52
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES6
Memfile derivation of the IPv6 statistical lease data query.
virtual size_t wipeLeases6(const SubnetID &subnet_id)
Removed specified IPv6 leases.
const isc::log::MessageID DHCPSRV_MEMFILE_GET6_DUID
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:524
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:482
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery6(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Creates and runs the IPv6 lease stats query for a single subnet.
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:48
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.
const isc::log::MessageID DHCPSRV_MEMFILE_CONVERTING_LEASE_FILES
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
virtual bool deleteLease(const Lease4Ptr &lease)
Deletes an IPv4 lease.
void start()
Creates the IPv4 lease statistical data result set.
Class to help with processing PID files.
Definition: pid_file.h:40
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
const isc::log::MessageID DHCPSRV_MEMFILE_GET_PAGE6
virtual Lease6Collection getLeases6() const
Returns all IPv6 leases.
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.
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
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery4(const SubnetID &subnet_id)
Creates and runs the IPv4 lease stats query for a single subnet.
MemfileLeaseStatsQuery6(Lease6Storage &storage6, const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for a subnet range query.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const
Returns existing IPv6 lease for a given IPv6 address.
const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR6
virtual std::pair< uint32_t, uint32_t > getVersion() const
Returns backend version.
const isc::log::MessageID DHCPSRV_MEMFILE_GET6
Lease6Storage::index< AddressIndexTag >::type Lease6StorageAddressIndex
DHCPv6 lease storage index by address.
MemfileLeaseStatsQuery6(Lease6Storage &storage6, const SubnetID &subnet_id)
Constructor for a single subnet query.
virtual LeaseStatsQueryPtr startLeaseStatsQuery6()
Creates and runs the IPv6 lease stats 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 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:278
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition: dhcpsrv_log.h:38
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
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs)
Deletes all expired-reclaimed DHCPv4 leases.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_ADDR4
virtual void commit()
Commit Transactions.
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 void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const
Returns a collection of expired DHCPv6 leases.
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:498
int version()
returns Kea hooks version.
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_ADDR
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.
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:635
bool isJsonSupported() const override
Checks if JSON support is enabled in the database.
Tag for index using DUID.
MemfileLeaseStatsQuery()
Constructor for all subnets query.
MemfileLeaseStatsQuery4(Lease4Storage &storage4, const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for a subnet range query.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED6
Tag for indexes by HW address, subnet identifier tuple.
const std::vector< uint8_t > & getDuid() const
Returns a const reference to the actual DUID value.
Definition: duid.cc:46
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery4(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Creates and runs the IPv4 lease stats query for a single subnet.
the lease contains non-temporary IPv6 address
Definition: lease.h:46
virtual size_t wipeLeases4(const SubnetID &subnet_id)
Removes specified IPv4 leases.
Memfile derivation of the IPv4 statistical lease data query.
const isc::log::MessageID DHCPSRV_MEMFILE_GET4
Invalid address family used as input to Lease Manager.
Definition: db_exceptions.h:59
virtual LeaseStatsQueryPtr startLeaseStatsQuery4()
Creates and runs the IPv4 lease stats query.
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.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_ADDR6
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_RENAME_FAIL
virtual void updateLease4(const Lease4Ptr &lease4)
Updates IPv4 lease.
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const
Returns a collection of expired DHCPv4 leases.
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.
Type
Type of lease or pool.
Definition: lease.h:45
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
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs)
Deletes all expired-reclaimed DHCPv6 leases.
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:68
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:71
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:119
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 void start()
Creates the IPv6 lease statistical data result set.
int getLFCExitStatus() const
Returns the status code returned by the last executed LFC process.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED4
virtual void updateLease6(const Lease6Ptr &lease6)
Updates IPv6 lease.
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:487
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.
virtual Lease4Collection getLeases4() const
Returns all IPv4 leases.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID_CLIENTID
MemfileLeaseStatsQuery4(Lease4Storage &storage4)
Constructor for an all subnets query.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const
Returns existing IPv4 lease for specified IPv4 address.
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
Lease6Storage::index< SubnetIdIndexTag >::type Lease6StorageSubnetIdIndex
DHCPv6 lease storage index by Subnet-id.
virtual bool addLease(const Lease4Ptr &lease)
Adds an IPv4 lease.
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