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