Kea 3.1.9
memfile_lease_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2026 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
13#include <dhcpsrv/cfgmgr.h>
15#include <dhcpsrv/dhcpsrv_log.h>
19#include <dhcpsrv/timer_mgr.h>
21#include <stats/stats_mgr.h>
22#include <util/filesystem.h>
24#include <util/pid_file.h>
25#include <util/reconnect_ctl.h>
26
27#include <cstdio>
28#include <cstdlib>
29#include <cstring>
30#include <iostream>
31#include <limits>
32#include <sstream>
33
34#include <boost/foreach.hpp>
35
36#include <errno.h>
37
38namespace {
39
47const char* KEA_LFC_EXECUTABLE_ENV_NAME = "KEA_LFC_EXECUTABLE";
48
49} // namespace
50
51using namespace isc::asiolink;
52using namespace isc::config;
53using namespace isc::data;
54using namespace isc::db;
55using namespace isc::util;
56using namespace isc::stats;
57using namespace isc::util::file;
58
59namespace isc {
60namespace dhcp {
61
76class LFCSetup {
77public:
78
87
91 ~LFCSetup();
92
104 void setup(const uint32_t lfc_interval,
105 const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
106 const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
107 bool run_once_now = false);
108
110 void execute(const std::string& lease_file);
111
115 bool isRunning() const;
116
118 int getExitStatus() const;
119
121 int getLastPid() const;
122
123private:
124
127 boost::scoped_ptr<ProcessSpawn> process_;
128
131
133 pid_t pid_;
134
139 TimerMgrPtr timer_mgr_;
140};
141
143 : process_(), callback_(callback), pid_(0),
144 timer_mgr_(TimerMgr::instance()) {
145}
146
148 try {
149 // Remove the timer. This will throw an exception if the timer does not
150 // exist. There are several possible reasons for this:
151 // a) It hasn't been registered (although if the LFC Setup instance
152 // exists it means that the timer must have been registered or that
153 // such registration has been attempted).
154 // b) The registration may fail if the duplicate timer exists or if the
155 // TimerMgr's worker thread is running but if this happens it is a
156 // programming error.
157 // c) The program is shutting down and the timer has been removed by
158 // another component.
159 timer_mgr_->unregisterTimer("memfile-lfc");
160
161 } catch (const std::exception& ex) {
162 // We don't want exceptions being thrown from the destructor so we just
163 // log a message here. The message is logged at debug severity as
164 // we don't want an error message output during shutdown.
167 }
168}
169
170void
171LFCSetup::setup(const uint32_t lfc_interval,
172 const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
173 const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
174 bool run_once_now) {
175
176 // Start preparing the command line for kea-lfc.
177 std::string executable;
178 char* c_executable = getenv(KEA_LFC_EXECUTABLE_ENV_NAME);
179 if (!c_executable) {
180 executable = KEA_LFC_EXECUTABLE;
181 } else {
182 executable = c_executable;
183 }
184
185 // Gather the base file name.
186 std::string lease_file = lease_file4 ? lease_file4->getFilename() :
187 lease_file6->getFilename();
188
189 // Create the other names by appending suffixes to the base name.
190 ProcessArgs args;
191 // Universe: v4 or v6.
192 args.push_back(lease_file4 ? "-4" : "-6");
193
194 // Previous file.
195 args.push_back("-x");
196 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
198 // Input file.
199 args.push_back("-i");
200 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
202 // Output file.
203 args.push_back("-o");
204 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
206 // Finish file.
207 args.push_back("-f");
208 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
210 // PID file.
211 args.push_back("-p");
212 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
214
215 // The configuration file is currently unused.
216 args.push_back("-c");
217 args.push_back("ignored-path");
218
219 // Create the process (do not start it yet).
220 process_.reset(new ProcessSpawn(ProcessSpawn::ASYNC, executable, args,
221 ProcessEnvVars(), true));
222
223 // If we've been told to run it once now, invoke the callback directly.
224 if (run_once_now) {
225 callback_();
226 }
227
228 // If it's supposed to run periodically, setup that now.
229 if (lfc_interval > 0) {
230 // Set the timer to call callback function periodically.
232
233 // Multiple the lfc_interval value by 1000 as this value specifies
234 // a timeout in seconds, whereas the setup() method expects the
235 // timeout in milliseconds.
236 timer_mgr_->registerTimer("memfile-lfc", callback_, lfc_interval * 1000,
238 timer_mgr_->setup("memfile-lfc");
239 }
240}
241
242void
243LFCSetup::execute(const std::string& lease_file) {
244 PIDFile pid_file(Memfile_LeaseMgr::appendSuffix(lease_file,
246 try {
247 // Look at lfc.dox for a description of this.
248
249 // Try to acquire the lock for the pid file.
250 PIDLock pid_lock(pid_file.getLockname());
251
252 // Verify that no lfc is still running.
253 if (!pid_lock.isLocked() || pid_file.check()) {
255 return;
256 }
257
258 // Cleanup the state (memory leak fix).
259 if (pid_ != 0) {
260 try {
261 process_->clearState(pid_);
262 } catch (...) {
263 // Ignore errors (and keep a possible slow memory leak).
264 }
265 }
266 // Reset pid to -1.
267 pid_ = -1;
268
269 // Check the pid file is writable.
270 pid_file.write(0);
271
273 .arg(process_->getCommandLine());
274 try {
275 pid_ = process_->spawn();
276 } catch (const ProcessSpawnError&) {
278 try {
279 pid_file.deleteFile();
280 } catch (...) {
281 // Ignore errors.
282 }
283 return;
284 }
285
286 // Write the pid of the child in the pid file.
287 pid_file.write(pid_);
288
289 } catch (const PIDFileError& ex) {
291 .arg(ex.what());
292 }
293}
294
295bool
297 return (process_ && process_->isRunning(pid_));
298}
299
300int
302 if (!process_) {
303 isc_throw(InvalidOperation, "unable to obtain LFC process exit code: "
304 " the process is null");
305 }
306 return (process_->getExitStatus(pid_));
307}
308
309int
311 return (pid_);
312}
313
320public:
326 : LeaseStatsQuery(select_mode), rows_(0), next_pos_(rows_.end()) {
327 };
328
333 : LeaseStatsQuery(subnet_id), rows_(0), next_pos_(rows_.end()) {
334 };
335
340 MemfileLeaseStatsQuery(const SubnetID& first_subnet_id, const SubnetID& last_subnet_id)
341 : LeaseStatsQuery(first_subnet_id, last_subnet_id), rows_(0), next_pos_(rows_.end()) {
342 };
343
346
357 virtual bool getNextRow(LeaseStatsRow& row) {
358 if (next_pos_ == rows_.end()) {
359 return (false);
360 }
361
362 row = *next_pos_;
363 ++next_pos_;
364 return (true);
365 }
366
368 int getRowCount() const {
369 return (rows_.size());
370 }
371
372protected:
374 std::vector<LeaseStatsRow> rows_;
375
377 std::vector<LeaseStatsRow>::iterator next_pos_;
378};
379
390public:
397 const SelectMode& select_mode = ALL_SUBNETS)
398 : MemfileLeaseStatsQuery(select_mode), storage4_(storage4) {
399 };
400
405 MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& subnet_id)
406 : MemfileLeaseStatsQuery(subnet_id), storage4_(storage4) {
407 };
408
414 MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& first_subnet_id,
415 const SubnetID& last_subnet_id)
416 : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage4_(storage4) {
417 };
418
421
436 void start() {
437 switch (getSelectMode()) {
438 case ALL_SUBNETS:
439 case SINGLE_SUBNET:
440 case SUBNET_RANGE:
441 startSubnets();
442 break;
443
444 case ALL_SUBNET_POOLS:
445 startSubnetPools();
446 break;
447 }
448 }
449
450private:
465 void startSubnets() {
467 = storage4_.get<SubnetIdIndexTag>();
468
469 // Set lower and upper bounds based on select mode
470 Lease4StorageSubnetIdIndex::const_iterator lower;
471 Lease4StorageSubnetIdIndex::const_iterator upper;
472
473 switch (getSelectMode()) {
474 case ALL_SUBNETS:
475 lower = idx.begin();
476 upper = idx.end();
477 break;
478
479 case SINGLE_SUBNET:
480 lower = idx.lower_bound(getFirstSubnetID());
481 upper = idx.upper_bound(getFirstSubnetID());
482 break;
483
484 case SUBNET_RANGE:
485 lower = idx.lower_bound(getFirstSubnetID());
486 upper = idx.upper_bound(getLastSubnetID());
487 break;
488
489 default:
490 return;
491 }
492
493 // Return an empty set if there are no rows.
494 if (lower == upper) {
495 return;
496 }
497
498 // Iterate over the leases in order by subnet, accumulating per
499 // subnet counts for each state of interest. As we finish each
500 // subnet, add the appropriate rows to our result set.
501 SubnetID cur_id = 0;
502 int64_t assigned = 0;
503 int64_t declined = 0;
504 for (Lease4StorageSubnetIdIndex::const_iterator lease = lower;
505 lease != upper; ++lease) {
506 // If we've hit the next subnet, add rows for the current subnet
507 // and wipe the accumulators
508 if ((*lease)->subnet_id_ != cur_id) {
509 if (cur_id > 0) {
510 if (assigned > 0) {
511 rows_.push_back(LeaseStatsRow(cur_id,
513 assigned));
514 assigned = 0;
515 }
516
517 if (declined > 0) {
518 rows_.push_back(LeaseStatsRow(cur_id,
520 declined));
521 declined = 0;
522 }
523 }
524
525 // Update current subnet id
526 cur_id = (*lease)->subnet_id_;
527 }
528
529 // Bump the appropriate accumulator
530 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
531 ++assigned;
532 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
533 ++declined;
534 }
535 }
536
537 // Make the rows for last subnet
538 if (assigned > 0) {
539 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
540 assigned));
541 }
542
543 if (declined > 0) {
544 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
545 declined));
546 }
547
548 // Reset the next row position back to the beginning of the rows.
549 next_pos_ = rows_.begin();
550 }
551
566 void startSubnetPools() {
568 = storage4_.get<SubnetIdPoolIdIndexTag>();
569
570 // Set lower and upper bounds based on select mode
571 Lease4StorageSubnetIdPoolIdIndex::const_iterator lower;
572 Lease4StorageSubnetIdPoolIdIndex::const_iterator upper;
573 switch (getSelectMode()) {
574 case ALL_SUBNET_POOLS:
575 lower = idx.begin();
576 upper = idx.end();
577 break;
578
579 default:
580 return;
581 }
582
583 // Return an empty set if there are no rows.
584 if (lower == upper) {
585 return;
586 }
587
588 // Iterate over the leases in order by subnet and pool, accumulating per
589 // subnet and pool counts for each state of interest. As we finish each
590 // subnet or pool, add the appropriate rows to our result set.
591 SubnetID cur_id = 0;
592 uint32_t cur_pool_id = 0;
593 int64_t assigned = 0;
594 int64_t declined = 0;
595 for (Lease4StorageSubnetIdPoolIdIndex::const_iterator lease = lower;
596 lease != upper; ++lease) {
597 // If we've hit the next pool, add rows for the current subnet and
598 // pool and wipe the accumulators
599 if ((*lease)->pool_id_ != cur_pool_id) {
600 if (assigned > 0) {
601 rows_.push_back(LeaseStatsRow(cur_id,
603 assigned, cur_pool_id));
604 assigned = 0;
605 }
606
607 if (declined > 0) {
608 rows_.push_back(LeaseStatsRow(cur_id,
610 declined, cur_pool_id));
611 declined = 0;
612 }
613
614 // Update current pool id
615 cur_pool_id = (*lease)->pool_id_;
616 }
617
618 // If we've hit the next subnet, add rows for the current subnet
619 // and wipe the accumulators
620 if ((*lease)->subnet_id_ != cur_id) {
621 if (cur_id > 0) {
622 if (assigned > 0) {
623 rows_.push_back(LeaseStatsRow(cur_id,
625 assigned, cur_pool_id));
626 assigned = 0;
627 }
628
629 if (declined > 0) {
630 rows_.push_back(LeaseStatsRow(cur_id,
632 declined, cur_pool_id));
633 declined = 0;
634 }
635 }
636
637 // Update current subnet id
638 cur_id = (*lease)->subnet_id_;
639
640 // Reset pool id
641 cur_pool_id = 0;
642 }
643
644 // Bump the appropriate accumulator
645 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
646 ++assigned;
647 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
648 ++declined;
649 }
650 }
651
652 // Make the rows for last subnet
653 if (assigned > 0) {
654 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
655 assigned, cur_pool_id));
656 }
657
658 if (declined > 0) {
659 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
660 declined, cur_pool_id));
661 }
662
663 // Reset the next row position back to the beginning of the rows.
664 next_pos_ = rows_.begin();
665 }
666
668 Lease4Storage& storage4_;
669};
670
671
682public:
689 const SelectMode& select_mode = ALL_SUBNETS)
690 : MemfileLeaseStatsQuery(select_mode), storage6_(storage6) {
691 };
692
697 MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& subnet_id)
698 : MemfileLeaseStatsQuery(subnet_id), storage6_(storage6) {
699 };
700
706 MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& first_subnet_id,
707 const SubnetID& last_subnet_id)
708 : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage6_(storage6) {
709 };
710
713
729 void start() {
730 switch (getSelectMode()) {
731 case ALL_SUBNETS:
732 case SINGLE_SUBNET:
733 case SUBNET_RANGE:
734 startSubnets();
735 break;
736
737 case ALL_SUBNET_POOLS:
738 startSubnetPools();
739 break;
740 }
741 }
742
743private:
759 virtual void startSubnets() {
761 = storage6_.get<SubnetIdIndexTag>();
762
763 // Set lower and upper bounds based on select mode
764 Lease6StorageSubnetIdIndex::const_iterator lower;
765 Lease6StorageSubnetIdIndex::const_iterator upper;
766 switch (getSelectMode()) {
767 case ALL_SUBNETS:
768 lower = idx.begin();
769 upper = idx.end();
770 break;
771
772 case SINGLE_SUBNET:
773 lower = idx.lower_bound(getFirstSubnetID());
774 upper = idx.upper_bound(getFirstSubnetID());
775 break;
776
777 case SUBNET_RANGE:
778 lower = idx.lower_bound(getFirstSubnetID());
779 upper = idx.upper_bound(getLastSubnetID());
780 break;
781
782 default:
783 return;
784 }
785
786 // Return an empty set if there are no rows.
787 if (lower == upper) {
788 return;
789 }
790
791 // Iterate over the leases in order by subnet, accumulating per
792 // subnet counts for each state of interest. As we finish each
793 // subnet, add the appropriate rows to our result set.
794 SubnetID cur_id = 0;
795 int64_t assigned = 0;
796 int64_t declined = 0;
797 int64_t assigned_pds = 0;
798 int64_t registered = 0;
799 for (Lease6StorageSubnetIdIndex::const_iterator lease = lower;
800 lease != upper; ++lease) {
801 // If we've hit the next subnet, add rows for the current subnet
802 // and wipe the accumulators
803 if ((*lease)->subnet_id_ != cur_id) {
804 if (cur_id > 0) {
805 if (assigned > 0) {
806 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
808 assigned));
809 assigned = 0;
810 }
811
812 if (declined > 0) {
813 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
815 declined));
816 declined = 0;
817 }
818
819 if (assigned_pds > 0) {
820 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
822 assigned_pds));
823 assigned_pds = 0;
824 }
825
826 if (registered > 0) {
827 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
829 registered));
830 registered = 0;
831 }
832 }
833
834 // Update current subnet id
835 cur_id = (*lease)->subnet_id_;
836 }
837
838 // Bump the appropriate accumulator
839 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
840 switch((*lease)->type_) {
841 case Lease::TYPE_NA:
842 ++assigned;
843 break;
844 case Lease::TYPE_PD:
845 ++assigned_pds;
846 break;
847 default:
848 break;
849 }
850 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
851 // In theory only NAs can be declined
852 if (((*lease)->type_) == Lease::TYPE_NA) {
853 ++declined;
854 }
855 } else if ((*lease)->state_ == Lease::STATE_REGISTERED) {
856 // In theory only NAs can be registered
857 if (((*lease)->type_) == Lease::TYPE_NA) {
858 ++registered;
859 }
860 }
861 }
862
863 // Make the rows for last subnet, unless there were no rows
864 if (assigned > 0) {
865 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
866 Lease::STATE_DEFAULT, assigned));
867 }
868
869 if (declined > 0) {
870 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
871 Lease::STATE_DECLINED, declined));
872 }
873
874 if (assigned_pds > 0) {
875 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
876 Lease::STATE_DEFAULT, assigned_pds));
877 }
878
879 if (registered > 0) {
880 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
881 Lease::STATE_REGISTERED, registered));
882 }
883
884 // Set the next row position to the beginning of the rows.
885 next_pos_ = rows_.begin();
886 }
887
902 virtual void startSubnetPools() {
904 = storage6_.get<SubnetIdPoolIdIndexTag>();
905
906 // Set lower and upper bounds based on select mode
907 Lease6StorageSubnetIdPoolIdIndex::const_iterator lower;
908 Lease6StorageSubnetIdPoolIdIndex::const_iterator upper;
909 switch (getSelectMode()) {
910 case ALL_SUBNET_POOLS:
911 lower = idx.begin();
912 upper = idx.end();
913 break;
914
915 default:
916 return;
917 }
918
919 // Return an empty set if there are no rows.
920 if (lower == upper) {
921 return;
922 }
923
924 // Iterate over the leases in order by subnet, accumulating per
925 // subnet counts for each state of interest. As we finish each
926 // subnet, add the appropriate rows to our result set.
927 SubnetID cur_id = 0;
928 uint32_t cur_pool_id = 0;
929 int64_t assigned = 0;
930 int64_t declined = 0;
931 int64_t assigned_pds = 0;
932 for (Lease6StorageSubnetIdPoolIdIndex::const_iterator lease = lower;
933 lease != upper; ++lease) {
934 // If we've hit the next pool, add rows for the current subnet and
935 // pool and wipe the accumulators
936 if ((*lease)->pool_id_ != cur_pool_id) {
937 if (assigned > 0) {
938 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
940 assigned, cur_pool_id));
941 assigned = 0;
942 }
943
944 if (declined > 0) {
945 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
947 declined, cur_pool_id));
948 declined = 0;
949 }
950
951 if (assigned_pds > 0) {
952 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
954 assigned_pds, cur_pool_id));
955 assigned_pds = 0;
956 }
957
958 // Update current pool id
959 cur_pool_id = (*lease)->pool_id_;
960 }
961
962 // If we've hit the next subnet, add rows for the current subnet
963 // and wipe the accumulators
964 if ((*lease)->subnet_id_ != cur_id) {
965 if (cur_id > 0) {
966 if (assigned > 0) {
967 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
969 assigned, cur_pool_id));
970 assigned = 0;
971 }
972
973 if (declined > 0) {
974 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
976 declined, cur_pool_id));
977 declined = 0;
978 }
979
980 if (assigned_pds > 0) {
981 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
983 assigned_pds, cur_pool_id));
984 assigned_pds = 0;
985 }
986 }
987
988 // Update current subnet id
989 cur_id = (*lease)->subnet_id_;
990
991 // Reset pool id
992 cur_pool_id = 0;
993 }
994
995 // Bump the appropriate accumulator
996 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
997 switch((*lease)->type_) {
998 case Lease::TYPE_NA:
999 ++assigned;
1000 break;
1001 case Lease::TYPE_PD:
1002 ++assigned_pds;
1003 break;
1004 default:
1005 break;
1006 }
1007 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
1008 // In theory only NAs can be declined
1009 if (((*lease)->type_) == Lease::TYPE_NA) {
1010 ++declined;
1011 }
1012 }
1013 }
1014
1015 // Make the rows for last subnet, unless there were no rows
1016 if (assigned > 0) {
1017 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
1018 Lease::STATE_DEFAULT, assigned,
1019 cur_pool_id));
1020 }
1021
1022 if (declined > 0) {
1023 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
1024 Lease::STATE_DECLINED, declined,
1025 cur_pool_id));
1026 }
1027
1028 if (assigned_pds > 0) {
1029 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
1030 Lease::STATE_DEFAULT, assigned_pds,
1031 cur_pool_id));
1032 }
1033
1034 // Set the next row position to the beginning of the rows.
1035 next_pos_ = rows_.begin();
1036 }
1037
1039 Lease6Storage& storage6_;
1040};
1041
1042// Explicit definition of class static constants. Values are given in the
1043// declaration so they're not needed here.
1048
1050 : TrackingLeaseMgr(), lfc_setup_(), conn_(parameters), mutex_(new std::mutex) {
1051 bool conversion_needed = false;
1052
1053 // Check if the extended info tables are enabled.
1054 setExtendedInfoTablesEnabled(parameters);
1055
1056 // Check the universe and use v4 file or v6 file.
1057 std::string universe = conn_.getParameter("universe");
1058 if (universe == "4") {
1059 std::string file4 = initLeaseFilePath(V4);
1060 if (!file4.empty()) {
1061 conversion_needed = loadLeasesFromFiles<Lease4,
1062 CSVLeaseFile4>(V4, file4,
1064 storage4_);
1065 static_cast<void>(extractExtendedInfo4(false, false));
1066 }
1067 } else {
1068 std::string file6 = initLeaseFilePath(V6);
1069 if (!file6.empty()) {
1070 conversion_needed = loadLeasesFromFiles<Lease6,
1071 CSVLeaseFile6>(V6, file6,
1073 storage6_);
1075 }
1076 }
1077
1078 // If lease persistence have been disabled for both v4 and v6,
1079 // issue a warning. It is ok not to write leases to disk when
1080 // doing testing, but it should not be done in normal server
1081 // operation.
1082 if (!persistLeases(V4) && !persistLeases(V6)) {
1083 // If the configuration is just checked, don't open any file and
1084 // do not log anything about lease storage persistence.
1085 if (!MultiThreadingMgr::instance().isTestMode()) {
1087 }
1088 } else {
1089 if (conversion_needed) {
1090 auto const& version(getVersion());
1092 .arg(version.first).arg(version.second);
1093 }
1094 lfcSetup(conversion_needed);
1095 }
1096
1097 // Create the reconnect ctl object.
1098 conn_.makeReconnectCtl("memfile-lease-mgr", NetworkState::DB_CONNECTION + 3);
1099
1100 // Sanity check the values.
1101 if (conn_.reconnectCtl()->maxRetries() > 0) {
1102 isc_throw(BadValue, "'max-reconnect-tries'"
1103 << " values greater than zero are not supported by memfile");
1104 }
1105
1106 if (conn_.reconnectCtl()->retryInterval() > 0) {
1107 isc_throw(BadValue, "'reconnect-wait-time'"
1108 << " values greater than zero are not supported by memfile");
1109 }
1110}
1111
1113 if (lease_file4_) {
1114 lease_file4_->close();
1115 lease_file4_.reset();
1116 }
1117 if (lease_file6_) {
1118 lease_file6_->close();
1119 lease_file6_.reset();
1120 }
1121}
1122
1123std::string
1125 std::stringstream tmp;
1126 tmp << "Memfile backend ";
1127 if (u == V4) {
1128 tmp << MAJOR_VERSION_V4 << "." << MINOR_VERSION_V4;
1129 } else if (u == V6) {
1130 tmp << MAJOR_VERSION_V6 << "." << MINOR_VERSION_V6;
1131 }
1132 return tmp.str();
1133}
1134
1135std::string
1137 uint16_t family = CfgMgr::instance().getFamily();
1138 if (family == AF_INET6) {
1140 } else {
1142 }
1143}
1144
1145void
1146Memfile_LeaseMgr::handleDbLost() {
1147 // Invoke application layer callback on the main IOService.
1148 auto ios = conn_.getIOService();
1149 if (ios) {
1150 ios->post(std::bind(DatabaseConnection::invokeDbLostCallback,
1151 conn_.reconnectCtl()));
1152 }
1153}
1154
1155bool
1156Memfile_LeaseMgr::addLeaseInternal(const Lease4Ptr& lease) {
1157 if (getLease4Internal(lease->addr_)) {
1158 // there is a lease with specified address already
1159 return (false);
1160 }
1161
1162 // Try to write a lease to disk first. If this fails, the lease will
1163 // not be inserted to the memory and the disk and in-memory data will
1164 // remain consistent.
1165 if (persistLeases(V4)) {
1166 try {
1167 lease_file4_->append(*lease);
1168 } catch (const CSVFileFatalError&) {
1169 handleDbLost();
1170 throw;
1171 }
1172 }
1173
1174 storage4_.insert(lease);
1175
1176 // Update lease current expiration time (allows update between the creation
1177 // of the Lease up to the point of insertion in the database).
1178 lease->updateCurrentExpirationTime();
1179
1180 // Increment class lease counters.
1181 class_lease_counter_.addLease(lease);
1182
1183 // Run installed callbacks.
1184 if (hasCallbacks()) {
1185 trackAddLease(lease);
1186 }
1187
1188 return (true);
1189}
1190
1191bool
1194 DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
1195
1196 if (MultiThreadingMgr::instance().getMode()) {
1197 std::lock_guard<std::mutex> lock(*mutex_);
1198 return (addLeaseInternal(lease));
1199 } else {
1200 return (addLeaseInternal(lease));
1201 }
1202}
1203
1204bool
1205Memfile_LeaseMgr::addLeaseInternal(const Lease6Ptr& lease) {
1206 if (getLease6Internal(lease->type_, lease->addr_)) {
1207 // there is a lease with specified address already
1208 return (false);
1209 }
1210
1211 // Try to write a lease to disk first. If this fails, the lease will
1212 // not be inserted to the memory and the disk and in-memory data will
1213 // remain consistent.
1214 if (persistLeases(V6)) {
1215 try {
1216 lease_file6_->append(*lease);
1217 } catch (const CSVFileFatalError&) {
1218 handleDbLost();
1219 throw;
1220 }
1221 }
1222
1223 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
1224 storage6_.insert(lease);
1225
1226 // Update lease current expiration time (allows update between the creation
1227 // of the Lease up to the point of insertion in the database).
1228 lease->updateCurrentExpirationTime();
1229
1230 // Increment class lease counters.
1231 class_lease_counter_.addLease(lease);
1232
1234 static_cast<void>(addExtendedInfo6(lease));
1235 }
1236
1237 // Run installed callbacks.
1238 if (hasCallbacks()) {
1239 trackAddLease(lease);
1240 }
1241
1242 return (true);
1243}
1244
1245bool
1248 DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
1249
1250 if (MultiThreadingMgr::instance().getMode()) {
1251 std::lock_guard<std::mutex> lock(*mutex_);
1252 return (addLeaseInternal(lease));
1253 } else {
1254 return (addLeaseInternal(lease));
1255 }
1256}
1257
1259Memfile_LeaseMgr::getLease4Internal(const isc::asiolink::IOAddress& addr) const {
1260 const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1261 Lease4StorageAddressIndex::iterator l = idx.find(addr);
1262 if (l == idx.end()) {
1263 return (Lease4Ptr());
1264 } else {
1265 return (Lease4Ptr(new Lease4(**l)));
1266 }
1267}
1268
1272 DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
1273
1274 if (MultiThreadingMgr::instance().getMode()) {
1275 std::lock_guard<std::mutex> lock(*mutex_);
1276 return (getLease4Internal(addr));
1277 } else {
1278 return (getLease4Internal(addr));
1279 }
1280}
1281
1282void
1283Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
1284 Lease4Collection& collection) const {
1285 // Using composite index by 'hw address' and 'subnet id'. It is
1286 // ok to use it for searching by the 'hw address' only.
1288 storage4_.get<HWAddressSubnetIdIndexTag>();
1289 std::pair<Lease4StorageHWAddressSubnetIdIndex::const_iterator,
1290 Lease4StorageHWAddressSubnetIdIndex::const_iterator> l
1291 = idx.equal_range(boost::make_tuple(hwaddr.hwaddr_));
1292
1293 BOOST_FOREACH(auto const& lease, l) {
1294 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1295 }
1296}
1297
1301 DHCPSRV_MEMFILE_GET_HWADDR4).arg(hwaddr.toText());
1302
1303 Lease4Collection collection;
1304 if (MultiThreadingMgr::instance().getMode()) {
1305 std::lock_guard<std::mutex> lock(*mutex_);
1306 getLease4Internal(hwaddr, collection);
1307 } else {
1308 getLease4Internal(hwaddr, collection);
1309 }
1310
1311 return (collection);
1312}
1313
1315Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
1316 SubnetID subnet_id) const {
1317 // Get the index by HW Address and Subnet Identifier.
1319 storage4_.get<HWAddressSubnetIdIndexTag>();
1320 // Try to find the lease using HWAddr and subnet id.
1321 Lease4StorageHWAddressSubnetIdIndex::const_iterator lease =
1322 idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
1323 // Lease was not found. Return empty pointer to the caller.
1324 if (lease == idx.end()) {
1325 return (Lease4Ptr());
1326 }
1327
1328 // Lease was found. Return it to the caller.
1329 return (Lease4Ptr(new Lease4(**lease)));
1330}
1331
1334 SubnetID subnet_id) const {
1336 DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
1337 .arg(hwaddr.toText());
1338
1339 if (MultiThreadingMgr::instance().getMode()) {
1340 std::lock_guard<std::mutex> lock(*mutex_);
1341 return (getLease4Internal(hwaddr, subnet_id));
1342 } else {
1343 return (getLease4Internal(hwaddr, subnet_id));
1344 }
1345}
1346
1347void
1348Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
1349 Lease4Collection& collection) const {
1350 // Using composite index by 'client id' and 'subnet id'. It is ok
1351 // to use it to search by 'client id' only.
1353 storage4_.get<ClientIdSubnetIdIndexTag>();
1354 std::pair<Lease4StorageClientIdSubnetIdIndex::const_iterator,
1355 Lease4StorageClientIdSubnetIdIndex::const_iterator> l
1356 = idx.equal_range(boost::make_tuple(client_id.getClientId()));
1357
1358 BOOST_FOREACH(auto const& lease, l) {
1359 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1360 }
1361}
1362
1364Memfile_LeaseMgr::getLease4(const ClientId& client_id) const {
1366 DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.toText());
1367
1368 Lease4Collection collection;
1369 if (MultiThreadingMgr::instance().getMode()) {
1370 std::lock_guard<std::mutex> lock(*mutex_);
1371 getLease4Internal(client_id, collection);
1372 } else {
1373 getLease4Internal(client_id, collection);
1374 }
1375
1376 return (collection);
1377}
1378
1380Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
1381 SubnetID subnet_id) const {
1382 // Get the index by client and subnet id.
1384 storage4_.get<ClientIdSubnetIdIndexTag>();
1385 // Try to get the lease using client id and subnet id.
1386 Lease4StorageClientIdSubnetIdIndex::const_iterator lease =
1387 idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
1388 // Lease was not found. Return empty pointer to the caller.
1389 if (lease == idx.end()) {
1390 return (Lease4Ptr());
1391 }
1392 // Lease was found. Return it to the caller.
1393 return (Lease4Ptr(new Lease4(**lease)));
1394}
1395
1398 SubnetID subnet_id) const {
1401 .arg(client_id.toText());
1402
1403 if (MultiThreadingMgr::instance().getMode()) {
1404 std::lock_guard<std::mutex> lock(*mutex_);
1405 return (getLease4Internal(client_id, subnet_id));
1406 } else {
1407 return (getLease4Internal(client_id, subnet_id));
1408 }
1409}
1410
1411void
1412Memfile_LeaseMgr::getLeases4Internal(SubnetID subnet_id,
1413 Lease4Collection& collection) const {
1414 const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
1415 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
1416 Lease4StorageSubnetIdIndex::const_iterator> l =
1417 idx.equal_range(subnet_id);
1418
1419 BOOST_FOREACH(auto const& lease, l) {
1420 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1421 }
1422}
1423
1427 .arg(subnet_id);
1428
1429 Lease4Collection collection;
1430 if (MultiThreadingMgr::instance().getMode()) {
1431 std::lock_guard<std::mutex> lock(*mutex_);
1432 getLeases4Internal(subnet_id, collection);
1433 } else {
1434 getLeases4Internal(subnet_id, collection);
1435 }
1436
1437 return (collection);
1438}
1439
1440void
1441Memfile_LeaseMgr::getLeases4Internal(const std::string& hostname,
1442 Lease4Collection& collection) const {
1443 const Lease4StorageHostnameIndex& idx = storage4_.get<HostnameIndexTag>();
1444 std::pair<Lease4StorageHostnameIndex::const_iterator,
1445 Lease4StorageHostnameIndex::const_iterator> l =
1446 idx.equal_range(hostname);
1447
1448 BOOST_FOREACH(auto const& lease, l) {
1449 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1450 }
1451}
1452
1454Memfile_LeaseMgr::getLeases4(const std::string& hostname) const {
1456 .arg(hostname);
1457
1458 Lease4Collection collection;
1459 if (MultiThreadingMgr::instance().getMode()) {
1460 std::lock_guard<std::mutex> lock(*mutex_);
1461 getLeases4Internal(hostname, collection);
1462 } else {
1463 getLeases4Internal(hostname, collection);
1464 }
1465
1466 return (collection);
1467}
1468
1469void
1470Memfile_LeaseMgr::getLeases4Internal(Lease4Collection& collection) const {
1471 for (auto const& lease : storage4_) {
1472 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1473 }
1474}
1475
1479
1480 Lease4Collection collection;
1481 if (MultiThreadingMgr::instance().getMode()) {
1482 std::lock_guard<std::mutex> lock(*mutex_);
1483 getLeases4Internal(collection);
1484 } else {
1485 getLeases4Internal(collection);
1486 }
1487
1488 return (collection);
1489}
1490
1491void
1492Memfile_LeaseMgr::getLeases4Internal(const asiolink::IOAddress& lower_bound_address,
1493 const LeasePageSize& page_size,
1494 Lease4Collection& collection) const {
1495 const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1496 Lease4StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1497
1498 // Exclude the lower bound address specified by the caller.
1499 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1500 ++lb;
1501 }
1502
1503 // Return all other leases being within the page size.
1504 for (auto lease = lb;
1505 (lease != idx.end()) &&
1506 (static_cast<size_t>(std::distance(lb, lease)) < page_size.page_size_);
1507 ++lease) {
1508 collection.push_back(Lease4Ptr(new Lease4(**lease)));
1509 }
1510}
1511
1514 const LeasePageSize& page_size) const {
1515 // Expecting IPv4 address.
1516 if (!lower_bound_address.isV4()) {
1517 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
1518 "retrieving leases from the lease database, got "
1519 << lower_bound_address);
1520 }
1521
1523 .arg(page_size.page_size_)
1524 .arg(lower_bound_address.toText());
1525
1526 Lease4Collection collection;
1527 if (MultiThreadingMgr::instance().getMode()) {
1528 std::lock_guard<std::mutex> lock(*mutex_);
1529 getLeases4Internal(lower_bound_address, page_size, collection);
1530 } else {
1531 getLeases4Internal(lower_bound_address, page_size, collection);
1532 }
1533
1534 return (collection);
1535}
1536
1538Memfile_LeaseMgr::getLeases4(uint32_t state, SubnetID subnet_id) const {
1539 Lease4Collection collection;
1540 if (MultiThreadingMgr::instance().getMode()) {
1541 std::lock_guard<std::mutex> lock(*mutex_);
1542 getLeases4ByStateInternal(state, subnet_id, collection);
1543 } else {
1544 getLeases4ByStateInternal(state, subnet_id, collection);
1545 }
1546
1547 return (collection);
1548}
1549
1550void
1551Memfile_LeaseMgr::getLeases4ByStateInternal(uint32_t state,
1552 SubnetID subnet_id,
1553 Lease4Collection& collection) const {
1554 if (subnet_id == 0) {
1555 return (getLeases4ByStateInternal(state, collection));
1556 }
1557 const Lease4StorageStateIndex& idx = storage4_.get<StateIndexTag>();
1558 std::pair<Lease4StorageStateIndex::const_iterator,
1559 Lease4StorageStateIndex::const_iterator> l =
1560 idx.equal_range(boost::make_tuple(state, subnet_id));
1561
1562 BOOST_FOREACH(auto const& lease, l) {
1563 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1564 }
1565}
1566
1567void
1568Memfile_LeaseMgr::getLeases4ByStateInternal(uint32_t state,
1569 Lease4Collection& collection) const {
1570 const Lease4StorageStateIndex& idx = storage4_.get<StateIndexTag>();
1571 std::pair<Lease4StorageStateIndex::const_iterator,
1572 Lease4StorageStateIndex::const_iterator> l =
1573 idx.equal_range(boost::make_tuple(state));
1574
1575 BOOST_FOREACH(auto const& lease, l) {
1576 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1577 }
1578}
1579
1581Memfile_LeaseMgr::getLease6Internal(Lease::Type type,
1582 const isc::asiolink::IOAddress& addr) const {
1583 Lease6Storage::iterator l = storage6_.find(addr);
1584 if (l == storage6_.end() || !(*l) || ((*l)->type_ != type)) {
1585 return (Lease6Ptr());
1586 } else {
1587 return (Lease6Ptr(new Lease6(**l)));
1588 }
1589}
1590
1591void
1592Memfile_LeaseMgr::getLease6Internal(const HWAddr& hwaddr,
1593 Lease6Collection& collection) const {
1594 const Lease6StorageHWAddressIndex& idx =
1595 storage6_.get<HWAddressIndexTag>();
1596 std::pair<Lease6StorageHWAddressIndex::const_iterator,
1597 Lease6StorageHWAddressIndex::const_iterator> l
1598 = idx.equal_range(hwaddr.hwaddr_);
1599
1600 BOOST_FOREACH(auto const& lease, l) {
1601 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1602 }
1603}
1604
1608 DHCPSRV_MEMFILE_GET_HWADDR6).arg(hwaddr.toText());
1609
1610 Lease6Collection collection;
1611 if (MultiThreadingMgr::instance().getMode()) {
1612 std::lock_guard<std::mutex> lock(*mutex_);
1613 getLease6Internal(hwaddr, collection);
1614 } else {
1615 getLease6Internal(hwaddr, collection);
1616 }
1617
1618 return (collection);
1619}
1620
1622Memfile_LeaseMgr::getAnyLease6Internal(const isc::asiolink::IOAddress& addr) const {
1623 Lease6Storage::iterator l = storage6_.find(addr);
1624 if (l == storage6_.end() || !(*l)) {
1625 return (Lease6Ptr());
1626 } else {
1627 return (Lease6Ptr(new Lease6(**l)));
1628 }
1629}
1630
1633 const isc::asiolink::IOAddress& addr) const {
1636 .arg(addr.toText())
1637 .arg(Lease::typeToText(type));
1638
1639 if (MultiThreadingMgr::instance().getMode()) {
1640 std::lock_guard<std::mutex> lock(*mutex_);
1641 return (getLease6Internal(type, addr));
1642 } else {
1643 return (getLease6Internal(type, addr));
1644 }
1645}
1646
1647void
1648Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1649 const DUID& duid,
1650 uint32_t iaid,
1651 Lease6Collection& collection) const {
1652 // Get the index by DUID, IAID, lease type.
1653 const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1654 // Try to get the lease using the DUID, IAID and lease type.
1655 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1656 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1657 idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1658
1659 for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1660 l.first; lease != l.second; ++lease) {
1661 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1662 }
1663}
1664
1667 const DUID& duid,
1668 uint32_t iaid) const {
1671 .arg(iaid)
1672 .arg(duid.toText())
1673 .arg(Lease::typeToText(type));
1674
1675 Lease6Collection collection;
1676 if (MultiThreadingMgr::instance().getMode()) {
1677 std::lock_guard<std::mutex> lock(*mutex_);
1678 getLeases6Internal(type, duid, iaid, collection);
1679 } else {
1680 getLeases6Internal(type, duid, iaid, collection);
1681 }
1682
1683 return (collection);
1684}
1685
1686void
1687Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1688 const DUID& duid,
1689 uint32_t iaid,
1690 SubnetID subnet_id,
1691 Lease6Collection& collection) const {
1692 // Get the index by DUID, IAID, lease type.
1693 const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1694 // Try to get the lease using the DUID, IAID and lease type.
1695 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1696 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1697 idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1698
1699 for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1700 l.first; lease != l.second; ++lease) {
1701 // Filter out the leases which subnet id doesn't match.
1702 if ((*lease)->subnet_id_ == subnet_id) {
1703 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1704 }
1705 }
1706}
1707
1710 const DUID& duid,
1711 uint32_t iaid,
1712 SubnetID subnet_id) const {
1715 .arg(iaid)
1716 .arg(subnet_id)
1717 .arg(duid.toText())
1718 .arg(Lease::typeToText(type));
1719
1720 Lease6Collection collection;
1721 if (MultiThreadingMgr::instance().getMode()) {
1722 std::lock_guard<std::mutex> lock(*mutex_);
1723 getLeases6Internal(type, duid, iaid, subnet_id, collection);
1724 } else {
1725 getLeases6Internal(type, duid, iaid, subnet_id, collection);
1726 }
1727
1728 return (collection);
1729}
1730
1731void
1732Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1733 Lease6Collection& collection) const {
1734 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1735 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
1736 Lease6StorageSubnetIdIndex::const_iterator> l =
1737 idx.equal_range(subnet_id);
1738
1739 BOOST_FOREACH(auto const& lease, l) {
1740 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1741 }
1742}
1743
1747 .arg(subnet_id);
1748
1749 Lease6Collection collection;
1750 if (MultiThreadingMgr::instance().getMode()) {
1751 std::lock_guard<std::mutex> lock(*mutex_);
1752 getLeases6Internal(subnet_id, collection);
1753 } else {
1754 getLeases6Internal(subnet_id, collection);
1755 }
1756
1757 return (collection);
1758}
1759
1760void
1761Memfile_LeaseMgr::getLeases6Internal(const std::string& hostname,
1762 Lease6Collection& collection) const {
1763 const Lease6StorageHostnameIndex& idx = storage6_.get<HostnameIndexTag>();
1764 std::pair<Lease6StorageHostnameIndex::const_iterator,
1765 Lease6StorageHostnameIndex::const_iterator> l =
1766 idx.equal_range(hostname);
1767
1768 BOOST_FOREACH(auto const& lease, l) {
1769 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1770 }
1771}
1772
1774Memfile_LeaseMgr::getLeases6(const std::string& hostname) const {
1776 .arg(hostname);
1777
1778 Lease6Collection collection;
1779 if (MultiThreadingMgr::instance().getMode()) {
1780 std::lock_guard<std::mutex> lock(*mutex_);
1781 getLeases6Internal(hostname, collection);
1782 } else {
1783 getLeases6Internal(hostname, collection);
1784 }
1785
1786 return (collection);
1787}
1788
1789void
1790Memfile_LeaseMgr::getLeases6Internal(Lease6Collection& collection) const {
1791 for (auto const& lease : storage6_) {
1792 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1793 }
1794}
1795
1799
1800 Lease6Collection collection;
1801 if (MultiThreadingMgr::instance().getMode()) {
1802 std::lock_guard<std::mutex> lock(*mutex_);
1803 getLeases6Internal(collection);
1804 } else {
1805 getLeases6Internal(collection);
1806 }
1807
1808 return (collection);
1809}
1810
1811void
1812Memfile_LeaseMgr::getLeases6Internal(const DUID& duid,
1813 Lease6Collection& collection) const {
1814 const Lease6StorageDuidIndex& idx = storage6_.get<DuidIndexTag>();
1815 std::pair<Lease6StorageDuidIndex::const_iterator,
1816 Lease6StorageDuidIndex::const_iterator> l =
1817 idx.equal_range(duid.getDuid());
1818
1819 BOOST_FOREACH(auto const& lease, l) {
1820 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1821 }
1822}
1823
1827 .arg(duid.toText());
1828
1829 Lease6Collection collection;
1830 if (MultiThreadingMgr::instance().getMode()) {
1831 std::lock_guard<std::mutex> lock(*mutex_);
1832 getLeases6Internal(duid, collection);
1833 } else {
1834 getLeases6Internal(duid, collection);
1835 }
1836
1837 return (collection);
1838}
1839
1840void
1841Memfile_LeaseMgr::getLeases6Internal(const asiolink::IOAddress& lower_bound_address,
1842 const LeasePageSize& page_size,
1843 Lease6Collection& collection) const {
1844 const Lease6StorageAddressIndex& idx = storage6_.get<AddressIndexTag>();
1845 Lease6StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1846
1847 // Exclude the lower bound address specified by the caller.
1848 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1849 ++lb;
1850 }
1851
1852 // Return all other leases being within the page size.
1853 for (auto lease = lb;
1854 (lease != idx.end()) &&
1855 (static_cast<size_t>(std::distance(lb, lease)) < page_size.page_size_);
1856 ++lease) {
1857 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1858 }
1859}
1860
1863 const LeasePageSize& page_size) const {
1864 // Expecting IPv6 address.
1865 if (!lower_bound_address.isV6()) {
1866 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1867 "retrieving leases from the lease database, got "
1868 << lower_bound_address);
1869 }
1870
1872 .arg(page_size.page_size_)
1873 .arg(lower_bound_address.toText());
1874
1875 Lease6Collection collection;
1876 if (MultiThreadingMgr::instance().getMode()) {
1877 std::lock_guard<std::mutex> lock(*mutex_);
1878 getLeases6Internal(lower_bound_address, page_size, collection);
1879 } else {
1880 getLeases6Internal(lower_bound_address, page_size, collection);
1881 }
1882
1883 return (collection);
1884}
1885
1887Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1888 const IOAddress& lower_bound_address,
1889 const LeasePageSize& page_size) const {
1890 Lease6Collection collection;
1891 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1892 Lease6StorageSubnetIdIndex::const_iterator lb =
1893 idx.lower_bound(boost::make_tuple(subnet_id, lower_bound_address));
1894
1895 // Exclude the lower bound address specified by the caller.
1896 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1897 ++lb;
1898 }
1899
1900 // Return all leases being within the page size.
1901 for (auto it = lb; it != idx.end(); ++it) {
1902 if ((*it)->subnet_id_ != subnet_id) {
1903 // Gone after the subnet id index.
1904 break;
1905 }
1906 collection.push_back(Lease6Ptr(new Lease6(**it)));
1907 if (collection.size() >= page_size.page_size_) {
1908 break;
1909 }
1910 }
1911 return (collection);
1912}
1913
1916 const IOAddress& lower_bound_address,
1917 const LeasePageSize& page_size) const {
1920 .arg(page_size.page_size_)
1921 .arg(lower_bound_address.toText())
1922 .arg(subnet_id);
1923
1924 // Expecting IPv6 valid address.
1925 if (!lower_bound_address.isV6()) {
1926 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1927 "retrieving leases from the lease database, got "
1928 << lower_bound_address);
1929 }
1930
1931 if (MultiThreadingMgr::instance().getMode()) {
1932 std::lock_guard<std::mutex> lock(*mutex_);
1933 return (getLeases6Internal(subnet_id,
1934 lower_bound_address,
1935 page_size));
1936 } else {
1937 return (getLeases6Internal(subnet_id,
1938 lower_bound_address,
1939 page_size));
1940 }
1941}
1942
1944Memfile_LeaseMgr::getLeases6(uint32_t state, SubnetID subnet_id) const {
1945 Lease6Collection collection;
1946 if (MultiThreadingMgr::instance().getMode()) {
1947 std::lock_guard<std::mutex> lock(*mutex_);
1948 getLeases6ByStateInternal(state, subnet_id, collection);
1949 } else {
1950 getLeases6ByStateInternal(state, subnet_id, collection);
1951 }
1952
1953 return (collection);
1954}
1955
1956void
1957Memfile_LeaseMgr::getLeases6ByStateInternal(uint32_t state,
1958 SubnetID subnet_id,
1959 Lease6Collection& collection) const {
1960 if (subnet_id == 0) {
1961 return (getLeases6ByStateInternal(state, collection));
1962 }
1963 const Lease6StorageStateIndex& idx = storage6_.get<StateIndexTag>();
1964 std::pair<Lease6StorageStateIndex::const_iterator,
1965 Lease6StorageStateIndex::const_iterator> l =
1966 idx.equal_range(boost::make_tuple(state, subnet_id));
1967
1968 BOOST_FOREACH(auto const& lease, l) {
1969 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1970 }
1971}
1972
1973void
1974Memfile_LeaseMgr::getLeases6ByStateInternal(uint32_t state,
1975 Lease6Collection& collection) const {
1976 const Lease6StorageStateIndex& idx = storage6_.get<StateIndexTag>();
1977 std::pair<Lease6StorageStateIndex::const_iterator,
1978 Lease6StorageStateIndex::const_iterator> l =
1979 idx.equal_range(boost::make_tuple(state));
1980
1981 BOOST_FOREACH(auto const& lease, l) {
1982 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1983 }
1984}
1985
1986void
1987Memfile_LeaseMgr::getExpiredLeases4Internal(Lease4Collection& expired_leases,
1988 const size_t max_leases) const {
1989 // Obtain the index which segragates leases by state and time.
1990 const Lease4StorageExpirationIndex& index = storage4_.get<ExpirationIndexTag>();
1991
1992 // Retrieve leases which are not reclaimed and which haven't expired. The
1993 // 'less-than' operator will be used for both components of the index. So,
1994 // for the 'state' 'false' is less than 'true'. Also the leases with
1995 // expiration time lower than current time will be returned.
1996 Lease4StorageExpirationIndex::const_iterator ub =
1997 index.upper_bound(boost::make_tuple(false, time(0)));
1998
1999 // Copy only the number of leases indicated by the max_leases parameter.
2000 for (Lease4StorageExpirationIndex::const_iterator lease = index.begin();
2001 (lease != ub) &&
2002 ((max_leases == 0) ||
2003 (static_cast<size_t>(std::distance(index.begin(), lease)) < max_leases));
2004 ++lease) {
2005 expired_leases.push_back(Lease4Ptr(new Lease4(**lease)));
2006 }
2007}
2008
2009void
2011 const size_t max_leases) const {
2013 .arg(max_leases);
2014
2015 if (MultiThreadingMgr::instance().getMode()) {
2016 std::lock_guard<std::mutex> lock(*mutex_);
2017 getExpiredLeases4Internal(expired_leases, max_leases);
2018 } else {
2019 getExpiredLeases4Internal(expired_leases, max_leases);
2020 }
2021}
2022
2023void
2024Memfile_LeaseMgr::getExpiredLeases6Internal(Lease6Collection& expired_leases,
2025 const size_t max_leases) const {
2026 // Obtain the index which segragates leases by state and time.
2027 const Lease6StorageExpirationIndex& index = storage6_.get<ExpirationIndexTag>();
2028
2029 // Retrieve leases which are not reclaimed and which haven't expired. The
2030 // 'less-than' operator will be used for both components of the index. So,
2031 // for the 'state' 'false' is less than 'true'. Also the leases with
2032 // expiration time lower than current time will be returned.
2033 Lease6StorageExpirationIndex::const_iterator ub =
2034 index.upper_bound(boost::make_tuple(false, time(0)));
2035
2036 // Copy only the number of leases indicated by the max_leases parameter.
2037 for (Lease6StorageExpirationIndex::const_iterator lease = index.begin();
2038 (lease != ub) &&
2039 ((max_leases == 0) ||
2040 (static_cast<size_t>(std::distance(index.begin(), lease)) < max_leases));
2041 ++lease) {
2042 expired_leases.push_back(Lease6Ptr(new Lease6(**lease)));
2043 }
2044}
2045
2046void
2048 const size_t max_leases) const {
2050 .arg(max_leases);
2051
2052 if (MultiThreadingMgr::instance().getMode()) {
2053 std::lock_guard<std::mutex> lock(*mutex_);
2054 getExpiredLeases6Internal(expired_leases, max_leases);
2055 } else {
2056 getExpiredLeases6Internal(expired_leases, max_leases);
2057 }
2058}
2059
2060void
2061Memfile_LeaseMgr::updateLease4Internal(const Lease4Ptr& lease) {
2062 // Obtain 'by address' index.
2063 Lease4StorageAddressIndex& index = storage4_.get<AddressIndexTag>();
2064
2065 bool persist = persistLeases(V4);
2066
2067 // Lease must exist if it is to be updated.
2068 Lease4StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
2069 if (lease_it == index.end()) {
2070 isc_throw(NoSuchLease, "failed to update the lease with address "
2071 << lease->addr_ << " - no such lease");
2072 } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
2073 ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
2074 // For test purpose only: check that the lease has not changed in
2075 // the database.
2076 isc_throw(NoSuchLease, "unable to update lease for address " <<
2077 lease->addr_.toText() << " either because the lease does not exist, "
2078 "it has been deleted or it has changed in the database.");
2079 }
2080
2081 // Try to write a lease to disk first. If this fails, the lease will
2082 // not be inserted to the memory and the disk and in-memory data will
2083 // remain consistent.
2084 if (persist) {
2085 try {
2086 lease_file4_->append(*lease);
2087 } catch (const CSVFileFatalError&) {
2088 handleDbLost();
2089 throw;
2090 }
2091 }
2092
2093 // Update lease current expiration time.
2094 lease->updateCurrentExpirationTime();
2095
2096 // Save a copy of the old lease as lease_it will point to the new
2097 // one after the replacement.
2098 Lease4Ptr old_lease = *lease_it;
2099
2100 // Use replace() to re-index leases.
2101 index.replace(lease_it, Lease4Ptr(new Lease4(*lease)));
2102
2103 // Adjust class lease counters.
2104 class_lease_counter_.updateLease(lease, old_lease);
2105
2106 // Run installed callbacks.
2107 if (hasCallbacks()) {
2108 trackUpdateLease(lease);
2109 }
2110}
2111
2112void
2115 DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
2116
2117 if (MultiThreadingMgr::instance().getMode()) {
2118 std::lock_guard<std::mutex> lock(*mutex_);
2119 updateLease4Internal(lease);
2120 } else {
2121 updateLease4Internal(lease);
2122 }
2123}
2124
2125void
2126Memfile_LeaseMgr::updateLease6Internal(const Lease6Ptr& lease) {
2127 // Obtain 'by address' index.
2128 Lease6StorageAddressIndex& index = storage6_.get<AddressIndexTag>();
2129
2130 bool persist = persistLeases(V6);
2131
2132 // Get the recorded action and reset it.
2133 Lease6::ExtendedInfoAction recorded_action = lease->extended_info_action_;
2134 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
2135
2136 // Lease must exist if it is to be updated.
2137 Lease6StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
2138 if (lease_it == index.end()) {
2139 isc_throw(NoSuchLease, "failed to update the lease with address "
2140 << lease->addr_ << " - no such lease");
2141 } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
2142 ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
2143 // For test purpose only: check that the lease has not changed in
2144 // the database.
2145 isc_throw(NoSuchLease, "unable to update lease for address " <<
2146 lease->addr_.toText() << " either because the lease does not exist, "
2147 "it has been deleted or it has changed in the database.");
2148 }
2149
2150 // Try to write a lease to disk first. If this fails, the lease will
2151 // not be inserted to the memory and the disk and in-memory data will
2152 // remain consistent.
2153 if (persist) {
2154 try {
2155 lease_file6_->append(*lease);
2156 } catch (const CSVFileFatalError&) {
2157 handleDbLost();
2158 throw;
2159 }
2160 }
2161
2162 // Update lease current expiration time.
2163 lease->updateCurrentExpirationTime();
2164
2165 // Save a copy of the old lease as lease_it will point to the new
2166 // one after the replacement.
2167 Lease6Ptr old_lease = *lease_it;
2168
2169 // Use replace() to re-index leases.
2170 index.replace(lease_it, Lease6Ptr(new Lease6(*lease)));
2171
2172 // Adjust class lease counters.
2173 class_lease_counter_.updateLease(lease, old_lease);
2174
2175 // Update extended info tables.
2177 switch (recorded_action) {
2179 break;
2180
2182 deleteExtendedInfo6(lease->addr_);
2183 break;
2184
2186 deleteExtendedInfo6(lease->addr_);
2187 static_cast<void>(addExtendedInfo6(lease));
2188 break;
2189 }
2190 }
2191
2192 // Run installed callbacks.
2193 if (hasCallbacks()) {
2194 trackUpdateLease(lease);
2195 }
2196}
2197
2198void
2201 DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
2202
2203 if (MultiThreadingMgr::instance().getMode()) {
2204 std::lock_guard<std::mutex> lock(*mutex_);
2205 updateLease6Internal(lease);
2206 } else {
2207 updateLease6Internal(lease);
2208 }
2209}
2210
2211bool
2212Memfile_LeaseMgr::deleteLeaseInternal(const Lease4Ptr& lease) {
2213 const isc::asiolink::IOAddress& addr = lease->addr_;
2214 Lease4Storage::iterator l = storage4_.find(addr);
2215 if (l == storage4_.end()) {
2216 // No such lease
2217 return (false);
2218 } else {
2219 if (persistLeases(V4)) {
2220 // Copy the lease. The valid lifetime needs to be modified and
2221 // we don't modify the original lease.
2222 Lease4 lease_copy = **l;
2223 // Setting valid lifetime to 0 means that lease is being
2224 // removed.
2225 lease_copy.valid_lft_ = 0;
2226 try {
2227 lease_file4_->append(lease_copy);
2228 } catch (const CSVFileFatalError&) {
2229 handleDbLost();
2230 throw;
2231 }
2232 } else {
2233 // For test purpose only: check that the lease has not changed in
2234 // the database.
2235 if (((*l)->cltt_ != lease->current_cltt_) ||
2236 ((*l)->valid_lft_ != lease->current_valid_lft_)) {
2237 return false;
2238 }
2239 }
2240
2241 storage4_.erase(l);
2242
2243 // Decrement class lease counters.
2244 class_lease_counter_.removeLease(lease);
2245
2246 // Run installed callbacks.
2247 if (hasCallbacks()) {
2248 trackDeleteLease(lease);
2249 }
2250
2251 return (true);
2252 }
2253}
2254
2255bool
2258 DHCPSRV_MEMFILE_DELETE_ADDR4).arg(lease->addr_.toText());
2259
2260 if (MultiThreadingMgr::instance().getMode()) {
2261 std::lock_guard<std::mutex> lock(*mutex_);
2262 return (deleteLeaseInternal(lease));
2263 } else {
2264 return (deleteLeaseInternal(lease));
2265 }
2266}
2267
2268bool
2269Memfile_LeaseMgr::deleteLeaseInternal(const Lease6Ptr& lease) {
2270 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
2271
2272 const isc::asiolink::IOAddress& addr = lease->addr_;
2273 Lease6Storage::iterator l = storage6_.find(addr);
2274 if (l == storage6_.end()) {
2275 // No such lease
2276 return (false);
2277 } else {
2278 if (persistLeases(V6)) {
2279 // Copy the lease. The lifetimes need to be modified and we
2280 // don't modify the original lease.
2281 Lease6 lease_copy = **l;
2282 // Setting lifetimes to 0 means that lease is being removed.
2283 lease_copy.valid_lft_ = 0;
2284 lease_copy.preferred_lft_ = 0;
2285 try {
2286 lease_file6_->append(lease_copy);
2287 } catch (const CSVFileFatalError&) {
2288 handleDbLost();
2289 throw;
2290 }
2291 } else {
2292 // For test purpose only: check that the lease has not changed in
2293 // the database.
2294 if (((*l)->cltt_ != lease->current_cltt_) ||
2295 ((*l)->valid_lft_ != lease->current_valid_lft_)) {
2296 return false;
2297 }
2298 }
2299
2300 storage6_.erase(l);
2301
2302 // Decrement class lease counters.
2303 class_lease_counter_.removeLease(lease);
2304
2305 // Delete references from extended info tables.
2307 deleteExtendedInfo6(lease->addr_);
2308 }
2309
2310 // Run installed callbacks.
2311 if (hasCallbacks()) {
2312 trackDeleteLease(lease);
2313 }
2314
2315 return (true);
2316 }
2317}
2318
2319bool
2322 DHCPSRV_MEMFILE_DELETE_ADDR6).arg(lease->addr_.toText());
2323
2324 if (MultiThreadingMgr::instance().getMode()) {
2325 std::lock_guard<std::mutex> lock(*mutex_);
2326 return (deleteLeaseInternal(lease));
2327 } else {
2328 return (deleteLeaseInternal(lease));
2329 }
2330}
2331
2332uint64_t
2336 .arg(secs);
2337
2338 if (MultiThreadingMgr::instance().getMode()) {
2339 std::lock_guard<std::mutex> lock(*mutex_);
2340 return (deleteExpiredReclaimedLeases<
2342 >(secs, V4, storage4_, lease_file4_));
2343 } else {
2344 return (deleteExpiredReclaimedLeases<
2346 >(secs, V4, storage4_, lease_file4_));
2347 }
2348}
2349
2350uint64_t
2354 .arg(secs);
2355
2356 if (MultiThreadingMgr::instance().getMode()) {
2357 std::lock_guard<std::mutex> lock(*mutex_);
2358 return (deleteExpiredReclaimedLeases<
2360 >(secs, V6, storage6_, lease_file6_));
2361 } else {
2362 return (deleteExpiredReclaimedLeases<
2364 >(secs, V6, storage6_, lease_file6_));
2365 }
2366}
2367
2368template<typename IndexType, typename LeaseType, typename StorageType,
2369 typename LeaseFileType>
2370uint64_t
2371Memfile_LeaseMgr::deleteExpiredReclaimedLeases(const uint32_t secs,
2372 const Universe& universe,
2373 StorageType& storage,
2374 LeaseFileType& lease_file) {
2375 // Obtain the index which segragates leases by state and time.
2376 IndexType& index = storage.template get<ExpirationIndexTag>();
2377
2378 // This returns the first element which is greater than the specified
2379 // tuple (true, time(0) - secs). However, the range between the
2380 // beginning of the index and returned element also includes all the
2381 // elements for which the first value is false (lease state is NOT
2382 // reclaimed), because false < true. All elements between the
2383 // beginning of the index and the element returned, for which the
2384 // first value is true, represent the reclaimed leases which should
2385 // be deleted, because their expiration time + secs has occurred earlier
2386 // than current time.
2387 typename IndexType::const_iterator upper_limit =
2388 index.upper_bound(boost::make_tuple(true, time(0) - secs));
2389
2390 // Now, we have to exclude all elements of the index which represent
2391 // leases in the state other than reclaimed - with the first value
2392 // in the index equal to false. Note that elements in the index are
2393 // ordered from the lower to the higher ones. So, all elements with
2394 // the first value of false are placed before the elements with the
2395 // value of true. Hence, we have to find the first element which
2396 // contains value of true. The time value is the lowest possible.
2397 typename IndexType::const_iterator lower_limit =
2398 index.upper_bound(boost::make_tuple(true, std::numeric_limits<int64_t>::min()));
2399
2400 // If there are some elements in this range, delete them.
2401 uint64_t num_leases = static_cast<uint64_t>(std::distance(lower_limit, upper_limit));
2402 if (num_leases > 0) {
2403
2406 .arg(num_leases);
2407
2408 // If lease persistence is enabled, we also have to mark leases
2409 // as deleted in the lease file. We do this by setting the
2410 // lifetime to 0.
2411 if (persistLeases(universe)) {
2412 for (typename IndexType::const_iterator lease = lower_limit;
2413 lease != upper_limit; ++lease) {
2414 // Copy lease to not affect the lease in the container.
2415 LeaseType lease_copy(**lease);
2416 // Set the valid lifetime to 0 to indicate the removal
2417 // of the lease.
2418 lease_copy.valid_lft_ = 0;
2419 try {
2420 lease_file->append(lease_copy);
2421 } catch (const CSVFileFatalError&) {
2422 handleDbLost();
2423 throw;
2424 }
2425 }
2426 }
2427
2428 // Erase leases from memory.
2429 index.erase(lower_limit, upper_limit);
2430
2431 }
2432 // Return number of leases deleted.
2433 return (num_leases);
2434}
2435
2436std::string
2438 return (std::string("In memory database with leases stored in a CSV file."));
2439}
2440
2441std::pair<uint32_t, uint32_t>
2442Memfile_LeaseMgr::getVersion(const std::string& /* timer_name */) const {
2443 std::string const& universe(conn_.getParameter("universe"));
2444 if (universe == "4") {
2445 return std::make_pair(MAJOR_VERSION_V4, MINOR_VERSION_V4);
2446 } else if (universe == "6") {
2447 return std::make_pair(MAJOR_VERSION_V6, MINOR_VERSION_V6);
2448 }
2449 isc_throw(BadValue, "cannot determine version for universe " << universe);
2450}
2451
2452void
2456
2457void
2462
2463bool
2464Memfile_LeaseMgr::isLFCProcessRunning(const std::string file_name, Universe u) {
2465 std::string lease_file(file_name);
2466 if (lease_file.empty()) {
2468 }
2469 PIDFile pid_file(Memfile_LeaseMgr::appendSuffix(lease_file, FILE_PID));
2470 PIDLock pid_lock(pid_file.getLockname());
2471 return (!pid_lock.isLocked() || pid_file.check());
2472}
2473
2476 std::string file_name;
2477 if (lease_file4_) {
2478 file_name = lease_file4_->getFilename();
2479 } else if (lease_file6_) {
2480 file_name = lease_file6_->getFilename();
2481 } else {
2482 return (ElementPtr());
2483 }
2484 if (file_name.empty()) {
2485 // Should not happen.
2486 return (ElementPtr());
2487 }
2488 ElementPtr status = Element::createMap();
2489 status->set("csv-lease-file", Element::create(file_name));
2490 return (status);
2491}
2492
2493std::string
2494Memfile_LeaseMgr::appendSuffix(const std::string& file_name,
2495 const LFCFileType& file_type) {
2496 std::string name(file_name);
2497 switch (file_type) {
2498 case FILE_INPUT:
2499 name += ".1";
2500 break;
2501 case FILE_PREVIOUS:
2502 name += ".2";
2503 break;
2504 case FILE_OUTPUT:
2505 name += ".output";
2506 break;
2507 case FILE_FINISH:
2508 name += ".completed";
2509 break;
2510 case FILE_PID:
2511 name += ".pid";
2512 break;
2513 default:
2514 // Do not append any suffix for the FILE_CURRENT.
2515 ;
2516 }
2517
2518 return (name);
2519}
2520
2521std::string
2523 std::string filename /* = "" */) {
2524 std::ostringstream s;;
2526 if (filename.empty()) {
2527 s << "/kea-leases";
2528 s << (u == V4 ? "4" : "6");
2529 s << ".csv";
2530 } else {
2531 s << "/" << filename;
2532 }
2533
2534 return (s.str());
2535}
2536
2537std::string
2539 if (u == V4) {
2540 return (lease_file4_ ? lease_file4_->getFilename() : "");
2541 }
2542
2543 return (lease_file6_ ? lease_file6_->getFilename() : "");
2544}
2545
2546bool
2548 // Currently, if the lease file IO is not created, it means that writes to
2549 // disk have been explicitly disabled by the administrator. At some point,
2550 // there may be a dedicated ON/OFF flag implemented to control this.
2551 if (u == V4 && lease_file4_) {
2552 return (true);
2553 }
2554
2555 return (u == V6 && lease_file6_);
2556}
2557
2558std::string
2559Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
2560 std::string persist_val;
2561 try {
2562 persist_val = conn_.getParameter("persist");
2563 } catch (const Exception&) {
2564 // If parameter persist hasn't been specified, we use a default value
2565 // 'yes'.
2566 persist_val = "true";
2567 }
2568 // If persist_val is 'false' we will not store leases to disk, so let's
2569 // return empty file name.
2570 if (persist_val == "false" || MultiThreadingMgr::instance().isTestMode()) {
2571 return ("");
2572
2573 } else if (persist_val != "true") {
2574 isc_throw(isc::BadValue, "invalid value 'persist="
2575 << persist_val << "'");
2576 }
2577
2578 std::string lease_file;
2579 try {
2580 lease_file = conn_.getParameter("name");
2581 } catch (const Exception&) {
2582 // Not specified, use the default.
2584 }
2585
2586 try {
2587 lease_file = CfgMgr::instance().validatePath(lease_file);
2588 } catch (const SecurityWarn& ex) {
2590 .arg(ex.what());
2591 }
2592
2593 return (lease_file);
2594}
2595
2596template<typename LeaseObjectType, typename LeaseFileType, typename StorageType>
2597bool
2598Memfile_LeaseMgr::loadLeasesFromFiles(Universe u, const std::string& filename,
2599 boost::shared_ptr<LeaseFileType>& lease_file,
2600 StorageType& storage) {
2601 // Check if the instance of the LFC is running right now. If it is
2602 // running, we refuse to load leases as the LFC may be writing to the
2603 // lease files right now. When the user retries server configuration
2604 // it should go through.
2607 if (Memfile_LeaseMgr::isLFCProcessRunning(filename, u)) {
2608 isc_throw(DbOpenError, "unable to load leases from files while the "
2609 "lease file cleanup is in progress");
2610 }
2611
2612 storage.clear();
2613
2614 std::string max_row_errors_str = "0";
2615 try {
2616 max_row_errors_str = conn_.getParameter("max-row-errors");
2617 } catch (const std::exception&) {
2618 // Ignore and default to 0.
2619 }
2620
2621 int64_t max_row_errors64;
2622 try {
2623 max_row_errors64 = boost::lexical_cast<int64_t>(max_row_errors_str);
2624 } catch (const boost::bad_lexical_cast&) {
2625 isc_throw(isc::BadValue, "invalid value of the max-row-errors "
2626 << max_row_errors_str << " specified");
2627 }
2628 if ((max_row_errors64 < 0) ||
2629 (max_row_errors64 > std::numeric_limits<uint32_t>::max())) {
2630 isc_throw(isc::BadValue, "invalid value of the max-row-errors "
2631 << max_row_errors_str << " specified");
2632 }
2633 uint32_t max_row_errors = static_cast<uint32_t>(max_row_errors64);
2634
2635 // Load the leasefile.completed, if exists.
2636 bool conversion_needed = false;
2637 lease_file.reset(new LeaseFileType(std::string(filename + ".completed")));
2638 if (lease_file->exists()) {
2639 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2640 max_row_errors);
2641 conversion_needed = conversion_needed || lease_file->needsConversion();
2642 } else {
2643 // If the leasefile.completed doesn't exist, let's load the leases
2644 // from leasefile.2 and leasefile.1, if they exist.
2645 lease_file.reset(new LeaseFileType(Memfile_LeaseMgr::appendSuffix(filename, FILE_PREVIOUS)));
2646 if (lease_file->exists()) {
2647 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2648 max_row_errors);
2649 conversion_needed = conversion_needed || lease_file->needsConversion();
2650 }
2651
2652 lease_file.reset(new LeaseFileType(Memfile_LeaseMgr::appendSuffix(filename, FILE_INPUT)));
2653 if (lease_file->exists()) {
2654 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2655 max_row_errors);
2656 conversion_needed = conversion_needed || lease_file->needsConversion();
2657 }
2658 }
2659
2660 // Always load leases from the primary lease file. If the lease file
2661 // doesn't exist it will be created by the LeaseFileLoader. Note
2662 // that the false value passed as the last parameter to load
2663 // function causes the function to leave the file open after
2664 // it is parsed. This file will be used by the backend to record
2665 // future lease updates.
2666 lease_file.reset(new LeaseFileType(filename));
2667 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2668 max_row_errors, false);
2669 conversion_needed = conversion_needed || lease_file->needsConversion();
2670
2671 return (conversion_needed);
2672}
2673
2674bool
2676 return (lfc_setup_->isRunning());
2677}
2678
2679int
2681 return (lfc_setup_->getExitStatus());
2682}
2683
2684int
2686 return (lfc_setup_->getLastPid());
2687}
2688
2689void
2691 // Check if we're in the v4 or v6 space and use the appropriate file.
2692 if (lease_file4_) {
2694 lfcExecute(lease_file4_);
2695 } else if (lease_file6_) {
2697 lfcExecute(lease_file6_);
2698 }
2699}
2700
2701void
2702Memfile_LeaseMgr::lfcSetup(bool conversion_needed) {
2703 std::string lfc_interval_str = "3600";
2704 try {
2705 lfc_interval_str = conn_.getParameter("lfc-interval");
2706 } catch (const std::exception&) {
2707 // Ignore and default to 3600.
2708 }
2709
2710 uint32_t lfc_interval = 0;
2711 try {
2712 lfc_interval = boost::lexical_cast<uint32_t>(lfc_interval_str);
2713 } catch (const boost::bad_lexical_cast&) {
2714 isc_throw(isc::BadValue, "invalid value of the lfc-interval "
2715 << lfc_interval_str << " specified");
2716 }
2717
2718 lfc_setup_.reset(new LFCSetup(std::bind(&Memfile_LeaseMgr::lfcCallback, this)));
2719 lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_, conversion_needed);
2720}
2721
2722template<typename LeaseFileType>
2723void
2724Memfile_LeaseMgr::lfcExecute(boost::shared_ptr<LeaseFileType>& lease_file) {
2726
2727 bool do_lfc = true;
2728
2729 // Check the status of the LFC instance.
2730 // If the finish file exists or the copy of the lease file exists it
2731 // is an indication that another LFC instance may be in progress or
2732 // may be stalled. In that case we don't want to rotate the current
2733 // lease file to avoid overriding the contents of the existing file.
2734 CSVFile lease_file_finish(Memfile_LeaseMgr::appendSuffix(lease_file->getFilename(), FILE_FINISH));
2735 CSVFile lease_file_copy(Memfile_LeaseMgr::appendSuffix(lease_file->getFilename(), FILE_INPUT));
2736 if (!lease_file_finish.exists() && !lease_file_copy.exists()) {
2737 // Close the current file so as we can move it to the copy file.
2738 lease_file->close();
2739 // Move the current file to the copy file. Remember the result
2740 // because we don't want to run LFC if the rename failed.
2741 do_lfc = (rename(lease_file->getFilename().c_str(),
2742 lease_file_copy.getFilename().c_str()) == 0);
2743
2744 if (!do_lfc) {
2746 .arg(lease_file->getFilename())
2747 .arg(lease_file_copy.getFilename())
2748 .arg(strerror(errno));
2749 }
2750
2751 // Regardless if we successfully moved the current file or not,
2752 // we need to re-open the current file for the server to write
2753 // new lease updates. If the file has been successfully moved,
2754 // this will result in creation of the new file. Otherwise,
2755 // an existing file will be opened.
2756 try {
2757 lease_file->open(true);
2758
2759 } catch (const CSVFileError& ex) {
2760 // If we're unable to open the lease file this is a serious
2761 // error because the server will not be able to persist
2762 // leases.
2770 .arg(lease_file->getFilename())
2771 .arg(ex.what());
2772 // Reset the pointer to the file so as the backend doesn't
2773 // try to write leases to disk.
2774 lease_file.reset();
2775 do_lfc = false;
2776 }
2777 }
2778 // Once the files have been rotated, or untouched if another LFC had
2779 // not finished, a new process is started.
2780 if (do_lfc) {
2781 lfc_setup_->execute(lease_file->getFilename());
2782 }
2783}
2784
2787 if (!persistLeases(V4) && !persistLeases(V6)) {
2788 std::ostringstream msg;
2789 msg << "'persist' parameter of 'memfile' lease backend "
2790 << "was configured to 'false'";
2792 }
2794 // Reschedule the periodic lfc run.
2795 if (TimerMgr::instance()->isTimerRegistered("memfile-lfc")) {
2796 TimerMgr::instance()->cancel("memfile-lfc");
2797 TimerMgr::instance()->setup("memfile-lfc");
2799 }
2800 int previous_pid = getLFCLastPid();
2801 if (lease_file4_) {
2802 lfcExecute(lease_file4_);
2803 } else if (lease_file6_) {
2804 lfcExecute(lease_file6_);
2805 }
2806 int new_pid = getLFCLastPid();
2807 if (new_pid == -1) {
2808 return (createAnswer(CONTROL_RESULT_ERROR, "failed to start kea-lfc"));
2809 } else if (new_pid != previous_pid) {
2810 return (createAnswer(CONTROL_RESULT_SUCCESS, "kea-lfc started"));
2811 } else {
2812 return (createAnswer(CONTROL_RESULT_EMPTY, "kea-lfc already running"));
2813 }
2814}
2815
2818 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_));
2819 if (MultiThreadingMgr::instance().getMode()) {
2820 std::lock_guard<std::mutex> lock(*mutex_);
2821 query->start();
2822 } else {
2823 query->start();
2824 }
2825
2826 return(query);
2827}
2828
2832 if (MultiThreadingMgr::instance().getMode()) {
2833 std::lock_guard<std::mutex> lock(*mutex_);
2834 query->start();
2835 } else {
2836 query->start();
2837 }
2838
2839 return(query);
2840}
2841
2844 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, subnet_id));
2845 if (MultiThreadingMgr::instance().getMode()) {
2846 std::lock_guard<std::mutex> lock(*mutex_);
2847 query->start();
2848 } else {
2849 query->start();
2850 }
2851
2852 return(query);
2853}
2854
2857 const SubnetID& last_subnet_id) {
2858 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, first_subnet_id,
2859 last_subnet_id));
2860 if (MultiThreadingMgr::instance().getMode()) {
2861 std::lock_guard<std::mutex> lock(*mutex_);
2862 query->start();
2863 } else {
2864 query->start();
2865 }
2866
2867 return(query);
2868}
2869
2872 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_));
2873 if (MultiThreadingMgr::instance().getMode()) {
2874 std::lock_guard<std::mutex> lock(*mutex_);
2875 query->start();
2876 } else {
2877 query->start();
2878 }
2879
2880 return(query);
2881}
2882
2886 if (MultiThreadingMgr::instance().getMode()) {
2887 std::lock_guard<std::mutex> lock(*mutex_);
2888 query->start();
2889 } else {
2890 query->start();
2891 }
2892
2893 return(query);
2894}
2895
2898 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, subnet_id));
2899 if (MultiThreadingMgr::instance().getMode()) {
2900 std::lock_guard<std::mutex> lock(*mutex_);
2901 query->start();
2902 } else {
2903 query->start();
2904 }
2905
2906 return(query);
2907}
2908
2911 const SubnetID& last_subnet_id) {
2912 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, first_subnet_id,
2913 last_subnet_id));
2914 if (MultiThreadingMgr::instance().getMode()) {
2915 std::lock_guard<std::mutex> lock(*mutex_);
2916 query->start();
2917 } else {
2918 query->start();
2919 }
2920
2921 return(query);
2922}
2923
2924size_t
2927 .arg(subnet_id);
2928
2929 // Get the index by DUID, IAID, lease type.
2930 const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
2931
2932 // Try to get the lease using the DUID, IAID and lease type.
2933 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
2934 Lease4StorageSubnetIdIndex::const_iterator> r =
2935 idx.equal_range(subnet_id);
2936
2937 // Let's collect all leases.
2938 Lease4Collection leases;
2939 BOOST_FOREACH(auto const& lease, r) {
2940 leases.push_back(lease);
2941 }
2942
2943 size_t num = leases.size();
2944 for (auto const& l : leases) {
2945 deleteLease(l);
2946 }
2948 .arg(subnet_id).arg(num);
2949
2950 return (num);
2951}
2952
2953size_t
2956 .arg(subnet_id);
2957
2958 // Get the index by DUID, IAID, lease type.
2959 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
2960
2961 // Try to get the lease using the DUID, IAID and lease type.
2962 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
2963 Lease6StorageSubnetIdIndex::const_iterator> r =
2964 idx.equal_range(subnet_id);
2965
2966 // Let's collect all leases.
2967 Lease6Collection leases;
2968 BOOST_FOREACH(auto const& lease, r) {
2969 leases.push_back(lease);
2970 }
2971
2972 size_t num = leases.size();
2973 for (auto const& l : leases) {
2974 deleteLease(l);
2975 }
2977 .arg(subnet_id).arg(num);
2978
2979 return (num);
2980}
2981
2982void
2984 class_lease_counter_.clear();
2985 for (auto const& lease : storage4_) {
2986 // Bump the appropriate accumulator
2987 if (lease->state_ == Lease::STATE_DEFAULT) {
2988 class_lease_counter_.addLease(lease);
2989 }
2990 }
2991}
2992
2993void
2995 class_lease_counter_.clear();
2996 for (auto const& lease : storage6_) {
2997 // Bump the appropriate accumulator
2998 if (lease->state_ == Lease::STATE_DEFAULT) {
2999 class_lease_counter_.addLease(lease);
3000 }
3001 }
3002}
3003
3004size_t
3006 const Lease::Type& ltype /* = Lease::TYPE_V4*/) const {
3007 if (MultiThreadingMgr::instance().getMode()) {
3008 std::lock_guard<std::mutex> lock(*mutex_);
3009 return(class_lease_counter_.getClassCount(client_class, ltype));
3010 } else {
3011 return(class_lease_counter_.getClassCount(client_class, ltype));
3012 }
3013}
3014
3015void
3017 return(class_lease_counter_.clear());
3018}
3019
3020std::string
3022 if (!user_context) {
3023 return ("");
3024 }
3025
3026 ConstElementPtr limits = user_context->find("ISC/limits");
3027 if (!limits) {
3028 return ("");
3029 }
3030
3031 // Iterate of the 'client-classes' list in 'limits'. For each class that specifies
3032 // an "address-limit", check its value against the class's lease count.
3033 ConstElementPtr classes = limits->get("client-classes");
3034 if (classes) {
3035 for (unsigned i = 0; i < classes->size(); ++i) {
3036 ConstElementPtr class_elem = classes->get(i);
3037 // Get class name.
3038 ConstElementPtr name_elem = class_elem->get("name");
3039 if (!name_elem) {
3040 isc_throw(BadValue, "checkLimits4 - client-class.name is missing: "
3041 << prettyPrint(limits));
3042 }
3043
3044 std::string name = name_elem->stringValue();
3045
3046 // Now look for an address-limit
3047 size_t limit;
3048 if (!getLeaseLimit(class_elem, Lease::TYPE_V4, limit)) {
3049 // No limit, go to the next class.
3050 continue;
3051 }
3052
3053 // If the limit is > 0 look up the class lease count. Limit of 0 always
3054 // denies the lease.
3055 size_t lease_count = 0;
3056 if (limit) {
3057 lease_count = getClassLeaseCount(name);
3058 }
3059
3060 // If we're over the limit, return the error, no need to evaluate any others.
3061 if (lease_count >= limit) {
3062 std::ostringstream ss;
3063 ss << "address limit " << limit << " for client class \""
3064 << name << "\", current lease count " << lease_count;
3065 return (ss.str());
3066 }
3067 }
3068 }
3069
3070 // If there were class limits we passed them, now look for a subnet limit.
3071 ConstElementPtr subnet_elem = limits->get("subnet");
3072 if (subnet_elem) {
3073 // Get the subnet id.
3074 ConstElementPtr id_elem = subnet_elem->get("id");
3075 if (!id_elem) {
3076 isc_throw(BadValue, "checkLimits4 - subnet.id is missing: "
3077 << prettyPrint(limits));
3078 }
3079
3080 SubnetID subnet_id = id_elem->intValue();
3081
3082 // Now look for an address-limit.
3083 size_t limit;
3084 if (getLeaseLimit(subnet_elem, Lease::TYPE_V4, limit)) {
3085 // If the limit is > 0 look up the subnet lease count. Limit of 0 always
3086 // denies the lease.
3087 int64_t lease_count = 0;
3088 if (limit) {
3089 lease_count = getSubnetStat(subnet_id, "assigned-addresses");
3090 }
3091
3092 // If we're over the limit, return the error.
3093 if (static_cast<uint64_t>(lease_count) >= limit) {
3094 std::ostringstream ss;
3095 ss << "address limit " << limit << " for subnet ID " << subnet_id
3096 << ", current lease count " << lease_count;
3097 return (ss.str());
3098 }
3099 }
3100 }
3101
3102 // No limits exceeded!
3103 return ("");
3104}
3105
3106std::string
3108 if (!user_context) {
3109 return ("");
3110 }
3111
3112 ConstElementPtr limits = user_context->find("ISC/limits");
3113 if (!limits) {
3114 return ("");
3115 }
3116
3117 // Iterate over the 'client-classes' list in 'limits'. For each class that specifies
3118 // limit (either "address-limit" or "prefix-limit", check its value against the appropriate
3119 // class lease count.
3120 ConstElementPtr classes = limits->get("client-classes");
3121 if (classes) {
3122 for (unsigned i = 0; i < classes->size(); ++i) {
3123 ConstElementPtr class_elem = classes->get(i);
3124 // Get class name.
3125 ConstElementPtr name_elem = class_elem->get("name");
3126 if (!name_elem) {
3127 isc_throw(BadValue, "checkLimits6 - client-class.name is missing: "
3128 << prettyPrint(limits));
3129 }
3130
3131 std::string name = name_elem->stringValue();
3132
3133 // Now look for either address-limit or a prefix=limit.
3134 size_t limit = 0;
3136 if (!getLeaseLimit(class_elem, ltype, limit)) {
3137 ltype = Lease::TYPE_PD;
3138 if (!getLeaseLimit(class_elem, ltype, limit)) {
3139 // No limits for this class, skip to the next.
3140 continue;
3141 }
3142 }
3143
3144 // If the limit is > 0 look up the class lease count. Limit of 0 always
3145 // denies the lease.
3146 size_t lease_count = 0;
3147 if (limit) {
3148 lease_count = getClassLeaseCount(name, ltype);
3149 }
3150
3151 // If we're over the limit, return the error, no need to evaluate any others.
3152 if (lease_count >= limit) {
3153 std::ostringstream ss;
3154 ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
3155 << " limit " << limit << " for client class \""
3156 << name << "\", current lease count " << lease_count;
3157 return (ss.str());
3158 }
3159 }
3160 }
3161
3162 // If there were class limits we passed them, now look for a subnet limit.
3163 ConstElementPtr subnet_elem = limits->get("subnet");
3164 if (subnet_elem) {
3165 // Get the subnet id.
3166 ConstElementPtr id_elem = subnet_elem->get("id");
3167 if (!id_elem) {
3168 isc_throw(BadValue, "checkLimits6 - subnet.id is missing: "
3169 << prettyPrint(limits));
3170 }
3171
3172 SubnetID subnet_id = id_elem->intValue();
3173
3174 // Now look for either address-limit or a prefix=limit.
3175 size_t limit = 0;
3177 if (!getLeaseLimit(subnet_elem, ltype, limit)) {
3178 ltype = Lease::TYPE_PD;
3179 if (!getLeaseLimit(subnet_elem, ltype, limit)) {
3180 // No limits for the subnet so none exceeded!
3181 return ("");
3182 }
3183 }
3184
3185 // If the limit is > 0 look up the class lease count. Limit of 0 always
3186 // denies the lease.
3187 int64_t lease_count = 0;
3188 if (limit) {
3189 lease_count = getSubnetStat(subnet_id, (ltype == Lease::TYPE_NA ?
3190 "assigned-nas" : "assigned-pds"));
3191 }
3192
3193 // If we're over the limit, return the error.
3194 if (static_cast<uint64_t>(lease_count) >= limit) {
3195 std::ostringstream ss;
3196 ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
3197 << " limit " << limit << " for subnet ID " << subnet_id
3198 << ", current lease count " << lease_count;
3199 return (ss.str());
3200 }
3201 }
3202
3203 // No limits exceeded!
3204 return ("");
3205}
3206
3207int64_t
3208Memfile_LeaseMgr::getSubnetStat(const SubnetID& subnet_id, const std::string& stat_label) const {
3211 std::string stat_name = StatsMgr::generateName("subnet", subnet_id, stat_label);
3212 ConstElementPtr stat = StatsMgr::instance().get(stat_name);
3213 ConstElementPtr samples = stat->get(stat_name);
3214 if (samples && samples->size()) {
3215 auto sample = samples->get(0);
3216 if (sample->size()) {
3217 auto count_elem = sample->get(0);
3218 return (count_elem->intValue());
3219 }
3220 }
3221
3222 return (0);
3223}
3224
3225bool
3226Memfile_LeaseMgr::getLeaseLimit(ConstElementPtr parent, Lease::Type ltype, size_t& limit) const {
3227 ConstElementPtr limit_elem = parent->get(ltype == Lease::TYPE_PD ?
3228 "prefix-limit" : "address-limit");
3229 if (limit_elem) {
3230 limit = limit_elem->intValue();
3231 return (true);
3232 }
3233
3234 return (false);
3235}
3236
3237namespace {
3238
3239std::string
3240idToText(const OptionBuffer& id) {
3241 std::stringstream tmp;
3242 tmp << std::hex;
3243 bool delim = false;
3244 for (auto const& it : id) {
3245 if (delim) {
3246 tmp << ":";
3247 }
3248 tmp << std::setw(2) << std::setfill('0')
3249 << static_cast<unsigned int>(it);
3250 delim = true;
3251 }
3252 return (tmp.str());
3253}
3254
3255} // anonymous namespace
3256
3259 const IOAddress& lower_bound_address,
3260 const LeasePageSize& page_size,
3261 const time_t& qry_start_time /* = 0 */,
3262 const time_t& qry_end_time /* = 0 */) {
3265 .arg(page_size.page_size_)
3266 .arg(lower_bound_address.toText())
3267 .arg(idToText(relay_id))
3268 .arg(qry_start_time)
3269 .arg(qry_end_time);
3270
3271 // Expecting IPv4 address.
3272 if (!lower_bound_address.isV4()) {
3273 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
3274 "retrieving leases from the lease database, got "
3275 << lower_bound_address);
3276 }
3277
3278 // Catch 2038 bug with 32 bit time_t.
3279 if ((qry_start_time < 0) || (qry_end_time < 0)) {
3280 isc_throw(BadValue, "negative time value");
3281 }
3282
3283 // Start time must be before end time.
3284 if ((qry_start_time > 0) && (qry_end_time > 0) &&
3285 (qry_start_time > qry_end_time)) {
3286 isc_throw(BadValue, "start time must be before end time");
3287 }
3288
3289 if (MultiThreadingMgr::instance().getMode()) {
3290 std::lock_guard<std::mutex> lock(*mutex_);
3291 return (getLeases4ByRelayIdInternal(relay_id,
3292 lower_bound_address,
3293 page_size,
3294 qry_start_time,
3295 qry_end_time));
3296 } else {
3297 return (getLeases4ByRelayIdInternal(relay_id,
3298 lower_bound_address,
3299 page_size,
3300 qry_start_time,
3301 qry_end_time));
3302 }
3303}
3304
3306Memfile_LeaseMgr::getLeases4ByRelayIdInternal(const OptionBuffer& relay_id,
3307 const IOAddress& lower_bound_address,
3308 const LeasePageSize& page_size,
3309 const time_t& qry_start_time,
3310 const time_t& qry_end_time) {
3311 Lease4Collection collection;
3312 const Lease4StorageRelayIdIndex& idx = storage4_.get<RelayIdIndexTag>();
3313 Lease4StorageRelayIdIndex::const_iterator lb =
3314 idx.lower_bound(boost::make_tuple(relay_id, lower_bound_address));
3315 // Return all convenient leases being within the page size.
3316 IOAddress last_addr = lower_bound_address;
3317 for (; lb != idx.end(); ++lb) {
3318 if ((*lb)->addr_ == last_addr) {
3319 // Already seen: skip it.
3320 continue;
3321 }
3322 if ((*lb)->relay_id_ != relay_id) {
3323 // Gone after the relay id index.
3324 break;
3325 }
3326 last_addr = (*lb)->addr_;
3327 if ((qry_start_time > 0) && ((*lb)->cltt_ < qry_start_time)) {
3328 // Too old.
3329 continue;
3330 }
3331 if ((qry_end_time > 0) && ((*lb)->cltt_ > qry_end_time)) {
3332 // Too young.
3333 continue;
3334 }
3335 collection.push_back(Lease4Ptr(new Lease4(**lb)));
3336 if (collection.size() >= page_size.page_size_) {
3337 break;
3338 }
3339 }
3340 return (collection);
3341}
3342
3345 const IOAddress& lower_bound_address,
3346 const LeasePageSize& page_size,
3347 const time_t& qry_start_time /* = 0 */,
3348 const time_t& qry_end_time /* = 0 */) {
3351 .arg(page_size.page_size_)
3352 .arg(lower_bound_address.toText())
3353 .arg(idToText(remote_id))
3354 .arg(qry_start_time)
3355 .arg(qry_end_time);
3356
3357 // Expecting IPv4 address.
3358 if (!lower_bound_address.isV4()) {
3359 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
3360 "retrieving leases from the lease database, got "
3361 << lower_bound_address);
3362 }
3363
3364 // Catch 2038 bug with 32 bit time_t.
3365 if ((qry_start_time < 0) || (qry_end_time < 0)) {
3366 isc_throw(BadValue, "negative time value");
3367 }
3368
3369 // Start time must be before end time.
3370 if ((qry_start_time > 0) && (qry_end_time > 0) &&
3371 (qry_start_time > qry_end_time)) {
3372 isc_throw(BadValue, "start time must be before end time");
3373 }
3374
3375 if (MultiThreadingMgr::instance().getMode()) {
3376 std::lock_guard<std::mutex> lock(*mutex_);
3377 return (getLeases4ByRemoteIdInternal(remote_id,
3378 lower_bound_address,
3379 page_size,
3380 qry_start_time,
3381 qry_end_time));
3382 } else {
3383 return (getLeases4ByRemoteIdInternal(remote_id,
3384 lower_bound_address,
3385 page_size,
3386 qry_start_time,
3387 qry_end_time));
3388 }
3389}
3390
3392Memfile_LeaseMgr::getLeases4ByRemoteIdInternal(const OptionBuffer& remote_id,
3393 const IOAddress& lower_bound_address,
3394 const LeasePageSize& page_size,
3395 const time_t& qry_start_time,
3396 const time_t& qry_end_time) {
3397 Lease4Collection collection;
3398 std::map<IOAddress, Lease4Ptr> sorted;
3399 const Lease4StorageRemoteIdIndex& idx = storage4_.get<RemoteIdIndexTag>();
3400 Lease4StorageRemoteIdRange er = idx.equal_range(remote_id);
3401 // Store all convenient leases being within the page size.
3402 BOOST_FOREACH(auto const& it, er) {
3403 const IOAddress& addr = it->addr_;
3404 if (addr <= lower_bound_address) {
3405 // Not greater than lower_bound_address.
3406 continue;
3407 }
3408 if ((qry_start_time > 0) && (it->cltt_ < qry_start_time)) {
3409 // Too old.
3410 continue;
3411 }
3412 if ((qry_end_time > 0) && (it->cltt_ > qry_end_time)) {
3413 // Too young.
3414 continue;
3415 }
3416 sorted[addr] = it;
3417 }
3418
3419 // Return all leases being within the page size.
3420 for (auto const& it : sorted) {
3421 collection.push_back(Lease4Ptr(new Lease4(*it.second)));
3422 if (collection.size() >= page_size.page_size_) {
3423 break;
3424 }
3425 }
3426 return (collection);
3427}
3428
3429void
3431 if (MultiThreadingMgr::instance().getMode()) {
3432 std::lock_guard<std::mutex> lock(*mutex_);
3433 relay_id6_.clear();
3434 remote_id6_.clear();
3435 } else {
3436 relay_id6_.clear();
3437 remote_id6_.clear();
3438 }
3439}
3440
3441size_t
3443 return (relay_id6_.size());
3444}
3445
3446size_t
3448 return (remote_id6_.size());
3449}
3450
3453 const IOAddress& lower_bound_address,
3454 const LeasePageSize& page_size) {
3457 .arg(page_size.page_size_)
3458 .arg(lower_bound_address.toText())
3459 .arg(relay_id.toText());
3460
3461 // Expecting IPv6 valid address.
3462 if (!lower_bound_address.isV6()) {
3463 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3464 "retrieving leases from the lease database, got "
3465 << lower_bound_address);
3466 }
3467
3468 if (MultiThreadingMgr::instance().getMode()) {
3469 std::lock_guard<std::mutex> lock(*mutex_);
3470 return (getLeases6ByRelayIdInternal(relay_id,
3471 lower_bound_address,
3472 page_size));
3473 } else {
3474 return (getLeases6ByRelayIdInternal(relay_id,
3475 lower_bound_address,
3476 page_size));
3477 }
3478}
3479
3481Memfile_LeaseMgr::getLeases6ByRelayIdInternal(const DUID& relay_id,
3482 const IOAddress& lower_bound_address,
3483 const LeasePageSize& page_size) {
3484 const std::vector<uint8_t>& relay_id_data = relay_id.getDuid();
3485 Lease6Collection collection;
3486 const RelayIdIndex& idx = relay_id6_.get<RelayIdIndexTag>();
3487 RelayIdIndex::const_iterator lb =
3488 idx.lower_bound(boost::make_tuple(relay_id_data, lower_bound_address));
3489
3490 // Return all leases being within the page size.
3491 IOAddress last_addr = lower_bound_address;
3492 for (; lb != idx.end(); ++lb) {
3493 if ((*lb)->lease_addr_ == last_addr) {
3494 // Already seen: skip it.
3495 continue;
3496 }
3497 if ((*lb)->id_ != relay_id_data) {
3498 // Gone after the relay id index.
3499 break;
3500 }
3501 last_addr = (*lb)->lease_addr_;
3502 Lease6Ptr lease = getAnyLease6Internal(last_addr);
3503 if (lease) {
3504 collection.push_back(lease);
3505 if (collection.size() >= page_size.page_size_) {
3506 break;
3507 }
3508 }
3509 }
3510 return (collection);
3511}
3512
3515 const IOAddress& lower_bound_address,
3516 const LeasePageSize& page_size) {
3519 .arg(page_size.page_size_)
3520 .arg(lower_bound_address.toText())
3521 .arg(idToText(remote_id));
3522
3523 // Expecting IPv6 valid address.
3524 if (!lower_bound_address.isV6()) {
3525 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3526 "retrieving leases from the lease database, got "
3527 << lower_bound_address);
3528 }
3529
3530 if (MultiThreadingMgr::instance().getMode()) {
3531 std::lock_guard<std::mutex> lock(*mutex_);
3532 return (getLeases6ByRemoteIdInternal(remote_id,
3533 lower_bound_address,
3534 page_size));
3535 } else {
3536 return (getLeases6ByRemoteIdInternal(remote_id,
3537 lower_bound_address,
3538 page_size));
3539 }
3540}
3541
3543Memfile_LeaseMgr::getLeases6ByRemoteIdInternal(const OptionBuffer& remote_id,
3544 const IOAddress& lower_bound_address,
3545 const LeasePageSize& page_size) {
3546 Lease6Collection collection;
3547 std::set<IOAddress> sorted;
3548 const RemoteIdIndex& idx = remote_id6_.get<RemoteIdIndexTag>();
3549 RemoteIdIndexRange er = idx.equal_range(remote_id);
3550 // Store all addresses greater than lower_bound_address.
3551 BOOST_FOREACH(auto const& it, er) {
3552 const IOAddress& addr = it->lease_addr_;
3553 if (addr <= lower_bound_address) {
3554 continue;
3555 }
3556 static_cast<void>(sorted.insert(addr));
3557 }
3558
3559 // Return all leases being within the page size.
3560 for (const IOAddress& addr : sorted) {
3561 Lease6Ptr lease = getAnyLease6Internal(addr);
3562 if (lease) {
3563 collection.push_back(lease);
3564 if (collection.size() >= page_size.page_size_) {
3565 break;
3566 }
3567 }
3568 }
3569 return (collection);
3570}
3571
3572size_t
3573Memfile_LeaseMgr::extractExtendedInfo4(bool update, bool current) {
3575 if (current) {
3576 cfg = CfgMgr::instance().getCurrentCfg()->getConsistency();
3577 } else {
3578 cfg = CfgMgr::instance().getStagingCfg()->getConsistency();
3579 }
3580 if (!cfg) {
3581 isc_throw(Unexpected, "the " << (current ? "current" : "staging")
3582 << " consistency configuration is null");
3583 }
3584 auto check = cfg->getExtendedInfoSanityCheck();
3585
3589 .arg(update ? " updating in file" : "");
3590
3591 size_t leases = 0;
3592 size_t modified = 0;
3593 size_t updated = 0;
3594 size_t processed = 0;
3595 auto& index = storage4_.get<AddressIndexTag>();
3596 auto lease_it = index.begin();
3597 auto next_it = index.end();
3598
3599 for (; lease_it != index.end(); lease_it = next_it) {
3600 next_it = std::next(lease_it);
3601 Lease4Ptr lease = *lease_it;
3602 ++leases;
3603 try {
3604 if (upgradeLease4ExtendedInfo(lease, check)) {
3605 ++modified;
3606 if (update && persistLeases(V4)) {
3607 try {
3608 lease_file4_->append(*lease);
3609 } catch (const CSVFileFatalError&) {
3610 handleDbLost();
3611 throw;
3612 }
3613
3614 ++updated;
3615 }
3616 }
3617 // Work on a copy as the multi-index requires fields used
3618 // as indexes to be read-only.
3619 Lease4Ptr copy(new Lease4(*lease));
3621 if (!copy->relay_id_.empty() || !copy->remote_id_.empty()) {
3622 index.replace(lease_it, copy);
3623 ++processed;
3624 }
3625 } catch (const std::exception& ex) {
3628 .arg(lease->addr_.toText())
3629 .arg(ex.what());
3630 }
3631 }
3632
3634 .arg(leases)
3635 .arg(modified)
3636 .arg(updated)
3637 .arg(processed);
3638
3639 return (updated);
3640}
3641
3642size_t
3644 return (0);
3645}
3646
3647void
3649 CfgConsistencyPtr cfg = CfgMgr::instance().getStagingCfg()->getConsistency();
3650 if (!cfg) {
3651 isc_throw(Unexpected, "the staging consistency configuration is null");
3652 }
3653 auto check = cfg->getExtendedInfoSanityCheck();
3654 bool enabled = getExtendedInfoTablesEnabled();
3655
3659 .arg(enabled ? "enabled" : "disabled");
3660
3661 // Clear tables when enabled.
3662 if (enabled) {
3663 relay_id6_.clear();
3664 remote_id6_.clear();
3665 }
3666
3667 size_t leases = 0;
3668 size_t modified = 0;
3669 size_t processed = 0;
3670
3671 for (auto const& lease : storage6_) {
3672 ++leases;
3673 try {
3674 if (upgradeLease6ExtendedInfo(lease, check)) {
3675 ++modified;
3676 }
3677 if (enabled && addExtendedInfo6(lease)) {
3678 ++processed;
3679 }
3680 } catch (const std::exception& ex) {
3683 .arg(lease->addr_.toText())
3684 .arg(ex.what());
3685 }
3686 }
3687
3689 .arg(leases)
3690 .arg(modified)
3691 .arg(processed);
3692}
3693
3694size_t
3696 return (0);
3697}
3698
3699void
3701 LeaseAddressRelayIdIndex& relay_id_idx =
3703 static_cast<void>(relay_id_idx.erase(addr));
3704 LeaseAddressRemoteIdIndex& remote_id_idx =
3706 static_cast<void>(remote_id_idx.erase(addr));
3707}
3708
3709void
3711 const std::vector<uint8_t>& relay_id) {
3712 Lease6ExtendedInfoPtr ex_info;
3713 ex_info.reset(new Lease6ExtendedInfo(lease_addr, relay_id));
3714 relay_id6_.insert(ex_info);
3715}
3716
3717void
3719 const std::vector<uint8_t>& remote_id) {
3720 Lease6ExtendedInfoPtr ex_info;
3721 ex_info.reset(new Lease6ExtendedInfo(lease_addr, remote_id));
3722 remote_id6_.insert(ex_info);
3723}
3724
3725void
3726Memfile_LeaseMgr::writeLeases4(const std::string& filename) {
3727 if (MultiThreadingMgr::instance().getMode()) {
3728 std::lock_guard<std::mutex> lock(*mutex_);
3729 writeLeases4Internal(filename);
3730 } else {
3731 writeLeases4Internal(filename);
3732 }
3733}
3734
3735void
3736Memfile_LeaseMgr::writeLeases4Internal(const std::string& filename) {
3737 // Create the temp file name and remove it (if it exists).
3738 std::ostringstream tmp;
3739 tmp << filename << ".tmp" << getpid();
3740 auto tmpname = tmp.str();
3741 ::remove(tmpname.c_str());
3742
3743 // Dump in-memory leases to temp file.
3744 try {
3745 CSVLeaseFile4 tmpfile(tmpname);
3746 tmpfile.open();
3747 for (auto const& lease : storage4_) {
3748 tmpfile.append(*lease);
3749 }
3750 tmpfile.close();
3751 } catch (const std::exception&) {
3752 // Failed writing the temp file, remove it.
3753 ::remove(tmpname.c_str());
3754 throw;
3755 }
3756
3757 // Create the backup file name.
3758 std::ostringstream bak;
3759 bak << filename << ".bak" << getpid();
3760 auto bakname = bak.str();
3761
3762 if (lease_file4_ && lease_file4_->getFilename() == filename) {
3763 // Overwriting the existing lease file.
3764 // Close the existing lease file and move it to back up.
3765 lease_file4_->close();
3766 ::rename(filename.c_str(), bakname.c_str());
3767
3768 // Rename the temp file and open it as the lease file.
3769 ::rename(tmpname.c_str(), filename.c_str());
3770 lease_file4_->open(true);
3771 } else {
3772 // Dumping to a new file.
3773 // Rename the previous dump file (if one) to back up.
3774 ::rename(filename.c_str(), bakname.c_str());
3775
3776 // Rename temp file to dump file.
3777 ::rename(tmpname.c_str(), filename.c_str());
3778 }
3779}
3780
3781void
3782Memfile_LeaseMgr::writeLeases6(const std::string& filename) {
3783 if (MultiThreadingMgr::instance().getMode()) {
3784 std::lock_guard<std::mutex> lock(*mutex_);
3785 writeLeases6Internal(filename);
3786 } else {
3787 writeLeases6Internal(filename);
3788 }
3789}
3790
3791void
3792Memfile_LeaseMgr::writeLeases6Internal(const std::string& filename) {
3793 // Create the temp file name and remove it (if it exists).
3794 std::ostringstream tmp;
3795 tmp << filename << ".tmp" << getpid();
3796 auto tmpname = tmp.str();
3797 ::remove(tmpname.c_str());
3798
3799 // Dump in-memory leases to temp file.
3800 try {
3801 CSVLeaseFile6 tmpfile(tmpname);
3802 tmpfile.open();
3803 for (auto const& lease : storage6_) {
3804 tmpfile.append(*lease);
3805 }
3806 tmpfile.close();
3807 } catch (const std::exception&) {
3808 // Failed writing the temp file, remove it.
3809 ::remove(tmpname.c_str());
3810 throw;
3811 }
3812
3813 // Create the backup file name.
3814 std::ostringstream bak;
3815 bak << filename << ".bak" << getpid();
3816 auto bakname = bak.str();
3817
3818 if (lease_file6_ && lease_file6_->getFilename() == filename) {
3819 // Overwriting the existing lease file.
3820 // Close the existing lease file and move it to back up.
3821 lease_file6_->close();
3822 ::rename(filename.c_str(), bakname.c_str());
3823
3824 // Rename the temp file and open it as the lease file.
3825 ::rename(tmpname.c_str(), filename.c_str());
3826 lease_file6_->open(true);
3827 } else {
3828 // Dumping to a new file.
3829 // Rename the previous dump file (if one) to back up.
3830 ::rename(filename.c_str(), bakname.c_str());
3831
3832 // Rename temp file to dump file.
3833 ::rename(tmpname.c_str(), filename.c_str());
3834 }
3835}
3836
3839 try {
3842 return (TrackingLeaseMgrPtr(new Memfile_LeaseMgr(parameters)));
3843 } catch (const std::exception& ex) {
3845 .arg(ex.what());
3846 throw;
3847 }
3848}
3849
3850} // namespace dhcp
3851} // 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())
Create a NullElement.
Definition data.cc:299
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:354
std::string getParameter(const std::string &name) const
Returns value of a connection parameter.
util::ReconnectCtlPtr reconnectCtl()
The reconnect settings.
static bool invokeDbLostCallback(const util::ReconnectCtlPtr &db_reconnect_ctl)
Invokes the connection's lost connectivity callback.
static std::string redactedAccessString(const ParameterMap &parameters)
Redact database access string.
static isc::asiolink::IOServicePtr & getIOService()
Returns pointer to the IO service.
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 DHCP 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
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:1072
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:803
bool getExtendedInfoTablesEnabled() const
Returns the setting indicating if lease6 extended info tables are enabled.
Definition lease_mgr.h:1064
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:582
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:235
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.
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.
static const unsigned int DB_CONNECTION
The network state is being altered by the DB connection recovery mechanics.
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.
Exception thrown when an unrecoverable error occurs such as disk-full on write.
Definition csv_file.h:30
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.
void prettyPrint(ConstElementPtr element, std::ostream &out, unsigned indent, unsigned step)
Pretty prints the data into stream.
Definition data.cc:1752
ElementPtr copy(ConstElementPtr from, unsigned level)
Copy the data up to a nesting level.
Definition data.cc:1527
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_START
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition dhcpsrv_log.h:56
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID_CLIENTID
const isc::log::MessageID DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4
std::string ClientClass
Defines a single class name.
Definition classify.h:44
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID_HWADDR
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES6
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
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 > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< StateIndexTag >, boost::multi_index::composite_key< Lease6, boost::multi_index::member< Lease, uint32_t, &Lease::state_ >, boost::multi_index::member< Lease, SubnetID, &Lease::subnet_id_ > > > > > Lease6Storage
A multi index container holding DHCPv6 leases.
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
Lease4Storage::index< StateIndexTag >::type Lease4StorageStateIndex
DHCPv4 lease storage index by state (and subnet if).
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.
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_ > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< StateIndexTag >, boost::multi_index::composite_key< Lease4, boost::multi_index::member< Lease, uint32_t, &Lease::state_ >, boost::multi_index::member< Lease, SubnetID, &Lease::subnet_id_ > > > > > Lease4Storage
A multi index container holding DHCPv4 leases.
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
Lease6Storage::index< StateIndexTag >::type Lease6StorageStateIndex
DHCPv6 lease storage index by state (and subnet if).
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 constexpr uint32_t STATE_DEFAULT
A lease in the default state.
Definition lease.h:69
static constexpr uint32_t STATE_DECLINED
Declined lease.
Definition lease.h:72
static constexpr uint32_t STATE_REGISTERED
Registered self-generated lease.
Definition lease.h:81
Type
Type of lease or pool.
Definition lease.h:46
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
Definition lease.h:49
@ TYPE_V4
IPv4 lease.
Definition lease.h:50
@ TYPE_NA
the lease contains non-temporary IPv6 address
Definition lease.h:47
static std::string typeToText(Type type)
returns text representation of a lease type
Definition lease.cc:56
Tag for index using relay-id.
Tag for index using remote-id.
Tag for indexes by subnet-id (and address for v6).