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