Kea 3.0.0
memfile_lease_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2025 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
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 ProcessEnvVars(), true));
214
215 // If we've been told to run it once now, invoke the callback directly.
216 if (run_once_now) {
217 callback_();
218 }
219
220 // If it's supposed to run periodically, setup that now.
221 if (lfc_interval > 0) {
222 // Set the timer to call callback function periodically.
224
225 // Multiple the lfc_interval value by 1000 as this value specifies
226 // a timeout in seconds, whereas the setup() method expects the
227 // timeout in milliseconds.
228 timer_mgr_->registerTimer("memfile-lfc", callback_, lfc_interval * 1000,
230 timer_mgr_->setup("memfile-lfc");
231 }
232}
233
234void
236 try {
238 .arg(process_->getCommandLine());
239 pid_ = process_->spawn();
240
241 } catch (const ProcessSpawnError&) {
243 }
244}
245
246bool
248 return (process_ && process_->isRunning(pid_));
249}
250
251int
253 if (!process_) {
254 isc_throw(InvalidOperation, "unable to obtain LFC process exit code: "
255 " the process is null");
256 }
257 return (process_->getExitStatus(pid_));
258}
259
260
267public:
273 : LeaseStatsQuery(select_mode), rows_(0), next_pos_(rows_.end()) {
274 };
275
280 : LeaseStatsQuery(subnet_id), rows_(0), next_pos_(rows_.end()) {
281 };
282
287 MemfileLeaseStatsQuery(const SubnetID& first_subnet_id, const SubnetID& last_subnet_id)
288 : LeaseStatsQuery(first_subnet_id, last_subnet_id), rows_(0), next_pos_(rows_.end()) {
289 };
290
293
304 virtual bool getNextRow(LeaseStatsRow& row) {
305 if (next_pos_ == rows_.end()) {
306 return (false);
307 }
308
309 row = *next_pos_;
310 ++next_pos_;
311 return (true);
312 }
313
315 int getRowCount() const {
316 return (rows_.size());
317 }
318
319protected:
321 std::vector<LeaseStatsRow> rows_;
322
324 std::vector<LeaseStatsRow>::iterator next_pos_;
325};
326
337public:
344 const SelectMode& select_mode = ALL_SUBNETS)
345 : MemfileLeaseStatsQuery(select_mode), storage4_(storage4) {
346 };
347
352 MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& subnet_id)
353 : MemfileLeaseStatsQuery(subnet_id), storage4_(storage4) {
354 };
355
361 MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& first_subnet_id,
362 const SubnetID& last_subnet_id)
363 : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage4_(storage4) {
364 };
365
368
383 void start() {
384 switch (getSelectMode()) {
385 case ALL_SUBNETS:
386 case SINGLE_SUBNET:
387 case SUBNET_RANGE:
388 startSubnets();
389 break;
390
391 case ALL_SUBNET_POOLS:
392 startSubnetPools();
393 break;
394 }
395 }
396
397private:
412 void startSubnets() {
414 = storage4_.get<SubnetIdIndexTag>();
415
416 // Set lower and upper bounds based on select mode
417 Lease4StorageSubnetIdIndex::const_iterator lower;
418 Lease4StorageSubnetIdIndex::const_iterator upper;
419
420 switch (getSelectMode()) {
421 case ALL_SUBNETS:
422 lower = idx.begin();
423 upper = idx.end();
424 break;
425
426 case SINGLE_SUBNET:
427 lower = idx.lower_bound(getFirstSubnetID());
428 upper = idx.upper_bound(getFirstSubnetID());
429 break;
430
431 case SUBNET_RANGE:
432 lower = idx.lower_bound(getFirstSubnetID());
433 upper = idx.upper_bound(getLastSubnetID());
434 break;
435
436 default:
437 return;
438 }
439
440 // Return an empty set if there are no rows.
441 if (lower == upper) {
442 return;
443 }
444
445 // Iterate over the leases in order by subnet, accumulating per
446 // subnet counts for each state of interest. As we finish each
447 // subnet, add the appropriate rows to our result set.
448 SubnetID cur_id = 0;
449 int64_t assigned = 0;
450 int64_t declined = 0;
451 for (Lease4StorageSubnetIdIndex::const_iterator lease = lower;
452 lease != upper; ++lease) {
453 // If we've hit the next subnet, add rows for the current subnet
454 // and wipe the accumulators
455 if ((*lease)->subnet_id_ != cur_id) {
456 if (cur_id > 0) {
457 if (assigned > 0) {
458 rows_.push_back(LeaseStatsRow(cur_id,
460 assigned));
461 assigned = 0;
462 }
463
464 if (declined > 0) {
465 rows_.push_back(LeaseStatsRow(cur_id,
467 declined));
468 declined = 0;
469 }
470 }
471
472 // Update current subnet id
473 cur_id = (*lease)->subnet_id_;
474 }
475
476 // Bump the appropriate accumulator
477 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
478 ++assigned;
479 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
480 ++declined;
481 }
482 }
483
484 // Make the rows for last subnet
485 if (assigned > 0) {
486 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
487 assigned));
488 }
489
490 if (declined > 0) {
491 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
492 declined));
493 }
494
495 // Reset the next row position back to the beginning of the rows.
496 next_pos_ = rows_.begin();
497 }
498
513 void startSubnetPools() {
515 = storage4_.get<SubnetIdPoolIdIndexTag>();
516
517 // Set lower and upper bounds based on select mode
518 Lease4StorageSubnetIdPoolIdIndex::const_iterator lower;
519 Lease4StorageSubnetIdPoolIdIndex::const_iterator upper;
520 switch (getSelectMode()) {
521 case ALL_SUBNET_POOLS:
522 lower = idx.begin();
523 upper = idx.end();
524 break;
525
526 default:
527 return;
528 }
529
530 // Return an empty set if there are no rows.
531 if (lower == upper) {
532 return;
533 }
534
535 // Iterate over the leases in order by subnet and pool, accumulating per
536 // subnet and pool counts for each state of interest. As we finish each
537 // subnet or pool, add the appropriate rows to our result set.
538 SubnetID cur_id = 0;
539 uint32_t cur_pool_id = 0;
540 int64_t assigned = 0;
541 int64_t declined = 0;
542 for (Lease4StorageSubnetIdPoolIdIndex::const_iterator lease = lower;
543 lease != upper; ++lease) {
544 // If we've hit the next pool, add rows for the current subnet and
545 // pool and wipe the accumulators
546 if ((*lease)->pool_id_ != cur_pool_id) {
547 if (assigned > 0) {
548 rows_.push_back(LeaseStatsRow(cur_id,
550 assigned, cur_pool_id));
551 assigned = 0;
552 }
553
554 if (declined > 0) {
555 rows_.push_back(LeaseStatsRow(cur_id,
557 declined, cur_pool_id));
558 declined = 0;
559 }
560
561 // Update current pool id
562 cur_pool_id = (*lease)->pool_id_;
563 }
564
565 // If we've hit the next subnet, add rows for the current subnet
566 // and wipe the accumulators
567 if ((*lease)->subnet_id_ != cur_id) {
568 if (cur_id > 0) {
569 if (assigned > 0) {
570 rows_.push_back(LeaseStatsRow(cur_id,
572 assigned, cur_pool_id));
573 assigned = 0;
574 }
575
576 if (declined > 0) {
577 rows_.push_back(LeaseStatsRow(cur_id,
579 declined, cur_pool_id));
580 declined = 0;
581 }
582 }
583
584 // Update current subnet id
585 cur_id = (*lease)->subnet_id_;
586
587 // Reset pool id
588 cur_pool_id = 0;
589 }
590
591 // Bump the appropriate accumulator
592 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
593 ++assigned;
594 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
595 ++declined;
596 }
597 }
598
599 // Make the rows for last subnet
600 if (assigned > 0) {
601 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
602 assigned, cur_pool_id));
603 }
604
605 if (declined > 0) {
606 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
607 declined, cur_pool_id));
608 }
609
610 // Reset the next row position back to the beginning of the rows.
611 next_pos_ = rows_.begin();
612 }
613
615 Lease4Storage& storage4_;
616};
617
618
629public:
636 const SelectMode& select_mode = ALL_SUBNETS)
637 : MemfileLeaseStatsQuery(select_mode), storage6_(storage6) {
638 };
639
644 MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& subnet_id)
645 : MemfileLeaseStatsQuery(subnet_id), storage6_(storage6) {
646 };
647
653 MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& first_subnet_id,
654 const SubnetID& last_subnet_id)
655 : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage6_(storage6) {
656 };
657
660
676 void start() {
677 switch (getSelectMode()) {
678 case ALL_SUBNETS:
679 case SINGLE_SUBNET:
680 case SUBNET_RANGE:
681 startSubnets();
682 break;
683
684 case ALL_SUBNET_POOLS:
685 startSubnetPools();
686 break;
687 }
688 }
689
690private:
706 virtual void startSubnets() {
708 = storage6_.get<SubnetIdIndexTag>();
709
710 // Set lower and upper bounds based on select mode
711 Lease6StorageSubnetIdIndex::const_iterator lower;
712 Lease6StorageSubnetIdIndex::const_iterator upper;
713 switch (getSelectMode()) {
714 case ALL_SUBNETS:
715 lower = idx.begin();
716 upper = idx.end();
717 break;
718
719 case SINGLE_SUBNET:
720 lower = idx.lower_bound(getFirstSubnetID());
721 upper = idx.upper_bound(getFirstSubnetID());
722 break;
723
724 case SUBNET_RANGE:
725 lower = idx.lower_bound(getFirstSubnetID());
726 upper = idx.upper_bound(getLastSubnetID());
727 break;
728
729 default:
730 return;
731 }
732
733 // Return an empty set if there are no rows.
734 if (lower == upper) {
735 return;
736 }
737
738 // Iterate over the leases in order by subnet, accumulating per
739 // subnet counts for each state of interest. As we finish each
740 // subnet, add the appropriate rows to our result set.
741 SubnetID cur_id = 0;
742 int64_t assigned = 0;
743 int64_t declined = 0;
744 int64_t assigned_pds = 0;
745 int64_t registered = 0;
746 for (Lease6StorageSubnetIdIndex::const_iterator lease = lower;
747 lease != upper; ++lease) {
748 // If we've hit the next subnet, add rows for the current subnet
749 // and wipe the accumulators
750 if ((*lease)->subnet_id_ != cur_id) {
751 if (cur_id > 0) {
752 if (assigned > 0) {
753 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
755 assigned));
756 assigned = 0;
757 }
758
759 if (declined > 0) {
760 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
762 declined));
763 declined = 0;
764 }
765
766 if (assigned_pds > 0) {
767 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
769 assigned_pds));
770 assigned_pds = 0;
771 }
772
773 if (registered > 0) {
774 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
776 registered));
777 registered = 0;
778 }
779 }
780
781 // Update current subnet id
782 cur_id = (*lease)->subnet_id_;
783 }
784
785 // Bump the appropriate accumulator
786 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
787 switch((*lease)->type_) {
788 case Lease::TYPE_NA:
789 ++assigned;
790 break;
791 case Lease::TYPE_PD:
792 ++assigned_pds;
793 break;
794 default:
795 break;
796 }
797 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
798 // In theory only NAs can be declined
799 if (((*lease)->type_) == Lease::TYPE_NA) {
800 ++declined;
801 }
802 } else if ((*lease)->state_ == Lease::STATE_REGISTERED) {
803 // In theory only NAs can be registered
804 if (((*lease)->type_) == Lease::TYPE_NA) {
805 ++registered;
806 }
807 }
808 }
809
810 // Make the rows for last subnet, unless there were no rows
811 if (assigned > 0) {
812 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
813 Lease::STATE_DEFAULT, assigned));
814 }
815
816 if (declined > 0) {
817 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
818 Lease::STATE_DECLINED, declined));
819 }
820
821 if (assigned_pds > 0) {
822 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
823 Lease::STATE_DEFAULT, assigned_pds));
824 }
825
826 if (registered > 0) {
827 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
828 Lease::STATE_REGISTERED, registered));
829 }
830
831 // Set the next row position to the beginning of the rows.
832 next_pos_ = rows_.begin();
833 }
834
849 virtual void startSubnetPools() {
851 = storage6_.get<SubnetIdPoolIdIndexTag>();
852
853 // Set lower and upper bounds based on select mode
854 Lease6StorageSubnetIdPoolIdIndex::const_iterator lower;
855 Lease6StorageSubnetIdPoolIdIndex::const_iterator upper;
856 switch (getSelectMode()) {
857 case ALL_SUBNET_POOLS:
858 lower = idx.begin();
859 upper = idx.end();
860 break;
861
862 default:
863 return;
864 }
865
866 // Return an empty set if there are no rows.
867 if (lower == upper) {
868 return;
869 }
870
871 // Iterate over the leases in order by subnet, accumulating per
872 // subnet counts for each state of interest. As we finish each
873 // subnet, add the appropriate rows to our result set.
874 SubnetID cur_id = 0;
875 uint32_t cur_pool_id = 0;
876 int64_t assigned = 0;
877 int64_t declined = 0;
878 int64_t assigned_pds = 0;
879 for (Lease6StorageSubnetIdPoolIdIndex::const_iterator lease = lower;
880 lease != upper; ++lease) {
881 // If we've hit the next pool, add rows for the current subnet and
882 // pool and wipe the accumulators
883 if ((*lease)->pool_id_ != cur_pool_id) {
884 if (assigned > 0) {
885 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
887 assigned, cur_pool_id));
888 assigned = 0;
889 }
890
891 if (declined > 0) {
892 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
894 declined, cur_pool_id));
895 declined = 0;
896 }
897
898 if (assigned_pds > 0) {
899 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
901 assigned_pds, cur_pool_id));
902 assigned_pds = 0;
903 }
904
905 // Update current pool id
906 cur_pool_id = (*lease)->pool_id_;
907 }
908
909 // If we've hit the next subnet, add rows for the current subnet
910 // and wipe the accumulators
911 if ((*lease)->subnet_id_ != cur_id) {
912 if (cur_id > 0) {
913 if (assigned > 0) {
914 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
916 assigned, cur_pool_id));
917 assigned = 0;
918 }
919
920 if (declined > 0) {
921 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
923 declined, cur_pool_id));
924 declined = 0;
925 }
926
927 if (assigned_pds > 0) {
928 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
930 assigned_pds, cur_pool_id));
931 assigned_pds = 0;
932 }
933 }
934
935 // Update current subnet id
936 cur_id = (*lease)->subnet_id_;
937
938 // Reset pool id
939 cur_pool_id = 0;
940 }
941
942 // Bump the appropriate accumulator
943 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
944 switch((*lease)->type_) {
945 case Lease::TYPE_NA:
946 ++assigned;
947 break;
948 case Lease::TYPE_PD:
949 ++assigned_pds;
950 break;
951 default:
952 break;
953 }
954 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
955 // In theory only NAs can be declined
956 if (((*lease)->type_) == Lease::TYPE_NA) {
957 ++declined;
958 }
959 }
960 }
961
962 // Make the rows for last subnet, unless there were no rows
963 if (assigned > 0) {
964 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
965 Lease::STATE_DEFAULT, assigned,
966 cur_pool_id));
967 }
968
969 if (declined > 0) {
970 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
971 Lease::STATE_DECLINED, declined,
972 cur_pool_id));
973 }
974
975 if (assigned_pds > 0) {
976 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
977 Lease::STATE_DEFAULT, assigned_pds,
978 cur_pool_id));
979 }
980
981 // Set the next row position to the beginning of the rows.
982 next_pos_ = rows_.begin();
983 }
984
986 Lease6Storage& storage6_;
987};
988
989// Explicit definition of class static constants. Values are given in the
990// declaration so they're not needed here.
995
997 : TrackingLeaseMgr(), lfc_setup_(), conn_(parameters), mutex_(new std::mutex) {
998 bool conversion_needed = false;
999
1000 // Check if the extended info tables are enabled.
1001 setExtendedInfoTablesEnabled(parameters);
1002
1003 // Check the universe and use v4 file or v6 file.
1004 std::string universe = conn_.getParameter("universe");
1005 if (universe == "4") {
1006 std::string file4 = initLeaseFilePath(V4);
1007 if (!file4.empty()) {
1008 conversion_needed = loadLeasesFromFiles<Lease4,
1009 CSVLeaseFile4>(file4,
1011 storage4_);
1012 static_cast<void>(extractExtendedInfo4(false, false));
1013 }
1014 } else {
1015 std::string file6 = initLeaseFilePath(V6);
1016 if (!file6.empty()) {
1017 conversion_needed = loadLeasesFromFiles<Lease6,
1018 CSVLeaseFile6>(file6,
1020 storage6_);
1022 }
1023 }
1024
1025 // If lease persistence have been disabled for both v4 and v6,
1026 // issue a warning. It is ok not to write leases to disk when
1027 // doing testing, but it should not be done in normal server
1028 // operation.
1029 if (!persistLeases(V4) && !persistLeases(V6)) {
1031 } else {
1032 if (conversion_needed) {
1033 auto const& version(getVersion());
1035 .arg(version.first).arg(version.second);
1036 }
1037 lfcSetup(conversion_needed);
1038 }
1039}
1040
1042 if (lease_file4_) {
1043 lease_file4_->close();
1044 lease_file4_.reset();
1045 }
1046 if (lease_file6_) {
1047 lease_file6_->close();
1048 lease_file6_.reset();
1049 }
1050}
1051
1052std::string
1054 std::stringstream tmp;
1055 tmp << "Memfile backend ";
1056 if (u == V4) {
1057 tmp << MAJOR_VERSION_V4 << "." << MINOR_VERSION_V4;
1058 } else if (u == V6) {
1059 tmp << MAJOR_VERSION_V6 << "." << MINOR_VERSION_V6;
1060 }
1061 return tmp.str();
1062}
1063
1064std::string
1066 uint16_t family = CfgMgr::instance().getFamily();
1067 if (family == AF_INET6) {
1069 } else {
1071 }
1072}
1073
1074bool
1075Memfile_LeaseMgr::addLeaseInternal(const Lease4Ptr& lease) {
1076 if (getLease4Internal(lease->addr_)) {
1077 // there is a lease with specified address already
1078 return (false);
1079 }
1080
1081 // Try to write a lease to disk first. If this fails, the lease will
1082 // not be inserted to the memory and the disk and in-memory data will
1083 // remain consistent.
1084 if (persistLeases(V4)) {
1085 lease_file4_->append(*lease);
1086 }
1087
1088 storage4_.insert(lease);
1089
1090 // Update lease current expiration time (allows update between the creation
1091 // of the Lease up to the point of insertion in the database).
1092 lease->updateCurrentExpirationTime();
1093
1094 // Increment class lease counters.
1095 class_lease_counter_.addLease(lease);
1096
1097 // Run installed callbacks.
1098 if (hasCallbacks()) {
1099 trackAddLease(lease);
1100 }
1101
1102 return (true);
1103}
1104
1105bool
1108 DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
1109
1110 if (MultiThreadingMgr::instance().getMode()) {
1111 std::lock_guard<std::mutex> lock(*mutex_);
1112 return (addLeaseInternal(lease));
1113 } else {
1114 return (addLeaseInternal(lease));
1115 }
1116}
1117
1118bool
1119Memfile_LeaseMgr::addLeaseInternal(const Lease6Ptr& lease) {
1120 if (getLease6Internal(lease->type_, lease->addr_)) {
1121 // there is a lease with specified address already
1122 return (false);
1123 }
1124
1125 // Try to write a lease to disk first. If this fails, the lease will
1126 // not be inserted to the memory and the disk and in-memory data will
1127 // remain consistent.
1128 if (persistLeases(V6)) {
1129 lease_file6_->append(*lease);
1130 }
1131
1132 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
1133 storage6_.insert(lease);
1134
1135 // Update lease current expiration time (allows update between the creation
1136 // of the Lease up to the point of insertion in the database).
1137 lease->updateCurrentExpirationTime();
1138
1139 // Increment class lease counters.
1140 class_lease_counter_.addLease(lease);
1141
1143 static_cast<void>(addExtendedInfo6(lease));
1144 }
1145
1146 // Run installed callbacks.
1147 if (hasCallbacks()) {
1148 trackAddLease(lease);
1149 }
1150
1151 return (true);
1152}
1153
1154bool
1157 DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
1158
1159 if (MultiThreadingMgr::instance().getMode()) {
1160 std::lock_guard<std::mutex> lock(*mutex_);
1161 return (addLeaseInternal(lease));
1162 } else {
1163 return (addLeaseInternal(lease));
1164 }
1165}
1166
1168Memfile_LeaseMgr::getLease4Internal(const isc::asiolink::IOAddress& addr) const {
1169 const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1170 Lease4StorageAddressIndex::iterator l = idx.find(addr);
1171 if (l == idx.end()) {
1172 return (Lease4Ptr());
1173 } else {
1174 return (Lease4Ptr(new Lease4(**l)));
1175 }
1176}
1177
1181 DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
1182
1183 if (MultiThreadingMgr::instance().getMode()) {
1184 std::lock_guard<std::mutex> lock(*mutex_);
1185 return (getLease4Internal(addr));
1186 } else {
1187 return (getLease4Internal(addr));
1188 }
1189}
1190
1191void
1192Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
1193 Lease4Collection& collection) const {
1194 // Using composite index by 'hw address' and 'subnet id'. It is
1195 // ok to use it for searching by the 'hw address' only.
1197 storage4_.get<HWAddressSubnetIdIndexTag>();
1198 std::pair<Lease4StorageHWAddressSubnetIdIndex::const_iterator,
1199 Lease4StorageHWAddressSubnetIdIndex::const_iterator> l
1200 = idx.equal_range(boost::make_tuple(hwaddr.hwaddr_));
1201
1202 BOOST_FOREACH(auto const& lease, l) {
1203 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1204 }
1205}
1206
1210 DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.toText());
1211
1212 Lease4Collection collection;
1213 if (MultiThreadingMgr::instance().getMode()) {
1214 std::lock_guard<std::mutex> lock(*mutex_);
1215 getLease4Internal(hwaddr, collection);
1216 } else {
1217 getLease4Internal(hwaddr, collection);
1218 }
1219
1220 return (collection);
1221}
1222
1224Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
1225 SubnetID subnet_id) const {
1226 // Get the index by HW Address and Subnet Identifier.
1228 storage4_.get<HWAddressSubnetIdIndexTag>();
1229 // Try to find the lease using HWAddr and subnet id.
1230 Lease4StorageHWAddressSubnetIdIndex::const_iterator lease =
1231 idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
1232 // Lease was not found. Return empty pointer to the caller.
1233 if (lease == idx.end()) {
1234 return (Lease4Ptr());
1235 }
1236
1237 // Lease was found. Return it to the caller.
1238 return (Lease4Ptr(new Lease4(**lease)));
1239}
1240
1243 SubnetID subnet_id) const {
1245 DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
1246 .arg(hwaddr.toText());
1247
1248 if (MultiThreadingMgr::instance().getMode()) {
1249 std::lock_guard<std::mutex> lock(*mutex_);
1250 return (getLease4Internal(hwaddr, subnet_id));
1251 } else {
1252 return (getLease4Internal(hwaddr, subnet_id));
1253 }
1254}
1255
1256void
1257Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
1258 Lease4Collection& collection) const {
1259 // Using composite index by 'client id' and 'subnet id'. It is ok
1260 // to use it to search by 'client id' only.
1262 storage4_.get<ClientIdSubnetIdIndexTag>();
1263 std::pair<Lease4StorageClientIdSubnetIdIndex::const_iterator,
1264 Lease4StorageClientIdSubnetIdIndex::const_iterator> l
1265 = idx.equal_range(boost::make_tuple(client_id.getClientId()));
1266
1267 BOOST_FOREACH(auto const& lease, l) {
1268 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1269 }
1270}
1271
1273Memfile_LeaseMgr::getLease4(const ClientId& client_id) const {
1275 DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.toText());
1276
1277 Lease4Collection collection;
1278 if (MultiThreadingMgr::instance().getMode()) {
1279 std::lock_guard<std::mutex> lock(*mutex_);
1280 getLease4Internal(client_id, collection);
1281 } else {
1282 getLease4Internal(client_id, collection);
1283 }
1284
1285 return (collection);
1286}
1287
1289Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
1290 SubnetID subnet_id) const {
1291 // Get the index by client and subnet id.
1293 storage4_.get<ClientIdSubnetIdIndexTag>();
1294 // Try to get the lease using client id and subnet id.
1295 Lease4StorageClientIdSubnetIdIndex::const_iterator lease =
1296 idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
1297 // Lease was not found. Return empty pointer to the caller.
1298 if (lease == idx.end()) {
1299 return (Lease4Ptr());
1300 }
1301 // Lease was found. Return it to the caller.
1302 return (Lease4Ptr(new Lease4(**lease)));
1303}
1304
1307 SubnetID subnet_id) const {
1310 .arg(client_id.toText());
1311
1312 if (MultiThreadingMgr::instance().getMode()) {
1313 std::lock_guard<std::mutex> lock(*mutex_);
1314 return (getLease4Internal(client_id, subnet_id));
1315 } else {
1316 return (getLease4Internal(client_id, subnet_id));
1317 }
1318}
1319
1320void
1321Memfile_LeaseMgr::getLeases4Internal(SubnetID subnet_id,
1322 Lease4Collection& collection) const {
1323 const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
1324 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
1325 Lease4StorageSubnetIdIndex::const_iterator> l =
1326 idx.equal_range(subnet_id);
1327
1328 BOOST_FOREACH(auto const& lease, l) {
1329 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1330 }
1331}
1332
1336 .arg(subnet_id);
1337
1338 Lease4Collection collection;
1339 if (MultiThreadingMgr::instance().getMode()) {
1340 std::lock_guard<std::mutex> lock(*mutex_);
1341 getLeases4Internal(subnet_id, collection);
1342 } else {
1343 getLeases4Internal(subnet_id, collection);
1344 }
1345
1346 return (collection);
1347}
1348
1349void
1350Memfile_LeaseMgr::getLeases4Internal(const std::string& hostname,
1351 Lease4Collection& collection) const {
1352 const Lease4StorageHostnameIndex& idx = storage4_.get<HostnameIndexTag>();
1353 std::pair<Lease4StorageHostnameIndex::const_iterator,
1354 Lease4StorageHostnameIndex::const_iterator> l =
1355 idx.equal_range(hostname);
1356
1357 BOOST_FOREACH(auto const& lease, l) {
1358 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1359 }
1360}
1361
1363Memfile_LeaseMgr::getLeases4(const std::string& hostname) const {
1365 .arg(hostname);
1366
1367 Lease4Collection collection;
1368 if (MultiThreadingMgr::instance().getMode()) {
1369 std::lock_guard<std::mutex> lock(*mutex_);
1370 getLeases4Internal(hostname, collection);
1371 } else {
1372 getLeases4Internal(hostname, collection);
1373 }
1374
1375 return (collection);
1376}
1377
1378void
1379Memfile_LeaseMgr::getLeases4Internal(Lease4Collection& collection) const {
1380 for (auto const& lease : storage4_) {
1381 collection.push_back(Lease4Ptr(new Lease4(*lease)));
1382 }
1383}
1384
1388
1389 Lease4Collection collection;
1390 if (MultiThreadingMgr::instance().getMode()) {
1391 std::lock_guard<std::mutex> lock(*mutex_);
1392 getLeases4Internal(collection);
1393 } else {
1394 getLeases4Internal(collection);
1395 }
1396
1397 return (collection);
1398}
1399
1400void
1401Memfile_LeaseMgr::getLeases4Internal(const asiolink::IOAddress& lower_bound_address,
1402 const LeasePageSize& page_size,
1403 Lease4Collection& collection) const {
1404 const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1405 Lease4StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1406
1407 // Exclude the lower bound address specified by the caller.
1408 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1409 ++lb;
1410 }
1411
1412 // Return all other leases being within the page size.
1413 for (auto lease = lb;
1414 (lease != idx.end()) &&
1415 (static_cast<size_t>(std::distance(lb, lease)) < page_size.page_size_);
1416 ++lease) {
1417 collection.push_back(Lease4Ptr(new Lease4(**lease)));
1418 }
1419}
1420
1423 const LeasePageSize& page_size) const {
1424 // Expecting IPv4 address.
1425 if (!lower_bound_address.isV4()) {
1426 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
1427 "retrieving leases from the lease database, got "
1428 << lower_bound_address);
1429 }
1430
1432 .arg(page_size.page_size_)
1433 .arg(lower_bound_address.toText());
1434
1435 Lease4Collection collection;
1436 if (MultiThreadingMgr::instance().getMode()) {
1437 std::lock_guard<std::mutex> lock(*mutex_);
1438 getLeases4Internal(lower_bound_address, page_size, collection);
1439 } else {
1440 getLeases4Internal(lower_bound_address, page_size, collection);
1441 }
1442
1443 return (collection);
1444}
1445
1447Memfile_LeaseMgr::getLease6Internal(Lease::Type type,
1448 const isc::asiolink::IOAddress& addr) const {
1449 Lease6Storage::iterator l = storage6_.find(addr);
1450 if (l == storage6_.end() || !(*l) || ((*l)->type_ != type)) {
1451 return (Lease6Ptr());
1452 } else {
1453 return (Lease6Ptr(new Lease6(**l)));
1454 }
1455}
1456
1458Memfile_LeaseMgr::getAnyLease6Internal(const isc::asiolink::IOAddress& addr) const {
1459 Lease6Storage::iterator l = storage6_.find(addr);
1460 if (l == storage6_.end() || !(*l)) {
1461 return (Lease6Ptr());
1462 } else {
1463 return (Lease6Ptr(new Lease6(**l)));
1464 }
1465}
1466
1469 const isc::asiolink::IOAddress& addr) const {
1472 .arg(addr.toText())
1473 .arg(Lease::typeToText(type));
1474
1475 if (MultiThreadingMgr::instance().getMode()) {
1476 std::lock_guard<std::mutex> lock(*mutex_);
1477 return (getLease6Internal(type, addr));
1478 } else {
1479 return (getLease6Internal(type, addr));
1480 }
1481}
1482
1483void
1484Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1485 const DUID& duid,
1486 uint32_t iaid,
1487 Lease6Collection& collection) const {
1488 // Get the index by DUID, IAID, lease type.
1489 const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1490 // Try to get the lease using the DUID, IAID and lease type.
1491 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1492 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1493 idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1494
1495 for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1496 l.first; lease != l.second; ++lease) {
1497 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1498 }
1499}
1500
1503 const DUID& duid,
1504 uint32_t iaid) const {
1507 .arg(iaid)
1508 .arg(duid.toText())
1509 .arg(Lease::typeToText(type));
1510
1511 Lease6Collection collection;
1512 if (MultiThreadingMgr::instance().getMode()) {
1513 std::lock_guard<std::mutex> lock(*mutex_);
1514 getLeases6Internal(type, duid, iaid, collection);
1515 } else {
1516 getLeases6Internal(type, duid, iaid, collection);
1517 }
1518
1519 return (collection);
1520}
1521
1522void
1523Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1524 const DUID& duid,
1525 uint32_t iaid,
1526 SubnetID subnet_id,
1527 Lease6Collection& collection) const {
1528 // Get the index by DUID, IAID, lease type.
1529 const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1530 // Try to get the lease using the DUID, IAID and lease type.
1531 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1532 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1533 idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1534
1535 for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1536 l.first; lease != l.second; ++lease) {
1537 // Filter out the leases which subnet id doesn't match.
1538 if ((*lease)->subnet_id_ == subnet_id) {
1539 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1540 }
1541 }
1542}
1543
1546 const DUID& duid,
1547 uint32_t iaid,
1548 SubnetID subnet_id) const {
1551 .arg(iaid)
1552 .arg(subnet_id)
1553 .arg(duid.toText())
1554 .arg(Lease::typeToText(type));
1555
1556 Lease6Collection collection;
1557 if (MultiThreadingMgr::instance().getMode()) {
1558 std::lock_guard<std::mutex> lock(*mutex_);
1559 getLeases6Internal(type, duid, iaid, subnet_id, collection);
1560 } else {
1561 getLeases6Internal(type, duid, iaid, subnet_id, collection);
1562 }
1563
1564 return (collection);
1565}
1566
1567void
1568Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1569 Lease6Collection& collection) const {
1570 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1571 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
1572 Lease6StorageSubnetIdIndex::const_iterator> l =
1573 idx.equal_range(subnet_id);
1574
1575 BOOST_FOREACH(auto const& lease, l) {
1576 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1577 }
1578}
1579
1583 .arg(subnet_id);
1584
1585 Lease6Collection collection;
1586 if (MultiThreadingMgr::instance().getMode()) {
1587 std::lock_guard<std::mutex> lock(*mutex_);
1588 getLeases6Internal(subnet_id, collection);
1589 } else {
1590 getLeases6Internal(subnet_id, collection);
1591 }
1592
1593 return (collection);
1594}
1595
1596void
1597Memfile_LeaseMgr::getLeases6Internal(const std::string& hostname,
1598 Lease6Collection& collection) const {
1599 const Lease6StorageHostnameIndex& idx = storage6_.get<HostnameIndexTag>();
1600 std::pair<Lease6StorageHostnameIndex::const_iterator,
1601 Lease6StorageHostnameIndex::const_iterator> l =
1602 idx.equal_range(hostname);
1603
1604 BOOST_FOREACH(auto const& lease, l) {
1605 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1606 }
1607}
1608
1610Memfile_LeaseMgr::getLeases6(const std::string& hostname) const {
1612 .arg(hostname);
1613
1614 Lease6Collection collection;
1615 if (MultiThreadingMgr::instance().getMode()) {
1616 std::lock_guard<std::mutex> lock(*mutex_);
1617 getLeases6Internal(hostname, collection);
1618 } else {
1619 getLeases6Internal(hostname, collection);
1620 }
1621
1622 return (collection);
1623}
1624
1625void
1626Memfile_LeaseMgr::getLeases6Internal(Lease6Collection& collection) const {
1627 for (auto const& lease : storage6_) {
1628 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1629 }
1630}
1631
1635
1636 Lease6Collection collection;
1637 if (MultiThreadingMgr::instance().getMode()) {
1638 std::lock_guard<std::mutex> lock(*mutex_);
1639 getLeases6Internal(collection);
1640 } else {
1641 getLeases6Internal(collection);
1642 }
1643
1644 return (collection);
1645}
1646
1647void
1648Memfile_LeaseMgr::getLeases6Internal(const DUID& duid,
1649 Lease6Collection& collection) const {
1650 const Lease6StorageDuidIndex& idx = storage6_.get<DuidIndexTag>();
1651 std::pair<Lease6StorageDuidIndex::const_iterator,
1652 Lease6StorageDuidIndex::const_iterator> l =
1653 idx.equal_range(duid.getDuid());
1654
1655 BOOST_FOREACH(auto const& lease, l) {
1656 collection.push_back(Lease6Ptr(new Lease6(*lease)));
1657 }
1658}
1659
1663 .arg(duid.toText());
1664
1665 Lease6Collection collection;
1666 if (MultiThreadingMgr::instance().getMode()) {
1667 std::lock_guard<std::mutex> lock(*mutex_);
1668 getLeases6Internal(duid, collection);
1669 } else {
1670 getLeases6Internal(duid, collection);
1671 }
1672
1673 return (collection);
1674}
1675
1676void
1677Memfile_LeaseMgr::getLeases6Internal(const asiolink::IOAddress& lower_bound_address,
1678 const LeasePageSize& page_size,
1679 Lease6Collection& collection) const {
1680 const Lease6StorageAddressIndex& idx = storage6_.get<AddressIndexTag>();
1681 Lease6StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1682
1683 // Exclude the lower bound address specified by the caller.
1684 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1685 ++lb;
1686 }
1687
1688 // Return all other leases being within the page size.
1689 for (auto lease = lb;
1690 (lease != idx.end()) &&
1691 (static_cast<size_t>(std::distance(lb, lease)) < page_size.page_size_);
1692 ++lease) {
1693 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1694 }
1695}
1696
1699 const LeasePageSize& page_size) const {
1700 // Expecting IPv6 address.
1701 if (!lower_bound_address.isV6()) {
1702 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1703 "retrieving leases from the lease database, got "
1704 << lower_bound_address);
1705 }
1706
1708 .arg(page_size.page_size_)
1709 .arg(lower_bound_address.toText());
1710
1711 Lease6Collection collection;
1712 if (MultiThreadingMgr::instance().getMode()) {
1713 std::lock_guard<std::mutex> lock(*mutex_);
1714 getLeases6Internal(lower_bound_address, page_size, collection);
1715 } else {
1716 getLeases6Internal(lower_bound_address, page_size, collection);
1717 }
1718
1719 return (collection);
1720}
1721
1723Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1724 const IOAddress& lower_bound_address,
1725 const LeasePageSize& page_size) const {
1726 Lease6Collection collection;
1727 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1728 Lease6StorageSubnetIdIndex::const_iterator lb =
1729 idx.lower_bound(boost::make_tuple(subnet_id, lower_bound_address));
1730
1731 // Exclude the lower bound address specified by the caller.
1732 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1733 ++lb;
1734 }
1735
1736 // Return all leases being within the page size.
1737 for (auto it = lb; it != idx.end(); ++it) {
1738 if ((*it)->subnet_id_ != subnet_id) {
1739 // Gone after the subnet id index.
1740 break;
1741 }
1742 collection.push_back(Lease6Ptr(new Lease6(**it)));
1743 if (collection.size() >= page_size.page_size_) {
1744 break;
1745 }
1746 }
1747 return (collection);
1748}
1749
1752 const IOAddress& lower_bound_address,
1753 const LeasePageSize& page_size) const {
1756 .arg(page_size.page_size_)
1757 .arg(lower_bound_address.toText())
1758 .arg(subnet_id);
1759
1760 // Expecting IPv6 valid address.
1761 if (!lower_bound_address.isV6()) {
1762 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1763 "retrieving leases from the lease database, got "
1764 << lower_bound_address);
1765 }
1766
1767 if (MultiThreadingMgr::instance().getMode()) {
1768 std::lock_guard<std::mutex> lock(*mutex_);
1769 return (getLeases6Internal(subnet_id,
1770 lower_bound_address,
1771 page_size));
1772 } else {
1773 return (getLeases6Internal(subnet_id,
1774 lower_bound_address,
1775 page_size));
1776 }
1777}
1778
1779void
1780Memfile_LeaseMgr::getExpiredLeases4Internal(Lease4Collection& expired_leases,
1781 const size_t max_leases) const {
1782 // Obtain the index which segragates leases by state and time.
1783 const Lease4StorageExpirationIndex& index = storage4_.get<ExpirationIndexTag>();
1784
1785 // Retrieve leases which are not reclaimed and which haven't expired. The
1786 // 'less-than' operator will be used for both components of the index. So,
1787 // for the 'state' 'false' is less than 'true'. Also the leases with
1788 // expiration time lower than current time will be returned.
1789 Lease4StorageExpirationIndex::const_iterator ub =
1790 index.upper_bound(boost::make_tuple(false, time(0)));
1791
1792 // Copy only the number of leases indicated by the max_leases parameter.
1793 for (Lease4StorageExpirationIndex::const_iterator lease = index.begin();
1794 (lease != ub) &&
1795 ((max_leases == 0) ||
1796 (static_cast<size_t>(std::distance(index.begin(), lease)) < max_leases));
1797 ++lease) {
1798 expired_leases.push_back(Lease4Ptr(new Lease4(**lease)));
1799 }
1800}
1801
1802void
1804 const size_t max_leases) const {
1806 .arg(max_leases);
1807
1808 if (MultiThreadingMgr::instance().getMode()) {
1809 std::lock_guard<std::mutex> lock(*mutex_);
1810 getExpiredLeases4Internal(expired_leases, max_leases);
1811 } else {
1812 getExpiredLeases4Internal(expired_leases, max_leases);
1813 }
1814}
1815
1816void
1817Memfile_LeaseMgr::getExpiredLeases6Internal(Lease6Collection& expired_leases,
1818 const size_t max_leases) const {
1819 // Obtain the index which segragates leases by state and time.
1820 const Lease6StorageExpirationIndex& index = storage6_.get<ExpirationIndexTag>();
1821
1822 // Retrieve leases which are not reclaimed and which haven't expired. The
1823 // 'less-than' operator will be used for both components of the index. So,
1824 // for the 'state' 'false' is less than 'true'. Also the leases with
1825 // expiration time lower than current time will be returned.
1826 Lease6StorageExpirationIndex::const_iterator ub =
1827 index.upper_bound(boost::make_tuple(false, time(0)));
1828
1829 // Copy only the number of leases indicated by the max_leases parameter.
1830 for (Lease6StorageExpirationIndex::const_iterator lease = index.begin();
1831 (lease != ub) &&
1832 ((max_leases == 0) ||
1833 (static_cast<size_t>(std::distance(index.begin(), lease)) < max_leases));
1834 ++lease) {
1835 expired_leases.push_back(Lease6Ptr(new Lease6(**lease)));
1836 }
1837}
1838
1839void
1841 const size_t max_leases) const {
1843 .arg(max_leases);
1844
1845 if (MultiThreadingMgr::instance().getMode()) {
1846 std::lock_guard<std::mutex> lock(*mutex_);
1847 getExpiredLeases6Internal(expired_leases, max_leases);
1848 } else {
1849 getExpiredLeases6Internal(expired_leases, max_leases);
1850 }
1851}
1852
1853void
1854Memfile_LeaseMgr::updateLease4Internal(const Lease4Ptr& lease) {
1855 // Obtain 'by address' index.
1856 Lease4StorageAddressIndex& index = storage4_.get<AddressIndexTag>();
1857
1858 bool persist = persistLeases(V4);
1859
1860 // Lease must exist if it is to be updated.
1861 Lease4StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1862 if (lease_it == index.end()) {
1863 isc_throw(NoSuchLease, "failed to update the lease with address "
1864 << lease->addr_ << " - no such lease");
1865 } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1866 ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1867 // For test purpose only: check that the lease has not changed in
1868 // the database.
1869 isc_throw(NoSuchLease, "unable to update lease for address " <<
1870 lease->addr_.toText() << " either because the lease does not exist, "
1871 "it has been deleted or it has changed in the database.");
1872 }
1873
1874 // Try to write a lease to disk first. If this fails, the lease will
1875 // not be inserted to the memory and the disk and in-memory data will
1876 // remain consistent.
1877 if (persist) {
1878 lease_file4_->append(*lease);
1879 }
1880
1881 // Update lease current expiration time.
1882 lease->updateCurrentExpirationTime();
1883
1884 // Save a copy of the old lease as lease_it will point to the new
1885 // one after the replacement.
1886 Lease4Ptr old_lease = *lease_it;
1887
1888 // Use replace() to re-index leases.
1889 index.replace(lease_it, Lease4Ptr(new Lease4(*lease)));
1890
1891 // Adjust class lease counters.
1892 class_lease_counter_.updateLease(lease, old_lease);
1893
1894 // Run installed callbacks.
1895 if (hasCallbacks()) {
1896 trackUpdateLease(lease);
1897 }
1898}
1899
1900void
1903 DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
1904
1905 if (MultiThreadingMgr::instance().getMode()) {
1906 std::lock_guard<std::mutex> lock(*mutex_);
1907 updateLease4Internal(lease);
1908 } else {
1909 updateLease4Internal(lease);
1910 }
1911}
1912
1913void
1914Memfile_LeaseMgr::updateLease6Internal(const Lease6Ptr& lease) {
1915 // Obtain 'by address' index.
1916 Lease6StorageAddressIndex& index = storage6_.get<AddressIndexTag>();
1917
1918 bool persist = persistLeases(V6);
1919
1920 // Get the recorded action and reset it.
1921 Lease6::ExtendedInfoAction recorded_action = lease->extended_info_action_;
1922 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
1923
1924 // Lease must exist if it is to be updated.
1925 Lease6StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1926 if (lease_it == index.end()) {
1927 isc_throw(NoSuchLease, "failed to update the lease with address "
1928 << lease->addr_ << " - no such lease");
1929 } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1930 ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1931 // For test purpose only: check that the lease has not changed in
1932 // the database.
1933 isc_throw(NoSuchLease, "unable to update lease for address " <<
1934 lease->addr_.toText() << " either because the lease does not exist, "
1935 "it has been deleted or it has changed in the database.");
1936 }
1937
1938 // Try to write a lease to disk first. If this fails, the lease will
1939 // not be inserted to the memory and the disk and in-memory data will
1940 // remain consistent.
1941 if (persist) {
1942 lease_file6_->append(*lease);
1943 }
1944
1945 // Update lease current expiration time.
1946 lease->updateCurrentExpirationTime();
1947
1948 // Save a copy of the old lease as lease_it will point to the new
1949 // one after the replacement.
1950 Lease6Ptr old_lease = *lease_it;
1951
1952 // Use replace() to re-index leases.
1953 index.replace(lease_it, Lease6Ptr(new Lease6(*lease)));
1954
1955 // Adjust class lease counters.
1956 class_lease_counter_.updateLease(lease, old_lease);
1957
1958 // Update extended info tables.
1960 switch (recorded_action) {
1962 break;
1963
1965 deleteExtendedInfo6(lease->addr_);
1966 break;
1967
1969 deleteExtendedInfo6(lease->addr_);
1970 static_cast<void>(addExtendedInfo6(lease));
1971 break;
1972 }
1973 }
1974
1975 // Run installed callbacks.
1976 if (hasCallbacks()) {
1977 trackUpdateLease(lease);
1978 }
1979}
1980
1981void
1984 DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
1985
1986 if (MultiThreadingMgr::instance().getMode()) {
1987 std::lock_guard<std::mutex> lock(*mutex_);
1988 updateLease6Internal(lease);
1989 } else {
1990 updateLease6Internal(lease);
1991 }
1992}
1993
1994bool
1995Memfile_LeaseMgr::deleteLeaseInternal(const Lease4Ptr& lease) {
1996 const isc::asiolink::IOAddress& addr = lease->addr_;
1997 Lease4Storage::iterator l = storage4_.find(addr);
1998 if (l == storage4_.end()) {
1999 // No such lease
2000 return (false);
2001 } else {
2002 if (persistLeases(V4)) {
2003 // Copy the lease. The valid lifetime needs to be modified and
2004 // we don't modify the original lease.
2005 Lease4 lease_copy = **l;
2006 // Setting valid lifetime to 0 means that lease is being
2007 // removed.
2008 lease_copy.valid_lft_ = 0;
2009 lease_file4_->append(lease_copy);
2010 } else {
2011 // For test purpose only: check that the lease has not changed in
2012 // the database.
2013 if (((*l)->cltt_ != lease->current_cltt_) ||
2014 ((*l)->valid_lft_ != lease->current_valid_lft_)) {
2015 return false;
2016 }
2017 }
2018
2019 storage4_.erase(l);
2020
2021 // Decrement class lease counters.
2022 class_lease_counter_.removeLease(lease);
2023
2024 // Run installed callbacks.
2025 if (hasCallbacks()) {
2026 trackDeleteLease(lease);
2027 }
2028
2029 return (true);
2030 }
2031}
2032
2033bool
2036 DHCPSRV_MEMFILE_DELETE_ADDR4).arg(lease->addr_.toText());
2037
2038 if (MultiThreadingMgr::instance().getMode()) {
2039 std::lock_guard<std::mutex> lock(*mutex_);
2040 return (deleteLeaseInternal(lease));
2041 } else {
2042 return (deleteLeaseInternal(lease));
2043 }
2044}
2045
2046bool
2047Memfile_LeaseMgr::deleteLeaseInternal(const Lease6Ptr& lease) {
2048 lease->extended_info_action_ = Lease6::ACTION_IGNORE;
2049
2050 const isc::asiolink::IOAddress& addr = lease->addr_;
2051 Lease6Storage::iterator l = storage6_.find(addr);
2052 if (l == storage6_.end()) {
2053 // No such lease
2054 return (false);
2055 } else {
2056 if (persistLeases(V6)) {
2057 // Copy the lease. The lifetimes need to be modified and we
2058 // don't modify the original lease.
2059 Lease6 lease_copy = **l;
2060 // Setting lifetimes to 0 means that lease is being removed.
2061 lease_copy.valid_lft_ = 0;
2062 lease_copy.preferred_lft_ = 0;
2063 lease_file6_->append(lease_copy);
2064 } else {
2065 // For test purpose only: check that the lease has not changed in
2066 // the database.
2067 if (((*l)->cltt_ != lease->current_cltt_) ||
2068 ((*l)->valid_lft_ != lease->current_valid_lft_)) {
2069 return false;
2070 }
2071 }
2072
2073 storage6_.erase(l);
2074
2075 // Decrement class lease counters.
2076 class_lease_counter_.removeLease(lease);
2077
2078 // Delete references from extended info tables.
2080 deleteExtendedInfo6(lease->addr_);
2081 }
2082
2083 // Run installed callbacks.
2084 if (hasCallbacks()) {
2085 trackDeleteLease(lease);
2086 }
2087
2088 return (true);
2089 }
2090}
2091
2092bool
2095 DHCPSRV_MEMFILE_DELETE_ADDR6).arg(lease->addr_.toText());
2096
2097 if (MultiThreadingMgr::instance().getMode()) {
2098 std::lock_guard<std::mutex> lock(*mutex_);
2099 return (deleteLeaseInternal(lease));
2100 } else {
2101 return (deleteLeaseInternal(lease));
2102 }
2103}
2104
2105uint64_t
2109 .arg(secs);
2110
2111 if (MultiThreadingMgr::instance().getMode()) {
2112 std::lock_guard<std::mutex> lock(*mutex_);
2113 return (deleteExpiredReclaimedLeases<
2115 >(secs, V4, storage4_, lease_file4_));
2116 } else {
2117 return (deleteExpiredReclaimedLeases<
2119 >(secs, V4, storage4_, lease_file4_));
2120 }
2121}
2122
2123uint64_t
2127 .arg(secs);
2128
2129 if (MultiThreadingMgr::instance().getMode()) {
2130 std::lock_guard<std::mutex> lock(*mutex_);
2131 return (deleteExpiredReclaimedLeases<
2133 >(secs, V6, storage6_, lease_file6_));
2134 } else {
2135 return (deleteExpiredReclaimedLeases<
2137 >(secs, V6, storage6_, lease_file6_));
2138 }
2139}
2140
2141template<typename IndexType, typename LeaseType, typename StorageType,
2142 typename LeaseFileType>
2143uint64_t
2144Memfile_LeaseMgr::deleteExpiredReclaimedLeases(const uint32_t secs,
2145 const Universe& universe,
2146 StorageType& storage,
2147 LeaseFileType& lease_file) {
2148 // Obtain the index which segragates leases by state and time.
2149 IndexType& index = storage.template get<ExpirationIndexTag>();
2150
2151 // This returns the first element which is greater than the specified
2152 // tuple (true, time(0) - secs). However, the range between the
2153 // beginning of the index and returned element also includes all the
2154 // elements for which the first value is false (lease state is NOT
2155 // reclaimed), because false < true. All elements between the
2156 // beginning of the index and the element returned, for which the
2157 // first value is true, represent the reclaimed leases which should
2158 // be deleted, because their expiration time + secs has occurred earlier
2159 // than current time.
2160 typename IndexType::const_iterator upper_limit =
2161 index.upper_bound(boost::make_tuple(true, time(0) - secs));
2162
2163 // Now, we have to exclude all elements of the index which represent
2164 // leases in the state other than reclaimed - with the first value
2165 // in the index equal to false. Note that elements in the index are
2166 // ordered from the lower to the higher ones. So, all elements with
2167 // the first value of false are placed before the elements with the
2168 // value of true. Hence, we have to find the first element which
2169 // contains value of true. The time value is the lowest possible.
2170 typename IndexType::const_iterator lower_limit =
2171 index.upper_bound(boost::make_tuple(true, std::numeric_limits<int64_t>::min()));
2172
2173 // If there are some elements in this range, delete them.
2174 uint64_t num_leases = static_cast<uint64_t>(std::distance(lower_limit, upper_limit));
2175 if (num_leases > 0) {
2176
2179 .arg(num_leases);
2180
2181 // If lease persistence is enabled, we also have to mark leases
2182 // as deleted in the lease file. We do this by setting the
2183 // lifetime to 0.
2184 if (persistLeases(universe)) {
2185 for (typename IndexType::const_iterator lease = lower_limit;
2186 lease != upper_limit; ++lease) {
2187 // Copy lease to not affect the lease in the container.
2188 LeaseType lease_copy(**lease);
2189 // Set the valid lifetime to 0 to indicate the removal
2190 // of the lease.
2191 lease_copy.valid_lft_ = 0;
2192 lease_file->append(lease_copy);
2193 }
2194 }
2195
2196 // Erase leases from memory.
2197 index.erase(lower_limit, upper_limit);
2198
2199 }
2200 // Return number of leases deleted.
2201 return (num_leases);
2202}
2203
2204std::string
2206 return (std::string("In memory database with leases stored in a CSV file."));
2207}
2208
2209std::pair<uint32_t, uint32_t>
2210Memfile_LeaseMgr::getVersion(const std::string& /* timer_name */) const {
2211 std::string const& universe(conn_.getParameter("universe"));
2212 if (universe == "4") {
2213 return std::make_pair(MAJOR_VERSION_V4, MINOR_VERSION_V4);
2214 } else if (universe == "6") {
2215 return std::make_pair(MAJOR_VERSION_V6, MINOR_VERSION_V6);
2216 }
2217 isc_throw(BadValue, "cannot determine version for universe " << universe);
2218}
2219
2220void
2224
2225void
2230
2231std::string
2232Memfile_LeaseMgr::appendSuffix(const std::string& file_name,
2233 const LFCFileType& file_type) {
2234 std::string name(file_name);
2235 switch (file_type) {
2236 case FILE_INPUT:
2237 name += ".1";
2238 break;
2239 case FILE_PREVIOUS:
2240 name += ".2";
2241 break;
2242 case FILE_OUTPUT:
2243 name += ".output";
2244 break;
2245 case FILE_FINISH:
2246 name += ".completed";
2247 break;
2248 case FILE_PID:
2249 name += ".pid";
2250 break;
2251 default:
2252 // Do not append any suffix for the FILE_CURRENT.
2253 ;
2254 }
2255
2256 return (name);
2257}
2258
2259std::string
2261 std::string filename /* = "" */) const {
2262 std::ostringstream s;;
2264 if (filename.empty()) {
2265 s << "/kea-leases";
2266 s << (u == V4 ? "4" : "6");
2267 s << ".csv";
2268 } else {
2269 s << "/" << filename;
2270 }
2271
2272 return (s.str());
2273}
2274
2275std::string
2277 if (u == V4) {
2278 return (lease_file4_ ? lease_file4_->getFilename() : "");
2279 }
2280
2281 return (lease_file6_ ? lease_file6_->getFilename() : "");
2282}
2283
2284bool
2286 // Currently, if the lease file IO is not created, it means that writes to
2287 // disk have been explicitly disabled by the administrator. At some point,
2288 // there may be a dedicated ON/OFF flag implemented to control this.
2289 if (u == V4 && lease_file4_) {
2290 return (true);
2291 }
2292
2293 return (u == V6 && lease_file6_);
2294}
2295
2296std::string
2297Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
2298 std::string persist_val;
2299 try {
2300 persist_val = conn_.getParameter("persist");
2301 } catch (const Exception&) {
2302 // If parameter persist hasn't been specified, we use a default value
2303 // 'yes'.
2304 persist_val = "true";
2305 }
2306 // If persist_val is 'false' we will not store leases to disk, so let's
2307 // return empty file name.
2308 if (persist_val == "false") {
2309 return ("");
2310
2311 } else if (persist_val != "true") {
2312 isc_throw(isc::BadValue, "invalid value 'persist="
2313 << persist_val << "'");
2314 }
2315
2316 std::string lease_file;
2317 try {
2318 lease_file = conn_.getParameter("name");
2319 } catch (const Exception&) {
2320 // Not specified, use the default.
2321 return (getDefaultLeaseFilePath(u));
2322 }
2323
2324 // If path is invalid this will throw.
2325 lease_file = CfgMgr::instance().validatePath(lease_file);
2326 return (lease_file);
2327}
2328
2329template<typename LeaseObjectType, typename LeaseFileType, typename StorageType>
2330bool
2331Memfile_LeaseMgr::loadLeasesFromFiles(const std::string& filename,
2332 boost::shared_ptr<LeaseFileType>& lease_file,
2333 StorageType& storage) {
2334 // Check if the instance of the LFC is running right now. If it is
2335 // running, we refuse to load leases as the LFC may be writing to the
2336 // lease files right now. When the user retries server configuration
2337 // it should go through.
2340 PIDFile pid_file(appendSuffix(filename, FILE_PID));
2341 if (pid_file.check()) {
2342 isc_throw(DbOpenError, "unable to load leases from files while the "
2343 "lease file cleanup is in progress");
2344 }
2345
2346 storage.clear();
2347
2348 std::string max_row_errors_str = "0";
2349 try {
2350 max_row_errors_str = conn_.getParameter("max-row-errors");
2351 } catch (const std::exception&) {
2352 // Ignore and default to 0.
2353 }
2354
2355 int64_t max_row_errors64;
2356 try {
2357 max_row_errors64 = boost::lexical_cast<int64_t>(max_row_errors_str);
2358 } catch (const boost::bad_lexical_cast&) {
2359 isc_throw(isc::BadValue, "invalid value of the max-row-errors "
2360 << max_row_errors_str << " specified");
2361 }
2362 if ((max_row_errors64 < 0) ||
2363 (max_row_errors64 > std::numeric_limits<uint32_t>::max())) {
2364 isc_throw(isc::BadValue, "invalid value of the max-row-errors "
2365 << max_row_errors_str << " specified");
2366 }
2367 uint32_t max_row_errors = static_cast<uint32_t>(max_row_errors64);
2368
2369 // Load the leasefile.completed, if exists.
2370 bool conversion_needed = false;
2371 lease_file.reset(new LeaseFileType(std::string(filename + ".completed")));
2372 if (lease_file->exists()) {
2373 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2374 max_row_errors);
2375 conversion_needed = conversion_needed || lease_file->needsConversion();
2376 } else {
2377 // If the leasefile.completed doesn't exist, let's load the leases
2378 // from leasefile.2 and leasefile.1, if they exist.
2379 lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_PREVIOUS)));
2380 if (lease_file->exists()) {
2381 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2382 max_row_errors);
2383 conversion_needed = conversion_needed || lease_file->needsConversion();
2384 }
2385
2386 lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_INPUT)));
2387 if (lease_file->exists()) {
2388 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2389 max_row_errors);
2390 conversion_needed = conversion_needed || lease_file->needsConversion();
2391 }
2392 }
2393
2394 // Always load leases from the primary lease file. If the lease file
2395 // doesn't exist it will be created by the LeaseFileLoader. Note
2396 // that the false value passed as the last parameter to load
2397 // function causes the function to leave the file open after
2398 // it is parsed. This file will be used by the backend to record
2399 // future lease updates.
2400 lease_file.reset(new LeaseFileType(filename));
2401 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
2402 max_row_errors, false);
2403 conversion_needed = conversion_needed || lease_file->needsConversion();
2404
2405 return (conversion_needed);
2406}
2407
2408
2409bool
2411 return (lfc_setup_->isRunning());
2412}
2413
2414int
2416 return (lfc_setup_->getExitStatus());
2417}
2418
2419void
2422
2423 // Check if we're in the v4 or v6 space and use the appropriate file.
2424 if (lease_file4_) {
2426 lfcExecute(lease_file4_);
2427 } else if (lease_file6_) {
2429 lfcExecute(lease_file6_);
2430 }
2431}
2432
2433void
2434Memfile_LeaseMgr::lfcSetup(bool conversion_needed) {
2435 std::string lfc_interval_str = "3600";
2436 try {
2437 lfc_interval_str = conn_.getParameter("lfc-interval");
2438 } catch (const std::exception&) {
2439 // Ignore and default to 3600.
2440 }
2441
2442 uint32_t lfc_interval = 0;
2443 try {
2444 lfc_interval = boost::lexical_cast<uint32_t>(lfc_interval_str);
2445 } catch (const boost::bad_lexical_cast&) {
2446 isc_throw(isc::BadValue, "invalid value of the lfc-interval "
2447 << lfc_interval_str << " specified");
2448 }
2449
2450 if (lfc_interval > 0 || conversion_needed) {
2451 lfc_setup_.reset(new LFCSetup(std::bind(&Memfile_LeaseMgr::lfcCallback, this)));
2452 lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_, conversion_needed);
2453 }
2454}
2455
2456template<typename LeaseFileType>
2457void
2458Memfile_LeaseMgr::lfcExecute(boost::shared_ptr<LeaseFileType>& lease_file) {
2459 bool do_lfc = true;
2460
2461 // Check the status of the LFC instance.
2462 // If the finish file exists or the copy of the lease file exists it
2463 // is an indication that another LFC instance may be in progress or
2464 // may be stalled. In that case we don't want to rotate the current
2465 // lease file to avoid overriding the contents of the existing file.
2466 CSVFile lease_file_finish(appendSuffix(lease_file->getFilename(), FILE_FINISH));
2467 CSVFile lease_file_copy(appendSuffix(lease_file->getFilename(), FILE_INPUT));
2468 if (!lease_file_finish.exists() && !lease_file_copy.exists()) {
2469 // Close the current file so as we can move it to the copy file.
2470 lease_file->close();
2471 // Move the current file to the copy file. Remember the result
2472 // because we don't want to run LFC if the rename failed.
2473 do_lfc = (rename(lease_file->getFilename().c_str(),
2474 lease_file_copy.getFilename().c_str()) == 0);
2475
2476 if (!do_lfc) {
2478 .arg(lease_file->getFilename())
2479 .arg(lease_file_copy.getFilename())
2480 .arg(strerror(errno));
2481 }
2482
2483 // Regardless if we successfully moved the current file or not,
2484 // we need to re-open the current file for the server to write
2485 // new lease updates. If the file has been successfully moved,
2486 // this will result in creation of the new file. Otherwise,
2487 // an existing file will be opened.
2488 try {
2489 lease_file->open(true);
2490
2491 } catch (const CSVFileError& ex) {
2492 // If we're unable to open the lease file this is a serious
2493 // error because the server will not be able to persist
2494 // leases.
2502 .arg(lease_file->getFilename())
2503 .arg(ex.what());
2504 // Reset the pointer to the file so as the backend doesn't
2505 // try to write leases to disk.
2506 lease_file.reset();
2507 do_lfc = false;
2508 }
2509 }
2510 // Once the files have been rotated, or untouched if another LFC had
2511 // not finished, a new process is started.
2512 if (do_lfc) {
2513 lfc_setup_->execute();
2514 }
2515}
2516
2519 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_));
2520 if (MultiThreadingMgr::instance().getMode()) {
2521 std::lock_guard<std::mutex> lock(*mutex_);
2522 query->start();
2523 } else {
2524 query->start();
2525 }
2526
2527 return(query);
2528}
2529
2533 if (MultiThreadingMgr::instance().getMode()) {
2534 std::lock_guard<std::mutex> lock(*mutex_);
2535 query->start();
2536 } else {
2537 query->start();
2538 }
2539
2540 return(query);
2541}
2542
2545 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, subnet_id));
2546 if (MultiThreadingMgr::instance().getMode()) {
2547 std::lock_guard<std::mutex> lock(*mutex_);
2548 query->start();
2549 } else {
2550 query->start();
2551 }
2552
2553 return(query);
2554}
2555
2558 const SubnetID& last_subnet_id) {
2559 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, first_subnet_id,
2560 last_subnet_id));
2561 if (MultiThreadingMgr::instance().getMode()) {
2562 std::lock_guard<std::mutex> lock(*mutex_);
2563 query->start();
2564 } else {
2565 query->start();
2566 }
2567
2568 return(query);
2569}
2570
2573 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_));
2574 if (MultiThreadingMgr::instance().getMode()) {
2575 std::lock_guard<std::mutex> lock(*mutex_);
2576 query->start();
2577 } else {
2578 query->start();
2579 }
2580
2581 return(query);
2582}
2583
2587 if (MultiThreadingMgr::instance().getMode()) {
2588 std::lock_guard<std::mutex> lock(*mutex_);
2589 query->start();
2590 } else {
2591 query->start();
2592 }
2593
2594 return(query);
2595}
2596
2599 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, subnet_id));
2600 if (MultiThreadingMgr::instance().getMode()) {
2601 std::lock_guard<std::mutex> lock(*mutex_);
2602 query->start();
2603 } else {
2604 query->start();
2605 }
2606
2607 return(query);
2608}
2609
2612 const SubnetID& last_subnet_id) {
2613 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, first_subnet_id,
2614 last_subnet_id));
2615 if (MultiThreadingMgr::instance().getMode()) {
2616 std::lock_guard<std::mutex> lock(*mutex_);
2617 query->start();
2618 } else {
2619 query->start();
2620 }
2621
2622 return(query);
2623}
2624
2625size_t
2628 .arg(subnet_id);
2629
2630 // Get the index by DUID, IAID, lease type.
2631 const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
2632
2633 // Try to get the lease using the DUID, IAID and lease type.
2634 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
2635 Lease4StorageSubnetIdIndex::const_iterator> r =
2636 idx.equal_range(subnet_id);
2637
2638 // Let's collect all leases.
2639 Lease4Collection leases;
2640 BOOST_FOREACH(auto const& lease, r) {
2641 leases.push_back(lease);
2642 }
2643
2644 size_t num = leases.size();
2645 for (auto const& l : leases) {
2646 deleteLease(l);
2647 }
2649 .arg(subnet_id).arg(num);
2650
2651 return (num);
2652}
2653
2654size_t
2657 .arg(subnet_id);
2658
2659 // Get the index by DUID, IAID, lease type.
2660 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
2661
2662 // Try to get the lease using the DUID, IAID and lease type.
2663 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
2664 Lease6StorageSubnetIdIndex::const_iterator> r =
2665 idx.equal_range(subnet_id);
2666
2667 // Let's collect all leases.
2668 Lease6Collection leases;
2669 BOOST_FOREACH(auto const& lease, r) {
2670 leases.push_back(lease);
2671 }
2672
2673 size_t num = leases.size();
2674 for (auto const& l : leases) {
2675 deleteLease(l);
2676 }
2678 .arg(subnet_id).arg(num);
2679
2680 return (num);
2681}
2682
2683void
2685 class_lease_counter_.clear();
2686 for (auto const& lease : storage4_) {
2687 // Bump the appropriate accumulator
2688 if (lease->state_ == Lease::STATE_DEFAULT) {
2689 class_lease_counter_.addLease(lease);
2690 }
2691 }
2692}
2693
2694void
2696 class_lease_counter_.clear();
2697 for (auto const& lease : storage6_) {
2698 // Bump the appropriate accumulator
2699 if (lease->state_ == Lease::STATE_DEFAULT) {
2700 class_lease_counter_.addLease(lease);
2701 }
2702 }
2703}
2704
2705size_t
2707 const Lease::Type& ltype /* = Lease::TYPE_V4*/) const {
2708 if (MultiThreadingMgr::instance().getMode()) {
2709 std::lock_guard<std::mutex> lock(*mutex_);
2710 return(class_lease_counter_.getClassCount(client_class, ltype));
2711 } else {
2712 return(class_lease_counter_.getClassCount(client_class, ltype));
2713 }
2714}
2715
2716void
2718 return(class_lease_counter_.clear());
2719}
2720
2721std::string
2723 if (!user_context) {
2724 return ("");
2725 }
2726
2727 ConstElementPtr limits = user_context->find("ISC/limits");
2728 if (!limits) {
2729 return ("");
2730 }
2731
2732 // Iterate of the 'client-classes' list in 'limits'. For each class that specifies
2733 // an "address-limit", check its value against the class's lease count.
2734 ConstElementPtr classes = limits->get("client-classes");
2735 if (classes) {
2736 for (unsigned i = 0; i < classes->size(); ++i) {
2737 ConstElementPtr class_elem = classes->get(i);
2738 // Get class name.
2739 ConstElementPtr name_elem = class_elem->get("name");
2740 if (!name_elem) {
2741 isc_throw(BadValue, "checkLimits4 - client-class.name is missing: "
2742 << prettyPrint(limits));
2743 }
2744
2745 std::string name = name_elem->stringValue();
2746
2747 // Now look for an address-limit
2748 size_t limit;
2749 if (!getLeaseLimit(class_elem, Lease::TYPE_V4, limit)) {
2750 // No limit, go to the next class.
2751 continue;
2752 }
2753
2754 // If the limit is > 0 look up the class lease count. Limit of 0 always
2755 // denies the lease.
2756 size_t lease_count = 0;
2757 if (limit) {
2758 lease_count = getClassLeaseCount(name);
2759 }
2760
2761 // If we're over the limit, return the error, no need to evaluate any others.
2762 if (lease_count >= limit) {
2763 std::ostringstream ss;
2764 ss << "address limit " << limit << " for client class \""
2765 << name << "\", current lease count " << lease_count;
2766 return (ss.str());
2767 }
2768 }
2769 }
2770
2771 // If there were class limits we passed them, now look for a subnet limit.
2772 ConstElementPtr subnet_elem = limits->get("subnet");
2773 if (subnet_elem) {
2774 // Get the subnet id.
2775 ConstElementPtr id_elem = subnet_elem->get("id");
2776 if (!id_elem) {
2777 isc_throw(BadValue, "checkLimits4 - subnet.id is missing: "
2778 << prettyPrint(limits));
2779 }
2780
2781 SubnetID subnet_id = id_elem->intValue();
2782
2783 // Now look for an address-limit.
2784 size_t limit;
2785 if (getLeaseLimit(subnet_elem, Lease::TYPE_V4, limit)) {
2786 // If the limit is > 0 look up the subnet lease count. Limit of 0 always
2787 // denies the lease.
2788 int64_t lease_count = 0;
2789 if (limit) {
2790 lease_count = getSubnetStat(subnet_id, "assigned-addresses");
2791 }
2792
2793 // If we're over the limit, return the error.
2794 if (static_cast<uint64_t>(lease_count) >= limit) {
2795 std::ostringstream ss;
2796 ss << "address limit " << limit << " for subnet ID " << subnet_id
2797 << ", current lease count " << lease_count;
2798 return (ss.str());
2799 }
2800 }
2801 }
2802
2803 // No limits exceeded!
2804 return ("");
2805}
2806
2807std::string
2809 if (!user_context) {
2810 return ("");
2811 }
2812
2813 ConstElementPtr limits = user_context->find("ISC/limits");
2814 if (!limits) {
2815 return ("");
2816 }
2817
2818 // Iterate over the 'client-classes' list in 'limits'. For each class that specifies
2819 // limit (either "address-limit" or "prefix-limit", check its value against the appropriate
2820 // class lease count.
2821 ConstElementPtr classes = limits->get("client-classes");
2822 if (classes) {
2823 for (unsigned i = 0; i < classes->size(); ++i) {
2824 ConstElementPtr class_elem = classes->get(i);
2825 // Get class name.
2826 ConstElementPtr name_elem = class_elem->get("name");
2827 if (!name_elem) {
2828 isc_throw(BadValue, "checkLimits6 - client-class.name is missing: "
2829 << prettyPrint(limits));
2830 }
2831
2832 std::string name = name_elem->stringValue();
2833
2834 // Now look for either address-limit or a prefix=limit.
2835 size_t limit = 0;
2837 if (!getLeaseLimit(class_elem, ltype, limit)) {
2838 ltype = Lease::TYPE_PD;
2839 if (!getLeaseLimit(class_elem, ltype, limit)) {
2840 // No limits for this class, skip to the next.
2841 continue;
2842 }
2843 }
2844
2845 // If the limit is > 0 look up the class lease count. Limit of 0 always
2846 // denies the lease.
2847 size_t lease_count = 0;
2848 if (limit) {
2849 lease_count = getClassLeaseCount(name, ltype);
2850 }
2851
2852 // If we're over the limit, return the error, no need to evaluate any others.
2853 if (lease_count >= limit) {
2854 std::ostringstream ss;
2855 ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
2856 << " limit " << limit << " for client class \""
2857 << name << "\", current lease count " << lease_count;
2858 return (ss.str());
2859 }
2860 }
2861 }
2862
2863 // If there were class limits we passed them, now look for a subnet limit.
2864 ConstElementPtr subnet_elem = limits->get("subnet");
2865 if (subnet_elem) {
2866 // Get the subnet id.
2867 ConstElementPtr id_elem = subnet_elem->get("id");
2868 if (!id_elem) {
2869 isc_throw(BadValue, "checkLimits6 - subnet.id is missing: "
2870 << prettyPrint(limits));
2871 }
2872
2873 SubnetID subnet_id = id_elem->intValue();
2874
2875 // Now look for either address-limit or a prefix=limit.
2876 size_t limit = 0;
2878 if (!getLeaseLimit(subnet_elem, ltype, limit)) {
2879 ltype = Lease::TYPE_PD;
2880 if (!getLeaseLimit(subnet_elem, ltype, limit)) {
2881 // No limits for the subnet so none exceeded!
2882 return ("");
2883 }
2884 }
2885
2886 // If the limit is > 0 look up the class lease count. Limit of 0 always
2887 // denies the lease.
2888 int64_t lease_count = 0;
2889 if (limit) {
2890 lease_count = getSubnetStat(subnet_id, (ltype == Lease::TYPE_NA ?
2891 "assigned-nas" : "assigned-pds"));
2892 }
2893
2894 // If we're over the limit, return the error.
2895 if (static_cast<uint64_t>(lease_count) >= limit) {
2896 std::ostringstream ss;
2897 ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
2898 << " limit " << limit << " for subnet ID " << subnet_id
2899 << ", current lease count " << lease_count;
2900 return (ss.str());
2901 }
2902 }
2903
2904 // No limits exceeded!
2905 return ("");
2906}
2907
2908bool
2910 return true;
2911}
2912
2913int64_t
2914Memfile_LeaseMgr::getSubnetStat(const SubnetID& subnet_id, const std::string& stat_label) const {
2917 std::string stat_name = StatsMgr::generateName("subnet", subnet_id, stat_label);
2918 ConstElementPtr stat = StatsMgr::instance().get(stat_name);
2919 ConstElementPtr samples = stat->get(stat_name);
2920 if (samples && samples->size()) {
2921 auto sample = samples->get(0);
2922 if (sample->size()) {
2923 auto count_elem = sample->get(0);
2924 return (count_elem->intValue());
2925 }
2926 }
2927
2928 return (0);
2929}
2930
2931bool
2932Memfile_LeaseMgr::getLeaseLimit(ConstElementPtr parent, Lease::Type ltype, size_t& limit) const {
2933 ConstElementPtr limit_elem = parent->get(ltype == Lease::TYPE_PD ?
2934 "prefix-limit" : "address-limit");
2935 if (limit_elem) {
2936 limit = limit_elem->intValue();
2937 return (true);
2938 }
2939
2940 return (false);
2941}
2942
2943namespace {
2944
2945std::string
2946idToText(const OptionBuffer& id) {
2947 std::stringstream tmp;
2948 tmp << std::hex;
2949 bool delim = false;
2950 for (auto const& it : id) {
2951 if (delim) {
2952 tmp << ":";
2953 }
2954 tmp << std::setw(2) << std::setfill('0')
2955 << static_cast<unsigned int>(it);
2956 delim = true;
2957 }
2958 return (tmp.str());
2959}
2960
2961} // anonymous namespace
2962
2965 const IOAddress& lower_bound_address,
2966 const LeasePageSize& page_size,
2967 const time_t& qry_start_time /* = 0 */,
2968 const time_t& qry_end_time /* = 0 */) {
2971 .arg(page_size.page_size_)
2972 .arg(lower_bound_address.toText())
2973 .arg(idToText(relay_id))
2974 .arg(qry_start_time)
2975 .arg(qry_end_time);
2976
2977 // Expecting IPv4 address.
2978 if (!lower_bound_address.isV4()) {
2979 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
2980 "retrieving leases from the lease database, got "
2981 << lower_bound_address);
2982 }
2983
2984 // Catch 2038 bug with 32 bit time_t.
2985 if ((qry_start_time < 0) || (qry_end_time < 0)) {
2986 isc_throw(BadValue, "negative time value");
2987 }
2988
2989 // Start time must be before end time.
2990 if ((qry_start_time > 0) && (qry_end_time > 0) &&
2991 (qry_start_time > qry_end_time)) {
2992 isc_throw(BadValue, "start time must be before end time");
2993 }
2994
2995 if (MultiThreadingMgr::instance().getMode()) {
2996 std::lock_guard<std::mutex> lock(*mutex_);
2997 return (getLeases4ByRelayIdInternal(relay_id,
2998 lower_bound_address,
2999 page_size,
3000 qry_start_time,
3001 qry_end_time));
3002 } else {
3003 return (getLeases4ByRelayIdInternal(relay_id,
3004 lower_bound_address,
3005 page_size,
3006 qry_start_time,
3007 qry_end_time));
3008 }
3009}
3010
3012Memfile_LeaseMgr::getLeases4ByRelayIdInternal(const OptionBuffer& relay_id,
3013 const IOAddress& lower_bound_address,
3014 const LeasePageSize& page_size,
3015 const time_t& qry_start_time,
3016 const time_t& qry_end_time) {
3017 Lease4Collection collection;
3018 const Lease4StorageRelayIdIndex& idx = storage4_.get<RelayIdIndexTag>();
3019 Lease4StorageRelayIdIndex::const_iterator lb =
3020 idx.lower_bound(boost::make_tuple(relay_id, lower_bound_address));
3021 // Return all convenient leases being within the page size.
3022 IOAddress last_addr = lower_bound_address;
3023 for (; lb != idx.end(); ++lb) {
3024 if ((*lb)->addr_ == last_addr) {
3025 // Already seen: skip it.
3026 continue;
3027 }
3028 if ((*lb)->relay_id_ != relay_id) {
3029 // Gone after the relay id index.
3030 break;
3031 }
3032 last_addr = (*lb)->addr_;
3033 if ((qry_start_time > 0) && ((*lb)->cltt_ < qry_start_time)) {
3034 // Too old.
3035 continue;
3036 }
3037 if ((qry_end_time > 0) && ((*lb)->cltt_ > qry_end_time)) {
3038 // Too young.
3039 continue;
3040 }
3041 collection.push_back(Lease4Ptr(new Lease4(**lb)));
3042 if (collection.size() >= page_size.page_size_) {
3043 break;
3044 }
3045 }
3046 return (collection);
3047}
3048
3051 const IOAddress& lower_bound_address,
3052 const LeasePageSize& page_size,
3053 const time_t& qry_start_time /* = 0 */,
3054 const time_t& qry_end_time /* = 0 */) {
3057 .arg(page_size.page_size_)
3058 .arg(lower_bound_address.toText())
3059 .arg(idToText(remote_id))
3060 .arg(qry_start_time)
3061 .arg(qry_end_time);
3062
3063 // Expecting IPv4 address.
3064 if (!lower_bound_address.isV4()) {
3065 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
3066 "retrieving leases from the lease database, got "
3067 << lower_bound_address);
3068 }
3069
3070 // Catch 2038 bug with 32 bit time_t.
3071 if ((qry_start_time < 0) || (qry_end_time < 0)) {
3072 isc_throw(BadValue, "negative time value");
3073 }
3074
3075 // Start time must be before end time.
3076 if ((qry_start_time > 0) && (qry_end_time > 0) &&
3077 (qry_start_time > qry_end_time)) {
3078 isc_throw(BadValue, "start time must be before end time");
3079 }
3080
3081 if (MultiThreadingMgr::instance().getMode()) {
3082 std::lock_guard<std::mutex> lock(*mutex_);
3083 return (getLeases4ByRemoteIdInternal(remote_id,
3084 lower_bound_address,
3085 page_size,
3086 qry_start_time,
3087 qry_end_time));
3088 } else {
3089 return (getLeases4ByRemoteIdInternal(remote_id,
3090 lower_bound_address,
3091 page_size,
3092 qry_start_time,
3093 qry_end_time));
3094 }
3095}
3096
3098Memfile_LeaseMgr::getLeases4ByRemoteIdInternal(const OptionBuffer& remote_id,
3099 const IOAddress& lower_bound_address,
3100 const LeasePageSize& page_size,
3101 const time_t& qry_start_time,
3102 const time_t& qry_end_time) {
3103 Lease4Collection collection;
3104 std::map<IOAddress, Lease4Ptr> sorted;
3105 const Lease4StorageRemoteIdIndex& idx = storage4_.get<RemoteIdIndexTag>();
3106 Lease4StorageRemoteIdRange er = idx.equal_range(remote_id);
3107 // Store all convenient leases being within the page size.
3108 BOOST_FOREACH(auto const& it, er) {
3109 const IOAddress& addr = it->addr_;
3110 if (addr <= lower_bound_address) {
3111 // Not greater than lower_bound_address.
3112 continue;
3113 }
3114 if ((qry_start_time > 0) && (it->cltt_ < qry_start_time)) {
3115 // Too old.
3116 continue;
3117 }
3118 if ((qry_end_time > 0) && (it->cltt_ > qry_end_time)) {
3119 // Too young.
3120 continue;
3121 }
3122 sorted[addr] = it;
3123 }
3124
3125 // Return all leases being within the page size.
3126 for (auto const& it : sorted) {
3127 collection.push_back(Lease4Ptr(new Lease4(*it.second)));
3128 if (collection.size() >= page_size.page_size_) {
3129 break;
3130 }
3131 }
3132 return (collection);
3133}
3134
3135void
3137 if (MultiThreadingMgr::instance().getMode()) {
3138 std::lock_guard<std::mutex> lock(*mutex_);
3139 relay_id6_.clear();
3140 remote_id6_.clear();
3141 } else {
3142 relay_id6_.clear();
3143 remote_id6_.clear();
3144 }
3145}
3146
3147size_t
3149 return (relay_id6_.size());
3150}
3151
3152size_t
3154 return (remote_id6_.size());
3155}
3156
3159 const IOAddress& lower_bound_address,
3160 const LeasePageSize& page_size) {
3163 .arg(page_size.page_size_)
3164 .arg(lower_bound_address.toText())
3165 .arg(relay_id.toText());
3166
3167 // Expecting IPv6 valid address.
3168 if (!lower_bound_address.isV6()) {
3169 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3170 "retrieving leases from the lease database, got "
3171 << lower_bound_address);
3172 }
3173
3174 if (MultiThreadingMgr::instance().getMode()) {
3175 std::lock_guard<std::mutex> lock(*mutex_);
3176 return (getLeases6ByRelayIdInternal(relay_id,
3177 lower_bound_address,
3178 page_size));
3179 } else {
3180 return (getLeases6ByRelayIdInternal(relay_id,
3181 lower_bound_address,
3182 page_size));
3183 }
3184}
3185
3187Memfile_LeaseMgr::getLeases6ByRelayIdInternal(const DUID& relay_id,
3188 const IOAddress& lower_bound_address,
3189 const LeasePageSize& page_size) {
3190 const std::vector<uint8_t>& relay_id_data = relay_id.getDuid();
3191 Lease6Collection collection;
3192 const RelayIdIndex& idx = relay_id6_.get<RelayIdIndexTag>();
3193 RelayIdIndex::const_iterator lb =
3194 idx.lower_bound(boost::make_tuple(relay_id_data, lower_bound_address));
3195
3196 // Return all leases being within the page size.
3197 IOAddress last_addr = lower_bound_address;
3198 for (; lb != idx.end(); ++lb) {
3199 if ((*lb)->lease_addr_ == last_addr) {
3200 // Already seen: skip it.
3201 continue;
3202 }
3203 if ((*lb)->id_ != relay_id_data) {
3204 // Gone after the relay id index.
3205 break;
3206 }
3207 last_addr = (*lb)->lease_addr_;
3208 Lease6Ptr lease = getAnyLease6Internal(last_addr);
3209 if (lease) {
3210 collection.push_back(lease);
3211 if (collection.size() >= page_size.page_size_) {
3212 break;
3213 }
3214 }
3215 }
3216 return (collection);
3217}
3218
3221 const IOAddress& lower_bound_address,
3222 const LeasePageSize& page_size) {
3225 .arg(page_size.page_size_)
3226 .arg(lower_bound_address.toText())
3227 .arg(idToText(remote_id));
3228
3229 // Expecting IPv6 valid address.
3230 if (!lower_bound_address.isV6()) {
3231 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
3232 "retrieving leases from the lease database, got "
3233 << lower_bound_address);
3234 }
3235
3236 if (MultiThreadingMgr::instance().getMode()) {
3237 std::lock_guard<std::mutex> lock(*mutex_);
3238 return (getLeases6ByRemoteIdInternal(remote_id,
3239 lower_bound_address,
3240 page_size));
3241 } else {
3242 return (getLeases6ByRemoteIdInternal(remote_id,
3243 lower_bound_address,
3244 page_size));
3245 }
3246}
3247
3249Memfile_LeaseMgr::getLeases6ByRemoteIdInternal(const OptionBuffer& remote_id,
3250 const IOAddress& lower_bound_address,
3251 const LeasePageSize& page_size) {
3252 Lease6Collection collection;
3253 std::set<IOAddress> sorted;
3254 const RemoteIdIndex& idx = remote_id6_.get<RemoteIdIndexTag>();
3255 RemoteIdIndexRange er = idx.equal_range(remote_id);
3256 // Store all addresses greater than lower_bound_address.
3257 BOOST_FOREACH(auto const& it, er) {
3258 const IOAddress& addr = it->lease_addr_;
3259 if (addr <= lower_bound_address) {
3260 continue;
3261 }
3262 static_cast<void>(sorted.insert(addr));
3263 }
3264
3265 // Return all leases being within the page size.
3266 for (const IOAddress& addr : sorted) {
3267 Lease6Ptr lease = getAnyLease6Internal(addr);
3268 if (lease) {
3269 collection.push_back(lease);
3270 if (collection.size() >= page_size.page_size_) {
3271 break;
3272 }
3273 }
3274 }
3275 return (collection);
3276}
3277
3278size_t
3279Memfile_LeaseMgr::extractExtendedInfo4(bool update, bool current) {
3281 if (current) {
3282 cfg = CfgMgr::instance().getCurrentCfg()->getConsistency();
3283 } else {
3284 cfg = CfgMgr::instance().getStagingCfg()->getConsistency();
3285 }
3286 if (!cfg) {
3287 isc_throw(Unexpected, "the " << (current ? "current" : "staging")
3288 << " consistency configuration is null");
3289 }
3290 auto check = cfg->getExtendedInfoSanityCheck();
3291
3295 .arg(update ? " updating in file" : "");
3296
3297 size_t leases = 0;
3298 size_t modified = 0;
3299 size_t updated = 0;
3300 size_t processed = 0;
3301 auto& index = storage4_.get<AddressIndexTag>();
3302 auto lease_it = index.begin();
3303 auto next_it = index.end();
3304
3305 for (; lease_it != index.end(); lease_it = next_it) {
3306 next_it = std::next(lease_it);
3307 Lease4Ptr lease = *lease_it;
3308 ++leases;
3309 try {
3310 if (upgradeLease4ExtendedInfo(lease, check)) {
3311 ++modified;
3312 if (update && persistLeases(V4)) {
3313 lease_file4_->append(*lease);
3314 ++updated;
3315 }
3316 }
3317 // Work on a copy as the multi-index requires fields used
3318 // as indexes to be read-only.
3319 Lease4Ptr copy(new Lease4(*lease));
3321 if (!copy->relay_id_.empty() || !copy->remote_id_.empty()) {
3322 index.replace(lease_it, copy);
3323 ++processed;
3324 }
3325 } catch (const std::exception& ex) {
3328 .arg(lease->addr_.toText())
3329 .arg(ex.what());
3330 }
3331 }
3332
3334 .arg(leases)
3335 .arg(modified)
3336 .arg(updated)
3337 .arg(processed);
3338
3339 return (updated);
3340}
3341
3342size_t
3344 return (0);
3345}
3346
3347void
3349 CfgConsistencyPtr cfg = CfgMgr::instance().getStagingCfg()->getConsistency();
3350 if (!cfg) {
3351 isc_throw(Unexpected, "the staging consistency configuration is null");
3352 }
3353 auto check = cfg->getExtendedInfoSanityCheck();
3354 bool enabled = getExtendedInfoTablesEnabled();
3355
3359 .arg(enabled ? "enabled" : "disabled");
3360
3361 // Clear tables when enabled.
3362 if (enabled) {
3363 relay_id6_.clear();
3364 remote_id6_.clear();
3365 }
3366
3367 size_t leases = 0;
3368 size_t modified = 0;
3369 size_t processed = 0;
3370
3371 for (auto const& lease : storage6_) {
3372 ++leases;
3373 try {
3374 if (upgradeLease6ExtendedInfo(lease, check)) {
3375 ++modified;
3376 }
3377 if (enabled && addExtendedInfo6(lease)) {
3378 ++processed;
3379 }
3380 } catch (const std::exception& ex) {
3383 .arg(lease->addr_.toText())
3384 .arg(ex.what());
3385 }
3386 }
3387
3389 .arg(leases)
3390 .arg(modified)
3391 .arg(processed);
3392}
3393
3394size_t
3396 return (0);
3397}
3398
3399void
3401 LeaseAddressRelayIdIndex& relay_id_idx =
3403 static_cast<void>(relay_id_idx.erase(addr));
3404 LeaseAddressRemoteIdIndex& remote_id_idx =
3406 static_cast<void>(remote_id_idx.erase(addr));
3407}
3408
3409void
3411 const std::vector<uint8_t>& relay_id) {
3412 Lease6ExtendedInfoPtr ex_info;
3413 ex_info.reset(new Lease6ExtendedInfo(lease_addr, relay_id));
3414 relay_id6_.insert(ex_info);
3415}
3416
3417void
3419 const std::vector<uint8_t>& remote_id) {
3420 Lease6ExtendedInfoPtr ex_info;
3421 ex_info.reset(new Lease6ExtendedInfo(lease_addr, remote_id));
3422 remote_id6_.insert(ex_info);
3423}
3424
3425void
3426Memfile_LeaseMgr::writeLeases4(const std::string& filename) {
3427 if (MultiThreadingMgr::instance().getMode()) {
3428 std::lock_guard<std::mutex> lock(*mutex_);
3429 writeLeases4Internal(filename);
3430 } else {
3431 writeLeases4Internal(filename);
3432 }
3433}
3434
3435void
3436Memfile_LeaseMgr::writeLeases4Internal(const std::string& filename) {
3437 bool overwrite = (lease_file4_ && lease_file4_->getFilename() == filename);
3438 try {
3439 if (overwrite) {
3440 lease_file4_->close();
3441 }
3442 std::ostringstream old;
3443 old << filename << ".bak" << getpid();
3444 ::rename(filename.c_str(), old.str().c_str());
3445 CSVLeaseFile4 backup(filename);
3446 backup.open();
3447 for (auto const& lease : storage4_) {
3448 backup.append(*lease);
3449 }
3450 backup.close();
3451 if (overwrite) {
3452 lease_file4_->open(true);
3453 }
3454 } catch (const std::exception&) {
3455 if (overwrite) {
3456 lease_file4_->open(true);
3457 }
3458 throw;
3459 }
3460}
3461
3462void
3463Memfile_LeaseMgr::writeLeases6(const std::string& filename) {
3464 if (MultiThreadingMgr::instance().getMode()) {
3465 std::lock_guard<std::mutex> lock(*mutex_);
3466 writeLeases6Internal(filename);
3467 } else {
3468 writeLeases6Internal(filename);
3469 }
3470}
3471
3472void
3473Memfile_LeaseMgr::writeLeases6Internal(const std::string& filename) {
3474 bool overwrite = (lease_file6_ && lease_file6_->getFilename() == filename);
3475 try {
3476 if (overwrite) {
3477 lease_file6_->close();
3478 }
3479 std::ostringstream old;
3480 old << filename << ".bak" << getpid();
3481 ::rename(filename.c_str(), old.str().c_str());
3482 CSVLeaseFile6 backup(filename);
3483 backup.open();
3484 for (auto const& lease : storage6_) {
3485 backup.append(*lease);
3486 }
3487 backup.close();
3488 if (overwrite) {
3489 lease_file6_->open(true);
3490 }
3491 } catch (const std::exception&) {
3492 if (overwrite) {
3493 lease_file6_->open(true);
3494 }
3495 throw;
3496 }
3497}
3498
3501 try {
3504 return (TrackingLeaseMgrPtr(new Memfile_LeaseMgr(parameters)));
3505 } catch (const std::exception& ex) {
3507 .arg(ex.what());
3508 throw;
3509 }
3510}
3511
3512} // namespace dhcp
3513} // namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown when an unexpected error condition occurs.
std::string getParameter(const std::string &name) const
Returns value of a connection parameter.
static std::string redactedAccessString(const ParameterMap &parameters)
Redact database access string.
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Invalid address family used as input to Lease Manager.
Provides methods to access CSV file with DHCPv4 leases.
Provides methods to access CSV file with DHCPv6 leases.
static std::string sanityCheckToText(LeaseSanity check_type)
Converts lease sanity check value to printable text.
uint16_t getFamily() const
Returns address family.
Definition cfgmgr.h:246
std::string validatePath(const std::string data_path) const
Validates a file path against the supported directory for DHDP data.
Definition cfgmgr.cc:40
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition cfgmgr.cc:121
std::string getDataDir(bool reset=false, const std::string explicit_path="")
Fetches the supported DHCP data directory.
Definition cfgmgr.cc:35
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition cfgmgr.cc:116
void addLease(LeasePtr lease)
Increment the counts for all of a lease's classes by one.
Holds Client identifier or client IPv4 address.
Definition duid.h:222
const std::vector< uint8_t > & getClientId() const
Returns reference to the client-id data.
Definition duid.cc:69
Holds DUID (DHCPv6 Unique Identifier)
Definition duid.h:142
const std::vector< uint8_t > & getDuid() const
Returns a const reference to the actual DUID value.
Definition duid.cc:33
std::string toText() const
Returns textual representation of the identifier (e.g.
Definition duid.h:88
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.
static void load(LeaseFileType &lease_file, StorageType &storage, const uint32_t max_errors=0, const bool close_file_on_exit=true)
Load leases from the lease file into the specified storage.
void setExtendedInfoTablesEnabled(const bool enabled)
Modifies the setting whether the lease6 extended info tables are enabled.
Definition lease_mgr.h:1020
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:776
bool getExtendedInfoTablesEnabled() const
Returns the setting indicating if lease6 extended info tables are enabled.
Definition lease_mgr.h:1012
static void extractLease4ExtendedInfo(const Lease4Ptr &lease, bool ignore_errors=true)
Extract relay and remote identifiers from the extended info.
static bool upgradeLease4ExtendedInfo(const Lease4Ptr &lease, CfgConsistency::ExtendedInfoSanity check=CfgConsistency::EXTENDED_INFO_CHECK_FIX)
The following queries are used to fulfill Bulk Lease Query queries.
Definition lease_mgr.cc:555
virtual bool addExtendedInfo6(const Lease6Ptr &lease)
Extract extended info from a lease6 and add it into tables.
Wraps value holding size of the page with leases.
Definition lease_mgr.h:46
const size_t page_size_
Holds page size.
Definition lease_mgr.h:56
LeaseStatsQuery(const SelectMode &select_mode=ALL_SUBNETS)
Constructor to query statistics for all subnets.
Definition lease_mgr.cc:220
SubnetID getLastSubnetID() const
Returns the value of last subnet ID specified (or zero)
Definition lease_mgr.h:209
SubnetID getFirstSubnetID() const
Returns the value of first subnet ID specified (or zero)
Definition lease_mgr.h:204
SelectMode getSelectMode() const
Returns the selection criteria mode The value returned is based upon the constructor variant used and...
Definition lease_mgr.h:216
SelectMode
Defines the types of selection criteria supported.
Definition lease_mgr.h:152
Memfile derivation of the IPv4 statistical lease data query.
MemfileLeaseStatsQuery4(Lease4Storage &storage4, const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for a subnet range query.
MemfileLeaseStatsQuery4(Lease4Storage &storage4, const SelectMode &select_mode=ALL_SUBNETS)
Constructor for an all subnets query.
virtual ~MemfileLeaseStatsQuery4()
Destructor.
void start()
Creates the IPv4 lease statistical data result set.
MemfileLeaseStatsQuery4(Lease4Storage &storage4, const SubnetID &subnet_id)
Constructor for a single subnet query.
Memfile derivation of the IPv6 statistical lease data query.
void start()
Creates the IPv6 lease statistical data result set.
virtual ~MemfileLeaseStatsQuery6()
Destructor.
MemfileLeaseStatsQuery6(Lease6Storage &storage6, const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for a subnet range query.
MemfileLeaseStatsQuery6(Lease6Storage &storage6, const SelectMode &select_mode=ALL_SUBNETS)
Constructor.
MemfileLeaseStatsQuery6(Lease6Storage &storage6, const SubnetID &subnet_id)
Constructor for a single subnet query.
std::vector< LeaseStatsRow >::iterator next_pos_
An iterator for accessing the next row within the result set.
MemfileLeaseStatsQuery(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Constructor for subnet range query.
virtual bool getNextRow(LeaseStatsRow &row)
Fetches the next row in the result set.
std::vector< LeaseStatsRow > rows_
A vector containing the "result set".
MemfileLeaseStatsQuery(const SelectMode &select_mode=ALL_SUBNETS)
Constructor for all subnets query.
virtual ~MemfileLeaseStatsQuery()
Destructor.
int getRowCount() const
Returns the number of rows in the result set.
MemfileLeaseStatsQuery(const SubnetID &subnet_id)
Constructor for single subnet query.
Lease6ExtendedInfoRemoteIdTable remote_id6_
stores IPv6 by-remote-id cross-reference table
virtual void rollback() override
Rollback Transactions.
size_t extractExtendedInfo4(bool update, bool current)
Extract extended info for v4 leases.
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery6(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id) override
Creates and runs the IPv6 lease stats query for a single subnet.
virtual void clearClassLeaseCounts() override
Clears the class-lease count map.
virtual size_t byRelayId6size() const override
Return the by-relay-id table size.
virtual 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)
static TrackingLeaseMgrPtr factory(const isc::db::DatabaseConnection::ParameterMap &parameters)
Factory class method.
LFCFileType
Types of the lease files used by the Lease File Cleanup.
@ FILE_PREVIOUS
Previous Lease File.
virtual bool deleteLease(const Lease4Ptr &lease) override
Deletes an IPv4 lease.
virtual void commit() override
Commit Transactions.
virtual size_t wipeLeases6(const SubnetID &subnet_id) override
Removed specified IPv6 leases.
virtual std::pair< uint32_t, uint32_t > getVersion(const std::string &timer_name=std::string()) const override
Returns backend version.
int getLFCExitStatus() const
Returns the status code returned by the last executed LFC process.
virtual LeaseStatsQueryPtr startPoolLeaseStatsQuery6() override
Creates and runs the IPv6 lease stats query for all subnets and pools.
bool persistLeases(Universe u) const
Specifies whether or not leases are written to disk.
virtual void addRemoteId6(const isc::asiolink::IOAddress &lease_addr, const std::vector< uint8_t > &remote_id) override
Add lease6 extended info into by-remote-id table.
static std::string getDBVersion()
Return extended version info.
virtual Lease4Collection getLeases4() const override
Returns all IPv4 leases.
virtual size_t getClassLeaseCount(const ClientClass &client_class, const Lease::Type &ltype=Lease::TYPE_V4) const override
Returns the class lease count for a given class and lease type.
virtual 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.
std::string getDefaultLeaseFilePath(Universe u, const std::string filename="") const
Returns default path to the lease file.
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.
static std::string getDBVersionInternal(Universe const &u)
Local version of getDBVersion() class method.
virtual LeaseStatsQueryPtr startPoolLeaseStatsQuery4() override
Creates and runs the IPv4 lease stats query for all subnets and pools.
virtual std::string checkLimits6(isc::data::ConstElementPtr const &user_context) const override
Checks if the IPv6 lease limits set in the given user context are exceeded.
virtual LeaseStatsQueryPtr startLeaseStatsQuery6() override
Creates and runs the IPv6 lease stats query.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const override
Returns existing IPv4 lease for specified IPv4 address.
virtual ~Memfile_LeaseMgr()
Destructor (closes file)
virtual std::string checkLimits4(isc::data::ConstElementPtr const &user_context) const override
Checks if the IPv4 lease limits set in the given user context are exceeded.
boost::shared_ptr< CSVLeaseFile6 > lease_file6_
Holds the pointer to the DHCPv6 lease file IO.
virtual size_t upgradeExtendedInfo4(const LeasePageSize &page_size) override
Upgrade extended info (v4).
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs) override
Deletes all expired-reclaimed DHCPv6 leases.
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const override
Returns a collection of expired DHCPv4 leases.
Attempt to update lease that was not there.
Manages a pool of asynchronous interval timers.
Definition timer_mgr.h:62
void trackAddLease(const LeasePtr &lease)
Invokes the callbacks when a new lease is added.
void trackUpdateLease(const LeasePtr &lease)
Invokes the callbacks when a lease is updated.
void trackDeleteLease(const LeasePtr &lease)
Invokes the callbacks when a lease is deleted.
bool hasCallbacks() const
Checks if any callbacks have been registered.
static StatsMgr & instance()
Statistics Manager accessor method.
static std::string generateName(const std::string &context, Type index, const std::string &stat_name)
Generates statistic name in a given context.
RAII class creating a critical section.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
int version()
returns Kea hooks version.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
isc::data::ConstElementPtr get(const std::string &name) const
Returns a single statistic as a JSON structure.
static const int MINOR_VERSION_V4
the minor version of the v4 memfile backend
static const int MINOR_VERSION_V6
the minor version of the v6 memfile backend
int get(CalloutHandle &handle)
The gss-tsig-get command.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition macros.h:26
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition macros.h:14
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:43
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
const isc::log::MessageID DHCPSRV_MEMFILE_DB
Lease6Storage::index< ExpirationIndexTag >::type Lease6StorageExpirationIndex
DHCPv6 lease storage index by expiration time.
const isc::log::MessageID DHCPSRV_MEMFILE_CONVERTING_LEASE_FILES
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_SETUP
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES6_FINISHED
Lease6Storage::index< DuidIndexTag >::type Lease6StorageDuidIndex
DHCPv6 lease storage index by DUID.
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition lease.h:528
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition lease.h:693
boost::shared_ptr< LeaseStatsQuery > LeaseStatsQueryPtr
Defines a pointer to a LeaseStatsQuery.
Definition lease_mgr.h:233
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES4
Lease6Storage::index< SubnetIdPoolIdIndexTag >::type Lease6StorageSubnetIdPoolIdIndex
DHCPv6 lease storage index subnet-id and pool-id.
Lease6Storage::index< DuidIaidTypeIndexTag >::type Lease6StorageDuidIaidTypeIndex
DHCPv6 lease storage index by DUID, IAID, lease type.
boost::shared_ptr< TimerMgr > TimerMgrPtr
Type definition of the shared pointer to TimerMgr.
Definition timer_mgr.h:27
const isc::log::MessageID DHCPSRV_MEMFILE_GET_RELAYID4
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_RENAME_FAIL
const isc::log::MessageID DHCPSRV_MEMFILE_UPDATE_ADDR4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_SUBID6
Lease4Storage::index< ExpirationIndexTag >::type Lease4StorageExpirationIndex
DHCPv4 lease storage index by expiration time.
Lease6Storage::index< AddressIndexTag >::type Lease6StorageAddressIndex
DHCPv6 lease storage index by address.
const 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
std::unique_ptr< TrackingLeaseMgr > TrackingLeaseMgrPtr
TrackingLeaseMgr pointer.
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
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_ADDR4
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition lease.h:520
const isc::log::MessageID DHCPSRV_MEMFILE_GET_ADDR6
const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_CLIENTID
Lease4Storage::index< AddressIndexTag >::type Lease4StorageAddressIndex
DHCPv4 lease storage index by address.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_IAID_DUID
const isc::log::MessageID DHCPSRV_MEMFILE_GET6
const isc::log::MessageID DHCPSRV_MEMFILE_GET_REMOTEID4
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition lease.h:315
Lease6ExtendedInfoRemoteIdTable::index< LeaseAddressIndexTag >::type LeaseAddressRemoteIdIndex
Lease6 extended information by lease address index of by remote id table.
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition dhcpsrv_log.h:26
const isc::log::MessageID DHCPSRV_MEMFILE_FAILED_TO_OPEN
Lease6Storage::index< SubnetIdIndexTag >::type Lease6StorageSubnetIdIndex
DHCPv6 lease storage index by subnet-id.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID
boost::shared_ptr< Lease6ExtendedInfo > Lease6ExtendedInfoPtr
Pointer to a Lease6ExtendedInfo object.
const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_ADDR6
Lease6ExtendedInfoRemoteIdTable::index< RemoteIdIndexTag >::type RemoteIdIndex
Lease6 extended information by remote id index.
Lease4Storage::index< SubnetIdPoolIdIndexTag >::type Lease4StorageSubnetIdPoolIdIndex
DHCPv4 lease storage index subnet-id and pool-id.
Lease4Storage::index< RelayIdIndexTag >::type Lease4StorageRelayIdIndex
DHCPv4 lease storage index by relay-id.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_PAGE6
Defines the logger used by the top-level component of kea-lfc.
Tag for indexes by address.
Tag for indexes by client-id, subnet-id tuple.
Tag for indexes by DUID, IAID, lease type tuple.
Tag for index using DUID.
Tag for indexes by expiration time.
Hardware type that represents information from DHCPv4 packet.
Definition hwaddr.h:20
std::vector< uint8_t > hwaddr_
Definition hwaddr.h:98
std::string toText(bool include_htype=true) const
Returns textual representation of a hardware address (e.g.
Definition hwaddr.cc:51
Tag for indexes by HW address, subnet-id tuple.
Tag for index using hostname.
Structure that holds a lease for IPv4 address.
Definition lease.h:323
Structure that holds a lease for IPv6 address and/or prefix.
Definition lease.h:536
ExtendedInfoAction
Action on extended info tables.
Definition lease.h:573
@ ACTION_UPDATE
update extended info tables.
Definition lease.h:576
@ ACTION_DELETE
delete reference to the lease
Definition lease.h:575
@ ACTION_IGNORE
ignore extended info,
Definition lease.h:574
Tag for indexes by lease address.
Contains a single row of lease statistical data.
Definition lease_mgr.h:64
static const uint32_t STATE_DEFAULT
A lease in the default state.
Definition lease.h:69
static const uint32_t STATE_DECLINED
Declined lease.
Definition lease.h:72
Type
Type of lease or pool.
Definition lease.h:46
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
Definition lease.h:49
@ TYPE_V4
IPv4 lease.
Definition lease.h:50
@ TYPE_NA
the lease contains non-temporary IPv6 address
Definition lease.h:47
static const uint32_t STATE_REGISTERED
Registered self-generated lease.
Definition lease.h:81
static std::string typeToText(Type type)
returns text representation of a lease type
Definition lease.cc:56
Tag for index using relay-id.
Tag for index using remote-id.
Tag for indexes by subnet-id (and address for v6).