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