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