Kea 3.1.3
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
12#include <dhcpsrv/cfgmgr.h>
14#include <dhcpsrv/dhcpsrv_log.h>
17#include <dhcpsrv/timer_mgr.h>
19#include <stats/stats_mgr.h>
21#include <util/pid_file.h>
22#include <util/filesystem.h>
23
24#include <boost/foreach.hpp>
25#include <cstdio>
26#include <cstring>
27#include <errno.h>
28#include <iostream>
29#include <limits>
30#include <sstream>
31
32namespace {
33
41const char* KEA_LFC_EXECUTABLE_ENV_NAME = "KEA_LFC_EXECUTABLE";
42
43} // namespace
44
45using namespace isc::asiolink;
46using namespace isc::config;
47using namespace isc::data;
48using namespace isc::db;
49using namespace isc::util;
50using namespace isc::stats;
51using namespace isc::util::file;
52
53namespace isc {
54namespace dhcp {
55
70class LFCSetup {
71public:
72
81
85 ~LFCSetup();
86
98 void setup(const uint32_t lfc_interval,
99 const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
100 const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
101 bool run_once_now = false);
102
104 void execute(const std::string& lease_file);
105
109 bool isRunning() const;
110
112 int getExitStatus() const;
113
115 int getLastPid() const;
116
117private:
118
121 boost::scoped_ptr<ProcessSpawn> process_;
122
125
127 pid_t pid_;
128
133 TimerMgrPtr timer_mgr_;
134};
135
137 : process_(), callback_(callback), pid_(0),
138 timer_mgr_(TimerMgr::instance()) {
139}
140
142 try {
143 // Remove the timer. This will throw an exception if the timer does not
144 // exist. There are several possible reasons for this:
145 // a) It hasn't been registered (although if the LFC Setup instance
146 // exists it means that the timer must have been registered or that
147 // such registration has been attempted).
148 // b) The registration may fail if the duplicate timer exists or if the
149 // TimerMgr's worker thread is running but if this happens it is a
150 // programming error.
151 // c) The program is shutting down and the timer has been removed by
152 // another component.
153 timer_mgr_->unregisterTimer("memfile-lfc");
154
155 } catch (const std::exception& ex) {
156 // We don't want exceptions being thrown from the destructor so we just
157 // log a message here. The message is logged at debug severity as
158 // we don't want an error message output during shutdown.
161 }
162}
163
164void
165LFCSetup::setup(const uint32_t lfc_interval,
166 const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
167 const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
168 bool run_once_now) {
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
237LFCSetup::execute(const std::string& lease_file) {
238 PIDFile pid_file(Memfile_LeaseMgr::appendSuffix(lease_file,
240 try {
241 // Look at lfc.dox for a description of this.
242
243 // Try to acquire the lock for the pid file.
244 PIDLock pid_lock(pid_file.getLockname());
245
246 // Verify that no lfc is still running.
247 if (!pid_lock.isLocked() || pid_file.check()) {
249 return;
250 }
251
252 // Cleanup the state (memory leak fix).
253 if (pid_ != 0) {
254 try {
255 process_->clearState(pid_);
256 } catch (...) {
257 // Ignore errors (and keep a possible slow memory leak).
258 }
259 }
260 // Reset pid to -1.
261 pid_ = -1;
262
263 // Check the pid file is writable.
264 pid_file.write(0);
265
267 .arg(process_->getCommandLine());
268 try {
269 pid_ = process_->spawn();
270 } catch (const ProcessSpawnError&) {
272 try {
273 pid_file.deleteFile();
274 } catch (...) {
275 // Ignore errors.
276 }
277 return;
278 }
279
280 // Write the pid of the child in the pid file.
281 pid_file.write(pid_);
282
283 } catch (const PIDFileError& ex) {
285 .arg(ex.what());
286 }
287}
288
289bool
291 return (process_ && process_->isRunning(pid_));
292}
293
294int
296 if (!process_) {
297 isc_throw(InvalidOperation, "unable to obtain LFC process exit code: "
298 " the process is null");
299 }
300 return (process_->getExitStatus(pid_));
301}
302
303int
305 return (pid_);
306}
307
314public:
320 : LeaseStatsQuery(select_mode), rows_(0), next_pos_(rows_.end()) {
321 };
322
327 : LeaseStatsQuery(subnet_id), rows_(0), next_pos_(rows_.end()) {
328 };
329
334 MemfileLeaseStatsQuery(const SubnetID& first_subnet_id, const SubnetID& last_subnet_id)
335 : LeaseStatsQuery(first_subnet_id, last_subnet_id), rows_(0), next_pos_(rows_.end()) {
336 };
337
340
351 virtual bool getNextRow(LeaseStatsRow& row) {
352 if (next_pos_ == rows_.end()) {
353 return (false);
354 }
355
356 row = *next_pos_;
357 ++next_pos_;
358 return (true);
359 }
360
362 int getRowCount() const {
363 return (rows_.size());
364 }
365
366protected:
368 std::vector<LeaseStatsRow> rows_;
369
371 std::vector<LeaseStatsRow>::iterator next_pos_;
372};
373
384public:
391 const SelectMode& select_mode = ALL_SUBNETS)
392 : MemfileLeaseStatsQuery(select_mode), storage4_(storage4) {
393 };
394
399 MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& subnet_id)
400 : MemfileLeaseStatsQuery(subnet_id), storage4_(storage4) {
401 };
402
408 MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& first_subnet_id,
409 const SubnetID& last_subnet_id)
410 : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage4_(storage4) {
411 };
412
415
430 void start() {
431 switch (getSelectMode()) {
432 case ALL_SUBNETS:
433 case SINGLE_SUBNET:
434 case SUBNET_RANGE:
435 startSubnets();
436 break;
437
438 case ALL_SUBNET_POOLS:
439 startSubnetPools();
440 break;
441 }
442 }
443
444private:
459 void startSubnets() {
461 = storage4_.get<SubnetIdIndexTag>();
462
463 // Set lower and upper bounds based on select mode
464 Lease4StorageSubnetIdIndex::const_iterator lower;
465 Lease4StorageSubnetIdIndex::const_iterator upper;
466
467 switch (getSelectMode()) {
468 case ALL_SUBNETS:
469 lower = idx.begin();
470 upper = idx.end();
471 break;
472
473 case SINGLE_SUBNET:
474 lower = idx.lower_bound(getFirstSubnetID());
475 upper = idx.upper_bound(getFirstSubnetID());
476 break;
477
478 case SUBNET_RANGE:
479 lower = idx.lower_bound(getFirstSubnetID());
480 upper = idx.upper_bound(getLastSubnetID());
481 break;
482
483 default:
484 return;
485 }
486
487 // Return an empty set if there are no rows.
488 if (lower == upper) {
489 return;
490 }
491
492 // Iterate over the leases in order by subnet, accumulating per
493 // subnet counts for each state of interest. As we finish each
494 // subnet, add the appropriate rows to our result set.
495 SubnetID cur_id = 0;
496 int64_t assigned = 0;
497 int64_t declined = 0;
498 for (Lease4StorageSubnetIdIndex::const_iterator lease = lower;
499 lease != upper; ++lease) {
500 // If we've hit the next subnet, add rows for the current subnet
501 // and wipe the accumulators
502 if ((*lease)->subnet_id_ != cur_id) {
503 if (cur_id > 0) {
504 if (assigned > 0) {
505 rows_.push_back(LeaseStatsRow(cur_id,
507 assigned));
508 assigned = 0;
509 }
510
511 if (declined > 0) {
512 rows_.push_back(LeaseStatsRow(cur_id,
514 declined));
515 declined = 0;
516 }
517 }
518
519 // Update current subnet id
520 cur_id = (*lease)->subnet_id_;
521 }
522
523 // Bump the appropriate accumulator
524 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
525 ++assigned;
526 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
527 ++declined;
528 }
529 }
530
531 // Make the rows for last subnet
532 if (assigned > 0) {
533 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
534 assigned));
535 }
536
537 if (declined > 0) {
538 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
539 declined));
540 }
541
542 // Reset the next row position back to the beginning of the rows.
543 next_pos_ = rows_.begin();
544 }
545
560 void startSubnetPools() {
562 = storage4_.get<SubnetIdPoolIdIndexTag>();
563
564 // Set lower and upper bounds based on select mode
565 Lease4StorageSubnetIdPoolIdIndex::const_iterator lower;
566 Lease4StorageSubnetIdPoolIdIndex::const_iterator upper;
567 switch (getSelectMode()) {
568 case ALL_SUBNET_POOLS:
569 lower = idx.begin();
570 upper = idx.end();
571 break;
572
573 default:
574 return;
575 }
576
577 // Return an empty set if there are no rows.
578 if (lower == upper) {
579 return;
580 }
581
582 // Iterate over the leases in order by subnet and pool, accumulating per
583 // subnet and pool counts for each state of interest. As we finish each
584 // subnet or pool, add the appropriate rows to our result set.
585 SubnetID cur_id = 0;
586 uint32_t cur_pool_id = 0;
587 int64_t assigned = 0;
588 int64_t declined = 0;
589 for (Lease4StorageSubnetIdPoolIdIndex::const_iterator lease = lower;
590 lease != upper; ++lease) {
591 // If we've hit the next pool, add rows for the current subnet and
592 // pool and wipe the accumulators
593 if ((*lease)->pool_id_ != cur_pool_id) {
594 if (assigned > 0) {
595 rows_.push_back(LeaseStatsRow(cur_id,
597 assigned, cur_pool_id));
598 assigned = 0;
599 }
600
601 if (declined > 0) {
602 rows_.push_back(LeaseStatsRow(cur_id,
604 declined, cur_pool_id));
605 declined = 0;
606 }
607
608 // Update current pool id
609 cur_pool_id = (*lease)->pool_id_;
610 }
611
612 // If we've hit the next subnet, add rows for the current subnet
613 // and wipe the accumulators
614 if ((*lease)->subnet_id_ != cur_id) {
615 if (cur_id > 0) {
616 if (assigned > 0) {
617 rows_.push_back(LeaseStatsRow(cur_id,
619 assigned, cur_pool_id));
620 assigned = 0;
621 }
622
623 if (declined > 0) {
624 rows_.push_back(LeaseStatsRow(cur_id,
626 declined, cur_pool_id));
627 declined = 0;
628 }
629 }
630
631 // Update current subnet id
632 cur_id = (*lease)->subnet_id_;
633
634 // Reset pool id
635 cur_pool_id = 0;
636 }
637
638 // Bump the appropriate accumulator
639 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
640 ++assigned;
641 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
642 ++declined;
643 }
644 }
645
646 // Make the rows for last subnet
647 if (assigned > 0) {
648 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
649 assigned, cur_pool_id));
650 }
651
652 if (declined > 0) {
653 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
654 declined, cur_pool_id));
655 }
656
657 // Reset the next row position back to the beginning of the rows.
658 next_pos_ = rows_.begin();
659 }
660
662 Lease4Storage& storage4_;
663};
664
665
676public:
683 const SelectMode& select_mode = ALL_SUBNETS)
684 : MemfileLeaseStatsQuery(select_mode), storage6_(storage6) {
685 };
686
691 MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& subnet_id)
692 : MemfileLeaseStatsQuery(subnet_id), storage6_(storage6) {
693 };
694
700 MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& first_subnet_id,
701 const SubnetID& last_subnet_id)
702 : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage6_(storage6) {
703 };
704
707
723 void start() {
724 switch (getSelectMode()) {
725 case ALL_SUBNETS:
726 case SINGLE_SUBNET:
727 case SUBNET_RANGE:
728 startSubnets();
729 break;
730
731 case ALL_SUBNET_POOLS:
732 startSubnetPools();
733 break;
734 }
735 }
736
737private:
753 virtual void startSubnets() {
755 = storage6_.get<SubnetIdIndexTag>();
756
757 // Set lower and upper bounds based on select mode
758 Lease6StorageSubnetIdIndex::const_iterator lower;
759 Lease6StorageSubnetIdIndex::const_iterator upper;
760 switch (getSelectMode()) {
761 case ALL_SUBNETS:
762 lower = idx.begin();
763 upper = idx.end();
764 break;
765
766 case SINGLE_SUBNET:
767 lower = idx.lower_bound(getFirstSubnetID());
768 upper = idx.upper_bound(getFirstSubnetID());
769 break;
770
771 case SUBNET_RANGE:
772 lower = idx.lower_bound(getFirstSubnetID());
773 upper = idx.upper_bound(getLastSubnetID());
774 break;
775
776 default:
777 return;
778 }
779
780 // Return an empty set if there are no rows.
781 if (lower == upper) {
782 return;
783 }
784
785 // Iterate over the leases in order by subnet, accumulating per
786 // subnet counts for each state of interest. As we finish each
787 // subnet, add the appropriate rows to our result set.
788 SubnetID cur_id = 0;
789 int64_t assigned = 0;
790 int64_t declined = 0;
791 int64_t assigned_pds = 0;
792 int64_t registered = 0;
793 for (Lease6StorageSubnetIdIndex::const_iterator lease = lower;
794 lease != upper; ++lease) {
795 // If we've hit the next subnet, add rows for the current subnet
796 // and wipe the accumulators
797 if ((*lease)->subnet_id_ != cur_id) {
798 if (cur_id > 0) {
799 if (assigned > 0) {
800 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
802 assigned));
803 assigned = 0;
804 }
805
806 if (declined > 0) {
807 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
809 declined));
810 declined = 0;
811 }
812
813 if (assigned_pds > 0) {
814 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
816 assigned_pds));
817 assigned_pds = 0;
818 }
819
820 if (registered > 0) {
821 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
823 registered));
824 registered = 0;
825 }
826 }
827
828 // Update current subnet id
829 cur_id = (*lease)->subnet_id_;
830 }
831
832 // Bump the appropriate accumulator
833 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
834 switch((*lease)->type_) {
835 case Lease::TYPE_NA:
836 ++assigned;
837 break;
838 case Lease::TYPE_PD:
839 ++assigned_pds;
840 break;
841 default:
842 break;
843 }
844 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
845 // In theory only NAs can be declined
846 if (((*lease)->type_) == Lease::TYPE_NA) {
847 ++declined;
848 }
849 } else if ((*lease)->state_ == Lease::STATE_REGISTERED) {
850 // In theory only NAs can be registered
851 if (((*lease)->type_) == Lease::TYPE_NA) {
852 ++registered;
853 }
854 }
855 }
856
857 // Make the rows for last subnet, unless there were no rows
858 if (assigned > 0) {
859 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
860 Lease::STATE_DEFAULT, assigned));
861 }
862
863 if (declined > 0) {
864 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
865 Lease::STATE_DECLINED, declined));
866 }
867
868 if (assigned_pds > 0) {
869 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
870 Lease::STATE_DEFAULT, assigned_pds));
871 }
872
873 if (registered > 0) {
874 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
875 Lease::STATE_REGISTERED, registered));
876 }
877
878 // Set the next row position to the beginning of the rows.
879 next_pos_ = rows_.begin();
880 }
881
896 virtual void startSubnetPools() {
898 = storage6_.get<SubnetIdPoolIdIndexTag>();
899
900 // Set lower and upper bounds based on select mode
901 Lease6StorageSubnetIdPoolIdIndex::const_iterator lower;
902 Lease6StorageSubnetIdPoolIdIndex::const_iterator upper;
903 switch (getSelectMode()) {
904 case ALL_SUBNET_POOLS:
905 lower = idx.begin();
906 upper = idx.end();
907 break;
908
909 default:
910 return;
911 }
912
913 // Return an empty set if there are no rows.
914 if (lower == upper) {
915 return;
916 }
917
918 // Iterate over the leases in order by subnet, accumulating per
919 // subnet counts for each state of interest. As we finish each
920 // subnet, add the appropriate rows to our result set.
921 SubnetID cur_id = 0;
922 uint32_t cur_pool_id = 0;
923 int64_t assigned = 0;
924 int64_t declined = 0;
925 int64_t assigned_pds = 0;
926 for (Lease6StorageSubnetIdPoolIdIndex::const_iterator lease = lower;
927 lease != upper; ++lease) {
928 // If we've hit the next pool, add rows for the current subnet and
929 // pool and wipe the accumulators
930 if ((*lease)->pool_id_ != cur_pool_id) {
931 if (assigned > 0) {
932 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
934 assigned, cur_pool_id));
935 assigned = 0;
936 }
937
938 if (declined > 0) {
939 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
941 declined, cur_pool_id));
942 declined = 0;
943 }
944
945 if (assigned_pds > 0) {
946 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
948 assigned_pds, cur_pool_id));
949 assigned_pds = 0;
950 }
951
952 // Update current pool id
953 cur_pool_id = (*lease)->pool_id_;
954 }
955
956 // If we've hit the next subnet, add rows for the current subnet
957 // and wipe the accumulators
958 if ((*lease)->subnet_id_ != cur_id) {
959 if (cur_id > 0) {
960 if (assigned > 0) {
961 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
963 assigned, cur_pool_id));
964 assigned = 0;
965 }
966
967 if (declined > 0) {
968 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
970 declined, cur_pool_id));
971 declined = 0;
972 }
973
974 if (assigned_pds > 0) {
975 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
977 assigned_pds, cur_pool_id));
978 assigned_pds = 0;
979 }
980 }
981
982 // Update current subnet id
983 cur_id = (*lease)->subnet_id_;
984
985 // Reset pool id
986 cur_pool_id = 0;
987 }
988
989 // Bump the appropriate accumulator
990 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
991 switch((*lease)->type_) {
992 case Lease::TYPE_NA:
993 ++assigned;
994 break;
995 case Lease::TYPE_PD:
996 ++assigned_pds;
997 break;
998 default:
999 break;
1000 }
1001 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
1002 // In theory only NAs can be declined
1003 if (((*lease)->type_) == Lease::TYPE_NA) {
1004 ++declined;
1005 }
1006 }
1007 }
1008
1009 // Make the rows for last subnet, unless there were no rows
1010 if (assigned > 0) {
1011 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
1012 Lease::STATE_DEFAULT, assigned,
1013 cur_pool_id));
1014 }
1015
1016 if (declined > 0) {
1017 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
1018 Lease::STATE_DECLINED, declined,
1019 cur_pool_id));
1020 }
1021
1022 if (assigned_pds > 0) {
1023 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
1024 Lease::STATE_DEFAULT, assigned_pds,
1025 cur_pool_id));
1026 }
1027
1028 // Set the next row position to the beginning of the rows.
1029 next_pos_ = rows_.begin();
1030 }
1031
1033 Lease6Storage& storage6_;
1034};
1035
1036// Explicit definition of class static constants. Values are given in the
1037// declaration so they're not needed here.
1042
1044 : TrackingLeaseMgr(), lfc_setup_(), conn_(parameters), mutex_(new std::mutex) {
1045 bool conversion_needed = false;
1046
1047 // Check if the extended info tables are enabled.
1048 setExtendedInfoTablesEnabled(parameters);
1049
1050 // Check the universe and use v4 file or v6 file.
1051 std::string universe = conn_.getParameter("universe");
1052 if (universe == "4") {
1053 std::string file4 = initLeaseFilePath(V4);
1054 if (!file4.empty()) {
1055 conversion_needed = loadLeasesFromFiles<Lease4,
1056 CSVLeaseFile4>(V4, file4,
1058 storage4_);
1059 static_cast<void>(extractExtendedInfo4(false, false));
1060 }
1061 } else {
1062 std::string file6 = initLeaseFilePath(V6);
1063 if (!file6.empty()) {
1064 conversion_needed = loadLeasesFromFiles<Lease6,
1065 CSVLeaseFile6>(V6, file6,
1067 storage6_);
1069 }
1070 }
1071
1072 // If lease persistence have been disabled for both v4 and v6,
1073 // issue a warning. It is ok not to write leases to disk when
1074 // doing testing, but it should not be done in normal server
1075 // operation.
1076 if (!persistLeases(V4) && !persistLeases(V6)) {
1078 } else {
1079 if (conversion_needed) {
1080 auto const& version(getVersion());
1082 .arg(version.first).arg(version.second);
1083 }
1084 lfcSetup(conversion_needed);
1085 }
1086}
1087
1089 if (lease_file4_) {
1090 lease_file4_->close();
1091 lease_file4_.reset();
1092 }
1093 if (lease_file6_) {
1094 lease_file6_->close();
1095 lease_file6_.reset();
1096 }
1097}
1098
1099std::string
1101 std::stringstream tmp;
1102 tmp << "Memfile backend ";
1103 if (u == V4) {
1104 tmp << MAJOR_VERSION_V4 << "." << MINOR_VERSION_V4;
1105 } else if (u == V6) {
1106 tmp << MAJOR_VERSION_V6 << "." << MINOR_VERSION_V6;
1107 }
1108 return tmp.str();
1109}
1110
1111std::string
1113 uint16_t family = CfgMgr::instance().getFamily();
1114 if (family == AF_INET6) {
1116 } else {
1118 }
1119}
1120
1121bool
1122Memfile_LeaseMgr::addLeaseInternal(const Lease4Ptr& lease) {
1123 if (getLease4Internal(lease->addr_)) {
1124 // there is a lease with specified address already
1125 return (false);
1126 }
1127
1128 // Try to write a lease to disk first. If this fails, the lease will
1129 // not be inserted to the memory and the disk and in-memory data will
1130 // remain consistent.
1131 if (persistLeases(V4)) {
1132 lease_file4_->append(*lease);
1133 }
1134
1135 storage4_.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
1144 // Run installed callbacks.
1145 if (hasCallbacks()) {
1146 trackAddLease(lease);
1147 }
1148
1149 return (true);
1150}
1151
1152bool
1155 DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
1156
1157 if (MultiThreadingMgr::instance().getMode()) {
1158 std::lock_guard<std::mutex> lock(*mutex_);
1159 return (addLeaseInternal(lease));
1160 } else {
1161 return (addLeaseInternal(lease));
1162 }
1163}
1164
1165bool
1166Memfile_LeaseMgr::addLeaseInternal(const Lease6Ptr& lease) {
1167 if (getLease6Internal(lease->type_, lease->addr_)) {
1168 // there is a lease with specified address already
1169 return (false);
1170 }
1171
1172 // Try to write a lease to disk first. If this fails, the lease will
1173 // not be inserted to the memory and the disk and in-memory data will
1174 // remain consistent.
1175 if (persistLeases(V6)) {
1176 lease_file6_->append(*lease);
1177 }
1178
1179 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
1180 storage6_.insert(lease);
1181
1182 // Update lease current expiration time (allows update between the creation
1183 // of the Lease up to the point of insertion in the database).
1184 lease->updateCurrentExpirationTime();
1185
1186 // Increment class lease counters.
1187 class_lease_counter_.addLease(lease);
1188
1190 static_cast<void>(addExtendedInfo6(lease));
1191 }
1192
1193 // Run installed callbacks.
1194 if (hasCallbacks()) {
1195 trackAddLease(lease);
1196 }
1197
1198 return (true);
1199}
1200
1201bool
1204 DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
1205
1206 if (MultiThreadingMgr::instance().getMode()) {
1207 std::lock_guard<std::mutex> lock(*mutex_);
1208 return (addLeaseInternal(lease));
1209 } else {
1210 return (addLeaseInternal(lease));
1211 }
1212}
1213
1215Memfile_LeaseMgr::getLease4Internal(const isc::asiolink::IOAddress& addr) const {
1216 const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1217 Lease4StorageAddressIndex::iterator l = idx.find(addr);
1218 if (l == idx.end()) {
1219 return (Lease4Ptr());
1220 } else {
1221 return (Lease4Ptr(new Lease4(**l)));
1222 }
1223}
1224
1228 DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
1229
1230 if (MultiThreadingMgr::instance().getMode()) {
1231 std::lock_guard<std::mutex> lock(*mutex_);
1232 return (getLease4Internal(addr));
1233 } else {
1234 return (getLease4Internal(addr));
1235 }
1236}
1237
1238void
1239Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
1240 Lease4Collection& collection) const {
1241 // Using composite index by 'hw address' and 'subnet id'. It is
1242 // ok to use it for searching by the 'hw address' only.
1244 storage4_.get<HWAddressSubnetIdIndexTag>();
1245 std::pair<Lease4StorageHWAddressSubnetIdIndex::const_iterator,
1246 Lease4StorageHWAddressSubnetIdIndex::const_iterator> l
1247 = idx.equal_range(boost::make_tuple(hwaddr.hwaddr_));
1248
1249 BOOST_FOREACH(auto const& lease, l) {
1250 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1251 }
1252}
1253
1257 DHCPSRV_MEMFILE_GET_HWADDR4).arg(hwaddr.toText());
1258
1259 Lease4Collection collection;
1260 if (MultiThreadingMgr::instance().getMode()) {
1261 std::lock_guard<std::mutex> lock(*mutex_);
1262 getLease4Internal(hwaddr, collection);
1263 } else {
1264 getLease4Internal(hwaddr, collection);
1265 }
1266
1267 return (collection);
1268}
1269
1271Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
1272 SubnetID subnet_id) const {
1273 // Get the index by HW Address and Subnet Identifier.
1275 storage4_.get<HWAddressSubnetIdIndexTag>();
1276 // Try to find the lease using HWAddr and subnet id.
1277 Lease4StorageHWAddressSubnetIdIndex::const_iterator lease =
1278 idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
1279 // Lease was not found. Return empty pointer to the caller.
1280 if (lease == idx.end()) {
1281 return (Lease4Ptr());
1282 }
1283
1284 // Lease was found. Return it to the caller.
1285 return (Lease4Ptr(new Lease4(**lease)));
1286}
1287
1290 SubnetID subnet_id) const {
1292 DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
1293 .arg(hwaddr.toText());
1294
1295 if (MultiThreadingMgr::instance().getMode()) {
1296 std::lock_guard<std::mutex> lock(*mutex_);
1297 return (getLease4Internal(hwaddr, subnet_id));
1298 } else {
1299 return (getLease4Internal(hwaddr, subnet_id));
1300 }
1301}
1302
1303void
1304Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
1305 Lease4Collection& collection) const {
1306 // Using composite index by 'client id' and 'subnet id'. It is ok
1307 // to use it to search by 'client id' only.
1309 storage4_.get<ClientIdSubnetIdIndexTag>();
1310 std::pair<Lease4StorageClientIdSubnetIdIndex::const_iterator,
1311 Lease4StorageClientIdSubnetIdIndex::const_iterator> l
1312 = idx.equal_range(boost::make_tuple(client_id.getClientId()));
1313
1314 BOOST_FOREACH(auto const& lease, l) {
1315 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1316 }
1317}
1318
1320Memfile_LeaseMgr::getLease4(const ClientId& client_id) const {
1322 DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.toText());
1323
1324 Lease4Collection collection;
1325 if (MultiThreadingMgr::instance().getMode()) {
1326 std::lock_guard<std::mutex> lock(*mutex_);
1327 getLease4Internal(client_id, collection);
1328 } else {
1329 getLease4Internal(client_id, collection);
1330 }
1331
1332 return (collection);
1333}
1334
1336Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
1337 SubnetID subnet_id) const {
1338 // Get the index by client and subnet id.
1340 storage4_.get<ClientIdSubnetIdIndexTag>();
1341 // Try to get the lease using client id and subnet id.
1342 Lease4StorageClientIdSubnetIdIndex::const_iterator lease =
1343 idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
1344 // Lease was not found. Return empty pointer to the caller.
1345 if (lease == idx.end()) {
1346 return (Lease4Ptr());
1347 }
1348 // Lease was found. Return it to the caller.
1349 return (Lease4Ptr(new Lease4(**lease)));
1350}
1351
1354 SubnetID subnet_id) const {
1357 .arg(client_id.toText());
1358
1359 if (MultiThreadingMgr::instance().getMode()) {
1360 std::lock_guard<std::mutex> lock(*mutex_);
1361 return (getLease4Internal(client_id, subnet_id));
1362 } else {
1363 return (getLease4Internal(client_id, subnet_id));
1364 }
1365}
1366
1367void
1368Memfile_LeaseMgr::getLeases4Internal(SubnetID subnet_id,
1369 Lease4Collection& collection) const {
1370 const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
1371 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
1372 Lease4StorageSubnetIdIndex::const_iterator> l =
1373 idx.equal_range(subnet_id);
1374
1375 BOOST_FOREACH(auto const& lease, l) {
1376 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1377 }
1378}
1379
1383 .arg(subnet_id);
1384
1385 Lease4Collection collection;
1386 if (MultiThreadingMgr::instance().getMode()) {
1387 std::lock_guard<std::mutex> lock(*mutex_);
1388 getLeases4Internal(subnet_id, collection);
1389 } else {
1390 getLeases4Internal(subnet_id, collection);
1391 }
1392
1393 return (collection);
1394}
1395
1396void
1397Memfile_LeaseMgr::getLeases4Internal(const std::string& hostname,
1398 Lease4Collection& collection) const {
1399 const Lease4StorageHostnameIndex& idx = storage4_.get<HostnameIndexTag>();
1400 std::pair<Lease4StorageHostnameIndex::const_iterator,
1401 Lease4StorageHostnameIndex::const_iterator> l =
1402 idx.equal_range(hostname);
1403
1404 BOOST_FOREACH(auto const& lease, l) {
1405 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1406 }
1407}
1408
1410Memfile_LeaseMgr::getLeases4(const std::string& hostname) const {
1412 .arg(hostname);
1413
1414 Lease4Collection collection;
1415 if (MultiThreadingMgr::instance().getMode()) {
1416 std::lock_guard<std::mutex> lock(*mutex_);
1417 getLeases4Internal(hostname, collection);
1418 } else {
1419 getLeases4Internal(hostname, collection);
1420 }
1421
1422 return (collection);
1423}
1424
1425void
1426Memfile_LeaseMgr::getLeases4Internal(Lease4Collection& collection) const {
1427 for (auto const& lease : storage4_) {
1428 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1429 }
1430}
1431
1435
1436 Lease4Collection collection;
1437 if (MultiThreadingMgr::instance().getMode()) {
1438 std::lock_guard<std::mutex> lock(*mutex_);
1439 getLeases4Internal(collection);
1440 } else {
1441 getLeases4Internal(collection);
1442 }
1443
1444 return (collection);
1445}
1446
1447void
1448Memfile_LeaseMgr::getLeases4Internal(const asiolink::IOAddress& lower_bound_address,
1449 const LeasePageSize& page_size,
1450 Lease4Collection& collection) const {
1451 const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1452 Lease4StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1453
1454 // Exclude the lower bound address specified by the caller.
1455 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1456 ++lb;
1457 }
1458
1459 // Return all other leases being within the page size.
1460 for (auto lease = lb;
1461 (lease != idx.end()) &&
1462 (static_cast<size_t>(std::distance(lb, lease)) < page_size.page_size_);
1463 ++lease) {
1464 collection.push_back(Lease4Ptr(new Lease4(**lease)));
1465 }
1466}
1467
1470 const LeasePageSize& page_size) const {
1471 // Expecting IPv4 address.
1472 if (!lower_bound_address.isV4()) {
1473 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
1474 "retrieving leases from the lease database, got "
1475 << lower_bound_address);
1476 }
1477
1479 .arg(page_size.page_size_)
1480 .arg(lower_bound_address.toText());
1481
1482 Lease4Collection collection;
1483 if (MultiThreadingMgr::instance().getMode()) {
1484 std::lock_guard<std::mutex> lock(*mutex_);
1485 getLeases4Internal(lower_bound_address, page_size, collection);
1486 } else {
1487 getLeases4Internal(lower_bound_address, page_size, collection);
1488 }
1489
1490 return (collection);
1491}
1492
1494Memfile_LeaseMgr::getLease6Internal(Lease::Type type,
1495 const isc::asiolink::IOAddress& addr) const {
1496 Lease6Storage::iterator l = storage6_.find(addr);
1497 if (l == storage6_.end() || !(*l) || ((*l)->type_ != type)) {
1498 return (Lease6Ptr());
1499 } else {
1500 return (Lease6Ptr(new Lease6(**l)));
1501 }
1502}
1503
1504void
1505Memfile_LeaseMgr::getLease6Internal(const HWAddr& hwaddr,
1506 Lease6Collection& collection) const {
1507 const Lease6StorageHWAddressIndex& idx =
1508 storage6_.get<HWAddressIndexTag>();
1509 std::pair<Lease6StorageHWAddressIndex::const_iterator,
1510 Lease6StorageHWAddressIndex::const_iterator> l
1511 = idx.equal_range(hwaddr.hwaddr_);
1512
1513 BOOST_FOREACH(auto const& lease, l) {
1514 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1515 }
1516}
1517
1521 DHCPSRV_MEMFILE_GET_HWADDR6).arg(hwaddr.toText());
1522
1523 Lease6Collection collection;
1524 if (MultiThreadingMgr::instance().getMode()) {
1525 std::lock_guard<std::mutex> lock(*mutex_);
1526 getLease6Internal(hwaddr, collection);
1527 } else {
1528 getLease6Internal(hwaddr, collection);
1529 }
1530
1531 return (collection);
1532}
1533
1535Memfile_LeaseMgr::getAnyLease6Internal(const isc::asiolink::IOAddress& addr) const {
1536 Lease6Storage::iterator l = storage6_.find(addr);
1537 if (l == storage6_.end() || !(*l)) {
1538 return (Lease6Ptr());
1539 } else {
1540 return (Lease6Ptr(new Lease6(**l)));
1541 }
1542}
1543
1546 const isc::asiolink::IOAddress& addr) const {
1549 .arg(addr.toText())
1550 .arg(Lease::typeToText(type));
1551
1552 if (MultiThreadingMgr::instance().getMode()) {
1553 std::lock_guard<std::mutex> lock(*mutex_);
1554 return (getLease6Internal(type, addr));
1555 } else {
1556 return (getLease6Internal(type, addr));
1557 }
1558}
1559
1560void
1561Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1562 const DUID& duid,
1563 uint32_t iaid,
1564 Lease6Collection& collection) const {
1565 // Get the index by DUID, IAID, lease type.
1566 const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1567 // Try to get the lease using the DUID, IAID and lease type.
1568 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1569 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1570 idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1571
1572 for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1573 l.first; lease != l.second; ++lease) {
1574 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1575 }
1576}
1577
1580 const DUID& duid,
1581 uint32_t iaid) const {
1584 .arg(iaid)
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, collection);
1592 } else {
1593 getLeases6Internal(type, duid, iaid, collection);
1594 }
1595
1596 return (collection);
1597}
1598
1599void
1600Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1601 const DUID& duid,
1602 uint32_t iaid,
1603 SubnetID subnet_id,
1604 Lease6Collection& collection) const {
1605 // Get the index by DUID, IAID, lease type.
1606 const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1607 // Try to get the lease using the DUID, IAID and lease type.
1608 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1609 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1610 idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1611
1612 for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1613 l.first; lease != l.second; ++lease) {
1614 // Filter out the leases which subnet id doesn't match.
1615 if ((*lease)->subnet_id_ == subnet_id) {
1616 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1617 }
1618 }
1619}
1620
1623 const DUID& duid,
1624 uint32_t iaid,
1625 SubnetID subnet_id) const {
1628 .arg(iaid)
1629 .arg(subnet_id)
1630 .arg(duid.toText())
1631 .arg(Lease::typeToText(type));
1632
1633 Lease6Collection collection;
1634 if (MultiThreadingMgr::instance().getMode()) {
1635 std::lock_guard<std::mutex> lock(*mutex_);
1636 getLeases6Internal(type, duid, iaid, subnet_id, collection);
1637 } else {
1638 getLeases6Internal(type, duid, iaid, subnet_id, collection);
1639 }
1640
1641 return (collection);
1642}
1643
1644void
1645Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1646 Lease6Collection& collection) const {
1647 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1648 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
1649 Lease6StorageSubnetIdIndex::const_iterator> l =
1650 idx.equal_range(subnet_id);
1651
1652 BOOST_FOREACH(auto const& lease, l) {
1653 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1654 }
1655}
1656
1660 .arg(subnet_id);
1661
1662 Lease6Collection collection;
1663 if (MultiThreadingMgr::instance().getMode()) {
1664 std::lock_guard<std::mutex> lock(*mutex_);
1665 getLeases6Internal(subnet_id, collection);
1666 } else {
1667 getLeases6Internal(subnet_id, collection);
1668 }
1669
1670 return (collection);
1671}
1672
1673void
1674Memfile_LeaseMgr::getLeases6Internal(const std::string& hostname,
1675 Lease6Collection& collection) const {
1676 const Lease6StorageHostnameIndex& idx = storage6_.get<HostnameIndexTag>();
1677 std::pair<Lease6StorageHostnameIndex::const_iterator,
1678 Lease6StorageHostnameIndex::const_iterator> l =
1679 idx.equal_range(hostname);
1680
1681 BOOST_FOREACH(auto const& lease, l) {
1682 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1683 }
1684}
1685
1687Memfile_LeaseMgr::getLeases6(const std::string& hostname) const {
1689 .arg(hostname);
1690
1691 Lease6Collection collection;
1692 if (MultiThreadingMgr::instance().getMode()) {
1693 std::lock_guard<std::mutex> lock(*mutex_);
1694 getLeases6Internal(hostname, collection);
1695 } else {
1696 getLeases6Internal(hostname, collection);
1697 }
1698
1699 return (collection);
1700}
1701
1702void
1703Memfile_LeaseMgr::getLeases6Internal(Lease6Collection& collection) const {
1704 for (auto const& lease : storage6_) {
1705 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1706 }
1707}
1708
1712
1713 Lease6Collection collection;
1714 if (MultiThreadingMgr::instance().getMode()) {
1715 std::lock_guard<std::mutex> lock(*mutex_);
1716 getLeases6Internal(collection);
1717 } else {
1718 getLeases6Internal(collection);
1719 }
1720
1721 return (collection);
1722}
1723
1724void
1725Memfile_LeaseMgr::getLeases6Internal(const DUID& duid,
1726 Lease6Collection& collection) const {
1727 const Lease6StorageDuidIndex& idx = storage6_.get<DuidIndexTag>();
1728 std::pair<Lease6StorageDuidIndex::const_iterator,
1729 Lease6StorageDuidIndex::const_iterator> l =
1730 idx.equal_range(duid.getDuid());
1731
1732 BOOST_FOREACH(auto const& lease, l) {
1733 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1734 }
1735}
1736
1740 .arg(duid.toText());
1741
1742 Lease6Collection collection;
1743 if (MultiThreadingMgr::instance().getMode()) {
1744 std::lock_guard<std::mutex> lock(*mutex_);
1745 getLeases6Internal(duid, collection);
1746 } else {
1747 getLeases6Internal(duid, collection);
1748 }
1749
1750 return (collection);
1751}
1752
1753void
1754Memfile_LeaseMgr::getLeases6Internal(const asiolink::IOAddress& lower_bound_address,
1755 const LeasePageSize& page_size,
1756 Lease6Collection& collection) const {
1757 const Lease6StorageAddressIndex& idx = storage6_.get<AddressIndexTag>();
1758 Lease6StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1759
1760 // Exclude the lower bound address specified by the caller.
1761 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1762 ++lb;
1763 }
1764
1765 // Return all other leases being within the page size.
1766 for (auto lease = lb;
1767 (lease != idx.end()) &&
1768 (static_cast<size_t>(std::distance(lb, lease)) < page_size.page_size_);
1769 ++lease) {
1770 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1771 }
1772}
1773
1776 const LeasePageSize& page_size) const {
1777 // Expecting IPv6 address.
1778 if (!lower_bound_address.isV6()) {
1779 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1780 "retrieving leases from the lease database, got "
1781 << lower_bound_address);
1782 }
1783
1785 .arg(page_size.page_size_)
1786 .arg(lower_bound_address.toText());
1787
1788 Lease6Collection collection;
1789 if (MultiThreadingMgr::instance().getMode()) {
1790 std::lock_guard<std::mutex> lock(*mutex_);
1791 getLeases6Internal(lower_bound_address, page_size, collection);
1792 } else {
1793 getLeases6Internal(lower_bound_address, page_size, collection);
1794 }
1795
1796 return (collection);
1797}
1798
1800Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1801 const IOAddress& lower_bound_address,
1802 const LeasePageSize& page_size) const {
1803 Lease6Collection collection;
1804 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1805 Lease6StorageSubnetIdIndex::const_iterator lb =
1806 idx.lower_bound(boost::make_tuple(subnet_id, lower_bound_address));
1807
1808 // Exclude the lower bound address specified by the caller.
1809 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1810 ++lb;
1811 }
1812
1813 // Return all leases being within the page size.
1814 for (auto it = lb; it != idx.end(); ++it) {
1815 if ((*it)->subnet_id_ != subnet_id) {
1816 // Gone after the subnet id index.
1817 break;
1818 }
1819 collection.push_back(Lease6Ptr(new Lease6(**it)));
1820 if (collection.size() >= page_size.page_size_) {
1821 break;
1822 }
1823 }
1824 return (collection);
1825}
1826
1829 const IOAddress& lower_bound_address,
1830 const LeasePageSize& page_size) const {
1833 .arg(page_size.page_size_)
1834 .arg(lower_bound_address.toText())
1835 .arg(subnet_id);
1836
1837 // Expecting IPv6 valid address.
1838 if (!lower_bound_address.isV6()) {
1839 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1840 "retrieving leases from the lease database, got "
1841 << lower_bound_address);
1842 }
1843
1844 if (MultiThreadingMgr::instance().getMode()) {
1845 std::lock_guard<std::mutex> lock(*mutex_);
1846 return (getLeases6Internal(subnet_id,
1847 lower_bound_address,
1848 page_size));
1849 } else {
1850 return (getLeases6Internal(subnet_id,
1851 lower_bound_address,
1852 page_size));
1853 }
1854}
1855
1856void
1857Memfile_LeaseMgr::getExpiredLeases4Internal(Lease4Collection& expired_leases,
1858 const size_t max_leases) const {
1859 // Obtain the index which segragates leases by state and time.
1860 const Lease4StorageExpirationIndex& index = storage4_.get<ExpirationIndexTag>();
1861
1862 // Retrieve leases which are not reclaimed and which haven't expired. The
1863 // 'less-than' operator will be used for both components of the index. So,
1864 // for the 'state' 'false' is less than 'true'. Also the leases with
1865 // expiration time lower than current time will be returned.
1866 Lease4StorageExpirationIndex::const_iterator ub =
1867 index.upper_bound(boost::make_tuple(false, time(0)));
1868
1869 // Copy only the number of leases indicated by the max_leases parameter.
1870 for (Lease4StorageExpirationIndex::const_iterator lease = index.begin();
1871 (lease != ub) &&
1872 ((max_leases == 0) ||
1873 (static_cast<size_t>(std::distance(index.begin(), lease)) < max_leases));
1874 ++lease) {
1875 expired_leases.push_back(Lease4Ptr(new Lease4(**lease)));
1876 }
1877}
1878
1879void
1881 const size_t max_leases) const {
1883 .arg(max_leases);
1884
1885 if (MultiThreadingMgr::instance().getMode()) {
1886 std::lock_guard<std::mutex> lock(*mutex_);
1887 getExpiredLeases4Internal(expired_leases, max_leases);
1888 } else {
1889 getExpiredLeases4Internal(expired_leases, max_leases);
1890 }
1891}
1892
1893void
1894Memfile_LeaseMgr::getExpiredLeases6Internal(Lease6Collection& expired_leases,
1895 const size_t max_leases) const {
1896 // Obtain the index which segragates leases by state and time.
1897 const Lease6StorageExpirationIndex& index = storage6_.get<ExpirationIndexTag>();
1898
1899 // Retrieve leases which are not reclaimed and which haven't expired. The
1900 // 'less-than' operator will be used for both components of the index. So,
1901 // for the 'state' 'false' is less than 'true'. Also the leases with
1902 // expiration time lower than current time will be returned.
1903 Lease6StorageExpirationIndex::const_iterator ub =
1904 index.upper_bound(boost::make_tuple(false, time(0)));
1905
1906 // Copy only the number of leases indicated by the max_leases parameter.
1907 for (Lease6StorageExpirationIndex::const_iterator lease = index.begin();
1908 (lease != ub) &&
1909 ((max_leases == 0) ||
1910 (static_cast<size_t>(std::distance(index.begin(), lease)) < max_leases));
1911 ++lease) {
1912 expired_leases.push_back(Lease6Ptr(new Lease6(**lease)));
1913 }
1914}
1915
1916void
1918 const size_t max_leases) const {
1920 .arg(max_leases);
1921
1922 if (MultiThreadingMgr::instance().getMode()) {
1923 std::lock_guard<std::mutex> lock(*mutex_);
1924 getExpiredLeases6Internal(expired_leases, max_leases);
1925 } else {
1926 getExpiredLeases6Internal(expired_leases, max_leases);
1927 }
1928}
1929
1930void
1931Memfile_LeaseMgr::updateLease4Internal(const Lease4Ptr& lease) {
1932 // Obtain 'by address' index.
1933 Lease4StorageAddressIndex& index = storage4_.get<AddressIndexTag>();
1934
1935 bool persist = persistLeases(V4);
1936
1937 // Lease must exist if it is to be updated.
1938 Lease4StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1939 if (lease_it == index.end()) {
1940 isc_throw(NoSuchLease, "failed to update the lease with address "
1941 << lease->addr_ << " - no such lease");
1942 } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1943 ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1944 // For test purpose only: check that the lease has not changed in
1945 // the database.
1946 isc_throw(NoSuchLease, "unable to update lease for address " <<
1947 lease->addr_.toText() << " either because the lease does not exist, "
1948 "it has been deleted or it has changed in the database.");
1949 }
1950
1951 // Try to write a lease to disk first. If this fails, the lease will
1952 // not be inserted to the memory and the disk and in-memory data will
1953 // remain consistent.
1954 if (persist) {
1955 lease_file4_->append(*lease);
1956 }
1957
1958 // Update lease current expiration time.
1959 lease->updateCurrentExpirationTime();
1960
1961 // Save a copy of the old lease as lease_it will point to the new
1962 // one after the replacement.
1963 Lease4Ptr old_lease = *lease_it;
1964
1965 // Use replace() to re-index leases.
1966 index.replace(lease_it, Lease4Ptr(new Lease4(*lease)));
1967
1968 // Adjust class lease counters.
1969 class_lease_counter_.updateLease(lease, old_lease);
1970
1971 // Run installed callbacks.
1972 if (hasCallbacks()) {
1973 trackUpdateLease(lease);
1974 }
1975}
1976
1977void
1980 DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
1981
1982 if (MultiThreadingMgr::instance().getMode()) {
1983 std::lock_guard<std::mutex> lock(*mutex_);
1984 updateLease4Internal(lease);
1985 } else {
1986 updateLease4Internal(lease);
1987 }
1988}
1989
1990void
1991Memfile_LeaseMgr::updateLease6Internal(const Lease6Ptr& lease) {
1992 // Obtain 'by address' index.
1993 Lease6StorageAddressIndex& index = storage6_.get<AddressIndexTag>();
1994
1995 bool persist = persistLeases(V6);
1996
1997 // Get the recorded action and reset it.
1998 Lease6::ExtendedInfoAction recorded_action = lease->extended_info_action_;
1999 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
2000
2001 // Lease must exist if it is to be updated.
2002 Lease6StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
2003 if (lease_it == index.end()) {
2004 isc_throw(NoSuchLease, "failed to update the lease with address "
2005 << lease->addr_ << " - no such lease");
2006 } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
2007 ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
2008 // For test purpose only: check that the lease has not changed in
2009 // the database.
2010 isc_throw(NoSuchLease, "unable to update lease for address " <<
2011 lease->addr_.toText() << " either because the lease does not exist, "
2012 "it has been deleted or it has changed in the database.");
2013 }
2014
2015 // Try to write a lease to disk first. If this fails, the lease will
2016 // not be inserted to the memory and the disk and in-memory data will
2017 // remain consistent.
2018 if (persist) {
2019 lease_file6_->append(*lease);
2020 }
2021
2022 // Update lease current expiration time.
2023 lease->updateCurrentExpirationTime();
2024
2025 // Save a copy of the old lease as lease_it will point to the new
2026 // one after the replacement.
2027 Lease6Ptr old_lease = *lease_it;
2028
2029 // Use replace() to re-index leases.
2030 index.replace(lease_it, Lease6Ptr(new Lease6(*lease)));
2031
2032 // Adjust class lease counters.
2033 class_lease_counter_.updateLease(lease, old_lease);
2034
2035 // Update extended info tables.
2037 switch (recorded_action) {
2039 break;
2040
2042 deleteExtendedInfo6(lease->addr_);
2043 break;
2044
2046 deleteExtendedInfo6(lease->addr_);
2047 static_cast<void>(addExtendedInfo6(lease));
2048 break;
2049 }
2050 }
2051
2052 // Run installed callbacks.
2053 if (hasCallbacks()) {
2054 trackUpdateLease(lease);
2055 }
2056}
2057
2058void
2061 DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
2062
2063 if (MultiThreadingMgr::instance().getMode()) {
2064 std::lock_guard<std::mutex> lock(*mutex_);
2065 updateLease6Internal(lease);
2066 } else {
2067 updateLease6Internal(lease);
2068 }
2069}
2070
2071bool
2072Memfile_LeaseMgr::deleteLeaseInternal(const Lease4Ptr& lease) {
2073 const isc::asiolink::IOAddress& addr = lease->addr_;
2074 Lease4Storage::iterator l = storage4_.find(addr);
2075 if (l == storage4_.end()) {
2076 // No such lease
2077 return (false);
2078 } else {
2079 if (persistLeases(V4)) {
2080 // Copy the lease. The valid lifetime needs to be modified and
2081 // we don't modify the original lease.
2082 Lease4 lease_copy = **l;
2083 // Setting valid lifetime to 0 means that lease is being
2084 // removed.
2085 lease_copy.valid_lft_ = 0;
2086 lease_file4_->append(lease_copy);
2087 } else {
2088 // For test purpose only: check that the lease has not changed in
2089 // the database.
2090 if (((*l)->cltt_ != lease->current_cltt_) ||
2091 ((*l)->valid_lft_ != lease->current_valid_lft_)) {
2092 return false;
2093 }
2094 }
2095
2096 storage4_.erase(l);
2097
2098 // Decrement class lease counters.
2099 class_lease_counter_.removeLease(lease);
2100
2101 // Run installed callbacks.
2102 if (hasCallbacks()) {
2103 trackDeleteLease(lease);
2104 }
2105
2106 return (true);
2107 }
2108}
2109
2110bool
2113 DHCPSRV_MEMFILE_DELETE_ADDR4).arg(lease->addr_.toText());
2114
2115 if (MultiThreadingMgr::instance().getMode()) {
2116 std::lock_guard<std::mutex> lock(*mutex_);
2117 return (deleteLeaseInternal(lease));
2118 } else {
2119 return (deleteLeaseInternal(lease));
2120 }
2121}
2122
2123bool
2124Memfile_LeaseMgr::deleteLeaseInternal(const Lease6Ptr& lease) {
2125 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
2126
2127 const isc::asiolink::IOAddress& addr = lease->addr_;
2128 Lease6Storage::iterator l = storage6_.find(addr);
2129 if (l == storage6_.end()) {
2130 // No such lease
2131 return (false);
2132 } else {
2133 if (persistLeases(V6)) {
2134 // Copy the lease. The lifetimes need to be modified and we
2135 // don't modify the original lease.
2136 Lease6 lease_copy = **l;
2137 // Setting lifetimes to 0 means that lease is being removed.
2138 lease_copy.valid_lft_ = 0;
2139 lease_copy.preferred_lft_ = 0;
2140 lease_file6_->append(lease_copy);
2141 } else {
2142 // For test purpose only: check that the lease has not changed in
2143 // the database.
2144 if (((*l)->cltt_ != lease->current_cltt_) ||
2145 ((*l)->valid_lft_ != lease->current_valid_lft_)) {
2146 return false;
2147 }
2148 }
2149
2150 storage6_.erase(l);
2151
2152 // Decrement class lease counters.
2153 class_lease_counter_.removeLease(lease);
2154
2155 // Delete references from extended info tables.
2157 deleteExtendedInfo6(lease->addr_);
2158 }
2159
2160 // Run installed callbacks.
2161 if (hasCallbacks()) {
2162 trackDeleteLease(lease);
2163 }
2164
2165 return (true);
2166 }
2167}
2168
2169bool
2172 DHCPSRV_MEMFILE_DELETE_ADDR6).arg(lease->addr_.toText());
2173
2174 if (MultiThreadingMgr::instance().getMode()) {
2175 std::lock_guard<std::mutex> lock(*mutex_);
2176 return (deleteLeaseInternal(lease));
2177 } else {
2178 return (deleteLeaseInternal(lease));
2179 }
2180}
2181
2182uint64_t
2186 .arg(secs);
2187
2188 if (MultiThreadingMgr::instance().getMode()) {
2189 std::lock_guard<std::mutex> lock(*mutex_);
2190 return (deleteExpiredReclaimedLeases<
2192 >(secs, V4, storage4_, lease_file4_));
2193 } else {
2194 return (deleteExpiredReclaimedLeases<
2196 >(secs, V4, storage4_, lease_file4_));
2197 }
2198}
2199
2200uint64_t
2204 .arg(secs);
2205
2206 if (MultiThreadingMgr::instance().getMode()) {
2207 std::lock_guard<std::mutex> lock(*mutex_);
2208 return (deleteExpiredReclaimedLeases<
2210 >(secs, V6, storage6_, lease_file6_));
2211 } else {
2212 return (deleteExpiredReclaimedLeases<
2214 >(secs, V6, storage6_, lease_file6_));
2215 }
2216}
2217
2218template<typename IndexType, typename LeaseType, typename StorageType,
2219 typename LeaseFileType>
2220uint64_t
2221Memfile_LeaseMgr::deleteExpiredReclaimedLeases(const uint32_t secs,
2222 const Universe& universe,
2223 StorageType& storage,
2224 LeaseFileType& lease_file) {
2225 // Obtain the index which segragates leases by state and time.
2226 IndexType& index = storage.template get<ExpirationIndexTag>();
2227
2228 // This returns the first element which is greater than the specified
2229 // tuple (true, time(0) - secs). However, the range between the
2230 // beginning of the index and returned element also includes all the
2231 // elements for which the first value is false (lease state is NOT
2232 // reclaimed), because false < true. All elements between the
2233 // beginning of the index and the element returned, for which the
2234 // first value is true, represent the reclaimed leases which should
2235 // be deleted, because their expiration time + secs has occurred earlier
2236 // than current time.
2237 typename IndexType::const_iterator upper_limit =
2238 index.upper_bound(boost::make_tuple(true, time(0) - secs));
2239
2240 // Now, we have to exclude all elements of the index which represent
2241 // leases in the state other than reclaimed - with the first value
2242 // in the index equal to false. Note that elements in the index are
2243 // ordered from the lower to the higher ones. So, all elements with
2244 // the first value of false are placed before the elements with the
2245 // value of true. Hence, we have to find the first element which
2246 // contains value of true. The time value is the lowest possible.
2247 typename IndexType::const_iterator lower_limit =
2248 index.upper_bound(boost::make_tuple(true, std::numeric_limits<int64_t>::min()));
2249
2250 // If there are some elements in this range, delete them.
2251 uint64_t num_leases = static_cast<uint64_t>(std::distance(lower_limit, upper_limit));
2252 if (num_leases > 0) {
2253
2256 .arg(num_leases);
2257
2258 // If lease persistence is enabled, we also have to mark leases
2259 // as deleted in the lease file. We do this by setting the
2260 // lifetime to 0.
2261 if (persistLeases(universe)) {
2262 for (typename IndexType::const_iterator lease = lower_limit;
2263 lease != upper_limit; ++lease) {
2264 // Copy lease to not affect the lease in the container.
2265 LeaseType lease_copy(**lease);
2266 // Set the valid lifetime to 0 to indicate the removal
2267 // of the lease.
2268 lease_copy.valid_lft_ = 0;
2269 lease_file->append(lease_copy);
2270 }
2271 }
2272
2273 // Erase leases from memory.
2274 index.erase(lower_limit, upper_limit);
2275
2276 }
2277 // Return number of leases deleted.
2278 return (num_leases);
2279}
2280
2281std::string
2283 return (std::string("In memory database with leases stored in a CSV file."));
2284}
2285
2286std::pair<uint32_t, uint32_t>
2287Memfile_LeaseMgr::getVersion(const std::string& /* timer_name */) const {
2288 std::string const& universe(conn_.getParameter("universe"));
2289 if (universe == "4") {
2290 return std::make_pair(MAJOR_VERSION_V4, MINOR_VERSION_V4);
2291 } else if (universe == "6") {
2292 return std::make_pair(MAJOR_VERSION_V6, MINOR_VERSION_V6);
2293 }
2294 isc_throw(BadValue, "cannot determine version for universe " << universe);
2295}
2296
2297void
2301
2302void
2307
2308bool
2309Memfile_LeaseMgr::isLFCProcessRunning(const std::string file_name, Universe u) {
2310 std::string lease_file(file_name);
2311 if (lease_file.empty()) {
2313 }
2314 PIDFile pid_file(Memfile_LeaseMgr::appendSuffix(lease_file, FILE_PID));
2315 PIDLock pid_lock(pid_file.getLockname());
2316 return (!pid_lock.isLocked() || pid_file.check());
2317}
2318
2321 std::string file_name;
2322 if (lease_file4_) {
2323 file_name = lease_file4_->getFilename();
2324 } else if (lease_file6_) {
2325 file_name = lease_file6_->getFilename();
2326 } else {
2327 return (ElementPtr());
2328 }
2329 if (file_name.empty()) {
2330 // Should not happen.
2331 return (ElementPtr());
2332 }
2333 ElementPtr status = Element::createMap();
2334 status->set("csv-lease-file", Element::create(file_name));
2335 return (status);
2336}
2337
2338std::string
2339Memfile_LeaseMgr::appendSuffix(const std::string& file_name,
2340 const LFCFileType& file_type) {
2341 std::string name(file_name);
2342 switch (file_type) {
2343 case FILE_INPUT:
2344 name += ".1";
2345 break;
2346 case FILE_PREVIOUS:
2347 name += ".2";
2348 break;
2349 case FILE_OUTPUT:
2350 name += ".output";
2351 break;
2352 case FILE_FINISH:
2353 name += ".completed";
2354 break;
2355 case FILE_PID:
2356 name += ".pid";
2357 break;
2358 default:
2359 // Do not append any suffix for the FILE_CURRENT.
2360 ;
2361 }
2362
2363 return (name);
2364}
2365
2366std::string
2368 std::string filename /* = "" */) {
2369 std::ostringstream s;;
2371 if (filename.empty()) {
2372 s << "/kea-leases";
2373 s << (u == V4 ? "4" : "6");
2374 s << ".csv";
2375 } else {
2376 s << "/" << filename;
2377 }
2378
2379 return (s.str());
2380}
2381
2382std::string
2384 if (u == V4) {
2385 return (lease_file4_ ? lease_file4_->getFilename() : "");
2386 }
2387
2388 return (lease_file6_ ? lease_file6_->getFilename() : "");
2389}
2390
2391bool
2393 // Currently, if the lease file IO is not created, it means that writes to
2394 // disk have been explicitly disabled by the administrator. At some point,
2395 // there may be a dedicated ON/OFF flag implemented to control this.
2396 if (u == V4 && lease_file4_) {
2397 return (true);
2398 }
2399
2400 return (u == V6 && lease_file6_);
2401}
2402
2403std::string
2404Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
2405 std::string persist_val;
2406 try {
2407 persist_val = conn_.getParameter("persist");
2408 } catch (const Exception&) {
2409 // If parameter persist hasn't been specified, we use a default value
2410 // 'yes'.
2411 persist_val = "true";
2412 }
2413 // If persist_val is 'false' we will not store leases to disk, so let's
2414 // return empty file name.
2415 if (persist_val == "false") {
2416 return ("");
2417
2418 } else if (persist_val != "true") {
2419 isc_throw(isc::BadValue, "invalid value 'persist="
2420 << persist_val << "'");
2421 }
2422
2423 std::string lease_file;
2424 try {
2425 lease_file = conn_.getParameter("name");
2426 } catch (const Exception&) {
2427 // Not specified, use the default.
2429 }
2430
2431 try {
2432 lease_file = CfgMgr::instance().validatePath(lease_file);
2433 } catch (const SecurityWarn& ex) {
2435 .arg(ex.what());
2436 }
2437
2438 return (lease_file);
2439}
2440
2441template<typename LeaseObjectType, typename LeaseFileType, typename StorageType>
2442bool
2443Memfile_LeaseMgr::loadLeasesFromFiles(Universe u, const std::string& filename,
2444 boost::shared_ptr<LeaseFileType>& lease_file,
2445 StorageType& storage) {
2446 // Check if the instance of the LFC is running right now. If it is
2447 // running, we refuse to load leases as the LFC may be writing to the
2448 // lease files right now. When the user retries server configuration
2449 // it should go through.
2452 if (Memfile_LeaseMgr::isLFCProcessRunning(filename, u)) {
2453 isc_throw(DbOpenError, "unable to load leases from files while the "
2454 "lease file cleanup is in progress");
2455 }
2456
2457 storage.clear();
2458
2459 std::string max_row_errors_str = "0";
2460 try {
2461 max_row_errors_str = conn_.getParameter("max-row-errors");
2462 } catch (const std::exception&) {
2463 // Ignore and default to 0.
2464 }
2465
2466 int64_t max_row_errors64;
2467 try {
2468 max_row_errors64 = boost::lexical_cast<int64_t>(max_row_errors_str);
2469 } catch (const boost::bad_lexical_cast&) {
2470 isc_throw(isc::BadValue, "invalid value of the max-row-errors "
2471 << max_row_errors_str << " specified");
2472 }
2473 if ((max_row_errors64 < 0) ||
2474 (max_row_errors64 > std::numeric_limits<uint32_t>::max())) {
2475 isc_throw(isc::BadValue, "invalid value of the max-row-errors "
2476 << max_row_errors_str << " specified");
2477 }
2478 uint32_t max_row_errors = static_cast<uint32_t>(max_row_errors64);
2479
2480 // Load the leasefile.completed, if exists.
2481 bool conversion_needed = false;
2482 lease_file.reset(new LeaseFileType(std::string(filename + ".completed")));
2483 if (lease_file->exists()) {
2484 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2485 max_row_errors);
2486 conversion_needed = conversion_needed || lease_file->needsConversion();
2487 } else {
2488 // If the leasefile.completed doesn't exist, let's load the leases
2489 // from leasefile.2 and leasefile.1, if they exist.
2490 lease_file.reset(new LeaseFileType(Memfile_LeaseMgr::appendSuffix(filename, FILE_PREVIOUS)));
2491 if (lease_file->exists()) {
2492 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2493 max_row_errors);
2494 conversion_needed = conversion_needed || lease_file->needsConversion();
2495 }
2496
2497 lease_file.reset(new LeaseFileType(Memfile_LeaseMgr::appendSuffix(filename, FILE_INPUT)));
2498 if (lease_file->exists()) {
2499 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2500 max_row_errors);
2501 conversion_needed = conversion_needed || lease_file->needsConversion();
2502 }
2503 }
2504
2505 // Always load leases from the primary lease file. If the lease file
2506 // doesn't exist it will be created by the LeaseFileLoader. Note
2507 // that the false value passed as the last parameter to load
2508 // function causes the function to leave the file open after
2509 // it is parsed. This file will be used by the backend to record
2510 // future lease updates.
2511 lease_file.reset(new LeaseFileType(filename));
2512 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2513 max_row_errors, false);
2514 conversion_needed = conversion_needed || lease_file->needsConversion();
2515
2516 return (conversion_needed);
2517}
2518
2519bool
2521 return (lfc_setup_->isRunning());
2522}
2523
2524int
2526 return (lfc_setup_->getExitStatus());
2527}
2528
2529int
2531 return (lfc_setup_->getLastPid());
2532}
2533
2534void
2536 // Check if we're in the v4 or v6 space and use the appropriate file.
2537 if (lease_file4_) {
2539 lfcExecute(lease_file4_);
2540 } else if (lease_file6_) {
2542 lfcExecute(lease_file6_);
2543 }
2544}
2545
2546void
2547Memfile_LeaseMgr::lfcSetup(bool conversion_needed) {
2548 std::string lfc_interval_str = "3600";
2549 try {
2550 lfc_interval_str = conn_.getParameter("lfc-interval");
2551 } catch (const std::exception&) {
2552 // Ignore and default to 3600.
2553 }
2554
2555 uint32_t lfc_interval = 0;
2556 try {
2557 lfc_interval = boost::lexical_cast<uint32_t>(lfc_interval_str);
2558 } catch (const boost::bad_lexical_cast&) {
2559 isc_throw(isc::BadValue, "invalid value of the lfc-interval "
2560 << lfc_interval_str << " specified");
2561 }
2562
2563 lfc_setup_.reset(new LFCSetup(std::bind(&Memfile_LeaseMgr::lfcCallback, this)));
2564 lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_, conversion_needed);
2565}
2566
2567template<typename LeaseFileType>
2568void
2569Memfile_LeaseMgr::lfcExecute(boost::shared_ptr<LeaseFileType>& lease_file) {
2571
2572 bool do_lfc = true;
2573
2574 // Check the status of the LFC instance.
2575 // If the finish file exists or the copy of the lease file exists it
2576 // is an indication that another LFC instance may be in progress or
2577 // may be stalled. In that case we don't want to rotate the current
2578 // lease file to avoid overriding the contents of the existing file.
2579 CSVFile lease_file_finish(Memfile_LeaseMgr::appendSuffix(lease_file->getFilename(), FILE_FINISH));
2580 CSVFile lease_file_copy(Memfile_LeaseMgr::appendSuffix(lease_file->getFilename(), FILE_INPUT));
2581 if (!lease_file_finish.exists() && !lease_file_copy.exists()) {
2582 // Close the current file so as we can move it to the copy file.
2583 lease_file->close();
2584 // Move the current file to the copy file. Remember the result
2585 // because we don't want to run LFC if the rename failed.
2586 do_lfc = (rename(lease_file->getFilename().c_str(),
2587 lease_file_copy.getFilename().c_str()) == 0);
2588
2589 if (!do_lfc) {
2591 .arg(lease_file->getFilename())
2592 .arg(lease_file_copy.getFilename())
2593 .arg(strerror(errno));
2594 }
2595
2596 // Regardless if we successfully moved the current file or not,
2597 // we need to re-open the current file for the server to write
2598 // new lease updates. If the file has been successfully moved,
2599 // this will result in creation of the new file. Otherwise,
2600 // an existing file will be opened.
2601 try {
2602 lease_file->open(true);
2603
2604 } catch (const CSVFileError& ex) {
2605 // If we're unable to open the lease file this is a serious
2606 // error because the server will not be able to persist
2607 // leases.
2615 .arg(lease_file->getFilename())
2616 .arg(ex.what());
2617 // Reset the pointer to the file so as the backend doesn't
2618 // try to write leases to disk.
2619 lease_file.reset();
2620 do_lfc = false;
2621 }
2622 }
2623 // Once the files have been rotated, or untouched if another LFC had
2624 // not finished, a new process is started.
2625 if (do_lfc) {
2626 lfc_setup_->execute(lease_file->getFilename());
2627 }
2628}
2629
2632 if (!persistLeases(V4) && !persistLeases(V6)) {
2633 std::ostringstream msg;
2634 msg << "'persist' parameter of 'memfile' lease backend "
2635 << "was configured to 'false'";
2637 }
2639 // Reschedule the periodic lfc run.
2640 if (TimerMgr::instance()->isTimerRegistered("memfile-lfc")) {
2641 TimerMgr::instance()->cancel("memfile-lfc");
2642 TimerMgr::instance()->setup("memfile-lfc");
2644 }
2645 int previous_pid = getLFCLastPid();
2646 if (lease_file4_) {
2647 lfcExecute(lease_file4_);
2648 } else if (lease_file6_) {
2649 lfcExecute(lease_file6_);
2650 }
2651 int new_pid = getLFCLastPid();
2652 if (new_pid == -1) {
2653 return (createAnswer(CONTROL_RESULT_ERROR, "failed to start kea-lfc"));
2654 } else if (new_pid != previous_pid) {
2655 return (createAnswer(CONTROL_RESULT_SUCCESS, "kea-lfc started"));
2656 } else {
2657 return (createAnswer(CONTROL_RESULT_EMPTY, "kea-lfc already running"));
2658 }
2659}
2660
2663 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_));
2664 if (MultiThreadingMgr::instance().getMode()) {
2665 std::lock_guard<std::mutex> lock(*mutex_);
2666 query->start();
2667 } else {
2668 query->start();
2669 }
2670
2671 return(query);
2672}
2673
2677 if (MultiThreadingMgr::instance().getMode()) {
2678 std::lock_guard<std::mutex> lock(*mutex_);
2679 query->start();
2680 } else {
2681 query->start();
2682 }
2683
2684 return(query);
2685}
2686
2689 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, subnet_id));
2690 if (MultiThreadingMgr::instance().getMode()) {
2691 std::lock_guard<std::mutex> lock(*mutex_);
2692 query->start();
2693 } else {
2694 query->start();
2695 }
2696
2697 return(query);
2698}
2699
2702 const SubnetID& last_subnet_id) {
2703 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, first_subnet_id,
2704 last_subnet_id));
2705 if (MultiThreadingMgr::instance().getMode()) {
2706 std::lock_guard<std::mutex> lock(*mutex_);
2707 query->start();
2708 } else {
2709 query->start();
2710 }
2711
2712 return(query);
2713}
2714
2717 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_));
2718 if (MultiThreadingMgr::instance().getMode()) {
2719 std::lock_guard<std::mutex> lock(*mutex_);
2720 query->start();
2721 } else {
2722 query->start();
2723 }
2724
2725 return(query);
2726}
2727
2731 if (MultiThreadingMgr::instance().getMode()) {
2732 std::lock_guard<std::mutex> lock(*mutex_);
2733 query->start();
2734 } else {
2735 query->start();
2736 }
2737
2738 return(query);
2739}
2740
2743 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, subnet_id));
2744 if (MultiThreadingMgr::instance().getMode()) {
2745 std::lock_guard<std::mutex> lock(*mutex_);
2746 query->start();
2747 } else {
2748 query->start();
2749 }
2750
2751 return(query);
2752}
2753
2756 const SubnetID& last_subnet_id) {
2757 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, first_subnet_id,
2758 last_subnet_id));
2759 if (MultiThreadingMgr::instance().getMode()) {
2760 std::lock_guard<std::mutex> lock(*mutex_);
2761 query->start();
2762 } else {
2763 query->start();
2764 }
2765
2766 return(query);
2767}
2768
2769size_t
2772 .arg(subnet_id);
2773
2774 // Get the index by DUID, IAID, lease type.
2775 const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
2776
2777 // Try to get the lease using the DUID, IAID and lease type.
2778 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
2779 Lease4StorageSubnetIdIndex::const_iterator> r =
2780 idx.equal_range(subnet_id);
2781
2782 // Let's collect all leases.
2783 Lease4Collection leases;
2784 BOOST_FOREACH(auto const& lease, r) {
2785 leases.push_back(lease);
2786 }
2787
2788 size_t num = leases.size();
2789 for (auto const& l : leases) {
2790 deleteLease(l);
2791 }
2793 .arg(subnet_id).arg(num);
2794
2795 return (num);
2796}
2797
2798size_t
2801 .arg(subnet_id);
2802
2803 // Get the index by DUID, IAID, lease type.
2804 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
2805
2806 // Try to get the lease using the DUID, IAID and lease type.
2807 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
2808 Lease6StorageSubnetIdIndex::const_iterator> r =
2809 idx.equal_range(subnet_id);
2810
2811 // Let's collect all leases.
2812 Lease6Collection leases;
2813 BOOST_FOREACH(auto const& lease, r) {
2814 leases.push_back(lease);
2815 }
2816
2817 size_t num = leases.size();
2818 for (auto const& l : leases) {
2819 deleteLease(l);
2820 }
2822 .arg(subnet_id).arg(num);
2823
2824 return (num);
2825}
2826
2827void
2829 class_lease_counter_.clear();
2830 for (auto const& lease : storage4_) {
2831 // Bump the appropriate accumulator
2832 if (lease->state_ == Lease::STATE_DEFAULT) {
2833 class_lease_counter_.addLease(lease);
2834 }
2835 }
2836}
2837
2838void
2840 class_lease_counter_.clear();
2841 for (auto const& lease : storage6_) {
2842 // Bump the appropriate accumulator
2843 if (lease->state_ == Lease::STATE_DEFAULT) {
2844 class_lease_counter_.addLease(lease);
2845 }
2846 }
2847}
2848
2849size_t
2851 const Lease::Type& ltype /* = Lease::TYPE_V4*/) const {
2852 if (MultiThreadingMgr::instance().getMode()) {
2853 std::lock_guard<std::mutex> lock(*mutex_);
2854 return(class_lease_counter_.getClassCount(client_class, ltype));
2855 } else {
2856 return(class_lease_counter_.getClassCount(client_class, ltype));
2857 }
2858}
2859
2860void
2862 return(class_lease_counter_.clear());
2863}
2864
2865std::string
2867 if (!user_context) {
2868 return ("");
2869 }
2870
2871 ConstElementPtr limits = user_context->find("ISC/limits");
2872 if (!limits) {
2873 return ("");
2874 }
2875
2876 // Iterate of the 'client-classes' list in 'limits'. For each class that specifies
2877 // an "address-limit", check its value against the class's lease count.
2878 ConstElementPtr classes = limits->get("client-classes");
2879 if (classes) {
2880 for (unsigned i = 0; i < classes->size(); ++i) {
2881 ConstElementPtr class_elem = classes->get(i);
2882 // Get class name.
2883 ConstElementPtr name_elem = class_elem->get("name");
2884 if (!name_elem) {
2885 isc_throw(BadValue, "checkLimits4 - client-class.name is missing: "
2886 << prettyPrint(limits));
2887 }
2888
2889 std::string name = name_elem->stringValue();
2890
2891 // Now look for an address-limit
2892 size_t limit;
2893 if (!getLeaseLimit(class_elem, Lease::TYPE_V4, limit)) {
2894 // No limit, go to the next class.
2895 continue;
2896 }
2897
2898 // If the limit is > 0 look up the class lease count. Limit of 0 always
2899 // denies the lease.
2900 size_t lease_count = 0;
2901 if (limit) {
2902 lease_count = getClassLeaseCount(name);
2903 }
2904
2905 // If we're over the limit, return the error, no need to evaluate any others.
2906 if (lease_count >= limit) {
2907 std::ostringstream ss;
2908 ss << "address limit " << limit << " for client class \""
2909 << name << "\", current lease count " << lease_count;
2910 return (ss.str());
2911 }
2912 }
2913 }
2914
2915 // If there were class limits we passed them, now look for a subnet limit.
2916 ConstElementPtr subnet_elem = limits->get("subnet");
2917 if (subnet_elem) {
2918 // Get the subnet id.
2919 ConstElementPtr id_elem = subnet_elem->get("id");
2920 if (!id_elem) {
2921 isc_throw(BadValue, "checkLimits4 - subnet.id is missing: "
2922 << prettyPrint(limits));
2923 }
2924
2925 SubnetID subnet_id = id_elem->intValue();
2926
2927 // Now look for an address-limit.
2928 size_t limit;
2929 if (getLeaseLimit(subnet_elem, Lease::TYPE_V4, limit)) {
2930 // If the limit is > 0 look up the subnet lease count. Limit of 0 always
2931 // denies the lease.
2932 int64_t lease_count = 0;
2933 if (limit) {
2934 lease_count = getSubnetStat(subnet_id, "assigned-addresses");
2935 }
2936
2937 // If we're over the limit, return the error.
2938 if (static_cast<uint64_t>(lease_count) >= limit) {
2939 std::ostringstream ss;
2940 ss << "address limit " << limit << " for subnet ID " << subnet_id
2941 << ", current lease count " << lease_count;
2942 return (ss.str());
2943 }
2944 }
2945 }
2946
2947 // No limits exceeded!
2948 return ("");
2949}
2950
2951std::string
2953 if (!user_context) {
2954 return ("");
2955 }
2956
2957 ConstElementPtr limits = user_context->find("ISC/limits");
2958 if (!limits) {
2959 return ("");
2960 }
2961
2962 // Iterate over the 'client-classes' list in 'limits'. For each class that specifies
2963 // limit (either "address-limit" or "prefix-limit", check its value against the appropriate
2964 // class lease count.
2965 ConstElementPtr classes = limits->get("client-classes");
2966 if (classes) {
2967 for (unsigned i = 0; i < classes->size(); ++i) {
2968 ConstElementPtr class_elem = classes->get(i);
2969 // Get class name.
2970 ConstElementPtr name_elem = class_elem->get("name");
2971 if (!name_elem) {
2972 isc_throw(BadValue, "checkLimits6 - client-class.name is missing: "
2973 << prettyPrint(limits));
2974 }
2975
2976 std::string name = name_elem->stringValue();
2977
2978 // Now look for either address-limit or a prefix=limit.
2979 size_t limit = 0;
2981 if (!getLeaseLimit(class_elem, ltype, limit)) {
2982 ltype = Lease::TYPE_PD;
2983 if (!getLeaseLimit(class_elem, ltype, limit)) {
2984 // No limits for this class, skip to the next.
2985 continue;
2986 }
2987 }
2988
2989 // If the limit is > 0 look up the class lease count. Limit of 0 always
2990 // denies the lease.
2991 size_t lease_count = 0;
2992 if (limit) {
2993 lease_count = getClassLeaseCount(name, ltype);
2994 }
2995
2996 // If we're over the limit, return the error, no need to evaluate any others.
2997 if (lease_count >= limit) {
2998 std::ostringstream ss;
2999 ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
3000 << " limit " << limit << " for client class \""
3001 << name << "\", current lease count " << lease_count;
3002 return (ss.str());
3003 }
3004 }
3005 }
3006
3007 // If there were class limits we passed them, now look for a subnet limit.
3008 ConstElementPtr subnet_elem = limits->get("subnet");
3009 if (subnet_elem) {
3010 // Get the subnet id.
3011 ConstElementPtr id_elem = subnet_elem->get("id");
3012 if (!id_elem) {
3013 isc_throw(BadValue, "checkLimits6 - subnet.id is missing: "
3014 << prettyPrint(limits));
3015 }
3016
3017 SubnetID subnet_id = id_elem->intValue();
3018
3019 // Now look for either address-limit or a prefix=limit.
3020 size_t limit = 0;
3022 if (!getLeaseLimit(subnet_elem, ltype, limit)) {
3023 ltype = Lease::TYPE_PD;
3024 if (!getLeaseLimit(subnet_elem, ltype, limit)) {
3025 // No limits for the subnet so none exceeded!
3026 return ("");
3027 }
3028 }
3029
3030 // If the limit is > 0 look up the class lease count. Limit of 0 always
3031 // denies the lease.
3032 int64_t lease_count = 0;
3033 if (limit) {
3034 lease_count = getSubnetStat(subnet_id, (ltype == Lease::TYPE_NA ?
3035 "assigned-nas" : "assigned-pds"));
3036 }
3037
3038 // If we're over the limit, return the error.
3039 if (static_cast<uint64_t>(lease_count) >= limit) {
3040 std::ostringstream ss;
3041 ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
3042 << " limit " << limit << " for subnet ID " << subnet_id
3043 << ", current lease count " << lease_count;
3044 return (ss.str());
3045 }
3046 }
3047
3048 // No limits exceeded!
3049 return ("");
3050}
3051
3052bool
3054 return true;
3055}
3056
3057int64_t
3058Memfile_LeaseMgr::getSubnetStat(const SubnetID& subnet_id, const std::string& stat_label) const {
3061 std::string stat_name = StatsMgr::generateName("subnet", subnet_id, stat_label);
3062 ConstElementPtr stat = StatsMgr::instance().get(stat_name);
3063 ConstElementPtr samples = stat->get(stat_name);
3064 if (samples && samples->size()) {
3065 auto sample = samples->get(0);
3066 if (sample->size()) {
3067 auto count_elem = sample->get(0);
3068 return (count_elem->intValue());
3069 }
3070 }
3071
3072 return (0);
3073}
3074
3075bool
3076Memfile_LeaseMgr::getLeaseLimit(ConstElementPtr parent, Lease::Type ltype, size_t& limit) const {
3077 ConstElementPtr limit_elem = parent->get(ltype == Lease::TYPE_PD ?
3078 "prefix-limit" : "address-limit");
3079 if (limit_elem) {
3080 limit = limit_elem->intValue();
3081 return (true);
3082 }
3083
3084 return (false);
3085}
3086
3087namespace {
3088
3089std::string
3090idToText(const OptionBuffer& id) {
3091 std::stringstream tmp;
3092 tmp << std::hex;
3093 bool delim = false;
3094 for (auto const& it : id) {
3095 if (delim) {
3096 tmp << ":";
3097 }
3098 tmp << std::setw(2) << std::setfill('0')
3099 << static_cast<unsigned int>(it);
3100 delim = true;
3101 }
3102 return (tmp.str());
3103}
3104
3105} // anonymous namespace
3106
3109 const IOAddress& lower_bound_address,
3110 const LeasePageSize& page_size,
3111 const time_t& qry_start_time /* = 0 */,
3112 const time_t& qry_end_time /* = 0 */) {
3115 .arg(page_size.page_size_)
3116 .arg(lower_bound_address.toText())
3117 .arg(idToText(relay_id))
3118 .arg(qry_start_time)
3119 .arg(qry_end_time);
3120
3121 // Expecting IPv4 address.
3122 if (!lower_bound_address.isV4()) {
3123 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
3124 "retrieving leases from the lease database, got "
3125 << lower_bound_address);
3126 }
3127
3128 // Catch 2038 bug with 32 bit time_t.
3129 if ((qry_start_time < 0) || (qry_end_time < 0)) {
3130 isc_throw(BadValue, "negative time value");
3131 }
3132
3133 // Start time must be before end time.
3134 if ((qry_start_time > 0) && (qry_end_time > 0) &&
3135 (qry_start_time > qry_end_time)) {
3136 isc_throw(BadValue, "start time must be before end time");
3137 }
3138
3139 if (MultiThreadingMgr::instance().getMode()) {
3140 std::lock_guard<std::mutex> lock(*mutex_);
3141 return (getLeases4ByRelayIdInternal(relay_id,
3142 lower_bound_address,
3143 page_size,
3144 qry_start_time,
3145 qry_end_time));
3146 } else {
3147 return (getLeases4ByRelayIdInternal(relay_id,
3148 lower_bound_address,
3149 page_size,
3150 qry_start_time,
3151 qry_end_time));
3152 }
3153}
3154
3156Memfile_LeaseMgr::getLeases4ByRelayIdInternal(const OptionBuffer& relay_id,
3157 const IOAddress& lower_bound_address,
3158 const LeasePageSize& page_size,
3159 const time_t& qry_start_time,
3160 const time_t& qry_end_time) {
3161 Lease4Collection collection;
3162 const Lease4StorageRelayIdIndex& idx = storage4_.get<RelayIdIndexTag>();
3163 Lease4StorageRelayIdIndex::const_iterator lb =
3164 idx.lower_bound(boost::make_tuple(relay_id, lower_bound_address));
3165 // Return all convenient leases being within the page size.
3166 IOAddress last_addr = lower_bound_address;
3167 for (; lb != idx.end(); ++lb) {
3168 if ((*lb)->addr_ == last_addr) {
3169 // Already seen: skip it.
3170 continue;
3171 }
3172 if ((*lb)->relay_id_ != relay_id) {
3173 // Gone after the relay id index.
3174 break;
3175 }
3176 last_addr = (*lb)->addr_;
3177 if ((qry_start_time > 0) && ((*lb)->cltt_ < qry_start_time)) {
3178 // Too old.
3179 continue;
3180 }
3181 if ((qry_end_time > 0) && ((*lb)->cltt_ > qry_end_time)) {
3182 // Too young.
3183 continue;
3184 }
3185 collection.push_back(Lease4Ptr(new Lease4(**lb)));
3186 if (collection.size() >= page_size.page_size_) {
3187 break;
3188 }
3189 }
3190 return (collection);
3191}
3192
3195 const IOAddress& lower_bound_address,
3196 const LeasePageSize& page_size,
3197 const time_t& qry_start_time /* = 0 */,
3198 const time_t& qry_end_time /* = 0 */) {
3201 .arg(page_size.page_size_)
3202 .arg(lower_bound_address.toText())
3203 .arg(idToText(remote_id))
3204 .arg(qry_start_time)
3205 .arg(qry_end_time);
3206
3207 // Expecting IPv4 address.
3208 if (!lower_bound_address.isV4()) {
3209 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
3210 "retrieving leases from the lease database, got "
3211 << lower_bound_address);
3212 }
3213
3214 // Catch 2038 bug with 32 bit time_t.
3215 if ((qry_start_time < 0) || (qry_end_time < 0)) {
3216 isc_throw(BadValue, "negative time value");
3217 }
3218
3219 // Start time must be before end time.
3220 if ((qry_start_time > 0) && (qry_end_time > 0) &&
3221 (qry_start_time > qry_end_time)) {
3222 isc_throw(BadValue, "start time must be before end time");
3223 }
3224
3225 if (MultiThreadingMgr::instance().getMode()) {
3226 std::lock_guard<std::mutex> lock(*mutex_);
3227 return (getLeases4ByRemoteIdInternal(remote_id,
3228 lower_bound_address,
3229 page_size,
3230 qry_start_time,
3231 qry_end_time));
3232 } else {
3233 return (getLeases4ByRemoteIdInternal(remote_id,
3234 lower_bound_address,
3235 page_size,
3236 qry_start_time,
3237 qry_end_time));
3238 }
3239}
3240
3242Memfile_LeaseMgr::getLeases4ByRemoteIdInternal(const OptionBuffer& remote_id,
3243 const IOAddress& lower_bound_address,
3244 const LeasePageSize& page_size,
3245 const time_t& qry_start_time,
3246 const time_t& qry_end_time) {
3247 Lease4Collection collection;
3248 std::map<IOAddress, Lease4Ptr> sorted;
3249 const Lease4StorageRemoteIdIndex& idx = storage4_.get<RemoteIdIndexTag>();
3250 Lease4StorageRemoteIdRange er = idx.equal_range(remote_id);
3251 // Store all convenient leases being within the page size.
3252 BOOST_FOREACH(auto const& it, er) {
3253 const IOAddress& addr = it->addr_;
3254 if (addr <= lower_bound_address) {
3255 // Not greater than lower_bound_address.
3256 continue;
3257 }
3258 if ((qry_start_time > 0) && (it->cltt_ < qry_start_time)) {
3259 // Too old.
3260 continue;
3261 }
3262 if ((qry_end_time > 0) && (it->cltt_ > qry_end_time)) {
3263 // Too young.
3264 continue;
3265 }
3266 sorted[addr] = it;
3267 }
3268
3269 // Return all leases being within the page size.
3270 for (auto const& it : sorted) {
3271 collection.push_back(Lease4Ptr(new Lease4(*it.second)));
3272 if (collection.size() >= page_size.page_size_) {
3273 break;
3274 }
3275 }
3276 return (collection);
3277}
3278
3279void
3281 if (MultiThreadingMgr::instance().getMode()) {
3282 std::lock_guard<std::mutex> lock(*mutex_);
3283 relay_id6_.clear();
3284 remote_id6_.clear();
3285 } else {
3286 relay_id6_.clear();
3287 remote_id6_.clear();
3288 }
3289}
3290
3291size_t
3293 return (relay_id6_.size());
3294}
3295
3296size_t
3298 return (remote_id6_.size());
3299}
3300
3303 const IOAddress& lower_bound_address,
3304 const LeasePageSize& page_size) {
3307 .arg(page_size.page_size_)
3308 .arg(lower_bound_address.toText())
3309 .arg(relay_id.toText());
3310
3311 // Expecting IPv6 valid address.
3312 if (!lower_bound_address.isV6()) {
3313 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3314 "retrieving leases from the lease database, got "
3315 << lower_bound_address);
3316 }
3317
3318 if (MultiThreadingMgr::instance().getMode()) {
3319 std::lock_guard<std::mutex> lock(*mutex_);
3320 return (getLeases6ByRelayIdInternal(relay_id,
3321 lower_bound_address,
3322 page_size));
3323 } else {
3324 return (getLeases6ByRelayIdInternal(relay_id,
3325 lower_bound_address,
3326 page_size));
3327 }
3328}
3329
3331Memfile_LeaseMgr::getLeases6ByRelayIdInternal(const DUID& relay_id,
3332 const IOAddress& lower_bound_address,
3333 const LeasePageSize& page_size) {
3334 const std::vector<uint8_t>& relay_id_data = relay_id.getDuid();
3335 Lease6Collection collection;
3336 const RelayIdIndex& idx = relay_id6_.get<RelayIdIndexTag>();
3337 RelayIdIndex::const_iterator lb =
3338 idx.lower_bound(boost::make_tuple(relay_id_data, lower_bound_address));
3339
3340 // Return all leases being within the page size.
3341 IOAddress last_addr = lower_bound_address;
3342 for (; lb != idx.end(); ++lb) {
3343 if ((*lb)->lease_addr_ == last_addr) {
3344 // Already seen: skip it.
3345 continue;
3346 }
3347 if ((*lb)->id_ != relay_id_data) {
3348 // Gone after the relay id index.
3349 break;
3350 }
3351 last_addr = (*lb)->lease_addr_;
3352 Lease6Ptr lease = getAnyLease6Internal(last_addr);
3353 if (lease) {
3354 collection.push_back(lease);
3355 if (collection.size() >= page_size.page_size_) {
3356 break;
3357 }
3358 }
3359 }
3360 return (collection);
3361}
3362
3365 const IOAddress& lower_bound_address,
3366 const LeasePageSize& page_size) {
3369 .arg(page_size.page_size_)
3370 .arg(lower_bound_address.toText())
3371 .arg(idToText(remote_id));
3372
3373 // Expecting IPv6 valid address.
3374 if (!lower_bound_address.isV6()) {
3375 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3376 "retrieving leases from the lease database, got "
3377 << lower_bound_address);
3378 }
3379
3380 if (MultiThreadingMgr::instance().getMode()) {
3381 std::lock_guard<std::mutex> lock(*mutex_);
3382 return (getLeases6ByRemoteIdInternal(remote_id,
3383 lower_bound_address,
3384 page_size));
3385 } else {
3386 return (getLeases6ByRemoteIdInternal(remote_id,
3387 lower_bound_address,
3388 page_size));
3389 }
3390}
3391
3393Memfile_LeaseMgr::getLeases6ByRemoteIdInternal(const OptionBuffer& remote_id,
3394 const IOAddress& lower_bound_address,
3395 const LeasePageSize& page_size) {
3396 Lease6Collection collection;
3397 std::set<IOAddress> sorted;
3398 const RemoteIdIndex& idx = remote_id6_.get<RemoteIdIndexTag>();
3399 RemoteIdIndexRange er = idx.equal_range(remote_id);
3400 // Store all addresses greater than lower_bound_address.
3401 BOOST_FOREACH(auto const& it, er) {
3402 const IOAddress& addr = it->lease_addr_;
3403 if (addr <= lower_bound_address) {
3404 continue;
3405 }
3406 static_cast<void>(sorted.insert(addr));
3407 }
3408
3409 // Return all leases being within the page size.
3410 for (const IOAddress& addr : sorted) {
3411 Lease6Ptr lease = getAnyLease6Internal(addr);
3412 if (lease) {
3413 collection.push_back(lease);
3414 if (collection.size() >= page_size.page_size_) {
3415 break;
3416 }
3417 }
3418 }
3419 return (collection);
3420}
3421
3422size_t
3423Memfile_LeaseMgr::extractExtendedInfo4(bool update, bool current) {
3425 if (current) {
3426 cfg = CfgMgr::instance().getCurrentCfg()->getConsistency();
3427 } else {
3428 cfg = CfgMgr::instance().getStagingCfg()->getConsistency();
3429 }
3430 if (!cfg) {
3431 isc_throw(Unexpected, "the " << (current ? "current" : "staging")
3432 << " consistency configuration is null");
3433 }
3434 auto check = cfg->getExtendedInfoSanityCheck();
3435
3439 .arg(update ? " updating in file" : "");
3440
3441 size_t leases = 0;
3442 size_t modified = 0;
3443 size_t updated = 0;
3444 size_t processed = 0;
3445 auto& index = storage4_.get<AddressIndexTag>();
3446 auto lease_it = index.begin();
3447 auto next_it = index.end();
3448
3449 for (; lease_it != index.end(); lease_it = next_it) {
3450 next_it = std::next(lease_it);
3451 Lease4Ptr lease = *lease_it;
3452 ++leases;
3453 try {
3454 if (upgradeLease4ExtendedInfo(lease, check)) {
3455 ++modified;
3456 if (update && persistLeases(V4)) {
3457 lease_file4_->append(*lease);
3458 ++updated;
3459 }
3460 }
3461 // Work on a copy as the multi-index requires fields used
3462 // as indexes to be read-only.
3463 Lease4Ptr copy(new Lease4(*lease));
3465 if (!copy->relay_id_.empty() || !copy->remote_id_.empty()) {
3466 index.replace(lease_it, copy);
3467 ++processed;
3468 }
3469 } catch (const std::exception& ex) {
3472 .arg(lease->addr_.toText())
3473 .arg(ex.what());
3474 }
3475 }
3476
3478 .arg(leases)
3479 .arg(modified)
3480 .arg(updated)
3481 .arg(processed);
3482
3483 return (updated);
3484}
3485
3486size_t
3488 return (0);
3489}
3490
3491void
3493 CfgConsistencyPtr cfg = CfgMgr::instance().getStagingCfg()->getConsistency();
3494 if (!cfg) {
3495 isc_throw(Unexpected, "the staging consistency configuration is null");
3496 }
3497 auto check = cfg->getExtendedInfoSanityCheck();
3498 bool enabled = getExtendedInfoTablesEnabled();
3499
3503 .arg(enabled ? "enabled" : "disabled");
3504
3505 // Clear tables when enabled.
3506 if (enabled) {
3507 relay_id6_.clear();
3508 remote_id6_.clear();
3509 }
3510
3511 size_t leases = 0;
3512 size_t modified = 0;
3513 size_t processed = 0;
3514
3515 for (auto const& lease : storage6_) {
3516 ++leases;
3517 try {
3518 if (upgradeLease6ExtendedInfo(lease, check)) {
3519 ++modified;
3520 }
3521 if (enabled && addExtendedInfo6(lease)) {
3522 ++processed;
3523 }
3524 } catch (const std::exception& ex) {
3527 .arg(lease->addr_.toText())
3528 .arg(ex.what());
3529 }
3530 }
3531
3533 .arg(leases)
3534 .arg(modified)
3535 .arg(processed);
3536}
3537
3538size_t
3540 return (0);
3541}
3542
3543void
3545 LeaseAddressRelayIdIndex& relay_id_idx =
3547 static_cast<void>(relay_id_idx.erase(addr));
3548 LeaseAddressRemoteIdIndex& remote_id_idx =
3550 static_cast<void>(remote_id_idx.erase(addr));
3551}
3552
3553void
3555 const std::vector<uint8_t>& relay_id) {
3556 Lease6ExtendedInfoPtr ex_info;
3557 ex_info.reset(new Lease6ExtendedInfo(lease_addr, relay_id));
3558 relay_id6_.insert(ex_info);
3559}
3560
3561void
3563 const std::vector<uint8_t>& remote_id) {
3564 Lease6ExtendedInfoPtr ex_info;
3565 ex_info.reset(new Lease6ExtendedInfo(lease_addr, remote_id));
3566 remote_id6_.insert(ex_info);
3567}
3568
3569void
3570Memfile_LeaseMgr::writeLeases4(const std::string& filename) {
3571 if (MultiThreadingMgr::instance().getMode()) {
3572 std::lock_guard<std::mutex> lock(*mutex_);
3573 writeLeases4Internal(filename);
3574 } else {
3575 writeLeases4Internal(filename);
3576 }
3577}
3578
3579void
3580Memfile_LeaseMgr::writeLeases4Internal(const std::string& filename) {
3581 bool overwrite = (lease_file4_ && lease_file4_->getFilename() == filename);
3582 try {
3583 if (overwrite) {
3584 lease_file4_->close();
3585 }
3586 std::ostringstream old;
3587 old << filename << ".bak" << getpid();
3588 ::rename(filename.c_str(), old.str().c_str());
3589 CSVLeaseFile4 backup(filename);
3590 backup.open();
3591 for (auto const& lease : storage4_) {
3592 backup.append(*lease);
3593 }
3594 backup.close();
3595 if (overwrite) {
3596 lease_file4_->open(true);
3597 }
3598 } catch (const std::exception&) {
3599 if (overwrite) {
3600 lease_file4_->open(true);
3601 }
3602 throw;
3603 }
3604}
3605
3606void
3607Memfile_LeaseMgr::writeLeases6(const std::string& filename) {
3608 if (MultiThreadingMgr::instance().getMode()) {
3609 std::lock_guard<std::mutex> lock(*mutex_);
3610 writeLeases6Internal(filename);
3611 } else {
3612 writeLeases6Internal(filename);
3613 }
3614}
3615
3616void
3617Memfile_LeaseMgr::writeLeases6Internal(const std::string& filename) {
3618 bool overwrite = (lease_file6_ && lease_file6_->getFilename() == filename);
3619 try {
3620 if (overwrite) {
3621 lease_file6_->close();
3622 }
3623 std::ostringstream old;
3624 old << filename << ".bak" << getpid();
3625 ::rename(filename.c_str(), old.str().c_str());
3626 CSVLeaseFile6 backup(filename);
3627 backup.open();
3628 for (auto const& lease : storage6_) {
3629 backup.append(*lease);
3630 }
3631 backup.close();
3632 if (overwrite) {
3633 lease_file6_->open(true);
3634 }
3635 } catch (const std::exception&) {
3636 if (overwrite) {
3637 lease_file6_->open(true);
3638 }
3639 throw;
3640 }
3641}
3642
3645 try {
3648 return (TrackingLeaseMgrPtr(new Memfile_LeaseMgr(parameters)));
3649 } catch (const std::exception& ex) {
3651 .arg(ex.what());
3652 throw;
3653 }
3654}
3655
3656} // namespace dhcp
3657} // 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.
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition data.cc:249
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
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
int getLastPid() const
Returns pid of the last lease file cleanup.
void execute(const std::string &lease_file)
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:1033
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:801
bool getExtendedInfoTablesEnabled() const
Returns the setting indicating if lease6 extended info tables are enabled.
Definition lease_mgr.h:1025
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:580
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:231
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 data::ElementPtr getStatus() const override
Return status information.
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 isc::data::ConstElementPtr lfcStartHandler() override
Handler for kea-lfc-start command.
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.
int getLFCLastPid() const
Returns the last lfc process id.
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
static const TimerMgrPtr & instance()
Returns pointer to the sole instance of the TimerMgr.
Definition timer_mgr.cc:446
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.
Exception thrown when an error occurs during PID file processing.
Definition pid_file.h:20
Class to help with processing PID files.
Definition pid_file.h:40
void write(int) const
Write the PID to the file.
Definition pid_file.cc:60
void deleteFile() const
Delete the PID file.
Definition pid_file.cc:81
std::string getLockname() const
Returns the path to the lock file.
Definition pid_file.h:97
int check() const
Read the PID in from the file and check it.
Definition pid_file.cc:23
RAII device to handle a lock file to avoid race conditions.
Definition pid_file.h:115
bool isLocked()
Return the lock status.
Definition pid_file.h:131
This file contains several functions and constants that are used for handling commands and responses ...
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
const int CONTROL_RESULT_EMPTY
Status code indicating that the specified command was completed correctly, but failed to produce any ...
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
ConstElementPtr createAnswer()
Creates a standard config/command level success answer message (i.e.
const int CONTROL_RESULT_COMMAND_UNSUPPORTED
Status code indicating that the specified command is not supported.
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
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
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
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_LFC_RUNNING
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 isc::log::MessageID DHCPSRV_MEMFILE_LFC_FAIL_PID_CREATE
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.
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_RESCHEDULED
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).