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