Kea 2.5.9
memfile_lease_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
11#include <dhcpsrv/cfgmgr.h>
13#include <dhcpsrv/dhcpsrv_log.h>
16#include <dhcpsrv/timer_mgr.h>
18#include <stats/stats_mgr.h>
20#include <util/pid_file.h>
21
22#include <boost/foreach.hpp>
23#include <cstdio>
24#include <cstring>
25#include <errno.h>
26#include <iostream>
27#include <limits>
28#include <sstream>
29
30namespace {
31
39const char* KEA_LFC_EXECUTABLE_ENV_NAME = "KEA_LFC_EXECUTABLE";
40
41} // namespace
42
43using namespace isc::asiolink;
44using namespace isc::data;
45using namespace isc::db;
46using namespace isc::util;
47using namespace isc::stats;
48
49namespace isc {
50namespace dhcp {
51
66class LFCSetup {
67public:
68
77
81 ~LFCSetup();
82
94 void setup(const uint32_t lfc_interval,
95 const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
96 const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
97 bool run_once_now = false);
98
100 void execute();
101
105 bool isRunning() const;
106
108 int getExitStatus() const;
109
110private:
111
114 boost::scoped_ptr<ProcessSpawn> process_;
115
118
120 pid_t pid_;
121
126 TimerMgrPtr timer_mgr_;
127};
128
130 : process_(), callback_(callback), pid_(0),
131 timer_mgr_(TimerMgr::instance()) {
132}
133
135 try {
136 // Remove the timer. This will throw an exception if the timer does not
137 // exist. There are several possible reasons for this:
138 // a) It hasn't been registered (although if the LFC Setup instance
139 // exists it means that the timer must have been registered or that
140 // such registration has been attempted).
141 // b) The registration may fail if the duplicate timer exists or if the
142 // TimerMgr's worker thread is running but if this happens it is a
143 // programming error.
144 // c) The program is shutting down and the timer has been removed by
145 // another component.
146 timer_mgr_->unregisterTimer("memfile-lfc");
147
148 } catch (const std::exception& ex) {
149 // We don't want exceptions being thrown from the destructor so we just
150 // log a message here. The message is logged at debug severity as
151 // we don't want an error message output during shutdown.
154 }
155}
156
157void
158LFCSetup::setup(const uint32_t lfc_interval,
159 const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
160 const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
161 bool run_once_now) {
162
163 // If to nothing to do, punt
164 if (lfc_interval == 0 && !run_once_now) {
165 return;
166 }
167
168 // Start preparing the command line for kea-lfc.
169 std::string executable;
170 char* c_executable = getenv(KEA_LFC_EXECUTABLE_ENV_NAME);
171 if (!c_executable) {
172 executable = KEA_LFC_EXECUTABLE;
173 } else {
174 executable = c_executable;
175 }
176
177 // Gather the base file name.
178 std::string lease_file = lease_file4 ? lease_file4->getFilename() :
179 lease_file6->getFilename();
180
181 // Create the other names by appending suffixes to the base name.
182 ProcessArgs args;
183 // Universe: v4 or v6.
184 args.push_back(lease_file4 ? "-4" : "-6");
185
186 // Previous file.
187 args.push_back("-x");
188 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
190 // Input file.
191 args.push_back("-i");
192 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
194 // Output file.
195 args.push_back("-o");
196 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
198 // Finish file.
199 args.push_back("-f");
200 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
202 // PID file.
203 args.push_back("-p");
204 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
206
207 // The configuration file is currently unused.
208 args.push_back("-c");
209 args.push_back("ignored-path");
210
211 // Create the process (do not start it yet).
212 process_.reset(new ProcessSpawn(ProcessSpawn::ASYNC, executable, args));
213
214 // If we've been told to run it once now, invoke the callback directly.
215 if (run_once_now) {
216 callback_();
217 }
218
219 // If it's supposed to run periodically, setup that now.
220 if (lfc_interval > 0) {
221 // Set the timer to call callback function periodically.
223
224 // Multiple the lfc_interval value by 1000 as this value specifies
225 // a timeout in seconds, whereas the setup() method expects the
226 // timeout in milliseconds.
227 timer_mgr_->registerTimer("memfile-lfc", callback_, lfc_interval * 1000,
229 timer_mgr_->setup("memfile-lfc");
230 }
231}
232
233void
235 try {
237 .arg(process_->getCommandLine());
238 pid_ = process_->spawn();
239
240 } catch (const ProcessSpawnError&) {
242 }
243}
244
245bool
247 return (process_ && process_->isRunning(pid_));
248}
249
250int
252 if (!process_) {
253 isc_throw(InvalidOperation, "unable to obtain LFC process exit code: "
254 " the process is null");
255 }
256 return (process_->getExitStatus(pid_));
257}
258
259
266public:
272 : LeaseStatsQuery(select_mode), rows_(0), next_pos_(rows_.end()) {
273 };
274
279 : LeaseStatsQuery(subnet_id), rows_(0), next_pos_(rows_.end()) {
280 };
281
286 MemfileLeaseStatsQuery(const SubnetID& first_subnet_id, const SubnetID& last_subnet_id)
287 : LeaseStatsQuery(first_subnet_id, last_subnet_id), rows_(0), next_pos_(rows_.end()) {
288 };
289
292
303 virtual bool getNextRow(LeaseStatsRow& row) {
304 if (next_pos_ == rows_.end()) {
305 return (false);
306 }
307
308 row = *next_pos_;
309 ++next_pos_;
310 return (true);
311 }
312
314 int getRowCount() const {
315 return (rows_.size());
316 }
317
318protected:
320 std::vector<LeaseStatsRow> rows_;
321
323 std::vector<LeaseStatsRow>::iterator next_pos_;
324};
325
336public:
343 const SelectMode& select_mode = ALL_SUBNETS)
344 : MemfileLeaseStatsQuery(select_mode), storage4_(storage4) {
345 };
346
351 MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& subnet_id)
352 : MemfileLeaseStatsQuery(subnet_id), storage4_(storage4) {
353 };
354
360 MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& first_subnet_id,
361 const SubnetID& last_subnet_id)
362 : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage4_(storage4) {
363 };
364
367
382 void start() {
383 switch (getSelectMode()) {
384 case ALL_SUBNETS:
385 case SINGLE_SUBNET:
386 case SUBNET_RANGE:
387 startSubnets();
388 break;
389
390 case ALL_SUBNET_POOLS:
391 startSubnetPools();
392 break;
393 }
394 }
395
396private:
411 void startSubnets() {
413 = storage4_.get<SubnetIdIndexTag>();
414
415 // Set lower and upper bounds based on select mode
416 Lease4StorageSubnetIdIndex::const_iterator lower;
417 Lease4StorageSubnetIdIndex::const_iterator upper;
418
419 switch (getSelectMode()) {
420 case ALL_SUBNETS:
421 lower = idx.begin();
422 upper = idx.end();
423 break;
424
425 case SINGLE_SUBNET:
426 lower = idx.lower_bound(getFirstSubnetID());
427 upper = idx.upper_bound(getFirstSubnetID());
428 break;
429
430 case SUBNET_RANGE:
431 lower = idx.lower_bound(getFirstSubnetID());
432 upper = idx.upper_bound(getLastSubnetID());
433 break;
434
435 default:
436 return;
437 }
438
439 // Return an empty set if there are no rows.
440 if (lower == upper) {
441 return;
442 }
443
444 // Iterate over the leases in order by subnet, accumulating per
445 // subnet counts for each state of interest. As we finish each
446 // subnet, add the appropriate rows to our result set.
447 SubnetID cur_id = 0;
448 int64_t assigned = 0;
449 int64_t declined = 0;
450 for (Lease4StorageSubnetIdIndex::const_iterator lease = lower;
451 lease != upper; ++lease) {
452 // If we've hit the next subnet, add rows for the current subnet
453 // and wipe the accumulators
454 if ((*lease)->subnet_id_ != cur_id) {
455 if (cur_id > 0) {
456 if (assigned > 0) {
457 rows_.push_back(LeaseStatsRow(cur_id,
459 assigned));
460 assigned = 0;
461 }
462
463 if (declined > 0) {
464 rows_.push_back(LeaseStatsRow(cur_id,
466 declined));
467 declined = 0;
468 }
469 }
470
471 // Update current subnet id
472 cur_id = (*lease)->subnet_id_;
473 }
474
475 // Bump the appropriate accumulator
476 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
477 ++assigned;
478 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
479 ++declined;
480 }
481 }
482
483 // Make the rows for last subnet
484 if (assigned > 0) {
485 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
486 assigned));
487 }
488
489 if (declined > 0) {
490 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
491 declined));
492 }
493
494 // Reset the next row position back to the beginning of the rows.
495 next_pos_ = rows_.begin();
496 }
497
512 void startSubnetPools() {
514 = storage4_.get<SubnetIdPoolIdIndexTag>();
515
516 // Set lower and upper bounds based on select mode
517 Lease4StorageSubnetIdPoolIdIndex::const_iterator lower;
518 Lease4StorageSubnetIdPoolIdIndex::const_iterator upper;
519 switch (getSelectMode()) {
520 case ALL_SUBNET_POOLS:
521 lower = idx.begin();
522 upper = idx.end();
523 break;
524
525 default:
526 return;
527 }
528
529 // Return an empty set if there are no rows.
530 if (lower == upper) {
531 return;
532 }
533
534 // Iterate over the leases in order by subnet and pool, accumulating per
535 // subnet and pool counts for each state of interest. As we finish each
536 // subnet or pool, add the appropriate rows to our result set.
537 SubnetID cur_id = 0;
538 uint32_t cur_pool_id = 0;
539 int64_t assigned = 0;
540 int64_t declined = 0;
541 for (Lease4StorageSubnetIdPoolIdIndex::const_iterator lease = lower;
542 lease != upper; ++lease) {
543 // If we've hit the next pool, add rows for the current subnet and
544 // pool and wipe the accumulators
545 if ((*lease)->pool_id_ != cur_pool_id) {
546 if (assigned > 0) {
547 rows_.push_back(LeaseStatsRow(cur_id,
549 assigned, cur_pool_id));
550 assigned = 0;
551 }
552
553 if (declined > 0) {
554 rows_.push_back(LeaseStatsRow(cur_id,
556 declined, cur_pool_id));
557 declined = 0;
558 }
559
560 // Update current pool id
561 cur_pool_id = (*lease)->pool_id_;
562 }
563
564 // If we've hit the next subnet, add rows for the current subnet
565 // and wipe the accumulators
566 if ((*lease)->subnet_id_ != cur_id) {
567 if (cur_id > 0) {
568 if (assigned > 0) {
569 rows_.push_back(LeaseStatsRow(cur_id,
571 assigned, cur_pool_id));
572 assigned = 0;
573 }
574
575 if (declined > 0) {
576 rows_.push_back(LeaseStatsRow(cur_id,
578 declined, cur_pool_id));
579 declined = 0;
580 }
581 }
582
583 // Update current subnet id
584 cur_id = (*lease)->subnet_id_;
585
586 // Reset pool id
587 cur_pool_id = 0;
588 }
589
590 // Bump the appropriate accumulator
591 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
592 ++assigned;
593 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
594 ++declined;
595 }
596 }
597
598 // Make the rows for last subnet
599 if (assigned > 0) {
600 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
601 assigned, cur_pool_id));
602 }
603
604 if (declined > 0) {
605 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
606 declined, cur_pool_id));
607 }
608
609 // Reset the next row position back to the beginning of the rows.
610 next_pos_ = rows_.begin();
611 }
612
614 Lease4Storage& storage4_;
615};
616
617
628public:
635 const SelectMode& select_mode = ALL_SUBNETS)
636 : MemfileLeaseStatsQuery(select_mode), storage6_(storage6) {
637 };
638
643 MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& subnet_id)
644 : MemfileLeaseStatsQuery(subnet_id), storage6_(storage6) {
645 };
646
652 MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& first_subnet_id,
653 const SubnetID& last_subnet_id)
654 : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage6_(storage6) {
655 };
656
659
674 void start() {
675 switch (getSelectMode()) {
676 case ALL_SUBNETS:
677 case SINGLE_SUBNET:
678 case SUBNET_RANGE:
679 startSubnets();
680 break;
681
682 case ALL_SUBNET_POOLS:
683 startSubnetPools();
684 break;
685 }
686 }
687
688private:
703 virtual void startSubnets() {
705 = storage6_.get<SubnetIdIndexTag>();
706
707 // Set lower and upper bounds based on select mode
708 Lease6StorageSubnetIdIndex::const_iterator lower;
709 Lease6StorageSubnetIdIndex::const_iterator upper;
710 switch (getSelectMode()) {
711 case ALL_SUBNETS:
712 lower = idx.begin();
713 upper = idx.end();
714 break;
715
716 case SINGLE_SUBNET:
717 lower = idx.lower_bound(getFirstSubnetID());
718 upper = idx.upper_bound(getFirstSubnetID());
719 break;
720
721 case SUBNET_RANGE:
722 lower = idx.lower_bound(getFirstSubnetID());
723 upper = idx.upper_bound(getLastSubnetID());
724 break;
725
726 default:
727 return;
728 }
729
730 // Return an empty set if there are no rows.
731 if (lower == upper) {
732 return;
733 }
734
735 // Iterate over the leases in order by subnet, accumulating per
736 // subnet counts for each state of interest. As we finish each
737 // subnet, add the appropriate rows to our result set.
738 SubnetID cur_id = 0;
739 int64_t assigned = 0;
740 int64_t declined = 0;
741 int64_t assigned_pds = 0;
742 for (Lease6StorageSubnetIdIndex::const_iterator lease = lower;
743 lease != upper; ++lease) {
744 // If we've hit the next subnet, add rows for the current subnet
745 // and wipe the accumulators
746 if ((*lease)->subnet_id_ != cur_id) {
747 if (cur_id > 0) {
748 if (assigned > 0) {
749 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
751 assigned));
752 assigned = 0;
753 }
754
755 if (declined > 0) {
756 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
758 declined));
759 declined = 0;
760 }
761
762 if (assigned_pds > 0) {
763 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
765 assigned_pds));
766 assigned_pds = 0;
767 }
768 }
769
770 // Update current subnet id
771 cur_id = (*lease)->subnet_id_;
772 }
773
774 // Bump the appropriate accumulator
775 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
776 switch((*lease)->type_) {
777 case Lease::TYPE_NA:
778 ++assigned;
779 break;
780 case Lease::TYPE_PD:
781 ++assigned_pds;
782 break;
783 default:
784 break;
785 }
786 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
787 // In theory only NAs can be declined
788 if (((*lease)->type_) == Lease::TYPE_NA) {
789 ++declined;
790 }
791 }
792 }
793
794 // Make the rows for last subnet, unless there were no rows
795 if (assigned > 0) {
796 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
797 Lease::STATE_DEFAULT, assigned));
798 }
799
800 if (declined > 0) {
801 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
802 Lease::STATE_DECLINED, declined));
803 }
804
805 if (assigned_pds > 0) {
806 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
807 Lease::STATE_DEFAULT, assigned_pds));
808 }
809
810 // Set the next row position to the beginning of the rows.
811 next_pos_ = rows_.begin();
812 }
813
828 virtual void startSubnetPools() {
830 = storage6_.get<SubnetIdPoolIdIndexTag>();
831
832 // Set lower and upper bounds based on select mode
833 Lease6StorageSubnetIdPoolIdIndex::const_iterator lower;
834 Lease6StorageSubnetIdPoolIdIndex::const_iterator upper;
835 switch (getSelectMode()) {
836 case ALL_SUBNET_POOLS:
837 lower = idx.begin();
838 upper = idx.end();
839 break;
840
841 default:
842 return;
843 }
844
845 // Return an empty set if there are no rows.
846 if (lower == upper) {
847 return;
848 }
849
850 // Iterate over the leases in order by subnet, accumulating per
851 // subnet counts for each state of interest. As we finish each
852 // subnet, add the appropriate rows to our result set.
853 SubnetID cur_id = 0;
854 uint32_t cur_pool_id = 0;
855 int64_t assigned = 0;
856 int64_t declined = 0;
857 int64_t assigned_pds = 0;
858 for (Lease6StorageSubnetIdPoolIdIndex::const_iterator lease = lower;
859 lease != upper; ++lease) {
860 // If we've hit the next pool, add rows for the current subnet and
861 // pool and wipe the accumulators
862 if ((*lease)->pool_id_ != cur_pool_id) {
863 if (assigned > 0) {
864 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
866 assigned, cur_pool_id));
867 assigned = 0;
868 }
869
870 if (declined > 0) {
871 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
873 declined, cur_pool_id));
874 declined = 0;
875 }
876
877 if (assigned_pds > 0) {
878 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
880 assigned_pds, cur_pool_id));
881 assigned_pds = 0;
882 }
883
884 // Update current pool id
885 cur_pool_id = (*lease)->pool_id_;
886 }
887
888 // If we've hit the next subnet, add rows for the current subnet
889 // and wipe the accumulators
890 if ((*lease)->subnet_id_ != cur_id) {
891 if (cur_id > 0) {
892 if (assigned > 0) {
893 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
895 assigned, cur_pool_id));
896 assigned = 0;
897 }
898
899 if (declined > 0) {
900 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
902 declined, cur_pool_id));
903 declined = 0;
904 }
905
906 if (assigned_pds > 0) {
907 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
909 assigned_pds, cur_pool_id));
910 assigned_pds = 0;
911 }
912 }
913
914 // Update current subnet id
915 cur_id = (*lease)->subnet_id_;
916
917 // Reset pool id
918 cur_pool_id = 0;
919 }
920
921 // Bump the appropriate accumulator
922 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
923 switch((*lease)->type_) {
924 case Lease::TYPE_NA:
925 ++assigned;
926 break;
927 case Lease::TYPE_PD:
928 ++assigned_pds;
929 break;
930 default:
931 break;
932 }
933 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
934 // In theory only NAs can be declined
935 if (((*lease)->type_) == Lease::TYPE_NA) {
936 ++declined;
937 }
938 }
939 }
940
941 // Make the rows for last subnet, unless there were no rows
942 if (assigned > 0) {
943 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
944 Lease::STATE_DEFAULT, assigned,
945 cur_pool_id));
946 }
947
948 if (declined > 0) {
949 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
950 Lease::STATE_DECLINED, declined,
951 cur_pool_id));
952 }
953
954 if (assigned_pds > 0) {
955 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
956 Lease::STATE_DEFAULT, assigned_pds,
957 cur_pool_id));
958 }
959
960 // Set the next row position to the beginning of the rows.
961 next_pos_ = rows_.begin();
962 }
963
965 Lease6Storage& storage6_;
966};
967
968// Explicit definition of class static constants. Values are given in the
969// declaration so they're not needed here.
974
976 : TrackingLeaseMgr(), lfc_setup_(), conn_(parameters), mutex_(new std::mutex) {
977 bool conversion_needed = false;
978
979 // Check if the extended info tables are enabled.
981
982 // Check the universe and use v4 file or v6 file.
983 std::string universe = conn_.getParameter("universe");
984 if (universe == "4") {
985 std::string file4 = initLeaseFilePath(V4);
986 if (!file4.empty()) {
987 conversion_needed = loadLeasesFromFiles<Lease4,
988 CSVLeaseFile4>(file4,
990 storage4_);
991 static_cast<void>(extractExtendedInfo4(false, false));
992 }
993 } else {
994 std::string file6 = initLeaseFilePath(V6);
995 if (!file6.empty()) {
996 conversion_needed = loadLeasesFromFiles<Lease6,
997 CSVLeaseFile6>(file6,
999 storage6_);
1001 }
1002 }
1003
1004 // If lease persistence have been disabled for both v4 and v6,
1005 // issue a warning. It is ok not to write leases to disk when
1006 // doing testing, but it should not be done in normal server
1007 // operation.
1008 if (!persistLeases(V4) && !persistLeases(V6)) {
1010 } else {
1011 if (conversion_needed) {
1012 auto const& version(getVersion());
1014 .arg(version.first).arg(version.second);
1015 }
1016 lfcSetup(conversion_needed);
1017 }
1018}
1019
1021 if (lease_file4_) {
1022 lease_file4_->close();
1023 lease_file4_.reset();
1024 }
1025 if (lease_file6_) {
1026 lease_file6_->close();
1027 lease_file6_.reset();
1028 }
1029}
1030
1031std::string
1033 std::stringstream tmp;
1034 tmp << "Memfile backend ";
1035 if (u == V4) {
1036 tmp << MAJOR_VERSION_V4 << "." << MINOR_VERSION_V4;
1037 } else if (u == V6) {
1038 tmp << MAJOR_VERSION_V6 << "." << MINOR_VERSION_V6;
1039 }
1040 return tmp.str();
1041}
1042
1043bool
1044Memfile_LeaseMgr::addLeaseInternal(const Lease4Ptr& lease) {
1045 if (getLease4Internal(lease->addr_)) {
1046 // there is a lease with specified address already
1047 return (false);
1048 }
1049
1050 // Try to write a lease to disk first. If this fails, the lease will
1051 // not be inserted to the memory and the disk and in-memory data will
1052 // remain consistent.
1053 if (persistLeases(V4)) {
1054 lease_file4_->append(*lease);
1055 }
1056
1057 storage4_.insert(lease);
1058
1059 // Update lease current expiration time (allows update between the creation
1060 // of the Lease up to the point of insertion in the database).
1061 lease->updateCurrentExpirationTime();
1062
1063 // Increment class lease counters.
1064 class_lease_counter_.addLease(lease);
1065
1066 // Run installed callbacks.
1067 if (hasCallbacks()) {
1068 trackAddLease(lease);
1069 }
1070
1071 return (true);
1072}
1073
1074bool
1077 DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
1078
1079 if (MultiThreadingMgr::instance().getMode()) {
1080 std::lock_guard<std::mutex> lock(*mutex_);
1081 return (addLeaseInternal(lease));
1082 } else {
1083 return (addLeaseInternal(lease));
1084 }
1085}
1086
1087bool
1088Memfile_LeaseMgr::addLeaseInternal(const Lease6Ptr& lease) {
1089 if (getLease6Internal(lease->type_, lease->addr_)) {
1090 // there is a lease with specified address already
1091 return (false);
1092 }
1093
1094 // Try to write a lease to disk first. If this fails, the lease will
1095 // not be inserted to the memory and the disk and in-memory data will
1096 // remain consistent.
1097 if (persistLeases(V6)) {
1098 lease_file6_->append(*lease);
1099 }
1100
1101 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
1102 storage6_.insert(lease);
1103
1104 // Update lease current expiration time (allows update between the creation
1105 // of the Lease up to the point of insertion in the database).
1106 lease->updateCurrentExpirationTime();
1107
1108 // Increment class lease counters.
1109 class_lease_counter_.addLease(lease);
1110
1112 static_cast<void>(addExtendedInfo6(lease));
1113 }
1114
1115 // Run installed callbacks.
1116 if (hasCallbacks()) {
1117 trackAddLease(lease);
1118 }
1119
1120 return (true);
1121}
1122
1123bool
1126 DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
1127
1128 if (MultiThreadingMgr::instance().getMode()) {
1129 std::lock_guard<std::mutex> lock(*mutex_);
1130 return (addLeaseInternal(lease));
1131 } else {
1132 return (addLeaseInternal(lease));
1133 }
1134}
1135
1137Memfile_LeaseMgr::getLease4Internal(const isc::asiolink::IOAddress& addr) const {
1138 const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1139 Lease4StorageAddressIndex::iterator l = idx.find(addr);
1140 if (l == idx.end()) {
1141 return (Lease4Ptr());
1142 } else {
1143 return (Lease4Ptr(new Lease4(**l)));
1144 }
1145}
1146
1150 DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
1151
1152 if (MultiThreadingMgr::instance().getMode()) {
1153 std::lock_guard<std::mutex> lock(*mutex_);
1154 return (getLease4Internal(addr));
1155 } else {
1156 return (getLease4Internal(addr));
1157 }
1158}
1159
1160void
1161Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
1162 Lease4Collection& collection) const {
1163 // Using composite index by 'hw address' and 'subnet id'. It is
1164 // ok to use it for searching by the 'hw address' only.
1166 storage4_.get<HWAddressSubnetIdIndexTag>();
1167 std::pair<Lease4StorageHWAddressSubnetIdIndex::const_iterator,
1168 Lease4StorageHWAddressSubnetIdIndex::const_iterator> l
1169 = idx.equal_range(boost::make_tuple(hwaddr.hwaddr_));
1170
1171 BOOST_FOREACH(auto const& lease, l) {
1172 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1173 }
1174}
1175
1179 DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.toText());
1180
1181 Lease4Collection collection;
1182 if (MultiThreadingMgr::instance().getMode()) {
1183 std::lock_guard<std::mutex> lock(*mutex_);
1184 getLease4Internal(hwaddr, collection);
1185 } else {
1186 getLease4Internal(hwaddr, collection);
1187 }
1188
1189 return (collection);
1190}
1191
1193Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
1194 SubnetID subnet_id) const {
1195 // Get the index by HW Address and Subnet Identifier.
1197 storage4_.get<HWAddressSubnetIdIndexTag>();
1198 // Try to find the lease using HWAddr and subnet id.
1199 Lease4StorageHWAddressSubnetIdIndex::const_iterator lease =
1200 idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
1201 // Lease was not found. Return empty pointer to the caller.
1202 if (lease == idx.end()) {
1203 return (Lease4Ptr());
1204 }
1205
1206 // Lease was found. Return it to the caller.
1207 return (Lease4Ptr(new Lease4(**lease)));
1208}
1209
1212 SubnetID subnet_id) const {
1214 DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
1215 .arg(hwaddr.toText());
1216
1217 if (MultiThreadingMgr::instance().getMode()) {
1218 std::lock_guard<std::mutex> lock(*mutex_);
1219 return (getLease4Internal(hwaddr, subnet_id));
1220 } else {
1221 return (getLease4Internal(hwaddr, subnet_id));
1222 }
1223}
1224
1225void
1226Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
1227 Lease4Collection& collection) const {
1228 // Using composite index by 'client id' and 'subnet id'. It is ok
1229 // to use it to search by 'client id' only.
1231 storage4_.get<ClientIdSubnetIdIndexTag>();
1232 std::pair<Lease4StorageClientIdSubnetIdIndex::const_iterator,
1233 Lease4StorageClientIdSubnetIdIndex::const_iterator> l
1234 = idx.equal_range(boost::make_tuple(client_id.getClientId()));
1235
1236 BOOST_FOREACH(auto const& lease, l) {
1237 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1238 }
1239}
1240
1242Memfile_LeaseMgr::getLease4(const ClientId& client_id) const {
1244 DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.toText());
1245
1246 Lease4Collection collection;
1247 if (MultiThreadingMgr::instance().getMode()) {
1248 std::lock_guard<std::mutex> lock(*mutex_);
1249 getLease4Internal(client_id, collection);
1250 } else {
1251 getLease4Internal(client_id, collection);
1252 }
1253
1254 return (collection);
1255}
1256
1258Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
1259 SubnetID subnet_id) const {
1260 // Get the index by client and subnet id.
1262 storage4_.get<ClientIdSubnetIdIndexTag>();
1263 // Try to get the lease using client id and subnet id.
1264 Lease4StorageClientIdSubnetIdIndex::const_iterator lease =
1265 idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
1266 // Lease was not found. Return empty pointer to the caller.
1267 if (lease == idx.end()) {
1268 return (Lease4Ptr());
1269 }
1270 // Lease was found. Return it to the caller.
1271 return (Lease4Ptr(new Lease4(**lease)));
1272}
1273
1276 SubnetID subnet_id) const {
1279 .arg(client_id.toText());
1280
1281 if (MultiThreadingMgr::instance().getMode()) {
1282 std::lock_guard<std::mutex> lock(*mutex_);
1283 return (getLease4Internal(client_id, subnet_id));
1284 } else {
1285 return (getLease4Internal(client_id, subnet_id));
1286 }
1287}
1288
1289void
1290Memfile_LeaseMgr::getLeases4Internal(SubnetID subnet_id,
1291 Lease4Collection& collection) const {
1292 const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
1293 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
1294 Lease4StorageSubnetIdIndex::const_iterator> l =
1295 idx.equal_range(subnet_id);
1296
1297 BOOST_FOREACH(auto const& lease, l) {
1298 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1299 }
1300}
1301
1305 .arg(subnet_id);
1306
1307 Lease4Collection collection;
1308 if (MultiThreadingMgr::instance().getMode()) {
1309 std::lock_guard<std::mutex> lock(*mutex_);
1310 getLeases4Internal(subnet_id, collection);
1311 } else {
1312 getLeases4Internal(subnet_id, collection);
1313 }
1314
1315 return (collection);
1316}
1317
1318void
1319Memfile_LeaseMgr::getLeases4Internal(const std::string& hostname,
1320 Lease4Collection& collection) const {
1321 const Lease4StorageHostnameIndex& idx = storage4_.get<HostnameIndexTag>();
1322 std::pair<Lease4StorageHostnameIndex::const_iterator,
1323 Lease4StorageHostnameIndex::const_iterator> l =
1324 idx.equal_range(hostname);
1325
1326 BOOST_FOREACH(auto const& lease, l) {
1327 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1328 }
1329}
1330
1332Memfile_LeaseMgr::getLeases4(const std::string& hostname) const {
1334 .arg(hostname);
1335
1336 Lease4Collection collection;
1337 if (MultiThreadingMgr::instance().getMode()) {
1338 std::lock_guard<std::mutex> lock(*mutex_);
1339 getLeases4Internal(hostname, collection);
1340 } else {
1341 getLeases4Internal(hostname, collection);
1342 }
1343
1344 return (collection);
1345}
1346
1347void
1348Memfile_LeaseMgr::getLeases4Internal(Lease4Collection& collection) const {
1349 for (auto const& lease : storage4_) {
1350 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1351 }
1352}
1353
1357
1358 Lease4Collection collection;
1359 if (MultiThreadingMgr::instance().getMode()) {
1360 std::lock_guard<std::mutex> lock(*mutex_);
1361 getLeases4Internal(collection);
1362 } else {
1363 getLeases4Internal(collection);
1364 }
1365
1366 return (collection);
1367}
1368
1369void
1370Memfile_LeaseMgr::getLeases4Internal(const asiolink::IOAddress& lower_bound_address,
1371 const LeasePageSize& page_size,
1372 Lease4Collection& collection) const {
1373 const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1374 Lease4StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1375
1376 // Exclude the lower bound address specified by the caller.
1377 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1378 ++lb;
1379 }
1380
1381 // Return all other leases being within the page size.
1382 for (auto lease = lb;
1383 (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1384 ++lease) {
1385 collection.push_back(Lease4Ptr(new Lease4(**lease)));
1386 }
1387}
1388
1391 const LeasePageSize& page_size) const {
1392 // Expecting IPv4 address.
1393 if (!lower_bound_address.isV4()) {
1394 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
1395 "retrieving leases from the lease database, got "
1396 << lower_bound_address);
1397 }
1398
1400 .arg(page_size.page_size_)
1401 .arg(lower_bound_address.toText());
1402
1403 Lease4Collection collection;
1404 if (MultiThreadingMgr::instance().getMode()) {
1405 std::lock_guard<std::mutex> lock(*mutex_);
1406 getLeases4Internal(lower_bound_address, page_size, collection);
1407 } else {
1408 getLeases4Internal(lower_bound_address, page_size, collection);
1409 }
1410
1411 return (collection);
1412}
1413
1415Memfile_LeaseMgr::getLease6Internal(Lease::Type type,
1416 const isc::asiolink::IOAddress& addr) const {
1417 Lease6Storage::iterator l = storage6_.find(addr);
1418 if (l == storage6_.end() || !(*l) || ((*l)->type_ != type)) {
1419 return (Lease6Ptr());
1420 } else {
1421 return (Lease6Ptr(new Lease6(**l)));
1422 }
1423}
1424
1426Memfile_LeaseMgr::getAnyLease6Internal(const isc::asiolink::IOAddress& addr) const {
1427 Lease6Storage::iterator l = storage6_.find(addr);
1428 if (l == storage6_.end() || !(*l)) {
1429 return (Lease6Ptr());
1430 } else {
1431 return (Lease6Ptr(new Lease6(**l)));
1432 }
1433}
1434
1437 const isc::asiolink::IOAddress& addr) const {
1440 .arg(addr.toText())
1441 .arg(Lease::typeToText(type));
1442
1443 if (MultiThreadingMgr::instance().getMode()) {
1444 std::lock_guard<std::mutex> lock(*mutex_);
1445 return (getLease6Internal(type, addr));
1446 } else {
1447 return (getLease6Internal(type, addr));
1448 }
1449}
1450
1451void
1452Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1453 const DUID& duid,
1454 uint32_t iaid,
1455 Lease6Collection& collection) const {
1456 // Get the index by DUID, IAID, lease type.
1457 const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1458 // Try to get the lease using the DUID, IAID and lease type.
1459 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1460 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1461 idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1462
1463 for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1464 l.first; lease != l.second; ++lease) {
1465 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1466 }
1467}
1468
1471 const DUID& duid,
1472 uint32_t iaid) const {
1475 .arg(iaid)
1476 .arg(duid.toText())
1477 .arg(Lease::typeToText(type));
1478
1479 Lease6Collection collection;
1480 if (MultiThreadingMgr::instance().getMode()) {
1481 std::lock_guard<std::mutex> lock(*mutex_);
1482 getLeases6Internal(type, duid, iaid, collection);
1483 } else {
1484 getLeases6Internal(type, duid, iaid, collection);
1485 }
1486
1487 return (collection);
1488}
1489
1490void
1491Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1492 const DUID& duid,
1493 uint32_t iaid,
1494 SubnetID subnet_id,
1495 Lease6Collection& collection) const {
1496 // Get the index by DUID, IAID, lease type.
1497 const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1498 // Try to get the lease using the DUID, IAID and lease type.
1499 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1500 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1501 idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1502
1503 for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1504 l.first; lease != l.second; ++lease) {
1505 // Filter out the leases which subnet id doesn't match.
1506 if ((*lease)->subnet_id_ == subnet_id) {
1507 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1508 }
1509 }
1510}
1511
1514 const DUID& duid,
1515 uint32_t iaid,
1516 SubnetID subnet_id) const {
1519 .arg(iaid)
1520 .arg(subnet_id)
1521 .arg(duid.toText())
1522 .arg(Lease::typeToText(type));
1523
1524 Lease6Collection collection;
1525 if (MultiThreadingMgr::instance().getMode()) {
1526 std::lock_guard<std::mutex> lock(*mutex_);
1527 getLeases6Internal(type, duid, iaid, subnet_id, collection);
1528 } else {
1529 getLeases6Internal(type, duid, iaid, subnet_id, collection);
1530 }
1531
1532 return (collection);
1533}
1534
1535void
1536Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1537 Lease6Collection& collection) const {
1538 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1539 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
1540 Lease6StorageSubnetIdIndex::const_iterator> l =
1541 idx.equal_range(subnet_id);
1542
1543 BOOST_FOREACH(auto const& lease, l) {
1544 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1545 }
1546}
1547
1551 .arg(subnet_id);
1552
1553 Lease6Collection collection;
1554 if (MultiThreadingMgr::instance().getMode()) {
1555 std::lock_guard<std::mutex> lock(*mutex_);
1556 getLeases6Internal(subnet_id, collection);
1557 } else {
1558 getLeases6Internal(subnet_id, collection);
1559 }
1560
1561 return (collection);
1562}
1563
1564void
1565Memfile_LeaseMgr::getLeases6Internal(const std::string& hostname,
1566 Lease6Collection& collection) const {
1567 const Lease6StorageHostnameIndex& idx = storage6_.get<HostnameIndexTag>();
1568 std::pair<Lease6StorageHostnameIndex::const_iterator,
1569 Lease6StorageHostnameIndex::const_iterator> l =
1570 idx.equal_range(hostname);
1571
1572 BOOST_FOREACH(auto const& lease, l) {
1573 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1574 }
1575}
1576
1578Memfile_LeaseMgr::getLeases6(const std::string& hostname) const {
1580 .arg(hostname);
1581
1582 Lease6Collection collection;
1583 if (MultiThreadingMgr::instance().getMode()) {
1584 std::lock_guard<std::mutex> lock(*mutex_);
1585 getLeases6Internal(hostname, collection);
1586 } else {
1587 getLeases6Internal(hostname, collection);
1588 }
1589
1590 return (collection);
1591}
1592
1593void
1594Memfile_LeaseMgr::getLeases6Internal(Lease6Collection& collection) const {
1595 for (auto const& lease : storage6_) {
1596 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1597 }
1598}
1599
1603
1604 Lease6Collection collection;
1605 if (MultiThreadingMgr::instance().getMode()) {
1606 std::lock_guard<std::mutex> lock(*mutex_);
1607 getLeases6Internal(collection);
1608 } else {
1609 getLeases6Internal(collection);
1610 }
1611
1612 return (collection);
1613}
1614
1615void
1616Memfile_LeaseMgr::getLeases6Internal(const DUID& duid,
1617 Lease6Collection& collection) const {
1618 const Lease6StorageDuidIndex& idx = storage6_.get<DuidIndexTag>();
1619 std::pair<Lease6StorageDuidIndex::const_iterator,
1620 Lease6StorageDuidIndex::const_iterator> l =
1621 idx.equal_range(duid.getDuid());
1622
1623 BOOST_FOREACH(auto const& lease, l) {
1624 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1625 }
1626}
1627
1631 .arg(duid.toText());
1632
1633 Lease6Collection collection;
1634 if (MultiThreadingMgr::instance().getMode()) {
1635 std::lock_guard<std::mutex> lock(*mutex_);
1636 getLeases6Internal(duid, collection);
1637 } else {
1638 getLeases6Internal(duid, collection);
1639 }
1640
1641 return (collection);
1642}
1643
1644void
1645Memfile_LeaseMgr::getLeases6Internal(const asiolink::IOAddress& lower_bound_address,
1646 const LeasePageSize& page_size,
1647 Lease6Collection& collection) const {
1648 const Lease6StorageAddressIndex& idx = storage6_.get<AddressIndexTag>();
1649 Lease6StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1650
1651 // Exclude the lower bound address specified by the caller.
1652 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1653 ++lb;
1654 }
1655
1656 // Return all other leases being within the page size.
1657 for (auto lease = lb;
1658 (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1659 ++lease) {
1660 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1661 }
1662}
1663
1666 const LeasePageSize& page_size) const {
1667 // Expecting IPv6 address.
1668 if (!lower_bound_address.isV6()) {
1669 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1670 "retrieving leases from the lease database, got "
1671 << lower_bound_address);
1672 }
1673
1675 .arg(page_size.page_size_)
1676 .arg(lower_bound_address.toText());
1677
1678 Lease6Collection collection;
1679 if (MultiThreadingMgr::instance().getMode()) {
1680 std::lock_guard<std::mutex> lock(*mutex_);
1681 getLeases6Internal(lower_bound_address, page_size, collection);
1682 } else {
1683 getLeases6Internal(lower_bound_address, page_size, collection);
1684 }
1685
1686 return (collection);
1687}
1688
1690Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1691 const IOAddress& lower_bound_address,
1692 const LeasePageSize& page_size) const {
1693 Lease6Collection collection;
1694 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1695 Lease6StorageSubnetIdIndex::const_iterator lb =
1696 idx.lower_bound(boost::make_tuple(subnet_id, lower_bound_address));
1697
1698 // Exclude the lower bound address specified by the caller.
1699 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1700 ++lb;
1701 }
1702
1703 // Return all leases being within the page size.
1704 for (auto it = lb; it != idx.end(); ++it) {
1705 if ((*it)->subnet_id_ != subnet_id) {
1706 // Gone after the subnet id index.
1707 break;
1708 }
1709 collection.push_back(Lease6Ptr(new Lease6(**it)));
1710 if (collection.size() >= page_size.page_size_) {
1711 break;
1712 }
1713 }
1714 return (collection);
1715}
1716
1719 const IOAddress& lower_bound_address,
1720 const LeasePageSize& page_size) const {
1723 .arg(page_size.page_size_)
1724 .arg(lower_bound_address.toText())
1725 .arg(subnet_id);
1726
1727 // Expecting IPv6 valid address.
1728 if (!lower_bound_address.isV6()) {
1729 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1730 "retrieving leases from the lease database, got "
1731 << lower_bound_address);
1732 }
1733
1734 if (MultiThreadingMgr::instance().getMode()) {
1735 std::lock_guard<std::mutex> lock(*mutex_);
1736 return (getLeases6Internal(subnet_id,
1737 lower_bound_address,
1738 page_size));
1739 } else {
1740 return (getLeases6Internal(subnet_id,
1741 lower_bound_address,
1742 page_size));
1743 }
1744}
1745
1746void
1747Memfile_LeaseMgr::getExpiredLeases4Internal(Lease4Collection& expired_leases,
1748 const size_t max_leases) const {
1749 // Obtain the index which segragates leases by state and time.
1750 const Lease4StorageExpirationIndex& index = storage4_.get<ExpirationIndexTag>();
1751
1752 // Retrieve leases which are not reclaimed and which haven't expired. The
1753 // 'less-than' operator will be used for both components of the index. So,
1754 // for the 'state' 'false' is less than 'true'. Also the leases with
1755 // expiration time lower than current time will be returned.
1756 Lease4StorageExpirationIndex::const_iterator ub =
1757 index.upper_bound(boost::make_tuple(false, time(0)));
1758
1759 // Copy only the number of leases indicated by the max_leases parameter.
1760 for (Lease4StorageExpirationIndex::const_iterator lease = index.begin();
1761 (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1762 max_leases));
1763 ++lease) {
1764 expired_leases.push_back(Lease4Ptr(new Lease4(**lease)));
1765 }
1766}
1767
1768void
1770 const size_t max_leases) const {
1772 .arg(max_leases);
1773
1774 if (MultiThreadingMgr::instance().getMode()) {
1775 std::lock_guard<std::mutex> lock(*mutex_);
1776 getExpiredLeases4Internal(expired_leases, max_leases);
1777 } else {
1778 getExpiredLeases4Internal(expired_leases, max_leases);
1779 }
1780}
1781
1782void
1783Memfile_LeaseMgr::getExpiredLeases6Internal(Lease6Collection& expired_leases,
1784 const size_t max_leases) const {
1785 // Obtain the index which segragates leases by state and time.
1786 const Lease6StorageExpirationIndex& index = storage6_.get<ExpirationIndexTag>();
1787
1788 // Retrieve leases which are not reclaimed and which haven't expired. The
1789 // 'less-than' operator will be used for both components of the index. So,
1790 // for the 'state' 'false' is less than 'true'. Also the leases with
1791 // expiration time lower than current time will be returned.
1792 Lease6StorageExpirationIndex::const_iterator ub =
1793 index.upper_bound(boost::make_tuple(false, time(0)));
1794
1795 // Copy only the number of leases indicated by the max_leases parameter.
1796 for (Lease6StorageExpirationIndex::const_iterator lease = index.begin();
1797 (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1798 max_leases));
1799 ++lease) {
1800 expired_leases.push_back(Lease6Ptr(new Lease6(**lease)));
1801 }
1802}
1803
1804void
1806 const size_t max_leases) const {
1808 .arg(max_leases);
1809
1810 if (MultiThreadingMgr::instance().getMode()) {
1811 std::lock_guard<std::mutex> lock(*mutex_);
1812 getExpiredLeases6Internal(expired_leases, max_leases);
1813 } else {
1814 getExpiredLeases6Internal(expired_leases, max_leases);
1815 }
1816}
1817
1818void
1819Memfile_LeaseMgr::updateLease4Internal(const Lease4Ptr& lease) {
1820 // Obtain 'by address' index.
1821 Lease4StorageAddressIndex& index = storage4_.get<AddressIndexTag>();
1822
1823 bool persist = persistLeases(V4);
1824
1825 // Lease must exist if it is to be updated.
1826 Lease4StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1827 if (lease_it == index.end()) {
1828 isc_throw(NoSuchLease, "failed to update the lease with address "
1829 << lease->addr_ << " - no such lease");
1830 } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1831 ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1832 // For test purpose only: check that the lease has not changed in
1833 // the database.
1834 isc_throw(NoSuchLease, "failed to update the lease with address "
1835 << lease->addr_ << " - lease has changed in database");
1836 }
1837
1838 // Try to write a lease to disk first. If this fails, the lease will
1839 // not be inserted to the memory and the disk and in-memory data will
1840 // remain consistent.
1841 if (persist) {
1842 lease_file4_->append(*lease);
1843 }
1844
1845 // Update lease current expiration time.
1846 lease->updateCurrentExpirationTime();
1847
1848 // Save a copy of the old lease as lease_it will point to the new
1849 // one after the replacement.
1850 Lease4Ptr old_lease = *lease_it;
1851
1852 // Use replace() to re-index leases.
1853 index.replace(lease_it, Lease4Ptr(new Lease4(*lease)));
1854
1855 // Adjust class lease counters.
1856 class_lease_counter_.updateLease(lease, old_lease);
1857
1858 // Run installed callbacks.
1859 if (hasCallbacks()) {
1860 trackUpdateLease(lease);
1861 }
1862}
1863
1864void
1867 DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
1868
1869 if (MultiThreadingMgr::instance().getMode()) {
1870 std::lock_guard<std::mutex> lock(*mutex_);
1871 updateLease4Internal(lease);
1872 } else {
1873 updateLease4Internal(lease);
1874 }
1875}
1876
1877void
1878Memfile_LeaseMgr::updateLease6Internal(const Lease6Ptr& lease) {
1879 // Obtain 'by address' index.
1880 Lease6StorageAddressIndex& index = storage6_.get<AddressIndexTag>();
1881
1882 bool persist = persistLeases(V6);
1883
1884 // Get the recorded action and reset it.
1885 Lease6::ExtendedInfoAction recorded_action = lease->extended_info_action_;
1886 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
1887
1888 // Lease must exist if it is to be updated.
1889 Lease6StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1890 if (lease_it == index.end()) {
1891 isc_throw(NoSuchLease, "failed to update the lease with address "
1892 << lease->addr_ << " - no such lease");
1893 } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1894 ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1895 // For test purpose only: check that the lease has not changed in
1896 // the database.
1897 isc_throw(NoSuchLease, "failed to update the lease with address "
1898 << lease->addr_ << " - lease has changed in database");
1899 }
1900
1901 // Try to write a lease to disk first. If this fails, the lease will
1902 // not be inserted to the memory and the disk and in-memory data will
1903 // remain consistent.
1904 if (persist) {
1905 lease_file6_->append(*lease);
1906 }
1907
1908 // Update lease current expiration time.
1909 lease->updateCurrentExpirationTime();
1910
1911 // Save a copy of the old lease as lease_it will point to the new
1912 // one after the replacement.
1913 Lease6Ptr old_lease = *lease_it;
1914
1915 // Use replace() to re-index leases.
1916 index.replace(lease_it, Lease6Ptr(new Lease6(*lease)));
1917
1918 // Adjust class lease counters.
1919 class_lease_counter_.updateLease(lease, old_lease);
1920
1921 // Update extended info tables.
1923 switch (recorded_action) {
1925 break;
1926
1928 deleteExtendedInfo6(lease->addr_);
1929 break;
1930
1932 deleteExtendedInfo6(lease->addr_);
1933 static_cast<void>(addExtendedInfo6(lease));
1934 break;
1935 }
1936 }
1937
1938 // Run installed callbacks.
1939 if (hasCallbacks()) {
1940 trackUpdateLease(lease);
1941 }
1942}
1943
1944void
1947 DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
1948
1949 if (MultiThreadingMgr::instance().getMode()) {
1950 std::lock_guard<std::mutex> lock(*mutex_);
1951 updateLease6Internal(lease);
1952 } else {
1953 updateLease6Internal(lease);
1954 }
1955}
1956
1957bool
1958Memfile_LeaseMgr::deleteLeaseInternal(const Lease4Ptr& lease) {
1959 const isc::asiolink::IOAddress& addr = lease->addr_;
1960 Lease4Storage::iterator l = storage4_.find(addr);
1961 if (l == storage4_.end()) {
1962 // No such lease
1963 return (false);
1964 } else {
1965 if (persistLeases(V4)) {
1966 // Copy the lease. The valid lifetime needs to be modified and
1967 // we don't modify the original lease.
1968 Lease4 lease_copy = **l;
1969 // Setting valid lifetime to 0 means that lease is being
1970 // removed.
1971 lease_copy.valid_lft_ = 0;
1972 lease_file4_->append(lease_copy);
1973 } else {
1974 // For test purpose only: check that the lease has not changed in
1975 // the database.
1976 if (((*l)->cltt_ != lease->current_cltt_) ||
1977 ((*l)->valid_lft_ != lease->current_valid_lft_)) {
1978 return false;
1979 }
1980 }
1981
1982 storage4_.erase(l);
1983
1984 // Decrement class lease counters.
1985 class_lease_counter_.removeLease(lease);
1986
1987 // Run installed callbacks.
1988 if (hasCallbacks()) {
1989 trackDeleteLease(lease);
1990 }
1991
1992 return (true);
1993 }
1994}
1995
1996bool
1999 DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
2000
2001 if (MultiThreadingMgr::instance().getMode()) {
2002 std::lock_guard<std::mutex> lock(*mutex_);
2003 return (deleteLeaseInternal(lease));
2004 } else {
2005 return (deleteLeaseInternal(lease));
2006 }
2007}
2008
2009bool
2010Memfile_LeaseMgr::deleteLeaseInternal(const Lease6Ptr& lease) {
2011 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
2012
2013 const isc::asiolink::IOAddress& addr = lease->addr_;
2014 Lease6Storage::iterator l = storage6_.find(addr);
2015 if (l == storage6_.end()) {
2016 // No such lease
2017 return (false);
2018 } else {
2019 if (persistLeases(V6)) {
2020 // Copy the lease. The lifetimes need to be modified and we
2021 // don't modify the original lease.
2022 Lease6 lease_copy = **l;
2023 // Setting lifetimes to 0 means that lease is being removed.
2024 lease_copy.valid_lft_ = 0;
2025 lease_copy.preferred_lft_ = 0;
2026 lease_file6_->append(lease_copy);
2027 } else {
2028 // For test purpose only: check that the lease has not changed in
2029 // the database.
2030 if (((*l)->cltt_ != lease->current_cltt_) ||
2031 ((*l)->valid_lft_ != lease->current_valid_lft_)) {
2032 return false;
2033 }
2034 }
2035
2036 storage6_.erase(l);
2037
2038 // Decrement class lease counters.
2039 class_lease_counter_.removeLease(lease);
2040
2041 // Delete references from extended info tables.
2043 deleteExtendedInfo6(lease->addr_);
2044 }
2045
2046 // Run installed callbacks.
2047 if (hasCallbacks()) {
2048 trackDeleteLease(lease);
2049 }
2050
2051 return (true);
2052 }
2053}
2054
2055bool
2058 DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
2059
2060 if (MultiThreadingMgr::instance().getMode()) {
2061 std::lock_guard<std::mutex> lock(*mutex_);
2062 return (deleteLeaseInternal(lease));
2063 } else {
2064 return (deleteLeaseInternal(lease));
2065 }
2066}
2067
2068uint64_t
2072 .arg(secs);
2073
2074 if (MultiThreadingMgr::instance().getMode()) {
2075 std::lock_guard<std::mutex> lock(*mutex_);
2076 return (deleteExpiredReclaimedLeases<
2078 >(secs, V4, storage4_, lease_file4_));
2079 } else {
2080 return (deleteExpiredReclaimedLeases<
2082 >(secs, V4, storage4_, lease_file4_));
2083 }
2084}
2085
2086uint64_t
2090 .arg(secs);
2091
2092 if (MultiThreadingMgr::instance().getMode()) {
2093 std::lock_guard<std::mutex> lock(*mutex_);
2094 return (deleteExpiredReclaimedLeases<
2096 >(secs, V6, storage6_, lease_file6_));
2097 } else {
2098 return (deleteExpiredReclaimedLeases<
2100 >(secs, V6, storage6_, lease_file6_));
2101 }
2102}
2103
2104template<typename IndexType, typename LeaseType, typename StorageType,
2105 typename LeaseFileType>
2106uint64_t
2107Memfile_LeaseMgr::deleteExpiredReclaimedLeases(const uint32_t secs,
2108 const Universe& universe,
2109 StorageType& storage,
2110 LeaseFileType& lease_file) {
2111 // Obtain the index which segragates leases by state and time.
2112 IndexType& index = storage.template get<ExpirationIndexTag>();
2113
2114 // This returns the first element which is greater than the specified
2115 // tuple (true, time(0) - secs). However, the range between the
2116 // beginning of the index and returned element also includes all the
2117 // elements for which the first value is false (lease state is NOT
2118 // reclaimed), because false < true. All elements between the
2119 // beginning of the index and the element returned, for which the
2120 // first value is true, represent the reclaimed leases which should
2121 // be deleted, because their expiration time + secs has occurred earlier
2122 // than current time.
2123 typename IndexType::const_iterator upper_limit =
2124 index.upper_bound(boost::make_tuple(true, time(0) - secs));
2125
2126 // Now, we have to exclude all elements of the index which represent
2127 // leases in the state other than reclaimed - with the first value
2128 // in the index equal to false. Note that elements in the index are
2129 // ordered from the lower to the higher ones. So, all elements with
2130 // the first value of false are placed before the elements with the
2131 // value of true. Hence, we have to find the first element which
2132 // contains value of true. The time value is the lowest possible.
2133 typename IndexType::const_iterator lower_limit =
2134 index.upper_bound(boost::make_tuple(true, std::numeric_limits<int64_t>::min()));
2135
2136 // If there are some elements in this range, delete them.
2137 uint64_t num_leases = static_cast<uint64_t>(std::distance(lower_limit, upper_limit));
2138 if (num_leases > 0) {
2139
2142 .arg(num_leases);
2143
2144 // If lease persistence is enabled, we also have to mark leases
2145 // as deleted in the lease file. We do this by setting the
2146 // lifetime to 0.
2147 if (persistLeases(universe)) {
2148 for (typename IndexType::const_iterator lease = lower_limit;
2149 lease != upper_limit; ++lease) {
2150 // Copy lease to not affect the lease in the container.
2151 LeaseType lease_copy(**lease);
2152 // Set the valid lifetime to 0 to indicate the removal
2153 // of the lease.
2154 lease_copy.valid_lft_ = 0;
2155 lease_file->append(lease_copy);
2156 }
2157 }
2158
2159 // Erase leases from memory.
2160 index.erase(lower_limit, upper_limit);
2161
2162 }
2163 // Return number of leases deleted.
2164 return (num_leases);
2165}
2166
2167std::string
2169 return (std::string("In memory database with leases stored in a CSV file."));
2170}
2171
2172std::pair<uint32_t, uint32_t>
2173Memfile_LeaseMgr::getVersion(const std::string& /* timer_name */) const {
2174 std::string const& universe(conn_.getParameter("universe"));
2175 if (universe == "4") {
2176 return std::make_pair(MAJOR_VERSION_V4, MINOR_VERSION_V4);
2177 } else if (universe == "6") {
2178 return std::make_pair(MAJOR_VERSION_V6, MINOR_VERSION_V6);
2179 }
2180 isc_throw(BadValue, "cannot determine version for universe " << universe);
2181}
2182
2183void
2186}
2187
2188void
2192}
2193
2194std::string
2195Memfile_LeaseMgr::appendSuffix(const std::string& file_name,
2196 const LFCFileType& file_type) {
2197 std::string name(file_name);
2198 switch (file_type) {
2199 case FILE_INPUT:
2200 name += ".1";
2201 break;
2202 case FILE_PREVIOUS:
2203 name += ".2";
2204 break;
2205 case FILE_OUTPUT:
2206 name += ".output";
2207 break;
2208 case FILE_FINISH:
2209 name += ".completed";
2210 break;
2211 case FILE_PID:
2212 name += ".pid";
2213 break;
2214 default:
2215 // Do not append any suffix for the FILE_CURRENT.
2216 ;
2217 }
2218
2219 return (name);
2220}
2221
2222std::string
2224 std::ostringstream s;
2225 s << CfgMgr::instance().getDataDir() << "/kea-leases";
2226 s << (u == V4 ? "4" : "6");
2227 s << ".csv";
2228 return (s.str());
2229}
2230
2231std::string
2233 if (u == V4) {
2234 return (lease_file4_ ? lease_file4_->getFilename() : "");
2235 }
2236
2237 return (lease_file6_ ? lease_file6_->getFilename() : "");
2238}
2239
2240bool
2242 // Currently, if the lease file IO is not created, it means that writes to
2243 // disk have been explicitly disabled by the administrator. At some point,
2244 // there may be a dedicated ON/OFF flag implemented to control this.
2245 if (u == V4 && lease_file4_) {
2246 return (true);
2247 }
2248
2249 return (u == V6 && lease_file6_);
2250}
2251
2252std::string
2253Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
2254 std::string persist_val;
2255 try {
2256 persist_val = conn_.getParameter("persist");
2257 } catch (const Exception&) {
2258 // If parameter persist hasn't been specified, we use a default value
2259 // 'yes'.
2260 persist_val = "true";
2261 }
2262 // If persist_val is 'false' we will not store leases to disk, so let's
2263 // return empty file name.
2264 if (persist_val == "false") {
2265 return ("");
2266
2267 } else if (persist_val != "true") {
2268 isc_throw(isc::BadValue, "invalid value 'persist="
2269 << persist_val << "'");
2270 }
2271
2272 std::string lease_file;
2273 try {
2274 lease_file = conn_.getParameter("name");
2275 } catch (const Exception&) {
2276 lease_file = getDefaultLeaseFilePath(u);
2277 }
2278 return (lease_file);
2279}
2280
2281template<typename LeaseObjectType, typename LeaseFileType, typename StorageType>
2282bool
2283Memfile_LeaseMgr::loadLeasesFromFiles(const std::string& filename,
2284 boost::shared_ptr<LeaseFileType>& lease_file,
2285 StorageType& storage) {
2286 // Check if the instance of the LFC is running right now. If it is
2287 // running, we refuse to load leases as the LFC may be writing to the
2288 // lease files right now. When the user retries server configuration
2289 // it should go through.
2292 PIDFile pid_file(appendSuffix(filename, FILE_PID));
2293 if (pid_file.check()) {
2294 isc_throw(DbOpenError, "unable to load leases from files while the "
2295 "lease file cleanup is in progress");
2296 }
2297
2298 storage.clear();
2299
2300 std::string max_row_errors_str = "0";
2301 try {
2302 max_row_errors_str = conn_.getParameter("max-row-errors");
2303 } catch (const std::exception&) {
2304 // Ignore and default to 0.
2305 }
2306
2307 int64_t max_row_errors64;
2308 try {
2309 max_row_errors64 = boost::lexical_cast<int64_t>(max_row_errors_str);
2310 } catch (const boost::bad_lexical_cast&) {
2311 isc_throw(isc::BadValue, "invalid value of the max-row-errors "
2312 << max_row_errors_str << " specified");
2313 }
2314 if ((max_row_errors64 < 0) ||
2315 (max_row_errors64 > std::numeric_limits<uint32_t>::max())) {
2316 isc_throw(isc::BadValue, "invalid value of the max-row-errors "
2317 << max_row_errors_str << " specified");
2318 }
2319 uint32_t max_row_errors = static_cast<uint32_t>(max_row_errors64);
2320
2321 // Load the leasefile.completed, if exists.
2322 bool conversion_needed = false;
2323 lease_file.reset(new LeaseFileType(std::string(filename + ".completed")));
2324 if (lease_file->exists()) {
2325 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2326 max_row_errors);
2327 conversion_needed = conversion_needed || lease_file->needsConversion();
2328 } else {
2329 // If the leasefile.completed doesn't exist, let's load the leases
2330 // from leasefile.2 and leasefile.1, if they exist.
2331 lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_PREVIOUS)));
2332 if (lease_file->exists()) {
2333 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2334 max_row_errors);
2335 conversion_needed = conversion_needed || lease_file->needsConversion();
2336 }
2337
2338 lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_INPUT)));
2339 if (lease_file->exists()) {
2340 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2341 max_row_errors);
2342 conversion_needed = conversion_needed || lease_file->needsConversion();
2343 }
2344 }
2345
2346 // Always load leases from the primary lease file. If the lease file
2347 // doesn't exist it will be created by the LeaseFileLoader. Note
2348 // that the false value passed as the last parameter to load
2349 // function causes the function to leave the file open after
2350 // it is parsed. This file will be used by the backend to record
2351 // future lease updates.
2352 lease_file.reset(new LeaseFileType(filename));
2353 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2354 max_row_errors, false);
2355 conversion_needed = conversion_needed || lease_file->needsConversion();
2356
2357 return (conversion_needed);
2358}
2359
2360
2361bool
2363 return (lfc_setup_->isRunning());
2364}
2365
2366int
2368 return (lfc_setup_->getExitStatus());
2369}
2370
2371void
2374
2375 // Check if we're in the v4 or v6 space and use the appropriate file.
2376 if (lease_file4_) {
2378 lfcExecute(lease_file4_);
2379 } else if (lease_file6_) {
2381 lfcExecute(lease_file6_);
2382 }
2383}
2384
2385void
2386Memfile_LeaseMgr::lfcSetup(bool conversion_needed) {
2387 std::string lfc_interval_str = "3600";
2388 try {
2389 lfc_interval_str = conn_.getParameter("lfc-interval");
2390 } catch (const std::exception&) {
2391 // Ignore and default to 3600.
2392 }
2393
2394 uint32_t lfc_interval = 0;
2395 try {
2396 lfc_interval = boost::lexical_cast<uint32_t>(lfc_interval_str);
2397 } catch (const boost::bad_lexical_cast&) {
2398 isc_throw(isc::BadValue, "invalid value of the lfc-interval "
2399 << lfc_interval_str << " specified");
2400 }
2401
2402 if (lfc_interval > 0 || conversion_needed) {
2403 lfc_setup_.reset(new LFCSetup(std::bind(&Memfile_LeaseMgr::lfcCallback, this)));
2404 lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_, conversion_needed);
2405 }
2406}
2407
2408template<typename LeaseFileType>
2409void
2410Memfile_LeaseMgr::lfcExecute(boost::shared_ptr<LeaseFileType>& lease_file) {
2411 bool do_lfc = true;
2412
2413 // Check the status of the LFC instance.
2414 // If the finish file exists or the copy of the lease file exists it
2415 // is an indication that another LFC instance may be in progress or
2416 // may be stalled. In that case we don't want to rotate the current
2417 // lease file to avoid overriding the contents of the existing file.
2418 CSVFile lease_file_finish(appendSuffix(lease_file->getFilename(), FILE_FINISH));
2419 CSVFile lease_file_copy(appendSuffix(lease_file->getFilename(), FILE_INPUT));
2420 if (!lease_file_finish.exists() && !lease_file_copy.exists()) {
2421 // Close the current file so as we can move it to the copy file.
2422 lease_file->close();
2423 // Move the current file to the copy file. Remember the result
2424 // because we don't want to run LFC if the rename failed.
2425 do_lfc = (rename(lease_file->getFilename().c_str(),
2426 lease_file_copy.getFilename().c_str()) == 0);
2427
2428 if (!do_lfc) {
2430 .arg(lease_file->getFilename())
2431 .arg(lease_file_copy.getFilename())
2432 .arg(strerror(errno));
2433 }
2434
2435 // Regardless if we successfully moved the current file or not,
2436 // we need to re-open the current file for the server to write
2437 // new lease updates. If the file has been successfully moved,
2438 // this will result in creation of the new file. Otherwise,
2439 // an existing file will be opened.
2440 try {
2441 lease_file->open(true);
2442
2443 } catch (const CSVFileError& ex) {
2444 // If we're unable to open the lease file this is a serious
2445 // error because the server will not be able to persist
2446 // leases.
2454 .arg(lease_file->getFilename())
2455 .arg(ex.what());
2456 // Reset the pointer to the file so as the backend doesn't
2457 // try to write leases to disk.
2458 lease_file.reset();
2459 do_lfc = false;
2460 }
2461 }
2462 // Once the files have been rotated, or untouched if another LFC had
2463 // not finished, a new process is started.
2464 if (do_lfc) {
2465 lfc_setup_->execute();
2466 }
2467}
2468
2471 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_));
2472 if (MultiThreadingMgr::instance().getMode()) {
2473 std::lock_guard<std::mutex> lock(*mutex_);
2474 query->start();
2475 } else {
2476 query->start();
2477 }
2478
2479 return(query);
2480}
2481
2485 if (MultiThreadingMgr::instance().getMode()) {
2486 std::lock_guard<std::mutex> lock(*mutex_);
2487 query->start();
2488 } else {
2489 query->start();
2490 }
2491
2492 return(query);
2493}
2494
2497 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, subnet_id));
2498 if (MultiThreadingMgr::instance().getMode()) {
2499 std::lock_guard<std::mutex> lock(*mutex_);
2500 query->start();
2501 } else {
2502 query->start();
2503 }
2504
2505 return(query);
2506}
2507
2510 const SubnetID& last_subnet_id) {
2511 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, first_subnet_id,
2512 last_subnet_id));
2513 if (MultiThreadingMgr::instance().getMode()) {
2514 std::lock_guard<std::mutex> lock(*mutex_);
2515 query->start();
2516 } else {
2517 query->start();
2518 }
2519
2520 return(query);
2521}
2522
2525 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_));
2526 if (MultiThreadingMgr::instance().getMode()) {
2527 std::lock_guard<std::mutex> lock(*mutex_);
2528 query->start();
2529 } else {
2530 query->start();
2531 }
2532
2533 return(query);
2534}
2535
2539 if (MultiThreadingMgr::instance().getMode()) {
2540 std::lock_guard<std::mutex> lock(*mutex_);
2541 query->start();
2542 } else {
2543 query->start();
2544 }
2545
2546 return(query);
2547}
2548
2551 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, subnet_id));
2552 if (MultiThreadingMgr::instance().getMode()) {
2553 std::lock_guard<std::mutex> lock(*mutex_);
2554 query->start();
2555 } else {
2556 query->start();
2557 }
2558
2559 return(query);
2560}
2561
2564 const SubnetID& last_subnet_id) {
2565 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, first_subnet_id,
2566 last_subnet_id));
2567 if (MultiThreadingMgr::instance().getMode()) {
2568 std::lock_guard<std::mutex> lock(*mutex_);
2569 query->start();
2570 } else {
2571 query->start();
2572 }
2573
2574 return(query);
2575}
2576
2577size_t
2580 .arg(subnet_id);
2581
2582 // Get the index by DUID, IAID, lease type.
2583 const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
2584
2585 // Try to get the lease using the DUID, IAID and lease type.
2586 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
2587 Lease4StorageSubnetIdIndex::const_iterator> l =
2588 idx.equal_range(subnet_id);
2589
2590 // Let's collect all leases.
2591 Lease4Collection leases;
2592 BOOST_FOREACH(auto const& lease, l) {
2593 leases.push_back(lease);
2594 }
2595
2596 size_t num = leases.size();
2597 for (auto const& l : leases) {
2598 deleteLease(l);
2599 }
2601 .arg(subnet_id).arg(num);
2602
2603 return (num);
2604}
2605
2606size_t
2609 .arg(subnet_id);
2610
2611 // Get the index by DUID, IAID, lease type.
2612 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
2613
2614 // Try to get the lease using the DUID, IAID and lease type.
2615 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
2616 Lease6StorageSubnetIdIndex::const_iterator> l =
2617 idx.equal_range(subnet_id);
2618
2619 // Let's collect all leases.
2620 Lease6Collection leases;
2621 BOOST_FOREACH(auto const& lease, l) {
2622 leases.push_back(lease);
2623 }
2624
2625 size_t num = leases.size();
2626 for (auto const& l : leases) {
2627 deleteLease(l);
2628 }
2630 .arg(subnet_id).arg(num);
2631
2632 return (num);
2633}
2634
2635void
2637 class_lease_counter_.clear();
2638 for (auto const& lease : storage4_) {
2639 // Bump the appropriate accumulator
2640 if (lease->state_ == Lease::STATE_DEFAULT) {
2641 class_lease_counter_.addLease(lease);
2642 }
2643 }
2644}
2645
2646void
2648 class_lease_counter_.clear();
2649 for (auto const& lease : storage6_) {
2650 // Bump the appropriate accumulator
2651 if (lease->state_ == Lease::STATE_DEFAULT) {
2652 class_lease_counter_.addLease(lease);
2653 }
2654 }
2655}
2656
2657size_t
2659 const Lease::Type& ltype /* = Lease::TYPE_V4*/) const {
2660 if (MultiThreadingMgr::instance().getMode()) {
2661 std::lock_guard<std::mutex> lock(*mutex_);
2662 return(class_lease_counter_.getClassCount(client_class, ltype));
2663 } else {
2664 return(class_lease_counter_.getClassCount(client_class, ltype));
2665 }
2666}
2667
2668void
2670 return(class_lease_counter_.clear());
2671}
2672
2673std::string
2675 if (!user_context) {
2676 return ("");
2677 }
2678
2679 ConstElementPtr limits = user_context->find("ISC/limits");
2680 if (!limits) {
2681 return ("");
2682 }
2683
2684 // Iterate of the 'client-classes' list in 'limits'. For each class that specifies
2685 // an "address-limit", check its value against the class's lease count.
2686 ConstElementPtr classes = limits->get("client-classes");
2687 if (classes) {
2688 for (int i = 0; i < classes->size(); ++i) {
2689 ConstElementPtr class_elem = classes->get(i);
2690 // Get class name.
2691 ConstElementPtr name_elem = class_elem->get("name");
2692 if (!name_elem) {
2693 isc_throw(BadValue, "checkLimits4 - client-class.name is missing: "
2694 << prettyPrint(limits));
2695 }
2696
2697 std::string name = name_elem->stringValue();
2698
2699 // Now look for an address-limit
2700 size_t limit;
2701 if (!getLeaseLimit(class_elem, Lease::TYPE_V4, limit)) {
2702 // No limit, go to the next class.
2703 continue;
2704 }
2705
2706 // If the limit is > 0 look up the class lease count. Limit of 0 always
2707 // denies the lease.
2708 size_t lease_count = 0;
2709 if (limit) {
2710 lease_count = getClassLeaseCount(name);
2711 }
2712
2713 // If we're over the limit, return the error, no need to evaluate any others.
2714 if (lease_count >= limit) {
2715 std::ostringstream ss;
2716 ss << "address limit " << limit << " for client class \""
2717 << name << "\", current lease count " << lease_count;
2718 return (ss.str());
2719 }
2720 }
2721 }
2722
2723 // If there were class limits we passed them, now look for a subnet limit.
2724 ConstElementPtr subnet_elem = limits->get("subnet");
2725 if (subnet_elem) {
2726 // Get the subnet id.
2727 ConstElementPtr id_elem = subnet_elem->get("id");
2728 if (!id_elem) {
2729 isc_throw(BadValue, "checkLimits4 - subnet.id is missing: "
2730 << prettyPrint(limits));
2731 }
2732
2733 SubnetID subnet_id = id_elem->intValue();
2734
2735 // Now look for an address-limit.
2736 size_t limit;
2737 if (getLeaseLimit(subnet_elem, Lease::TYPE_V4, limit)) {
2738 // If the limit is > 0 look up the subnet lease count. Limit of 0 always
2739 // denies the lease.
2740 int64_t lease_count = 0;
2741 if (limit) {
2742 lease_count = getSubnetStat(subnet_id, "assigned-addresses");
2743 }
2744
2745 // If we're over the limit, return the error.
2746 if (lease_count >= limit) {
2747 std::ostringstream ss;
2748 ss << "address limit " << limit << " for subnet ID " << subnet_id
2749 << ", current lease count " << lease_count;
2750 return (ss.str());
2751 }
2752 }
2753 }
2754
2755 // No limits exceeded!
2756 return ("");
2757}
2758
2759std::string
2761 if (!user_context) {
2762 return ("");
2763 }
2764
2765 ConstElementPtr limits = user_context->find("ISC/limits");
2766 if (!limits) {
2767 return ("");
2768 }
2769
2770 // Iterate over the 'client-classes' list in 'limits'. For each class that specifies
2771 // limit (either "address-limit" or "prefix-limit", check its value against the appropriate
2772 // class lease count.
2773 ConstElementPtr classes = limits->get("client-classes");
2774 if (classes) {
2775 for (int i = 0; i < classes->size(); ++i) {
2776 ConstElementPtr class_elem = classes->get(i);
2777 // Get class name.
2778 ConstElementPtr name_elem = class_elem->get("name");
2779 if (!name_elem) {
2780 isc_throw(BadValue, "checkLimits6 - client-class.name is missing: "
2781 << prettyPrint(limits));
2782 }
2783
2784 std::string name = name_elem->stringValue();
2785
2786 // Now look for either address-limit or a prefix=limit.
2787 size_t limit = 0;
2789 if (!getLeaseLimit(class_elem, ltype, limit)) {
2790 ltype = Lease::TYPE_PD;
2791 if (!getLeaseLimit(class_elem, ltype, limit)) {
2792 // No limits for this class, skip to the next.
2793 continue;
2794 }
2795 }
2796
2797 // If the limit is > 0 look up the class lease count. Limit of 0 always
2798 // denies the lease.
2799 size_t lease_count = 0;
2800 if (limit) {
2801 lease_count = getClassLeaseCount(name, ltype);
2802 }
2803
2804 // If we're over the limit, return the error, no need to evaluate any others.
2805 if (lease_count >= limit) {
2806 std::ostringstream ss;
2807 ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
2808 << " limit " << limit << " for client class \""
2809 << name << "\", current lease count " << lease_count;
2810 return (ss.str());
2811 }
2812 }
2813 }
2814
2815 // If there were class limits we passed them, now look for a subnet limit.
2816 ConstElementPtr subnet_elem = limits->get("subnet");
2817 if (subnet_elem) {
2818 // Get the subnet id.
2819 ConstElementPtr id_elem = subnet_elem->get("id");
2820 if (!id_elem) {
2821 isc_throw(BadValue, "checkLimits6 - subnet.id is missing: "
2822 << prettyPrint(limits));
2823 }
2824
2825 SubnetID subnet_id = id_elem->intValue();
2826
2827 // Now look for either address-limit or a prefix=limit.
2828 size_t limit = 0;
2830 if (!getLeaseLimit(subnet_elem, ltype, limit)) {
2831 ltype = Lease::TYPE_PD;
2832 if (!getLeaseLimit(subnet_elem, ltype, limit)) {
2833 // No limits for the subnet so none exceeded!
2834 return ("");
2835 }
2836 }
2837
2838 // If the limit is > 0 look up the class lease count. Limit of 0 always
2839 // denies the lease.
2840 int64_t lease_count = 0;
2841 if (limit) {
2842 lease_count = getSubnetStat(subnet_id, (ltype == Lease::TYPE_NA ?
2843 "assigned-nas" : "assigned-pds"));
2844 }
2845
2846 // If we're over the limit, return the error.
2847 if (lease_count >= limit) {
2848 std::ostringstream ss;
2849 ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
2850 << " limit " << limit << " for subnet ID " << subnet_id
2851 << ", current lease count " << lease_count;
2852 return (ss.str());
2853 }
2854 }
2855
2856 // No limits exceeded!
2857 return ("");
2858}
2859
2860bool
2862 return true;
2863}
2864
2865int64_t
2866Memfile_LeaseMgr::getSubnetStat(const SubnetID& subnet_id, const std::string& stat_label) const {
2869 std::string stat_name = StatsMgr::generateName("subnet", subnet_id, stat_label);
2870 ConstElementPtr stat = StatsMgr::instance().get(stat_name);
2871 ConstElementPtr samples = stat->get(stat_name);
2872 if (samples && samples->size()) {
2873 auto sample = samples->get(0);
2874 if (sample->size()) {
2875 auto count_elem = sample->get(0);
2876 return (count_elem->intValue());
2877 }
2878 }
2879
2880 return (0);
2881}
2882
2883bool
2884Memfile_LeaseMgr::getLeaseLimit(ConstElementPtr parent, Lease::Type ltype, size_t& limit) const {
2885 ConstElementPtr limit_elem = parent->get(ltype == Lease::TYPE_PD ?
2886 "prefix-limit" : "address-limit");
2887 if (limit_elem) {
2888 limit = limit_elem->intValue();
2889 return (true);
2890 }
2891
2892 return (false);
2893}
2894
2895namespace {
2896
2897std::string
2898idToText(const OptionBuffer& id) {
2899 std::stringstream tmp;
2900 tmp << std::hex;
2901 bool delim = false;
2902 for (auto const& it : id) {
2903 if (delim) {
2904 tmp << ":";
2905 }
2906 tmp << std::setw(2) << std::setfill('0')
2907 << static_cast<unsigned int>(it);
2908 delim = true;
2909 }
2910 return (tmp.str());
2911}
2912
2913} // anonymous namespace
2914
2917 const IOAddress& lower_bound_address,
2918 const LeasePageSize& page_size,
2919 const time_t& qry_start_time /* = 0 */,
2920 const time_t& qry_end_time /* = 0 */) {
2923 .arg(page_size.page_size_)
2924 .arg(lower_bound_address.toText())
2925 .arg(idToText(relay_id))
2926 .arg(qry_start_time)
2927 .arg(qry_end_time);
2928
2929 // Expecting IPv4 address.
2930 if (!lower_bound_address.isV4()) {
2931 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
2932 "retrieving leases from the lease database, got "
2933 << lower_bound_address);
2934 }
2935
2936 // Catch 2038 bug with 32 bit time_t.
2937 if ((qry_start_time < 0) || (qry_end_time < 0)) {
2938 isc_throw(BadValue, "negative time value");
2939 }
2940
2941 // Start time must be before end time.
2942 if ((qry_start_time > 0) && (qry_end_time > 0) &&
2943 (qry_start_time > qry_end_time)) {
2944 isc_throw(BadValue, "start time must be before end time");
2945 }
2946
2947 if (MultiThreadingMgr::instance().getMode()) {
2948 std::lock_guard<std::mutex> lock(*mutex_);
2949 return (getLeases4ByRelayIdInternal(relay_id,
2950 lower_bound_address,
2951 page_size,
2952 qry_start_time,
2953 qry_end_time));
2954 } else {
2955 return (getLeases4ByRelayIdInternal(relay_id,
2956 lower_bound_address,
2957 page_size,
2958 qry_start_time,
2959 qry_end_time));
2960 }
2961}
2962
2964Memfile_LeaseMgr::getLeases4ByRelayIdInternal(const OptionBuffer& relay_id,
2965 const IOAddress& lower_bound_address,
2966 const LeasePageSize& page_size,
2967 const time_t& qry_start_time,
2968 const time_t& qry_end_time) {
2969 Lease4Collection collection;
2970 const Lease4StorageRelayIdIndex& idx = storage4_.get<RelayIdIndexTag>();
2971 Lease4StorageRelayIdIndex::const_iterator lb =
2972 idx.lower_bound(boost::make_tuple(relay_id, lower_bound_address));
2973 // Return all convenient leases being within the page size.
2974 IOAddress last_addr = lower_bound_address;
2975 for (; lb != idx.end(); ++lb) {
2976 if ((*lb)->addr_ == last_addr) {
2977 // Already seen: skip it.
2978 continue;
2979 }
2980 if ((*lb)->relay_id_ != relay_id) {
2981 // Gone after the relay id index.
2982 break;
2983 }
2984 last_addr = (*lb)->addr_;
2985 if ((qry_start_time > 0) && ((*lb)->cltt_ < qry_start_time)) {
2986 // Too old.
2987 continue;
2988 }
2989 if ((qry_end_time > 0) && ((*lb)->cltt_ > qry_end_time)) {
2990 // Too young.
2991 continue;
2992 }
2993 collection.push_back(Lease4Ptr(new Lease4(**lb)));
2994 if (collection.size() >= page_size.page_size_) {
2995 break;
2996 }
2997 }
2998 return (collection);
2999}
3000
3003 const IOAddress& lower_bound_address,
3004 const LeasePageSize& page_size,
3005 const time_t& qry_start_time /* = 0 */,
3006 const time_t& qry_end_time /* = 0 */) {
3009 .arg(page_size.page_size_)
3010 .arg(lower_bound_address.toText())
3011 .arg(idToText(remote_id))
3012 .arg(qry_start_time)
3013 .arg(qry_end_time);
3014
3015 // Expecting IPv4 address.
3016 if (!lower_bound_address.isV4()) {
3017 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
3018 "retrieving leases from the lease database, got "
3019 << lower_bound_address);
3020 }
3021
3022 // Catch 2038 bug with 32 bit time_t.
3023 if ((qry_start_time < 0) || (qry_end_time < 0)) {
3024 isc_throw(BadValue, "negative time value");
3025 }
3026
3027 // Start time must be before end time.
3028 if ((qry_start_time > 0) && (qry_end_time > 0) &&
3029 (qry_start_time > qry_end_time)) {
3030 isc_throw(BadValue, "start time must be before end time");
3031 }
3032
3033 if (MultiThreadingMgr::instance().getMode()) {
3034 std::lock_guard<std::mutex> lock(*mutex_);
3035 return (getLeases4ByRemoteIdInternal(remote_id,
3036 lower_bound_address,
3037 page_size,
3038 qry_start_time,
3039 qry_end_time));
3040 } else {
3041 return (getLeases4ByRemoteIdInternal(remote_id,
3042 lower_bound_address,
3043 page_size,
3044 qry_start_time,
3045 qry_end_time));
3046 }
3047}
3048
3050Memfile_LeaseMgr::getLeases4ByRemoteIdInternal(const OptionBuffer& remote_id,
3051 const IOAddress& lower_bound_address,
3052 const LeasePageSize& page_size,
3053 const time_t& qry_start_time,
3054 const time_t& qry_end_time) {
3055 Lease4Collection collection;
3056 std::map<IOAddress, Lease4Ptr> sorted;
3057 const Lease4StorageRemoteIdIndex& idx = storage4_.get<RemoteIdIndexTag>();
3058 Lease4StorageRemoteIdRange er = idx.equal_range(remote_id);
3059 // Store all convenient leases being within the page size.
3060 BOOST_FOREACH(auto const& it, er) {
3061 const IOAddress& addr = it->addr_;
3062 if (addr <= lower_bound_address) {
3063 // Not greater than lower_bound_address.
3064 continue;
3065 }
3066 if ((qry_start_time > 0) && (it->cltt_ < qry_start_time)) {
3067 // Too old.
3068 continue;
3069 }
3070 if ((qry_end_time > 0) && (it->cltt_ > qry_end_time)) {
3071 // Too young.
3072 continue;
3073 }
3074 sorted[addr] = it;
3075 }
3076
3077 // Return all leases being within the page size.
3078 for (auto const& it : sorted) {
3079 collection.push_back(Lease4Ptr(new Lease4(*it.second)));
3080 if (collection.size() >= page_size.page_size_) {
3081 break;
3082 }
3083 }
3084 return (collection);
3085}
3086
3087void
3089 if (MultiThreadingMgr::instance().getMode()) {
3090 std::lock_guard<std::mutex> lock(*mutex_);
3091 relay_id6_.clear();
3092 remote_id6_.clear();
3093 } else {
3094 relay_id6_.clear();
3095 remote_id6_.clear();
3096 }
3097}
3098
3099size_t
3101 return (relay_id6_.size());
3102}
3103
3104size_t
3106 return (remote_id6_.size());
3107}
3108
3111 const IOAddress& lower_bound_address,
3112 const LeasePageSize& page_size) {
3115 .arg(page_size.page_size_)
3116 .arg(lower_bound_address.toText())
3117 .arg(relay_id.toText());
3118
3119 // Expecting IPv6 valid address.
3120 if (!lower_bound_address.isV6()) {
3121 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3122 "retrieving leases from the lease database, got "
3123 << lower_bound_address);
3124 }
3125
3126 if (MultiThreadingMgr::instance().getMode()) {
3127 std::lock_guard<std::mutex> lock(*mutex_);
3128 return (getLeases6ByRelayIdInternal(relay_id,
3129 lower_bound_address,
3130 page_size));
3131 } else {
3132 return (getLeases6ByRelayIdInternal(relay_id,
3133 lower_bound_address,
3134 page_size));
3135 }
3136}
3137
3139Memfile_LeaseMgr::getLeases6ByRelayIdInternal(const DUID& relay_id,
3140 const IOAddress& lower_bound_address,
3141 const LeasePageSize& page_size) {
3142 const std::vector<uint8_t>& relay_id_data = relay_id.getDuid();
3143 Lease6Collection collection;
3144 const RelayIdIndex& idx = relay_id6_.get<RelayIdIndexTag>();
3145 RelayIdIndex::const_iterator lb =
3146 idx.lower_bound(boost::make_tuple(relay_id_data, lower_bound_address));
3147
3148 // Return all leases being within the page size.
3149 IOAddress last_addr = lower_bound_address;
3150 for (; lb != idx.end(); ++lb) {
3151 if ((*lb)->lease_addr_ == last_addr) {
3152 // Already seen: skip it.
3153 continue;
3154 }
3155 if ((*lb)->id_ != relay_id_data) {
3156 // Gone after the relay id index.
3157 break;
3158 }
3159 last_addr = (*lb)->lease_addr_;
3160 Lease6Ptr lease = getAnyLease6Internal(last_addr);
3161 if (lease) {
3162 collection.push_back(lease);
3163 if (collection.size() >= page_size.page_size_) {
3164 break;
3165 }
3166 }
3167 }
3168 return (collection);
3169}
3170
3173 const IOAddress& lower_bound_address,
3174 const LeasePageSize& page_size) {
3177 .arg(page_size.page_size_)
3178 .arg(lower_bound_address.toText())
3179 .arg(idToText(remote_id));
3180
3181 // Expecting IPv6 valid address.
3182 if (!lower_bound_address.isV6()) {
3183 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3184 "retrieving leases from the lease database, got "
3185 << lower_bound_address);
3186 }
3187
3188 if (MultiThreadingMgr::instance().getMode()) {
3189 std::lock_guard<std::mutex> lock(*mutex_);
3190 return (getLeases6ByRemoteIdInternal(remote_id,
3191 lower_bound_address,
3192 page_size));
3193 } else {
3194 return (getLeases6ByRemoteIdInternal(remote_id,
3195 lower_bound_address,
3196 page_size));
3197 }
3198}
3199
3201Memfile_LeaseMgr::getLeases6ByRemoteIdInternal(const OptionBuffer& remote_id,
3202 const IOAddress& lower_bound_address,
3203 const LeasePageSize& page_size) {
3204 Lease6Collection collection;
3205 std::set<IOAddress> sorted;
3206 const RemoteIdIndex& idx = remote_id6_.get<RemoteIdIndexTag>();
3207 RemoteIdIndexRange er = idx.equal_range(remote_id);
3208 // Store all addresses greater than lower_bound_address.
3209 BOOST_FOREACH(auto const& it, er) {
3210 const IOAddress& addr = it->lease_addr_;
3211 if (addr <= lower_bound_address) {
3212 continue;
3213 }
3214 static_cast<void>(sorted.insert(addr));
3215 }
3216
3217 // Return all leases being within the page size.
3218 for (const IOAddress& addr : sorted) {
3219 Lease6Ptr lease = getAnyLease6Internal(addr);
3220 if (lease) {
3221 collection.push_back(lease);
3222 if (collection.size() >= page_size.page_size_) {
3223 break;
3224 }
3225 }
3226 }
3227 return (collection);
3228}
3229
3230size_t
3231Memfile_LeaseMgr::extractExtendedInfo4(bool update, bool current) {
3233 if (current) {
3234 cfg = CfgMgr::instance().getCurrentCfg()->getConsistency();
3235 } else {
3236 cfg = CfgMgr::instance().getStagingCfg()->getConsistency();
3237 }
3238 if (!cfg) {
3239 isc_throw(Unexpected, "the " << (current ? "current" : "staging")
3240 << " consistency configuration is null");
3241 }
3242 auto check = cfg->getExtendedInfoSanityCheck();
3243
3247 .arg(update ? " updating in file" : "");
3248
3249 size_t leases = 0;
3250 size_t modified = 0;
3251 size_t updated = 0;
3252 size_t processed = 0;
3253 auto& index = storage4_.get<AddressIndexTag>();
3254 auto lease_it = index.begin();
3255 auto next_it = index.end();
3256
3257 for (; lease_it != index.end(); lease_it = next_it) {
3258 next_it = std::next(lease_it);
3259 Lease4Ptr lease = *lease_it;
3260 ++leases;
3261 try {
3262 if (upgradeLease4ExtendedInfo(lease, check)) {
3263 ++modified;
3264 if (update && persistLeases(V4)) {
3265 lease_file4_->append(*lease);
3266 ++updated;
3267 }
3268 }
3269 // Work on a copy as the multi-index requires fields used
3270 // as indexes to be read-only.
3271 Lease4Ptr copy(new Lease4(*lease));
3273 if (!copy->relay_id_.empty() || !copy->remote_id_.empty()) {
3274 index.replace(lease_it, copy);
3275 ++processed;
3276 }
3277 } catch (const std::exception& ex) {
3280 .arg(lease->addr_.toText())
3281 .arg(ex.what());
3282 }
3283 }
3284
3286 .arg(leases)
3287 .arg(modified)
3288 .arg(updated)
3289 .arg(processed);
3290
3291 return (updated);
3292}
3293
3294size_t
3296 return (0);
3297}
3298
3299void
3301 CfgConsistencyPtr cfg = CfgMgr::instance().getStagingCfg()->getConsistency();
3302 if (!cfg) {
3303 isc_throw(Unexpected, "the staging consistency configuration is null");
3304 }
3305 auto check = cfg->getExtendedInfoSanityCheck();
3306 bool enabled = getExtendedInfoTablesEnabled();
3307
3311 .arg(enabled ? "enabled" : "disabled");
3312
3313 // Clear tables when enabled.
3314 if (enabled) {
3315 relay_id6_.clear();
3316 remote_id6_.clear();
3317 }
3318
3319 size_t leases = 0;
3320 size_t modified = 0;
3321 size_t processed = 0;
3322
3323 for (auto const& lease : storage6_) {
3324 ++leases;
3325 try {
3326 if (upgradeLease6ExtendedInfo(lease, check)) {
3327 ++modified;
3328 }
3329 if (enabled && addExtendedInfo6(lease)) {
3330 ++processed;
3331 }
3332 } catch (const std::exception& ex) {
3335 .arg(lease->addr_.toText())
3336 .arg(ex.what());
3337 }
3338 }
3339
3341 .arg(leases)
3342 .arg(modified)
3343 .arg(processed);
3344}
3345
3346size_t
3348 return (0);
3349}
3350
3351void
3353 LeaseAddressRelayIdIndex& relay_id_idx =
3355 static_cast<void>(relay_id_idx.erase(addr));
3356 LeaseAddressRemoteIdIndex& remote_id_idx =
3358 static_cast<void>(remote_id_idx.erase(addr));
3359}
3360
3361void
3363 const std::vector<uint8_t>& relay_id) {
3364 Lease6ExtendedInfoPtr ex_info;
3365 ex_info.reset(new Lease6ExtendedInfo(lease_addr, relay_id));
3366 relay_id6_.insert(ex_info);
3367}
3368
3369void
3371 const std::vector<uint8_t>& remote_id) {
3372 Lease6ExtendedInfoPtr ex_info;
3373 ex_info.reset(new Lease6ExtendedInfo(lease_addr, remote_id));
3374 remote_id6_.insert(ex_info);
3375}
3376
3377void
3378Memfile_LeaseMgr::writeLeases4(const std::string& filename) {
3379 if (MultiThreadingMgr::instance().getMode()) {
3380 std::lock_guard<std::mutex> lock(*mutex_);
3381 writeLeases4Internal(filename);
3382 } else {
3383 writeLeases4Internal(filename);
3384 }
3385}
3386
3387void
3388Memfile_LeaseMgr::writeLeases4Internal(const std::string& filename) {
3389 bool overwrite = (lease_file4_ && lease_file4_->getFilename() == filename);
3390 try {
3391 if (overwrite) {
3392 lease_file4_->close();
3393 }
3394 std::ostringstream old;
3395 old << filename << ".bak" << getpid();
3396 ::rename(filename.c_str(), old.str().c_str());
3397 CSVLeaseFile4 backup(filename);
3398 backup.open();
3399 for (auto const& lease : storage4_) {
3400 backup.append(*lease);
3401 }
3402 backup.close();
3403 if (overwrite) {
3404 lease_file4_->open(true);
3405 }
3406 } catch (const std::exception&) {
3407 if (overwrite) {
3408 lease_file4_->open(true);
3409 }
3410 throw;
3411 }
3412}
3413
3414void
3415Memfile_LeaseMgr::writeLeases6(const std::string& filename) {
3416 if (MultiThreadingMgr::instance().getMode()) {
3417 std::lock_guard<std::mutex> lock(*mutex_);
3418 writeLeases6Internal(filename);
3419 } else {
3420 writeLeases6Internal(filename);
3421 }
3422}
3423
3424void
3425Memfile_LeaseMgr::writeLeases6Internal(const std::string& filename) {
3426 bool overwrite = (lease_file6_ && lease_file6_->getFilename() == filename);
3427 try {
3428 if (overwrite) {
3429 lease_file6_->close();
3430 }
3431 std::ostringstream old;
3432 old << filename << ".bak" << getpid();
3433 ::rename(filename.c_str(), old.str().c_str());
3434 CSVLeaseFile6 backup(filename);
3435 backup.open();
3436 for (auto const& lease : storage6_) {
3437 backup.append(*lease);
3438 }
3439 backup.close();
3440 if (overwrite) {
3441 lease_file6_->open(true);
3442 }
3443 } catch (const std::exception&) {
3444 if (overwrite) {
3445 lease_file6_->open(true);
3446 }
3447 throw;
3448 }
3449}
3450
3451} // namespace dhcp
3452} // namespace isc
int version()
returns Kea hooks version.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown when an unexpected error condition occurs.
std::string getParameter(const std::string &name) const
Returns value of a connection parameter.
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Exception thrown on failure to open database.
Invalid address family used as input to Lease Manager.
Definition: db_exceptions.h:59
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.
util::Optional< std::string > getDataDir() const
returns path do the data directory
Definition: cfgmgr.cc:31
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition: cfgmgr.cc:167
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition: cfgmgr.cc:161
void addLease(LeasePtr lease)
Increment the counts for all of a lease's classes by one.
void clear()
Remove all entries.
void removeLease(LeasePtr lease)
Decrement the counts for all of a lease's classes by one.
void updateLease(LeasePtr new_lease, LeasePtr old_lease)
Adjust class lease counts given a new and old version of a lease.
size_t getClassCount(const ClientClass &client_class, const Lease::Type &ltype=Lease::TYPE_V4) const
Fetches the lease count for the given class and lease type.
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
Represents a configuration for Lease File Cleanup.
void execute()
Spawns a new process.
int getExitStatus() const
Returns exit code of the last completed cleanup.
bool isRunning() const
Checks if the lease file cleanup is in progress.
LFCSetup(asiolink::IntervalTimer::Callback callback)
Constructor.
void setup(const uint32_t lfc_interval, const boost::shared_ptr< CSVLeaseFile4 > &lease_file4, const boost::shared_ptr< CSVLeaseFile6 > &lease_file6, bool run_once_now=false)
Sets the new configuration for the Lease File Cleanup.
Lease6 extended informations for Bulk Lease Query.
void setExtendedInfoTablesEnabled(const bool enabled)
Modifies the setting whether the lease6 extended info tables are enabled.
Definition: lease_mgr.h:1018
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:767
bool getExtendedInfoTablesEnabled() const
Returns the setting indicating if lease6 extended info tables are enabled.
Definition: lease_mgr.h:1010
static std::string getDBVersion()
Class method to return extended version info This class method must be redeclared and redefined in de...
Definition: lease_mgr.cc:516
static void extractLease4ExtendedInfo(const Lease4Ptr &lease, bool ignore_errors=true)
Extract relay and remote identifiers from the extended info.
Definition: lease_mgr.cc:1119
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:535
virtual bool addExtendedInfo6(const Lease6Ptr &lease)
Extract extended info from a lease6 and add it into tables.
Definition: lease_mgr.cc:1205
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
Base class for fulfilling a statistical lease data query.
Definition: lease_mgr.h:149
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.
Base Memfile derivation of the statistical lease data query.
std::vector< LeaseStatsRow >::iterator next_pos_
An iterator for accessing the next row within the result set.
MemfileLeaseStatsQuery(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for subnet range query.
virtual bool getNextRow(LeaseStatsRow &row)
Fetches the next row in the result set.
std::vector< LeaseStatsRow > rows_
A vector containing the "result set".
MemfileLeaseStatsQuery(const SelectMode &select_mode=ALL_SUBNETS)
Constructor for all subnets query.
virtual ~MemfileLeaseStatsQuery()
Destructor.
int getRowCount() const
Returns the number of rows in the result set.
MemfileLeaseStatsQuery(const SubnetID &subnet_id)
Constructor for single subnet query.
Lease6ExtendedInfoRemoteIdTable remote_id6_
stores IPv6 by-remote-id cross-reference table
virtual void rollback() override
Rollback Transactions.
size_t extractExtendedInfo4(bool update, bool current)
Extract extended info for v4 leases.
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery6(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id) override
Creates and runs the IPv6 lease stats query for a single subnet.
virtual void clearClassLeaseCounts() override
Clears the class-lease count map.
virtual size_t byRelayId6size() const override
Return the by-relay-id table size.
virtual Lease4Collection getLeases4ByRelayId(const OptionBuffer &relay_id, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size, const time_t &qry_start_time=0, const time_t &qry_end_time=0) override
The following queries are used to fulfill Bulk Lease Query queries.
Memfile_LeaseMgr(const db::DatabaseConnection::ParameterMap &parameters)
The sole lease manager constructor.
bool isLFCRunning() const
Checks if the process performing lease file cleanup is running.
virtual void writeLeases4(const std::string &filename) override
Write V4 leases to a file.
virtual void updateLease4(const Lease4Ptr &lease4) override
Updates IPv4 lease.
virtual size_t wipeLeases4(const SubnetID &subnet_id) override
Removes specified IPv4 leases.
virtual void deleteExtendedInfo6(const isc::asiolink::IOAddress &addr) override
Delete lease6 extended info from tables.
virtual bool isJsonSupported() const override
Checks if JSON support is enabled in the database.
Universe
Specifies universe (V4, V6)
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.
virtual Lease4Collection getLeases4() const override
Returns all IPv4 leases.
virtual size_t getClassLeaseCount(const ClientClass &client_class, const Lease::Type &ltype=Lease::TYPE_V4) const override
Returns the class lease count for a given class and lease type.
virtual void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv6 leases.
void buildExtendedInfoTables6()
Extended information / Bulk Lease Query shared interface.
virtual bool addLease(const Lease4Ptr &lease) override
Adds an IPv4 lease.
virtual size_t byRemoteId6size() const override
Return the by-remote-id table size.
virtual void writeLeases6(const std::string &filename) override
Write V6 leases to a file.
Lease6ExtendedInfoRelayIdTable relay_id6_
stores IPv6 by-relay-id cross-reference table
virtual void recountClassLeases6() override
Recount the leases per class for V6 leases.
virtual Lease4Collection getLeases4ByRemoteId(const OptionBuffer &remote_id, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size, const time_t &qry_start_time=0, const time_t &qry_end_time=0) override
Returns existing IPv4 leases with a given remote-id.
virtual void wipeExtendedInfoTables6() override
Wipe extended info table (v6).
boost::shared_ptr< CSVLeaseFile4 > lease_file4_
Holds the pointer to the DHCPv4 lease file IO.
std::string getLeaseFilePath(Universe u) const
Returns an absolute path to the lease file.
virtual Lease6Collection getLeases6ByRemoteId(const OptionBuffer &remote_id, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size) override
Returns existing IPv6 leases with a given remote-id.
virtual Lease6Collection getLeases6() const override
Returns all IPv6 leases.
virtual void lfcCallback()
A callback function triggering Lease File Cleanup (LFC).
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery4(const SubnetID &subnet_id) override
Creates and runs the IPv4 lease stats query for a single subnet.
virtual Lease6Collection getLeases6ByRelayId(const DUID &relay_id, const asiolink::IOAddress &lower_bound_address, const LeasePageSize &page_size) override
Returns existing IPv6 leases with a given relay-id.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery6(const SubnetID &subnet_id) override
Creates and runs the IPv6 lease stats query for a single subnet.
virtual std::string getDescription() const override
Returns description of the backend.
static std::string appendSuffix(const std::string &file_name, const LFCFileType &file_type)
Appends appropriate suffix to the file name.
virtual void addRelayId6(const isc::asiolink::IOAddress &lease_addr, const std::vector< uint8_t > &relay_id) override
Add lease6 extended info into by-relay-id table.
virtual size_t upgradeExtendedInfo6(const LeasePageSize &page_size) override
Upgrade extended info (v6).
virtual LeaseStatsQueryPtr startLeaseStatsQuery4() override
Creates and runs the IPv4 lease stats query.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const override
Returns existing IPv6 lease for a given IPv6 address.
virtual void recountClassLeases4() override
Recount the leases per class for V4 leases.
virtual void updateLease6(const Lease6Ptr &lease6) override
Updates IPv6 lease.
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery4(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id) override
Creates and runs the IPv4 lease stats query for a single subnet.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv4 leases.
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.
std::string getDefaultLeaseFilePath(Universe u) const
Returns default path to the lease file.
virtual size_t upgradeExtendedInfo4(const LeasePageSize &page_size) override
Upgrade extended info (v4).
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv6 leases.
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv4 leases.
Attempt to update lease that was not there.
Manages a pool of asynchronous interval timers.
Definition: timer_mgr.h:62
Introduces callbacks into the LeaseMgr.
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 error occurs during CSV file processing.
Definition: csv_file.h:22
Provides input/output access to CSV files.
Definition: csv_file.h:358
RAII class creating a critical section.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
Class to help with processing PID files.
Definition: pid_file.h:40
#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 MAJOR_VERSION_V4
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
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
Definition: data.cc:1420
void prettyPrint(ConstElementPtr element, std::ostream &out, unsigned indent, unsigned step)
Pretty prints the data into stream.
Definition: data.cc:1547
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:29
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_START
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID_CLIENTID
const isc::log::MessageID DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4
std::string ClientClass
Defines a single class name.
Definition: classify.h:42
boost::multi_index_container< Lease4Ptr, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< AddressIndexTag >, boost::multi_index::member< Lease, isc::asiolink::IOAddress, &Lease::addr_ > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< HWAddressSubnetIdIndexTag >, boost::multi_index::composite_key< Lease4, boost::multi_index::const_mem_fun< Lease, const std::vector< uint8_t > &, &Lease::getHWAddrVector >, boost::multi_index::member< Lease, SubnetID, &Lease::subnet_id_ > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< ClientIdSubnetIdIndexTag >, boost::multi_index::composite_key< Lease4, boost::multi_index::const_mem_fun< Lease4, const std::vector< uint8_t > &, &Lease4::getClientIdVector >, boost::multi_index::member< Lease, uint32_t, &Lease::subnet_id_ > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< ExpirationIndexTag >, boost::multi_index::composite_key< Lease4, boost::multi_index::const_mem_fun< Lease, bool, &Lease::stateExpiredReclaimed >, boost::multi_index::const_mem_fun< Lease, int64_t, &Lease::getExpirationTime > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetIdIndexTag >, boost::multi_index::member< Lease, isc::dhcp::SubnetID, &Lease::subnet_id_ > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< HostnameIndexTag >, boost::multi_index::member< Lease, std::string, &Lease::hostname_ > >, boost::multi_index::hashed_non_unique< boost::multi_index::tag< RemoteIdIndexTag >, boost::multi_index::member< Lease4, std::vector< uint8_t >, &Lease4::remote_id_ > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< RelayIdIndexTag >, boost::multi_index::composite_key< Lease4, boost::multi_index::member< Lease4, std::vector< uint8_t >, &Lease4::relay_id_ >, boost::multi_index::member< Lease, isc::asiolink::IOAddress, &Lease::addr_ > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetIdPoolIdIndexTag >, boost::multi_index::composite_key< Lease4, boost::multi_index::member< Lease, SubnetID, &Lease::subnet_id_ >, boost::multi_index::member< Lease, uint32_t, &Lease::pool_id_ > > > > > Lease4Storage
A multi index container holding DHCPv4 leases.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID_HWADDR
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES6
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
Lease6Storage::index< ExpirationIndexTag >::type Lease6StorageExpirationIndex
DHCPv6 lease storage index by expiration time.
const isc::log::MessageID DHCPSRV_MEMFILE_CONVERTING_LEASE_FILES
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_SETUP
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES6_FINISHED
Lease6Storage::index< DuidIndexTag >::type Lease6StorageDuidIndex
DHCPv6 lease storage index by DUID.
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:505
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:670
boost::shared_ptr< LeaseStatsQuery > LeaseStatsQueryPtr
Defines a pointer to a LeaseStatsQuery.
Definition: lease_mgr.h:233
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES4
Lease6Storage::index< SubnetIdPoolIdIndexTag >::type Lease6StorageSubnetIdPoolIdIndex
DHCPv6 lease storage index subnet-id and pool-id.
Lease6Storage::index< DuidIaidTypeIndexTag >::type Lease6StorageDuidIaidTypeIndex
DHCPv6 lease storage index by DUID, IAID, lease type.
boost::shared_ptr< TimerMgr > TimerMgrPtr
Type definition of the shared pointer to TimerMgr.
Definition: timer_mgr.h:27
const isc::log::MessageID DHCPSRV_MEMFILE_GET_RELAYID4
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_RENAME_FAIL
const isc::log::MessageID DHCPSRV_MEMFILE_UPDATE_ADDR4
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_ADDR
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID6
Lease4Storage::index< ExpirationIndexTag >::type Lease4StorageExpirationIndex
DHCPv4 lease storage index by expiration time.
Lease6Storage::index< AddressIndexTag >::type Lease6StorageAddressIndex
DHCPv6 lease storage index by address.
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition: dhcpsrv_log.h:38
const isc::log::MessageID DHCPSRV_MEMFILE_GET_ADDR4
const isc::log::MessageID DHCPSRV_MEMFILE_ROLLBACK
const isc::log::MessageID DHCPSRV_MEMFILE_UPDATE_ADDR6
Lease4Storage::index< HostnameIndexTag >::type Lease4StorageHostnameIndex
DHCPv4 lease storage index by hostname.
std::pair< Lease4StorageRemoteIdIndex::const_iterator, Lease4StorageRemoteIdIndex::const_iterator > Lease4StorageRemoteIdRange
DHCPv4 lease storage range by remote-id.
Lease6Storage::index< HostnameIndexTag >::type Lease6StorageHostnameIndex
DHCPv6 lease storage index by hostname.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED6
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HOSTNAME4
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_ > > > > > Lease6Storage
A multi index container holding DHCPv6 leases.
Lease4Storage::index< ClientIdSubnetIdIndexTag >::type Lease4StorageClientIdSubnetIdIndex
DHCPv4 lease storage index by client-id and subnet-id.
Lease4Storage::index< HWAddressSubnetIdIndexTag >::type Lease4StorageHWAddressSubnetIdIndex
DHCPv4 lease storage index by HW address and subnet-id.
const isc::log::MessageID DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4_ERROR
const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR6
Lease6ExtendedInfoRelayIdTable::index< LeaseAddressIndexTag >::type LeaseAddressRelayIdIndex
Lease6 extended information by lease address index of by relay id table.
Lease6ExtendedInfoRelayIdTable::index< RelayIdIndexTag >::type RelayIdIndex
Lease6 extended information by relay id index.
Lease4Storage::index< RemoteIdIndexTag >::type Lease4StorageRemoteIdIndex
DHCPv4 lease storage index by remote-id.
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:25
const isc::log::MessageID DHCPSRV_MEMFILE_BEGIN_EXTRACT_EXTENDED_INFO4
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES4_FINISHED
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID4
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_REOPEN_FAIL
const isc::log::MessageID DHCPSRV_MEMFILE_COMMIT
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED4
boost::shared_ptr< CfgConsistency > CfgConsistencyPtr
Type used to for pointing to CfgConsistency structure.
const isc::log::MessageID DHCPSRV_MEMFILE_BEGIN_BUILD_EXTENDED_INFO_TABLES6
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HOSTNAME6
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED6
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_EXECUTE
std::pair< RemoteIdIndex::const_iterator, RemoteIdIndex::const_iterator > RemoteIdIndexRange
Lease6 extended information by remote id range.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_RELAYID6
const isc::log::MessageID DHCPSRV_MEMFILE_NO_STORAGE
const isc::log::MessageID DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6
const isc::log::MessageID DHCPSRV_MEMFILE_GET_PAGE4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HWADDR
const isc::log::MessageID DHCPSRV_MEMFILE_GET6_DUID
Lease4Storage::index< SubnetIdIndexTag >::type Lease4StorageSubnetIdIndex
DHCPv4 lease storage index subnet-id.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition: lease.h:497
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:292
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
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.
Lease6ExtendedInfoRemoteIdTable::index< RemoteIdIndexTag >::type RemoteIdIndex
Lease6 extended information by remote id index.
Lease4Storage::index< SubnetIdPoolIdIndexTag >::type Lease4StorageSubnetIdPoolIdIndex
DHCPv4 lease storage index subnet-id and pool-id.
Lease4Storage::index< RelayIdIndexTag >::type Lease4StorageRelayIdIndex
DHCPv4 lease storage index by relay-id.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_PAGE6
Defines the logger used by the top-level component of kea-lfc.
Tag for indexes by address.
Tag for indexes by client-id, subnet-id tuple.
Tag for indexes by DUID, IAID, lease type tuple.
Tag for index using DUID.
Tag for indexes by expiration time.
Hardware type that represents information from DHCPv4 packet.
Definition: hwaddr.h:20
std::vector< uint8_t > hwaddr_
Definition: hwaddr.h:98
std::string toText(bool include_htype=true) const
Returns textual representation of a hardware address (e.g.
Definition: hwaddr.cc:51
Tag for indexes by HW address, subnet-id tuple.
Tag for index using hostname.
Structure that holds a lease for IPv4 address.
Definition: lease.h:300
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:513
ExtendedInfoAction
Action on extended info tables.
Definition: lease.h:550
@ ACTION_UPDATE
update extended info tables.
Definition: lease.h:553
@ ACTION_DELETE
delete reference to the lease
Definition: lease.h:552
@ ACTION_IGNORE
ignore extended info,
Definition: lease.h:551
Tag for indexes by lease address.
Contains a single row of lease statistical data.
Definition: lease_mgr.h:64
static const uint32_t STATE_DEFAULT
A lease in the default state.
Definition: lease.h:69
static const uint32_t STATE_DECLINED
Declined lease.
Definition: lease.h:72
Type
Type of lease or pool.
Definition: lease.h:46
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
Definition: lease.h:49
@ TYPE_V4
IPv4 lease.
Definition: lease.h:50
@ TYPE_NA
the lease contains non-temporary IPv6 address
Definition: lease.h:47
static std::string typeToText(Type type)
returns text representation of a lease type
Definition: lease.cc:54
Tag for index using relay-id.
Tag for index using remote-id.
Tag for indexes by subnet-id (and address for v6).