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