Kea 2.2.0
memfile_lease_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2022 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
10#include <dhcpsrv/cfgmgr.h>
12#include <dhcpsrv/dhcpsrv_log.h>
15#include <dhcpsrv/timer_mgr.h>
17#include <stats/stats_mgr.h>
19#include <util/pid_file.h>
20
21#include <cstdio>
22#include <cstring>
23#include <errno.h>
24#include <iostream>
25#include <limits>
26#include <sstream>
27
28namespace {
29
37const char* KEA_LFC_EXECUTABLE_ENV_NAME = "KEA_LFC_EXECUTABLE";
38
39} // namespace
40
41using namespace isc::asiolink;
42using namespace isc::data;
43using namespace isc::db;
44using namespace isc::util;
45using namespace isc::stats;
46
47namespace isc {
48namespace dhcp {
49
64class LFCSetup {
65public:
66
75
79 ~LFCSetup();
80
92 void setup(const uint32_t lfc_interval,
93 const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
94 const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
95 bool run_once_now = false);
96
98 void execute();
99
103 bool isRunning() const;
104
106 int getExitStatus() const;
107
108private:
109
112 boost::scoped_ptr<ProcessSpawn> process_;
113
116
118 pid_t pid_;
119
124 TimerMgrPtr timer_mgr_;
125};
126
128 : process_(), callback_(callback), pid_(0),
129 timer_mgr_(TimerMgr::instance()) {
130}
131
133 try {
134 // Remove the timer. This will throw an exception if the timer does not
135 // exist. There are several possible reasons for this:
136 // a) It hasn't been registered (although if the LFC Setup instance
137 // exists it means that the timer must have been registered or that
138 // such registration has been attempted).
139 // b) The registration may fail if the duplicate timer exists or if the
140 // TimerMgr's worker thread is running but if this happens it is a
141 // programming error.
142 // c) The program is shutting down and the timer has been removed by
143 // another component.
144 timer_mgr_->unregisterTimer("memfile-lfc");
145
146 } catch (const std::exception& ex) {
147 // We don't want exceptions being thrown from the destructor so we just
148 // log a message here. The message is logged at debug severity as
149 // we don't want an error message output during shutdown.
152 }
153}
154
155void
156LFCSetup::setup(const uint32_t lfc_interval,
157 const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
158 const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
159 bool run_once_now) {
160
161 // If to nothing to do, punt
162 if (lfc_interval == 0 && !run_once_now) {
163 return;
164 }
165
166 // Start preparing the command line for kea-lfc.
167 std::string executable;
168 char* c_executable = getenv(KEA_LFC_EXECUTABLE_ENV_NAME);
169 if (c_executable == NULL) {
170 executable = KEA_LFC_EXECUTABLE;
171 } else {
172 executable = c_executable;
173 }
174
175 // Gather the base file name.
176 std::string lease_file = lease_file4 ? lease_file4->getFilename() :
177 lease_file6->getFilename();
178
179 // Create the other names by appending suffixes to the base name.
180 ProcessArgs args;
181 // Universe: v4 or v6.
182 args.push_back(lease_file4 ? "-4" : "-6");
183
184 // Previous file.
185 args.push_back("-x");
186 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
188 // Input file.
189 args.push_back("-i");
190 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
192 // Output file.
193 args.push_back("-o");
194 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
196 // Finish file.
197 args.push_back("-f");
198 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
200 // PID file.
201 args.push_back("-p");
202 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
204
205 // The configuration file is currently unused.
206 args.push_back("-c");
207 args.push_back("ignored-path");
208
209 // Create the process (do not start it yet).
210 process_.reset(new ProcessSpawn(LeaseMgr::getIOService(), executable, args));
211
212 // If we've been told to run it once now, invoke the callback directly.
213 if (run_once_now) {
214 callback_();
215 }
216
217 // If it's supposed to run periodically, setup that now.
218 if (lfc_interval > 0) {
219 // Set the timer to call callback function periodically.
221
222 // Multiple the lfc_interval value by 1000 as this value specifies
223 // a timeout in seconds, whereas the setup() method expects the
224 // timeout in milliseconds.
225 timer_mgr_->registerTimer("memfile-lfc", callback_, lfc_interval * 1000,
227 timer_mgr_->setup("memfile-lfc");
228 }
229}
230
231void
233 try {
235 .arg(process_->getCommandLine());
236 pid_ = process_->spawn();
237
238 } catch (const ProcessSpawnError&) {
240 }
241}
242
243bool
245 return (process_ && process_->isRunning(pid_));
246}
247
248int
250 if (!process_) {
251 isc_throw(InvalidOperation, "unable to obtain LFC process exit code: "
252 " the process is NULL");
253 }
254 return (process_->getExitStatus(pid_));
255}
256
257
264public:
268 : rows_(0), next_pos_(rows_.end()) {
269 };
270
275 : LeaseStatsQuery(subnet_id), rows_(0), next_pos_(rows_.end()) {
276 };
277
282 MemfileLeaseStatsQuery(const SubnetID& first_subnet_id, const SubnetID& last_subnet_id)
283 : LeaseStatsQuery(first_subnet_id, last_subnet_id), rows_(0), next_pos_(rows_.end()) {
284 };
285
288
299 virtual bool getNextRow(LeaseStatsRow& row) {
300 if (next_pos_ == rows_.end()) {
301 return (false);
302 }
303
304 row = *next_pos_;
305 ++next_pos_;
306 return (true);
307 }
308
310 int getRowCount() const {
311 return (rows_.size());
312 }
313
314protected:
316 std::vector<LeaseStatsRow> rows_;
317
319 std::vector<LeaseStatsRow>::iterator next_pos_;
320};
321
332public:
337 : MemfileLeaseStatsQuery(), storage4_(storage4) {
338 };
339
344 MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& subnet_id)
345 : MemfileLeaseStatsQuery(subnet_id), storage4_(storage4) {
346 };
347
353 MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& first_subnet_id,
354 const SubnetID& last_subnet_id)
355 : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage4_(storage4) {
356 };
357
360
375 void start() {
377 = storage4_.get<SubnetIdIndexTag>();
378
379 // Set lower and upper bounds based on select mode
380 Lease4StorageSubnetIdIndex::const_iterator lower;
381 Lease4StorageSubnetIdIndex::const_iterator upper;
382 switch (getSelectMode()) {
383 case ALL_SUBNETS:
384 lower = idx.begin();
385 upper = idx.end();
386 break;
387
388 case SINGLE_SUBNET:
389 lower = idx.lower_bound(getFirstSubnetID());
390 upper = idx.upper_bound(getFirstSubnetID());
391 break;
392
393 case SUBNET_RANGE:
394 lower = idx.lower_bound(getFirstSubnetID());
395 upper = idx.upper_bound(getLastSubnetID());
396 break;
397 }
398
399 // Return an empty set if there are no rows.
400 if (lower == upper) {
401 return;
402 }
403
404 // Iterate over the leases in order by subnet, accumulating per
405 // subnet counts for each state of interest. As we finish each
406 // subnet, add the appropriate rows to our result set.
407 SubnetID cur_id = 0;
408 int64_t assigned = 0;
409 int64_t declined = 0;
410 for (Lease4StorageSubnetIdIndex::const_iterator lease = lower;
411 lease != upper; ++lease) {
412 // If we've hit the next subnet, add rows for the current subnet
413 // and wipe the accumulators
414 if ((*lease)->subnet_id_ != cur_id) {
415 if (cur_id > 0) {
416 if (assigned > 0) {
417 rows_.push_back(LeaseStatsRow(cur_id,
419 assigned));
420 assigned = 0;
421 }
422
423 if (declined > 0) {
424 rows_.push_back(LeaseStatsRow(cur_id,
426 declined));
427 declined = 0;
428 }
429 }
430
431 // Update current subnet id
432 cur_id = (*lease)->subnet_id_;
433 }
434
435 // Bump the appropriate accumulator
436 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
437 ++assigned;
438 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
439 ++declined;
440 }
441 }
442
443 // Make the rows for last subnet
444 if (assigned > 0) {
445 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
446 assigned));
447 }
448
449 if (declined > 0) {
450 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
451 declined));
452 }
453
454 // Reset the next row position back to the beginning of the rows.
455 next_pos_ = rows_.begin();
456 }
457
458private:
460 Lease4Storage& storage4_;
461};
462
463
474public:
479 : MemfileLeaseStatsQuery(), storage6_(storage6) {
480 };
481
486 MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& subnet_id)
487 : MemfileLeaseStatsQuery(subnet_id), storage6_(storage6) {
488 };
489
495 MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& first_subnet_id,
496 const SubnetID& last_subnet_id)
497 : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage6_(storage6) {
498 };
499
502
516 virtual void start() {
517 // Get the subnet_id index
519 = storage6_.get<SubnetIdIndexTag>();
520
521 // Set lower and upper bounds based on select mode
522 Lease6StorageSubnetIdIndex::const_iterator lower;
523 Lease6StorageSubnetIdIndex::const_iterator upper;
524 switch (getSelectMode()) {
525 case ALL_SUBNETS:
526 lower = idx.begin();
527 upper = idx.end();
528 break;
529
530 case SINGLE_SUBNET:
531 lower = idx.lower_bound(getFirstSubnetID());
532 upper = idx.upper_bound(getFirstSubnetID());
533 break;
534
535 case SUBNET_RANGE:
536 lower = idx.lower_bound(getFirstSubnetID());
537 upper = idx.upper_bound(getLastSubnetID());
538 break;
539 }
540
541 // Return an empty set if there are no rows.
542 if (lower == upper) {
543 return;
544 }
545
546 // Iterate over the leases in order by subnet, accumulating per
547 // subnet counts for each state of interest. As we finish each
548 // subnet, add the appropriate rows to our result set.
549 SubnetID cur_id = 0;
550 int64_t assigned = 0;
551 int64_t declined = 0;
552 int64_t assigned_pds = 0;
553 for (Lease6StorageSubnetIdIndex::const_iterator lease = lower;
554 lease != upper; ++lease) {
555 // If we've hit the next subnet, add rows for the current subnet
556 // and wipe the accumulators
557 if ((*lease)->subnet_id_ != cur_id) {
558 if (cur_id > 0) {
559 if (assigned > 0) {
560 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
562 assigned));
563 assigned = 0;
564 }
565
566 if (declined > 0) {
567 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
569 declined));
570 declined = 0;
571 }
572
573 if (assigned_pds > 0) {
574 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
576 assigned_pds));
577 assigned_pds = 0;
578 }
579 }
580
581 // Update current subnet id
582 cur_id = (*lease)->subnet_id_;
583 }
584
585 // Bump the appropriate accumulator
586 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
587 switch((*lease)->type_) {
588 case Lease::TYPE_NA:
589 ++assigned;
590 break;
591 case Lease::TYPE_PD:
592 ++assigned_pds;
593 break;
594 default:
595 break;
596 }
597 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
598 // In theory only NAs can be declined
599 if (((*lease)->type_) == Lease::TYPE_NA) {
600 ++declined;
601 }
602 }
603 }
604
605 // Make the rows for last subnet, unless there were no rows
606 if (assigned > 0) {
607 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
608 Lease::STATE_DEFAULT, assigned));
609 }
610
611 if (declined > 0) {
612 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
613 Lease::STATE_DECLINED, declined));
614 }
615
616 if (assigned_pds > 0) {
617 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
618 Lease::STATE_DEFAULT, assigned_pds));
619 }
620
621 // Set the next row position to the beginning of the rows.
622 next_pos_ = rows_.begin();
623 }
624
625private:
627 Lease6Storage& storage6_;
628};
629
630// Explicit definition of class static constants. Values are given in the
631// declaration so they're not needed here.
636
638 : LeaseMgr(), lfc_setup_(), conn_(parameters), mutex_(new std::mutex) {
639 bool conversion_needed = false;
640
641 // Check the universe and use v4 file or v6 file.
642 std::string universe = conn_.getParameter("universe");
643 if (universe == "4") {
644 std::string file4 = initLeaseFilePath(V4);
645 if (!file4.empty()) {
646 conversion_needed = loadLeasesFromFiles<Lease4,
647 CSVLeaseFile4>(file4,
648 lease_file4_,
649 storage4_);
650 }
651 } else {
652 std::string file6 = initLeaseFilePath(V6);
653 if (!file6.empty()) {
654 conversion_needed = loadLeasesFromFiles<Lease6,
655 CSVLeaseFile6>(file6,
656 lease_file6_,
657 storage6_);
658 }
659 }
660
661 // If lease persistence have been disabled for both v4 and v6,
662 // issue a warning. It is ok not to write leases to disk when
663 // doing testing, but it should not be done in normal server
664 // operation.
665 if (!persistLeases(V4) && !persistLeases(V6)) {
667 } else {
668 if (conversion_needed) {
669 auto const& version(getVersion());
671 .arg(version.first).arg(version.second);
672 }
673 lfcSetup(conversion_needed);
674 }
675}
676
678 if (lease_file4_) {
679 lease_file4_->close();
680 lease_file4_.reset();
681 }
682 if (lease_file6_) {
683 lease_file6_->close();
684 lease_file6_.reset();
685 }
686}
687
688std::string
690 std::stringstream tmp;
691 tmp << "Memfile backend ";
692 if (u == V4) {
693 tmp << MAJOR_VERSION_V4 << "." << MINOR_VERSION_V4;
694 } else if (u == V6) {
695 tmp << MAJOR_VERSION_V6 << "." << MINOR_VERSION_V6;
696 }
697 return tmp.str();
698}
699
700bool
701Memfile_LeaseMgr::addLeaseInternal(const Lease4Ptr& lease) {
702 if (getLease4Internal(lease->addr_)) {
703 // there is a lease with specified address already
704 return (false);
705 }
706
707 // Try to write a lease to disk first. If this fails, the lease will
708 // not be inserted to the memory and the disk and in-memory data will
709 // remain consistent.
710 if (persistLeases(V4)) {
711 lease_file4_->append(*lease);
712 }
713
714 storage4_.insert(lease);
715
716 // Update lease current expiration time (allows update between the creation
717 // of the Lease up to the point of insertion in the database).
718 lease->updateCurrentExpirationTime();
719
720 // Increment class lease counters.
721 class_lease_counter_.addLease(lease);
722
723 return (true);
724}
725
726bool
729 DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
730
731 if (MultiThreadingMgr::instance().getMode()) {
732 std::lock_guard<std::mutex> lock(*mutex_);
733 return (addLeaseInternal(lease));
734 } else {
735 return (addLeaseInternal(lease));
736 }
737}
738
739bool
740Memfile_LeaseMgr::addLeaseInternal(const Lease6Ptr& lease) {
741 if (getLease6Internal(lease->type_, lease->addr_)) {
742 // there is a lease with specified address already
743 return (false);
744 }
745
746 // Try to write a lease to disk first. If this fails, the lease will
747 // not be inserted to the memory and the disk and in-memory data will
748 // remain consistent.
749 if (persistLeases(V6)) {
750 lease_file6_->append(*lease);
751 }
752
753 storage6_.insert(lease);
754
755 // Update lease current expiration time (allows update between the creation
756 // of the Lease up to the point of insertion in the database).
757 lease->updateCurrentExpirationTime();
758
759 // Increment class lease counters.
760 class_lease_counter_.addLease(lease);
761
762 return (true);
763}
764
765bool
768 DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
769
770 if (MultiThreadingMgr::instance().getMode()) {
771 std::lock_guard<std::mutex> lock(*mutex_);
772 return (addLeaseInternal(lease));
773 } else {
774 return (addLeaseInternal(lease));
775 }
776}
777
779Memfile_LeaseMgr::getLease4Internal(const isc::asiolink::IOAddress& addr) const {
780 const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
781 Lease4StorageAddressIndex::iterator l = idx.find(addr);
782 if (l == idx.end()) {
783 return (Lease4Ptr());
784 } else {
785 return (Lease4Ptr(new Lease4(**l)));
786 }
787}
788
793
794 if (MultiThreadingMgr::instance().getMode()) {
795 std::lock_guard<std::mutex> lock(*mutex_);
796 return (getLease4Internal(addr));
797 } else {
798 return (getLease4Internal(addr));
799 }
800}
801
802void
803Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
804 Lease4Collection& collection) const {
805 // Using composite index by 'hw address' and 'subnet id'. It is
806 // ok to use it for searching by the 'hw address' only.
808 storage4_.get<HWAddressSubnetIdIndexTag>();
809 std::pair<Lease4StorageHWAddressSubnetIdIndex::const_iterator,
810 Lease4StorageHWAddressSubnetIdIndex::const_iterator> l
811 = idx.equal_range(boost::make_tuple(hwaddr.hwaddr_));
812
813 for (auto lease = l.first; lease != l.second; ++lease) {
814 collection.push_back(Lease4Ptr(new Lease4(**lease)));
815 }
816}
817
821 DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.toText());
822
823 Lease4Collection collection;
824 if (MultiThreadingMgr::instance().getMode()) {
825 std::lock_guard<std::mutex> lock(*mutex_);
826 getLease4Internal(hwaddr, collection);
827 } else {
828 getLease4Internal(hwaddr, collection);
829 }
830
831 return (collection);
832}
833
835Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
836 SubnetID subnet_id) const {
837 // Get the index by HW Address and Subnet Identifier.
839 storage4_.get<HWAddressSubnetIdIndexTag>();
840 // Try to find the lease using HWAddr and subnet id.
841 Lease4StorageHWAddressSubnetIdIndex::const_iterator lease =
842 idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
843 // Lease was not found. Return empty pointer to the caller.
844 if (lease == idx.end()) {
845 return (Lease4Ptr());
846 }
847
848 // Lease was found. Return it to the caller.
849 return (Lease4Ptr(new Lease4(**lease)));
850}
851
854 SubnetID subnet_id) const {
857 .arg(hwaddr.toText());
858
859 if (MultiThreadingMgr::instance().getMode()) {
860 std::lock_guard<std::mutex> lock(*mutex_);
861 return (getLease4Internal(hwaddr, subnet_id));
862 } else {
863 return (getLease4Internal(hwaddr, subnet_id));
864 }
865}
866
867void
868Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
869 Lease4Collection& collection) const {
870 // Using composite index by 'client id' and 'subnet id'. It is ok
871 // to use it to search by 'client id' only.
873 storage4_.get<ClientIdSubnetIdIndexTag>();
874 std::pair<Lease4StorageClientIdSubnetIdIndex::const_iterator,
875 Lease4StorageClientIdSubnetIdIndex::const_iterator> l
876 = idx.equal_range(boost::make_tuple(client_id.getClientId()));
877
878 for (auto lease = l.first; lease != l.second; ++lease) {
879 collection.push_back(Lease4Ptr(new Lease4(**lease)));
880 }
881}
882
884Memfile_LeaseMgr::getLease4(const ClientId& client_id) const {
886 DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.toText());
887
888 Lease4Collection collection;
889 if (MultiThreadingMgr::instance().getMode()) {
890 std::lock_guard<std::mutex> lock(*mutex_);
891 getLease4Internal(client_id, collection);
892 } else {
893 getLease4Internal(client_id, collection);
894 }
895
896 return (collection);
897}
898
900Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
901 SubnetID subnet_id) const {
902 // Get the index by client and subnet id.
904 storage4_.get<ClientIdSubnetIdIndexTag>();
905 // Try to get the lease using client id and subnet id.
906 Lease4StorageClientIdSubnetIdIndex::const_iterator lease =
907 idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
908 // Lease was not found. Return empty pointer to the caller.
909 if (lease == idx.end()) {
910 return (Lease4Ptr());
911 }
912 // Lease was found. Return it to the caller.
913 return (Lease4Ptr(new Lease4(**lease)));
914}
915
918 SubnetID subnet_id) const {
921 .arg(client_id.toText());
922
923 if (MultiThreadingMgr::instance().getMode()) {
924 std::lock_guard<std::mutex> lock(*mutex_);
925 return (getLease4Internal(client_id, subnet_id));
926 } else {
927 return (getLease4Internal(client_id, subnet_id));
928 }
929}
930
931void
932Memfile_LeaseMgr::getLeases4Internal(SubnetID subnet_id,
933 Lease4Collection& collection) const {
934 const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
935 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
936 Lease4StorageSubnetIdIndex::const_iterator> l =
937 idx.equal_range(subnet_id);
938
939 for (auto lease = l.first; lease != l.second; ++lease) {
940 collection.push_back(Lease4Ptr(new Lease4(**lease)));
941 }
942}
943
947 .arg(subnet_id);
948
949 Lease4Collection collection;
950 if (MultiThreadingMgr::instance().getMode()) {
951 std::lock_guard<std::mutex> lock(*mutex_);
952 getLeases4Internal(subnet_id, collection);
953 } else {
954 getLeases4Internal(subnet_id, collection);
955 }
956
957 return (collection);
958}
959
960void
961Memfile_LeaseMgr::getLeases4Internal(const std::string& hostname,
962 Lease4Collection& collection) const {
963 const Lease4StorageHostnameIndex& idx = storage4_.get<HostnameIndexTag>();
964 std::pair<Lease4StorageHostnameIndex::const_iterator,
965 Lease4StorageHostnameIndex::const_iterator> l =
966 idx.equal_range(hostname);
967
968 for (auto lease = l.first; lease != l.second; ++lease) {
969 collection.push_back(Lease4Ptr(new Lease4(**lease)));
970 }
971}
972
974Memfile_LeaseMgr::getLeases4(const std::string& hostname) const {
976 .arg(hostname);
977
978 Lease4Collection collection;
979 if (MultiThreadingMgr::instance().getMode()) {
980 std::lock_guard<std::mutex> lock(*mutex_);
981 getLeases4Internal(hostname, collection);
982 } else {
983 getLeases4Internal(hostname, collection);
984 }
985
986 return (collection);
987}
988
989void
990Memfile_LeaseMgr::getLeases4Internal(Lease4Collection& collection) const {
991 for (auto lease = storage4_.begin(); lease != storage4_.end(); ++lease) {
992 collection.push_back(Lease4Ptr(new Lease4(**lease)));
993 }
994}
995
999
1000 Lease4Collection collection;
1001 if (MultiThreadingMgr::instance().getMode()) {
1002 std::lock_guard<std::mutex> lock(*mutex_);
1003 getLeases4Internal(collection);
1004 } else {
1005 getLeases4Internal(collection);
1006 }
1007
1008 return (collection);
1009}
1010
1011void
1012Memfile_LeaseMgr::getLeases4Internal(const asiolink::IOAddress& lower_bound_address,
1013 const LeasePageSize& page_size,
1014 Lease4Collection& collection) const {
1015 const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
1016 Lease4StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1017
1018 // Exclude the lower bound address specified by the caller.
1019 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1020 ++lb;
1021 }
1022
1023 // Return all other leases being within the page size.
1024 for (auto lease = lb;
1025 (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1026 ++lease) {
1027 collection.push_back(Lease4Ptr(new Lease4(**lease)));
1028 }
1029}
1030
1033 const LeasePageSize& page_size) const {
1034 // Expecting IPv4 address.
1035 if (!lower_bound_address.isV4()) {
1036 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
1037 "retrieving leases from the lease database, got "
1038 << lower_bound_address);
1039 }
1040
1042 .arg(page_size.page_size_)
1043 .arg(lower_bound_address.toText());
1044
1045 Lease4Collection collection;
1046 if (MultiThreadingMgr::instance().getMode()) {
1047 std::lock_guard<std::mutex> lock(*mutex_);
1048 getLeases4Internal(lower_bound_address, page_size, collection);
1049 } else {
1050 getLeases4Internal(lower_bound_address, page_size, collection);
1051 }
1052
1053 return (collection);
1054}
1055
1057Memfile_LeaseMgr::getLease6Internal(Lease::Type type,
1058 const isc::asiolink::IOAddress& addr) const {
1059 Lease6Storage::iterator l = storage6_.find(addr);
1060 if (l == storage6_.end() || !(*l) || ((*l)->type_ != type)) {
1061 return (Lease6Ptr());
1062 } else {
1063 return (Lease6Ptr(new Lease6(**l)));
1064 }
1065}
1066
1069 const isc::asiolink::IOAddress& addr) const {
1072 .arg(addr.toText())
1073 .arg(Lease::typeToText(type));
1074
1075 if (MultiThreadingMgr::instance().getMode()) {
1076 std::lock_guard<std::mutex> lock(*mutex_);
1077 return (getLease6Internal(type, addr));
1078 } else {
1079 return (getLease6Internal(type, addr));
1080 }
1081}
1082
1083void
1084Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1085 const DUID& duid,
1086 uint32_t iaid,
1087 Lease6Collection& collection) const {
1088 // Get the index by DUID, IAID, lease type.
1089 const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1090 // Try to get the lease using the DUID, IAID and lease type.
1091 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1092 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1093 idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1094
1095 for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1096 l.first; lease != l.second; ++lease) {
1097 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1098 }
1099}
1100
1103 const DUID& duid,
1104 uint32_t iaid) const {
1107 .arg(iaid)
1108 .arg(duid.toText())
1109 .arg(Lease::typeToText(type));
1110
1111 Lease6Collection collection;
1112 if (MultiThreadingMgr::instance().getMode()) {
1113 std::lock_guard<std::mutex> lock(*mutex_);
1114 getLeases6Internal(type, duid, iaid, collection);
1115 } else {
1116 getLeases6Internal(type, duid, iaid, collection);
1117 }
1118
1119 return (collection);
1120}
1121
1122void
1123Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1124 const DUID& duid,
1125 uint32_t iaid,
1126 SubnetID subnet_id,
1127 Lease6Collection& collection) const {
1128 // Get the index by DUID, IAID, lease type.
1129 const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1130 // Try to get the lease using the DUID, IAID and lease type.
1131 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1132 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1133 idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1134
1135 for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1136 l.first; lease != l.second; ++lease) {
1137 // Filter out the leases which subnet id doesn't match.
1138 if ((*lease)->subnet_id_ == subnet_id) {
1139 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1140 }
1141 }
1142}
1143
1146 const DUID& duid,
1147 uint32_t iaid,
1148 SubnetID subnet_id) const {
1151 .arg(iaid)
1152 .arg(subnet_id)
1153 .arg(duid.toText())
1154 .arg(Lease::typeToText(type));
1155
1156 Lease6Collection collection;
1157 if (MultiThreadingMgr::instance().getMode()) {
1158 std::lock_guard<std::mutex> lock(*mutex_);
1159 getLeases6Internal(type, duid, iaid, subnet_id, collection);
1160 } else {
1161 getLeases6Internal(type, duid, iaid, subnet_id, collection);
1162 }
1163
1164 return (collection);
1165}
1166
1167void
1168Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1169 Lease6Collection& collection) const {
1170 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1171 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
1172 Lease6StorageSubnetIdIndex::const_iterator> l =
1173 idx.equal_range(subnet_id);
1174
1175 for (auto lease = l.first; lease != l.second; ++lease) {
1176 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1177 }
1178}
1179
1183 .arg(subnet_id);
1184
1185 Lease6Collection collection;
1186 if (MultiThreadingMgr::instance().getMode()) {
1187 std::lock_guard<std::mutex> lock(*mutex_);
1188 getLeases6Internal(subnet_id, collection);
1189 } else {
1190 getLeases6Internal(subnet_id, collection);
1191 }
1192
1193 return (collection);
1194}
1195
1196void
1197Memfile_LeaseMgr::getLeases6Internal(const std::string& hostname,
1198 Lease6Collection& collection) const {
1199 const Lease6StorageHostnameIndex& idx = storage6_.get<HostnameIndexTag>();
1200 std::pair<Lease6StorageHostnameIndex::const_iterator,
1201 Lease6StorageHostnameIndex::const_iterator> l =
1202 idx.equal_range(hostname);
1203
1204 for (auto lease = l.first; lease != l.second; ++lease) {
1205 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1206 }
1207}
1208
1210Memfile_LeaseMgr::getLeases6(const std::string& hostname) const {
1212 .arg(hostname);
1213
1214 Lease6Collection collection;
1215 if (MultiThreadingMgr::instance().getMode()) {
1216 std::lock_guard<std::mutex> lock(*mutex_);
1217 getLeases6Internal(hostname, collection);
1218 } else {
1219 getLeases6Internal(hostname, collection);
1220 }
1221
1222 return (collection);
1223}
1224
1225void
1226Memfile_LeaseMgr::getLeases6Internal(Lease6Collection& collection) const {
1227 for (auto lease = storage6_.begin(); lease != storage6_.end(); ++lease) {
1228 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1229 }
1230}
1231
1235
1236 Lease6Collection collection;
1237 if (MultiThreadingMgr::instance().getMode()) {
1238 std::lock_guard<std::mutex> lock(*mutex_);
1239 getLeases6Internal(collection);
1240 } else {
1241 getLeases6Internal(collection);
1242 }
1243
1244 return (collection);
1245}
1246
1247void
1248Memfile_LeaseMgr::getLeases6Internal(const DUID& duid,
1249 Lease6Collection& collection) const {
1250 const Lease6StorageDuidIndex& idx = storage6_.get<DuidIndexTag>();
1251 std::pair<Lease6StorageDuidIndex::const_iterator,
1252 Lease6StorageDuidIndex::const_iterator> l =
1253 idx.equal_range(duid.getDuid());
1254
1255 for (auto lease = l.first; lease != l.second; ++lease) {
1256 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1257 }
1258}
1259
1263 .arg(duid.toText());
1264
1265 Lease6Collection collection;
1266 if (MultiThreadingMgr::instance().getMode()) {
1267 std::lock_guard<std::mutex> lock(*mutex_);
1268 getLeases6Internal(duid, collection);
1269 } else {
1270 getLeases6Internal(duid, collection);
1271 }
1272
1273 return (collection);
1274}
1275
1276void
1277Memfile_LeaseMgr::getLeases6Internal(const asiolink::IOAddress& lower_bound_address,
1278 const LeasePageSize& page_size,
1279 Lease6Collection& collection) const {
1280 const Lease6StorageAddressIndex& idx = storage6_.get<AddressIndexTag>();
1281 Lease6StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1282
1283 // Exclude the lower bound address specified by the caller.
1284 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1285 ++lb;
1286 }
1287
1288 // Return all other leases being within the page size.
1289 for (auto lease = lb;
1290 (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1291 ++lease) {
1292 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1293 }
1294}
1295
1298 const LeasePageSize& page_size) const {
1299 // Expecting IPv6 address.
1300 if (!lower_bound_address.isV6()) {
1301 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1302 "retrieving leases from the lease database, got "
1303 << lower_bound_address);
1304 }
1305
1307 .arg(page_size.page_size_)
1308 .arg(lower_bound_address.toText());
1309
1310 Lease6Collection collection;
1311 if (MultiThreadingMgr::instance().getMode()) {
1312 std::lock_guard<std::mutex> lock(*mutex_);
1313 getLeases6Internal(lower_bound_address, page_size, collection);
1314 } else {
1315 getLeases6Internal(lower_bound_address, page_size, collection);
1316 }
1317
1318 return (collection);
1319}
1320
1321void
1322Memfile_LeaseMgr::getExpiredLeases4Internal(Lease4Collection& expired_leases,
1323 const size_t max_leases) const {
1324 // Obtain the index which segragates leases by state and time.
1325 const Lease4StorageExpirationIndex& index = storage4_.get<ExpirationIndexTag>();
1326
1327 // Retrieve leases which are not reclaimed and which haven't expired. The
1328 // 'less-than' operator will be used for both components of the index. So,
1329 // for the 'state' 'false' is less than 'true'. Also the leases with
1330 // expiration time lower than current time will be returned.
1331 Lease4StorageExpirationIndex::const_iterator ub =
1332 index.upper_bound(boost::make_tuple(false, time(NULL)));
1333
1334 // Copy only the number of leases indicated by the max_leases parameter.
1335 for (Lease4StorageExpirationIndex::const_iterator lease = index.begin();
1336 (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1337 max_leases));
1338 ++lease) {
1339 expired_leases.push_back(Lease4Ptr(new Lease4(**lease)));
1340 }
1341}
1342
1343void
1345 const size_t max_leases) const {
1347 .arg(max_leases);
1348
1349 if (MultiThreadingMgr::instance().getMode()) {
1350 std::lock_guard<std::mutex> lock(*mutex_);
1351 getExpiredLeases4Internal(expired_leases, max_leases);
1352 } else {
1353 getExpiredLeases4Internal(expired_leases, max_leases);
1354 }
1355}
1356
1357void
1358Memfile_LeaseMgr::getExpiredLeases6Internal(Lease6Collection& expired_leases,
1359 const size_t max_leases) const {
1360 // Obtain the index which segragates leases by state and time.
1361 const Lease6StorageExpirationIndex& index = storage6_.get<ExpirationIndexTag>();
1362
1363 // Retrieve leases which are not reclaimed and which haven't expired. The
1364 // 'less-than' operator will be used for both components of the index. So,
1365 // for the 'state' 'false' is less than 'true'. Also the leases with
1366 // expiration time lower than current time will be returned.
1367 Lease6StorageExpirationIndex::const_iterator ub =
1368 index.upper_bound(boost::make_tuple(false, time(NULL)));
1369
1370 // Copy only the number of leases indicated by the max_leases parameter.
1371 for (Lease6StorageExpirationIndex::const_iterator lease = index.begin();
1372 (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1373 max_leases));
1374 ++lease) {
1375 expired_leases.push_back(Lease6Ptr(new Lease6(**lease)));
1376 }
1377}
1378
1379void
1381 const size_t max_leases) const {
1383 .arg(max_leases);
1384
1385 if (MultiThreadingMgr::instance().getMode()) {
1386 std::lock_guard<std::mutex> lock(*mutex_);
1387 getExpiredLeases6Internal(expired_leases, max_leases);
1388 } else {
1389 getExpiredLeases6Internal(expired_leases, max_leases);
1390 }
1391}
1392
1393void
1394Memfile_LeaseMgr::updateLease4Internal(const Lease4Ptr& lease) {
1395 // Obtain 'by address' index.
1396 Lease4StorageAddressIndex& index = storage4_.get<AddressIndexTag>();
1397
1398 bool persist = persistLeases(V4);
1399
1400 // Lease must exist if it is to be updated.
1401 Lease4StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1402 if (lease_it == index.end()) {
1403 isc_throw(NoSuchLease, "failed to update the lease with address "
1404 << lease->addr_ << " - no such lease");
1405 } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1406 ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1407 // For test purpose only: check that the lease has not changed in
1408 // the database.
1409 isc_throw(NoSuchLease, "failed to update the lease with address "
1410 << lease->addr_ << " - lease has changed in database");
1411 }
1412
1413 // Try to write a lease to disk first. If this fails, the lease will
1414 // not be inserted to the memory and the disk and in-memory data will
1415 // remain consistent.
1416 if (persist) {
1417 lease_file4_->append(*lease);
1418 }
1419
1420 // Update lease current expiration time.
1421 lease->updateCurrentExpirationTime();
1422
1423 // Save a copy of the old lease as lease_it will point to the new
1424 // one after the replacement.
1425 Lease4Ptr old_lease = *lease_it;
1426
1427 // Use replace() to re-index leases.
1428 index.replace(lease_it, Lease4Ptr(new Lease4(*lease)));
1429
1430 // Adjust class lease counters.
1431 class_lease_counter_.updateLease(lease, old_lease);
1432}
1433
1434void
1437 DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
1438
1439 if (MultiThreadingMgr::instance().getMode()) {
1440 std::lock_guard<std::mutex> lock(*mutex_);
1441 updateLease4Internal(lease);
1442 } else {
1443 updateLease4Internal(lease);
1444 }
1445}
1446
1447void
1448Memfile_LeaseMgr::updateLease6Internal(const Lease6Ptr& lease) {
1449 // Obtain 'by address' index.
1450 Lease6StorageAddressIndex& index = storage6_.get<AddressIndexTag>();
1451
1452 bool persist = persistLeases(V6);
1453
1454 // Lease must exist if it is to be updated.
1455 Lease6StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1456 if (lease_it == index.end()) {
1457 isc_throw(NoSuchLease, "failed to update the lease with address "
1458 << lease->addr_ << " - no such lease");
1459 } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1460 ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1461 // For test purpose only: check that the lease has not changed in
1462 // the database.
1463 isc_throw(NoSuchLease, "failed to update the lease with address "
1464 << lease->addr_ << " - lease has changed in database");
1465 }
1466
1467 // Try to write a lease to disk first. If this fails, the lease will
1468 // not be inserted to the memory and the disk and in-memory data will
1469 // remain consistent.
1470 if (persist) {
1471 lease_file6_->append(*lease);
1472 }
1473
1474 // Update lease current expiration time.
1475 lease->updateCurrentExpirationTime();
1476
1477 // Save a copy of the old lease as lease_it will point to the new
1478 // one after the replacement.
1479 Lease6Ptr old_lease = *lease_it;
1480
1481 // Use replace() to re-index leases.
1482 index.replace(lease_it, Lease6Ptr(new Lease6(*lease)));
1483
1484 // Adjust class lease counters.
1485 class_lease_counter_.updateLease(lease, old_lease);
1486}
1487
1488void
1491 DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
1492
1493 if (MultiThreadingMgr::instance().getMode()) {
1494 std::lock_guard<std::mutex> lock(*mutex_);
1495 updateLease6Internal(lease);
1496 } else {
1497 updateLease6Internal(lease);
1498 }
1499}
1500
1501bool
1502Memfile_LeaseMgr::deleteLeaseInternal(const Lease4Ptr& lease) {
1503 const isc::asiolink::IOAddress& addr = lease->addr_;
1504 Lease4Storage::iterator l = storage4_.find(addr);
1505 if (l == storage4_.end()) {
1506 // No such lease
1507 return (false);
1508 } else {
1509 if (persistLeases(V4)) {
1510 // Copy the lease. The valid lifetime needs to be modified and
1511 // we don't modify the original lease.
1512 Lease4 lease_copy = **l;
1513 // Setting valid lifetime to 0 means that lease is being
1514 // removed.
1515 lease_copy.valid_lft_ = 0;
1516 lease_file4_->append(lease_copy);
1517 } else {
1518 // For test purpose only: check that the lease has not changed in
1519 // the database.
1520 if (((*l)->cltt_ != lease->current_cltt_) ||
1521 ((*l)->valid_lft_ != lease->current_valid_lft_)) {
1522 return false;
1523 }
1524 }
1525
1526 storage4_.erase(l);
1527
1528 // Decrement class lease counters.
1529 class_lease_counter_.removeLease(lease);
1530
1531 return (true);
1532 }
1533}
1534
1535bool
1538 DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
1539
1540 if (MultiThreadingMgr::instance().getMode()) {
1541 std::lock_guard<std::mutex> lock(*mutex_);
1542 return (deleteLeaseInternal(lease));
1543 } else {
1544 return (deleteLeaseInternal(lease));
1545 }
1546}
1547
1548bool
1549Memfile_LeaseMgr::deleteLeaseInternal(const Lease6Ptr& lease) {
1550 const isc::asiolink::IOAddress& addr = lease->addr_;
1551 Lease6Storage::iterator l = storage6_.find(addr);
1552 if (l == storage6_.end()) {
1553 // No such lease
1554 return (false);
1555 } else {
1556 if (persistLeases(V6)) {
1557 // Copy the lease. The lifetimes need to be modified and we
1558 // don't modify the original lease.
1559 Lease6 lease_copy = **l;
1560 // Setting lifetimes to 0 means that lease is being removed.
1561 lease_copy.valid_lft_ = 0;
1562 lease_copy.preferred_lft_ = 0;
1563 lease_file6_->append(lease_copy);
1564 } else {
1565 // For test purpose only: check that the lease has not changed in
1566 // the database.
1567 if (((*l)->cltt_ != lease->current_cltt_) ||
1568 ((*l)->valid_lft_ != lease->current_valid_lft_)) {
1569 return false;
1570 }
1571 }
1572
1573 storage6_.erase(l);
1574
1575 // Decrement class lease counters.
1576 class_lease_counter_.removeLease(lease);
1577
1578 return (true);
1579 }
1580}
1581
1582bool
1585 DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
1586
1587 if (MultiThreadingMgr::instance().getMode()) {
1588 std::lock_guard<std::mutex> lock(*mutex_);
1589 return (deleteLeaseInternal(lease));
1590 } else {
1591 return (deleteLeaseInternal(lease));
1592 }
1593}
1594
1595uint64_t
1599 .arg(secs);
1600
1601 if (MultiThreadingMgr::instance().getMode()) {
1602 std::lock_guard<std::mutex> lock(*mutex_);
1603 return (deleteExpiredReclaimedLeases<
1605 >(secs, V4, storage4_, lease_file4_));
1606 } else {
1607 return (deleteExpiredReclaimedLeases<
1609 >(secs, V4, storage4_, lease_file4_));
1610 }
1611}
1612
1613uint64_t
1617 .arg(secs);
1618
1619 if (MultiThreadingMgr::instance().getMode()) {
1620 std::lock_guard<std::mutex> lock(*mutex_);
1621 return (deleteExpiredReclaimedLeases<
1623 >(secs, V6, storage6_, lease_file6_));
1624 } else {
1625 return (deleteExpiredReclaimedLeases<
1627 >(secs, V6, storage6_, lease_file6_));
1628 }
1629}
1630
1631template<typename IndexType, typename LeaseType, typename StorageType,
1632 typename LeaseFileType>
1633uint64_t
1634Memfile_LeaseMgr::deleteExpiredReclaimedLeases(const uint32_t secs,
1635 const Universe& universe,
1636 StorageType& storage,
1637 LeaseFileType& lease_file) const {
1638 // Obtain the index which segragates leases by state and time.
1639 IndexType& index = storage.template get<ExpirationIndexTag>();
1640
1641 // This returns the first element which is greater than the specified
1642 // tuple (true, time(NULL) - secs). However, the range between the
1643 // beginning of the index and returned element also includes all the
1644 // elements for which the first value is false (lease state is NOT
1645 // reclaimed), because false < true. All elements between the
1646 // beginning of the index and the element returned, for which the
1647 // first value is true, represent the reclaimed leases which should
1648 // be deleted, because their expiration time + secs has occurred earlier
1649 // than current time.
1650 typename IndexType::const_iterator upper_limit =
1651 index.upper_bound(boost::make_tuple(true, time(NULL) - secs));
1652
1653 // Now, we have to exclude all elements of the index which represent
1654 // leases in the state other than reclaimed - with the first value
1655 // in the index equal to false. Note that elements in the index are
1656 // ordered from the lower to the higher ones. So, all elements with
1657 // the first value of false are placed before the elements with the
1658 // value of true. Hence, we have to find the first element which
1659 // contains value of true. The time value is the lowest possible.
1660 typename IndexType::const_iterator lower_limit =
1661 index.upper_bound(boost::make_tuple(true, std::numeric_limits<int64_t>::min()));
1662
1663 // If there are some elements in this range, delete them.
1664 uint64_t num_leases = static_cast<uint64_t>(std::distance(lower_limit, upper_limit));
1665 if (num_leases > 0) {
1666
1669 .arg(num_leases);
1670
1671 // If lease persistence is enabled, we also have to mark leases
1672 // as deleted in the lease file. We do this by setting the
1673 // lifetime to 0.
1674 if (persistLeases(universe)) {
1675 for (typename IndexType::const_iterator lease = lower_limit;
1676 lease != upper_limit; ++lease) {
1677 // Copy lease to not affect the lease in the container.
1678 LeaseType lease_copy(**lease);
1679 // Set the valid lifetime to 0 to indicate the removal
1680 // of the lease.
1681 lease_copy.valid_lft_ = 0;
1682 lease_file->append(lease_copy);
1683 }
1684 }
1685
1686 // Erase leases from memory.
1687 index.erase(lower_limit, upper_limit);
1688 }
1689 // Return number of leases deleted.
1690 return (num_leases);
1691}
1692
1693
1694std::string
1696 return (std::string("In memory database with leases stored in a CSV file."));
1697}
1698
1699std::pair<uint32_t, uint32_t>
1701 std::string const& universe(conn_.getParameter("universe"));
1702 if (universe == "4") {
1703 return std::make_pair(MAJOR_VERSION_V4, MINOR_VERSION_V4);
1704 } else if (universe == "6") {
1705 return std::make_pair(MAJOR_VERSION_V6, MINOR_VERSION_V6);
1706 }
1707 isc_throw(BadValue, "cannot determine version for universe " << universe);
1708}
1709
1710void
1713}
1714
1715void
1719}
1720
1721std::string
1722Memfile_LeaseMgr::appendSuffix(const std::string& file_name,
1723 const LFCFileType& file_type) {
1724 std::string name(file_name);
1725 switch (file_type) {
1726 case FILE_INPUT:
1727 name += ".1";
1728 break;
1729 case FILE_PREVIOUS:
1730 name += ".2";
1731 break;
1732 case FILE_OUTPUT:
1733 name += ".output";
1734 break;
1735 case FILE_FINISH:
1736 name += ".completed";
1737 break;
1738 case FILE_PID:
1739 name += ".pid";
1740 break;
1741 default:
1742 // Do not append any suffix for the FILE_CURRENT.
1743 ;
1744 }
1745
1746 return (name);
1747}
1748
1749std::string
1751 std::ostringstream s;
1752 s << CfgMgr::instance().getDataDir() << "/kea-leases";
1753 s << (u == V4 ? "4" : "6");
1754 s << ".csv";
1755 return (s.str());
1756}
1757
1758std::string
1760 if (u == V4) {
1761 return (lease_file4_ ? lease_file4_->getFilename() : "");
1762 }
1763
1764 return (lease_file6_ ? lease_file6_->getFilename() : "");
1765}
1766
1767bool
1769 // Currently, if the lease file IO is not created, it means that writes to
1770 // disk have been explicitly disabled by the administrator. At some point,
1771 // there may be a dedicated ON/OFF flag implemented to control this.
1772 if (u == V4 && lease_file4_) {
1773 return (true);
1774 }
1775
1776 return (u == V6 && lease_file6_);
1777}
1778
1779std::string
1780Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
1781 std::string persist_val;
1782 try {
1783 persist_val = conn_.getParameter("persist");
1784 } catch (const Exception&) {
1785 // If parameter persist hasn't been specified, we use a default value
1786 // 'yes'.
1787 persist_val = "true";
1788 }
1789 // If persist_val is 'false' we will not store leases to disk, so let's
1790 // return empty file name.
1791 if (persist_val == "false") {
1792 return ("");
1793
1794 } else if (persist_val != "true") {
1795 isc_throw(isc::BadValue, "invalid value 'persist="
1796 << persist_val << "'");
1797 }
1798
1799 std::string lease_file;
1800 try {
1801 lease_file = conn_.getParameter("name");
1802 } catch (const Exception&) {
1803 lease_file = getDefaultLeaseFilePath(u);
1804 }
1805 return (lease_file);
1806}
1807
1808template<typename LeaseObjectType, typename LeaseFileType, typename StorageType>
1809bool
1810Memfile_LeaseMgr::loadLeasesFromFiles(const std::string& filename,
1811 boost::shared_ptr<LeaseFileType>& lease_file,
1812 StorageType& storage) {
1813 // Check if the instance of the LFC is running right now. If it is
1814 // running, we refuse to load leases as the LFC may be writing to the
1815 // lease files right now. When the user retries server configuration
1816 // it should go through.
1819 PIDFile pid_file(appendSuffix(filename, FILE_PID));
1820 if (pid_file.check()) {
1821 isc_throw(DbOpenError, "unable to load leases from files while the "
1822 "lease file cleanup is in progress");
1823 }
1824
1825 storage.clear();
1826
1827 std::string max_row_errors_str = "0";
1828 try {
1829 max_row_errors_str = conn_.getParameter("max-row-errors");
1830 } catch (const std::exception&) {
1831 // Ignore and default to 0.
1832 }
1833
1834 uint32_t max_row_errors = 0;
1835 try {
1836 max_row_errors = boost::lexical_cast<uint32_t>(max_row_errors_str);
1837 } catch (const boost::bad_lexical_cast&) {
1838 isc_throw(isc::BadValue, "invalid value of the max-row-errors "
1839 << max_row_errors_str << " specified");
1840 }
1841
1842 // Load the leasefile.completed, if exists.
1843 bool conversion_needed = false;
1844 lease_file.reset(new LeaseFileType(std::string(filename + ".completed")));
1845 if (lease_file->exists()) {
1846 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1847 max_row_errors);
1848 conversion_needed = conversion_needed || lease_file->needsConversion();
1849 } else {
1850 // If the leasefile.completed doesn't exist, let's load the leases
1851 // from leasefile.2 and leasefile.1, if they exist.
1852 lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_PREVIOUS)));
1853 if (lease_file->exists()) {
1854 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1855 max_row_errors);
1856 conversion_needed = conversion_needed || lease_file->needsConversion();
1857 }
1858
1859 lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_INPUT)));
1860 if (lease_file->exists()) {
1861 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1862 max_row_errors);
1863 conversion_needed = conversion_needed || lease_file->needsConversion();
1864 }
1865 }
1866
1867 // Always load leases from the primary lease file. If the lease file
1868 // doesn't exist it will be created by the LeaseFileLoader. Note
1869 // that the false value passed as the last parameter to load
1870 // function causes the function to leave the file open after
1871 // it is parsed. This file will be used by the backend to record
1872 // future lease updates.
1873 lease_file.reset(new LeaseFileType(filename));
1874 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1875 max_row_errors, false);
1876 conversion_needed = conversion_needed || lease_file->needsConversion();
1877
1878 return (conversion_needed);
1879}
1880
1881
1882bool
1884 return (lfc_setup_->isRunning());
1885}
1886
1887int
1889 return (lfc_setup_->getExitStatus());
1890}
1891
1892void
1895
1896 // Check if we're in the v4 or v6 space and use the appropriate file.
1897 if (lease_file4_) {
1899 lfcExecute(lease_file4_);
1900 } else if (lease_file6_) {
1902 lfcExecute(lease_file6_);
1903 }
1904}
1905
1906void
1907Memfile_LeaseMgr::lfcSetup(bool conversion_needed) {
1908 std::string lfc_interval_str = "3600";
1909 try {
1910 lfc_interval_str = conn_.getParameter("lfc-interval");
1911 } catch (const std::exception&) {
1912 // Ignore and default to 3600.
1913 }
1914
1915 uint32_t lfc_interval = 0;
1916 try {
1917 lfc_interval = boost::lexical_cast<uint32_t>(lfc_interval_str);
1918 } catch (const boost::bad_lexical_cast&) {
1919 isc_throw(isc::BadValue, "invalid value of the lfc-interval "
1920 << lfc_interval_str << " specified");
1921 }
1922
1923 if (lfc_interval > 0 || conversion_needed) {
1924 lfc_setup_.reset(new LFCSetup(std::bind(&Memfile_LeaseMgr::lfcCallback, this)));
1925 lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_, conversion_needed);
1926 }
1927}
1928
1929template<typename LeaseFileType>
1930void
1931Memfile_LeaseMgr::lfcExecute(boost::shared_ptr<LeaseFileType>& lease_file) {
1932 bool do_lfc = true;
1933
1934 // Check the status of the LFC instance.
1935 // If the finish file exists or the copy of the lease file exists it
1936 // is an indication that another LFC instance may be in progress or
1937 // may be stalled. In that case we don't want to rotate the current
1938 // lease file to avoid overriding the contents of the existing file.
1939 CSVFile lease_file_finish(appendSuffix(lease_file->getFilename(), FILE_FINISH));
1940 CSVFile lease_file_copy(appendSuffix(lease_file->getFilename(), FILE_INPUT));
1941 if (!lease_file_finish.exists() && !lease_file_copy.exists()) {
1942 // Close the current file so as we can move it to the copy file.
1943 lease_file->close();
1944 // Move the current file to the copy file. Remember the result
1945 // because we don't want to run LFC if the rename failed.
1946 do_lfc = (rename(lease_file->getFilename().c_str(),
1947 lease_file_copy.getFilename().c_str()) == 0);
1948
1949 if (!do_lfc) {
1951 .arg(lease_file->getFilename())
1952 .arg(lease_file_copy.getFilename())
1953 .arg(strerror(errno));
1954 }
1955
1956 // Regardless if we successfully moved the current file or not,
1957 // we need to re-open the current file for the server to write
1958 // new lease updates. If the file has been successfully moved,
1959 // this will result in creation of the new file. Otherwise,
1960 // an existing file will be opened.
1961 try {
1962 lease_file->open(true);
1963
1964 } catch (const CSVFileError& ex) {
1965 // If we're unable to open the lease file this is a serious
1966 // error because the server will not be able to persist
1967 // leases.
1975 .arg(lease_file->getFilename())
1976 .arg(ex.what());
1977 // Reset the pointer to the file so as the backend doesn't
1978 // try to write leases to disk.
1979 lease_file.reset();
1980 do_lfc = false;
1981 }
1982 }
1983 // Once the files have been rotated, or untouched if another LFC had
1984 // not finished, a new process is started.
1985 if (do_lfc) {
1986 lfc_setup_->execute();
1987 }
1988}
1989
1992 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_));
1993 query->start();
1994 return(query);
1995}
1996
1999 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, subnet_id));
2000 query->start();
2001 return(query);
2002}
2003
2006 const SubnetID& last_subnet_id) {
2007 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, first_subnet_id,
2008 last_subnet_id));
2009 query->start();
2010 return(query);
2011}
2012
2015 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_));
2016 query->start();
2017 return(query);
2018}
2019
2022 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, subnet_id));
2023 query->start();
2024 return(query);
2025}
2026
2029 const SubnetID& last_subnet_id) {
2030 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, first_subnet_id,
2031 last_subnet_id));
2032 query->start();
2033 return(query);
2034}
2035
2036size_t
2039 .arg(subnet_id);
2040
2041 // Get the index by DUID, IAID, lease type.
2042 const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
2043
2044 // Try to get the lease using the DUID, IAID and lease type.
2045 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
2046 Lease4StorageSubnetIdIndex::const_iterator> l =
2047 idx.equal_range(subnet_id);
2048
2049 // Let's collect all leases.
2050 Lease4Collection leases;
2051 for (auto lease = l.first; lease != l.second; ++lease) {
2052 leases.push_back(*lease);
2053 }
2054
2055 size_t num = leases.size();
2056 for (auto l = leases.begin(); l != leases.end(); ++l) {
2057 deleteLease(*l);
2058 }
2060 .arg(subnet_id).arg(num);
2061
2062 return (num);
2063}
2064
2065size_t
2068 .arg(subnet_id);
2069
2070 // Get the index by DUID, IAID, lease type.
2071 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
2072
2073 // Try to get the lease using the DUID, IAID and lease type.
2074 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
2075 Lease6StorageSubnetIdIndex::const_iterator> l =
2076 idx.equal_range(subnet_id);
2077
2078 // Let's collect all leases.
2079 Lease6Collection leases;
2080 for (auto lease = l.first; lease != l.second; ++lease) {
2081 leases.push_back(*lease);
2082 }
2083
2084 size_t num = leases.size();
2085 for (auto l = leases.begin(); l != leases.end(); ++l) {
2086 deleteLease(*l);
2087 }
2089 .arg(subnet_id).arg(num);
2090
2091 return (num);
2092}
2093
2094void
2096 class_lease_counter_.clear();
2097 for (auto lease = storage4_.begin(); lease != storage4_.end(); ++lease) {
2098 // Bump the appropriate accumulator
2099 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
2100 class_lease_counter_.addLease(*lease);
2101 }
2102 }
2103}
2104
2105void
2107 class_lease_counter_.clear();
2108 for (auto lease = storage6_.begin(); lease != storage6_.end(); ++lease) {
2109 // Bump the appropriate accumulator
2110 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
2111 class_lease_counter_.addLease(*lease);
2112 }
2113 }
2114}
2115
2116size_t
2118 const Lease::Type& ltype /* = Lease::TYPE_V4*/) const {
2119 if (MultiThreadingMgr::instance().getMode()) {
2120 std::lock_guard<std::mutex> lock(*mutex_);
2121 return(class_lease_counter_.getClassCount(client_class, ltype));
2122 } else {
2123 return(class_lease_counter_.getClassCount(client_class, ltype));
2124 }
2125}
2126
2127void
2129 return(class_lease_counter_.clear());
2130}
2131
2132std::string
2134 if (!user_context) {
2135 return ("");
2136 }
2137
2138 ConstElementPtr limits = user_context->find("ISC/limits");
2139 if (!limits) {
2140 return ("");
2141 }
2142
2143 // Iterate of the 'client-classes' list in 'limits'. For each class that specifies
2144 // an "address-limit", check its value against the class's lease count.
2145 ConstElementPtr classes = limits->get("client-classes");
2146 if (classes) {
2147 for (int i = 0; i < classes->size(); ++i) {
2148 ConstElementPtr class_elem = classes->get(i);
2149 // Get class name.
2150 ConstElementPtr name_elem = class_elem->get("name");
2151 if (!name_elem) {
2152 isc_throw(BadValue, "checkLimits4 - client-class.name is missing: "
2153 << prettyPrint(limits));
2154 }
2155
2156 std::string name = name_elem->stringValue();
2157
2158 // Now look for an address-limit
2159 size_t limit;
2160 if (!getLeaseLimit(class_elem, Lease::TYPE_V4, limit)) {
2161 // No limit, go to the next class.
2162 continue;
2163 }
2164
2165 // If the limit is > 0 look up the class lease count. Limit of 0 always
2166 // denies the lease.
2167 size_t lease_count = 0;
2168 if (limit) {
2169 lease_count = getClassLeaseCount(name);
2170 }
2171
2172 // If we're over the limit, return the error, no need to evaluate any others.
2173 if (lease_count >= limit) {
2174 std::ostringstream ss;
2175 ss << "address limit " << limit << " for client class \""
2176 << name << "\", current lease count " << lease_count;
2177 return (ss.str());
2178 }
2179 }
2180 }
2181
2182 // If there were class limits we passed them, now look for a subnet limit.
2183 ConstElementPtr subnet_elem = limits->get("subnet");
2184 if (subnet_elem) {
2185 // Get the subnet id.
2186 ConstElementPtr id_elem = subnet_elem->get("id");
2187 if (!id_elem) {
2188 isc_throw(BadValue, "checkLimits4 - subnet.id is missing: "
2189 << prettyPrint(limits));
2190 }
2191
2192 SubnetID subnet_id = id_elem->intValue();
2193
2194 // Now look for an address-limit.
2195 size_t limit;
2196 if (getLeaseLimit(subnet_elem, Lease::TYPE_V4, limit)) {
2197 // If the limit is > 0 look up the subnet lease count. Limit of 0 always
2198 // denies the lease.
2199 int64_t lease_count = 0;
2200 if (limit) {
2201 lease_count = getSubnetStat(subnet_id, "assigned-addresses");
2202 }
2203
2204 // If we're over the limit, return the error.
2205 if (lease_count >= limit) {
2206 std::ostringstream ss;
2207 ss << "address limit " << limit << " for subnet ID " << subnet_id
2208 << ", current lease count " << lease_count;
2209 return (ss.str());
2210 }
2211 }
2212 }
2213
2214 // No limits exceeded!
2215 return ("");
2216}
2217
2218std::string
2220 if (!user_context) {
2221 return ("");
2222 }
2223
2224 ConstElementPtr limits = user_context->find("ISC/limits");
2225 if (!limits) {
2226 return ("");
2227 }
2228
2229 // Iterate over the 'client-classes' list in 'limits'. For each class that specifies
2230 // limit (either "address-limit" or "prefix-limit", check its value against the appropriate
2231 // class lease count.
2232 ConstElementPtr classes = limits->get("client-classes");
2233 if (classes) {
2234 for (int i = 0; i < classes->size(); ++i) {
2235 ConstElementPtr class_elem = classes->get(i);
2236 // Get class name.
2237 ConstElementPtr name_elem = class_elem->get("name");
2238 if (!name_elem) {
2239 isc_throw(BadValue, "checkLimits6 - client-class.name is missing: "
2240 << prettyPrint(limits));
2241 }
2242
2243 std::string name = name_elem->stringValue();
2244
2245 // Now look for either address-limit or a prefix=limit.
2246 size_t limit = 0;
2248 if (!getLeaseLimit(class_elem, ltype, limit)) {
2249 ltype = Lease::TYPE_PD;
2250 if (!getLeaseLimit(class_elem, ltype, limit)) {
2251 // No limits for this class, skip to the next.
2252 continue;
2253 }
2254 }
2255
2256 // If the limit is > 0 look up the class lease count. Limit of 0 always
2257 // denies the lease.
2258 size_t lease_count = 0;
2259 if (limit) {
2260 lease_count = getClassLeaseCount(name, ltype);
2261 }
2262
2263 // If we're over the limit, return the error, no need to evaluate any others.
2264 if (lease_count >= limit) {
2265 std::ostringstream ss;
2266 ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
2267 << " limit " << limit << " for client class \""
2268 << name << "\", current lease count " << lease_count;
2269 return (ss.str());
2270 }
2271 }
2272 }
2273
2274 // If there were class limits we passed them, now look for a subnet limit.
2275 ConstElementPtr subnet_elem = limits->get("subnet");
2276 if (subnet_elem) {
2277 // Get the subnet id.
2278 ConstElementPtr id_elem = subnet_elem->get("id");
2279 if (!id_elem) {
2280 isc_throw(BadValue, "checkLimits6 - subnet.id is missing: "
2281 << prettyPrint(limits));
2282 }
2283
2284 SubnetID subnet_id = id_elem->intValue();
2285
2286 // Now look for either address-limit or a prefix=limit.
2287 size_t limit = 0;
2289 if (!getLeaseLimit(subnet_elem, ltype, limit)) {
2290 ltype = Lease::TYPE_PD;
2291 if (!getLeaseLimit(subnet_elem, ltype, limit)) {
2292 // No limits for the subnet so none exceeded!
2293 return ("");
2294 }
2295 }
2296
2297 // If the limit is > 0 look up the class lease count. Limit of 0 always
2298 // denies the lease.
2299 int64_t lease_count = 0;
2300 if (limit) {
2301 lease_count = getSubnetStat(subnet_id, (ltype == Lease::TYPE_NA ?
2302 "assigned-nas" : "assigned-pds"));
2303 }
2304
2305 // If we're over the limit, return the error.
2306 if (lease_count >= limit) {
2307 std::ostringstream ss;
2308 ss << (ltype == Lease::TYPE_NA ? "address" : "prefix")
2309 << " limit " << limit << " for subnet ID " << subnet_id
2310 << ", current lease count " << lease_count;
2311 return (ss.str());
2312 }
2313 }
2314
2315 // No limits exceeded!
2316 return ("");
2317}
2318
2319bool
2321 return true;
2322}
2323
2324int64_t
2325Memfile_LeaseMgr::getSubnetStat(const SubnetID& subnet_id, const std::string& stat_label) const {
2328 std::string stat_name = StatsMgr::generateName("subnet", subnet_id, stat_label);
2329 ConstElementPtr stat = StatsMgr::instance().get(stat_name);
2330 ConstElementPtr samples = stat->get(stat_name);
2331 if (samples && samples->size()) {
2332 auto sample = samples->get(0);
2333 if (sample->size()) {
2334 auto count_elem = sample->get(0);
2335 return (count_elem->intValue());
2336 }
2337 }
2338
2339 return (0);
2340}
2341
2342bool
2343Memfile_LeaseMgr::getLeaseLimit(ConstElementPtr parent, Lease::Type ltype, size_t& limit) const {
2344 ConstElementPtr limit_elem = parent->get(ltype == Lease::TYPE_PD ?
2345 "prefix-limit" : "address-limit");
2346 if (limit_elem) {
2347 limit = limit_elem->intValue();
2348 return (true);
2349 }
2350
2351 return (false);
2352}
2353
2354
2355
2356} // namespace dhcp
2357} // namespace isc
int version()
returns Kea hooks version.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
std::string getParameter(const std::string &name) const
Returns value of a connection parameter.
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Exception thrown on failure to open database.
Invalid address family used as input to Lease Manager.
Definition: db_exceptions.h:59
Provides methods to access CSV file with DHCPv4 leases.
Provides methods to access CSV file with DHCPv6 leases.
util::Optional< std::string > getDataDir() const
returns path do the data directory
Definition: cfgmgr.cc:31
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
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:111
const std::vector< uint8_t > & getClientId() const
Returns reference to the client-id data.
Definition: duid.cc:117
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
Definition: duid.cc:122
Holds DUID (DHCPv6 Unique Identifier)
Definition: duid.h:27
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
Definition: duid.cc:75
const std::vector< uint8_t > & getDuid() const
Returns a const reference to the actual DUID value.
Definition: duid.cc:46
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.
Abstract Lease Manager.
Definition: lease_mgr.h:223
static isc::asiolink::IOServicePtr & getIOService()
Returns pointer to the IO service.
Definition: lease_mgr.h:791
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:354
Wraps value holding size of the page with leases.
Definition: lease_mgr.h:44
const size_t page_size_
Holds page size.
Definition: lease_mgr.h:54
Base class for fulfilling a statistical lease data query.
Definition: lease_mgr.h:129
SubnetID getLastSubnetID() const
Returns the value of last subnet ID specified (or zero)
Definition: lease_mgr.h:184
SubnetID getFirstSubnetID() const
Returns the value of first subnet ID specified (or zero)
Definition: lease_mgr.h:179
SelectMode getSelectMode() const
Returns the selection criteria mode The value returned is based upon the constructor variant used and...
Definition: lease_mgr.h:191
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.
virtual ~MemfileLeaseStatsQuery4()
Destructor.
void start()
Creates the IPv4 lease statistical data result set.
MemfileLeaseStatsQuery4(Lease4Storage &storage4)
Constructor for an all subnets query.
MemfileLeaseStatsQuery4(Lease4Storage &storage4, const SubnetID &subnet_id)
Constructor for a single subnet query.
Memfile derivation of the IPv6 statistical lease data query.
MemfileLeaseStatsQuery6(Lease6Storage &storage6)
Constructor.
virtual 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 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()
Constructor for all subnets query.
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".
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.
virtual void rollback() override
Rollback Transactions.
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.
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 updateLease4(const Lease4Ptr &lease4) override
Updates IPv4 lease.
virtual size_t wipeLeases4(const SubnetID &subnet_id) override
Removes specified IPv4 leases.
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.
int getLFCExitStatus() const
Returns the status code returned by the last executed LFC process.
bool persistLeases(Universe u) const
Specifies whether or not leases are written to disk.
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.
virtual bool addLease(const Lease4Ptr &lease) override
Adds an IPv4 lease.
virtual void recountClassLeases6() override
Recount the leases per class for V6 leases.
virtual std::pair< uint32_t, uint32_t > getVersion() const override
Returns backend version.
std::string getLeaseFilePath(Universe u) const
Returns an absolute path to the lease file.
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 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 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 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.
std::string getDefaultLeaseFilePath(Universe u) const
Returns default path to the lease file.
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
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.
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 MAJOR_VERSION_V4
static const int MINOR_VERSION_V4
the minor version of the v4 memfile backend
static const int MINOR_VERSION_V6
the minor version of the v6 memfile backend
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
void prettyPrint(ConstElementPtr element, std::ostream &out, unsigned indent, unsigned step)
Pretty prints the data into stream.
Definition: data.cc:1487
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
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
std::string ClientClass
Defines a single class name.
Definition: classify.h:42
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_LFC_UNREGISTER_TIMER_FAILED
const isc::log::MessageID DHCPSRV_MEMFILE_LFC_SPAWN_FAIL
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_ > > > > Lease4Storage
A multi index container holding DHCPv4 leases.
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:503
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:661
boost::shared_ptr< LeaseStatsQuery > LeaseStatsQueryPtr
Defines a pointer to a LeaseStatsQuery.
Definition: lease_mgr.h:208
const isc::log::MessageID DHCPSRV_MEMFILE_WIPE_LEASES4
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:24
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.
Lease6Storage::index< HostnameIndexTag >::type Lease6StorageHostnameIndex
DHCPv6 lease storage index by hostname.
const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED4
const isc::log::MessageID DHCPSRV_MEMFILE_GET_EXPIRED6
const isc::log::MessageID DHCPSRV_MEMFILE_GET_HOSTNAME4
Lease4Storage::index< ClientIdSubnetIdIndexTag >::type Lease4StorageClientIdSubnetIdIndex
DHCPv4 lease storage index by client and subnet identifier.
Lease4Storage::index< HWAddressSubnetIdIndexTag >::type Lease4StorageHWAddressSubnetIdIndex
DHCPv4 lease storage index by HW address and subnet identifier.
const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR6
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:24
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::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_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< 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_ > > > > Lease6Storage
A multi index container holding DHCPv6 leases.
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
const isc::log::MessageID DHCPSRV_MEMFILE_NO_STORAGE
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 identifier.
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition: lease.h:498
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
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:284
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
const isc::log::MessageID DHCPSRV_MEMFILE_GET_PAGE6
Definition: edns.h:19
Defines the logger used by the top-level component of kea-lfc.
Tag for indexes by address.
Tag for indexes by client and subnet identifiers.
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 identifier tuple.
Tag for index using hostname.
Structure that holds a lease for IPv4 address.
Definition: lease.h:295
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:514
Contains a single row of lease statistical data.
Definition: lease_mgr.h:62
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:52
Tag for indexes by subnet-id.