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