Kea 2.0.3
memfile_lease_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2021 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>
18#include <util/pid_file.h>
19#include <cstdio>
20#include <cstring>
21#include <errno.h>
22#include <iostream>
23#include <limits>
24#include <sstream>
25
26namespace {
27
35const char* KEA_LFC_EXECUTABLE_ENV_NAME = "KEA_LFC_EXECUTABLE";
36
37} // namespace
38
39using namespace isc::asiolink;
40using namespace isc::db;
41using namespace isc::util;
42
43namespace isc {
44namespace dhcp {
45
60class LFCSetup {
61public:
62
71
75 ~LFCSetup();
76
88 void setup(const uint32_t lfc_interval,
89 const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
90 const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
91 bool run_once_now = false);
92
94 void execute();
95
99 bool isRunning() const;
100
102 int getExitStatus() const;
103
104private:
105
108 boost::scoped_ptr<ProcessSpawn> process_;
109
112
114 pid_t pid_;
115
120 TimerMgrPtr timer_mgr_;
121};
122
124 : process_(), callback_(callback), pid_(0),
125 timer_mgr_(TimerMgr::instance()) {
126}
127
129 try {
130 // Remove the timer. This will throw an exception if the timer does not
131 // exist. There are several possible reasons for this:
132 // a) It hasn't been registered (although if the LFC Setup instance
133 // exists it means that the timer must have been registered or that
134 // such registration has been attempted).
135 // b) The registration may fail if the duplicate timer exists or if the
136 // TimerMgr's worker thread is running but if this happens it is a
137 // programming error.
138 // c) The program is shutting down and the timer has been removed by
139 // another component.
140 timer_mgr_->unregisterTimer("memfile-lfc");
141
142 } catch (const std::exception& ex) {
143 // We don't want exceptions being thrown from the destructor so we just
144 // log a message here. The message is logged at debug severity as
145 // we don't want an error message output during shutdown.
148 }
149}
150
151void
152LFCSetup::setup(const uint32_t lfc_interval,
153 const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
154 const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
155 bool run_once_now) {
156
157 // If to nothing to do, punt
158 if (lfc_interval == 0 && !run_once_now) {
159 return;
160 }
161
162 // Start preparing the command line for kea-lfc.
163 std::string executable;
164 char* c_executable = getenv(KEA_LFC_EXECUTABLE_ENV_NAME);
165 if (c_executable == NULL) {
166 executable = KEA_LFC_EXECUTABLE;
167 } else {
168 executable = c_executable;
169 }
170
171 // Gather the base file name.
172 std::string lease_file = lease_file4 ? lease_file4->getFilename() :
173 lease_file6->getFilename();
174
175 // Create the other names by appending suffixes to the base name.
176 ProcessArgs args;
177 // Universe: v4 or v6.
178 args.push_back(lease_file4 ? "-4" : "-6");
179
180 // Previous file.
181 args.push_back("-x");
182 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
184 // Input file.
185 args.push_back("-i");
186 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
188 // Output file.
189 args.push_back("-o");
190 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
192 // Finish file.
193 args.push_back("-f");
194 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
196 // PID file.
197 args.push_back("-p");
198 args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file,
200
201 // The configuration file is currently unused.
202 args.push_back("-c");
203 args.push_back("ignored-path");
204
205 // Create the process (do not start it yet).
206 process_.reset(new ProcessSpawn(LeaseMgr::getIOService(), executable, args));
207
208 // If we've been told to run it once now, invoke the callback directly.
209 if (run_once_now) {
210 callback_();
211 }
212
213 // If it's supposed to run periodically, setup that now.
214 if (lfc_interval > 0) {
215 // Set the timer to call callback function periodically.
217
218 // Multiple the lfc_interval value by 1000 as this value specifies
219 // a timeout in seconds, whereas the setup() method expects the
220 // timeout in milliseconds.
221 timer_mgr_->registerTimer("memfile-lfc", callback_, lfc_interval * 1000,
223 timer_mgr_->setup("memfile-lfc");
224 }
225}
226
227void
229 try {
231 .arg(process_->getCommandLine());
232 pid_ = process_->spawn();
233
234 } catch (const ProcessSpawnError&) {
236 }
237}
238
239bool
241 return (process_ && process_->isRunning(pid_));
242}
243
244int
246 if (!process_) {
247 isc_throw(InvalidOperation, "unable to obtain LFC process exit code: "
248 " the process is NULL");
249 }
250 return (process_->getExitStatus(pid_));
251}
252
253
260public:
264 : rows_(0), next_pos_(rows_.end()) {
265 };
266
271 : LeaseStatsQuery(subnet_id), rows_(0), next_pos_(rows_.end()) {
272 };
273
278 MemfileLeaseStatsQuery(const SubnetID& first_subnet_id, const SubnetID& last_subnet_id)
279 : LeaseStatsQuery(first_subnet_id, last_subnet_id), rows_(0), next_pos_(rows_.end()) {
280 };
281
284
295 virtual bool getNextRow(LeaseStatsRow& row) {
296 if (next_pos_ == rows_.end()) {
297 return (false);
298 }
299
300 row = *next_pos_;
301 ++next_pos_;
302 return (true);
303 }
304
306 int getRowCount() const {
307 return (rows_.size());
308 }
309
310protected:
312 std::vector<LeaseStatsRow> rows_;
313
315 std::vector<LeaseStatsRow>::iterator next_pos_;
316};
317
328public:
333 : MemfileLeaseStatsQuery(), storage4_(storage4) {
334 };
335
340 MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& subnet_id)
341 : MemfileLeaseStatsQuery(subnet_id), storage4_(storage4) {
342 };
343
349 MemfileLeaseStatsQuery4(Lease4Storage& storage4, const SubnetID& first_subnet_id,
350 const SubnetID& last_subnet_id)
351 : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage4_(storage4) {
352 };
353
356
371 void start() {
373 = storage4_.get<SubnetIdIndexTag>();
374
375 // Set lower and upper bounds based on select mode
376 Lease4StorageSubnetIdIndex::const_iterator lower;
377 Lease4StorageSubnetIdIndex::const_iterator upper;
378 switch (getSelectMode()) {
379 case ALL_SUBNETS:
380 lower = idx.begin();
381 upper = idx.end();
382 break;
383
384 case SINGLE_SUBNET:
385 lower = idx.lower_bound(getFirstSubnetID());
386 upper = idx.upper_bound(getFirstSubnetID());
387 break;
388
389 case SUBNET_RANGE:
390 lower = idx.lower_bound(getFirstSubnetID());
391 upper = idx.upper_bound(getLastSubnetID());
392 break;
393 }
394
395 // Return an empty set if there are no rows.
396 if (lower == upper) {
397 return;
398 }
399
400 // Iterate over the leases in order by subnet, accumulating per
401 // subnet counts for each state of interest. As we finish each
402 // subnet, add the appropriate rows to our result set.
403 SubnetID cur_id = 0;
404 int64_t assigned = 0;
405 int64_t declined = 0;
406 for (Lease4StorageSubnetIdIndex::const_iterator lease = lower;
407 lease != upper; ++lease) {
408 // If we've hit the next subnet, add rows for the current subnet
409 // and wipe the accumulators
410 if ((*lease)->subnet_id_ != cur_id) {
411 if (cur_id > 0) {
412 if (assigned > 0) {
413 rows_.push_back(LeaseStatsRow(cur_id,
415 assigned));
416 assigned = 0;
417 }
418
419 if (declined > 0) {
420 rows_.push_back(LeaseStatsRow(cur_id,
422 declined));
423 declined = 0;
424 }
425 }
426
427 // Update current subnet id
428 cur_id = (*lease)->subnet_id_;
429 }
430
431 // Bump the appropriate accumulator
432 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
433 ++assigned;
434 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
435 ++declined;
436 }
437 }
438
439 // Make the rows for last subnet
440 if (assigned > 0) {
441 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DEFAULT,
442 assigned));
443 }
444
445 if (declined > 0) {
446 rows_.push_back(LeaseStatsRow(cur_id, Lease::STATE_DECLINED,
447 declined));
448 }
449
450 // Reset the next row position back to the beginning of the rows.
451 next_pos_ = rows_.begin();
452 }
453
454private:
456 Lease4Storage& storage4_;
457};
458
459
470public:
475 : MemfileLeaseStatsQuery(), storage6_(storage6) {
476 };
477
482 MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& subnet_id)
483 : MemfileLeaseStatsQuery(subnet_id), storage6_(storage6) {
484 };
485
491 MemfileLeaseStatsQuery6(Lease6Storage& storage6, const SubnetID& first_subnet_id,
492 const SubnetID& last_subnet_id)
493 : MemfileLeaseStatsQuery(first_subnet_id, last_subnet_id), storage6_(storage6) {
494 };
495
498
512 virtual void start() {
513 // Get the subnet_id index
515 = storage6_.get<SubnetIdIndexTag>();
516
517 // Set lower and upper bounds based on select mode
518 Lease6StorageSubnetIdIndex::const_iterator lower;
519 Lease6StorageSubnetIdIndex::const_iterator upper;
520 switch (getSelectMode()) {
521 case ALL_SUBNETS:
522 lower = idx.begin();
523 upper = idx.end();
524 break;
525
526 case SINGLE_SUBNET:
527 lower = idx.lower_bound(getFirstSubnetID());
528 upper = idx.upper_bound(getFirstSubnetID());
529 break;
530
531 case SUBNET_RANGE:
532 lower = idx.lower_bound(getFirstSubnetID());
533 upper = idx.upper_bound(getLastSubnetID());
534 break;
535 }
536
537 // Return an empty set if there are no rows.
538 if (lower == upper) {
539 return;
540 }
541
542 // Iterate over the leases in order by subnet, accumulating per
543 // subnet counts for each state of interest. As we finish each
544 // subnet, add the appropriate rows to our result set.
545 SubnetID cur_id = 0;
546 int64_t assigned = 0;
547 int64_t declined = 0;
548 int64_t assigned_pds = 0;
549 for (Lease6StorageSubnetIdIndex::const_iterator lease = lower;
550 lease != upper; ++lease) {
551 // If we've hit the next subnet, add rows for the current subnet
552 // and wipe the accumulators
553 if ((*lease)->subnet_id_ != cur_id) {
554 if (cur_id > 0) {
555 if (assigned > 0) {
556 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
558 assigned));
559 assigned = 0;
560 }
561
562 if (declined > 0) {
563 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
565 declined));
566 declined = 0;
567 }
568
569 if (assigned_pds > 0) {
570 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
572 assigned_pds));
573 assigned_pds = 0;
574 }
575 }
576
577 // Update current subnet id
578 cur_id = (*lease)->subnet_id_;
579 }
580
581 // Bump the appropriate accumulator
582 if ((*lease)->state_ == Lease::STATE_DEFAULT) {
583 switch((*lease)->type_) {
584 case Lease::TYPE_NA:
585 ++assigned;
586 break;
587 case Lease::TYPE_PD:
588 ++assigned_pds;
589 break;
590 default:
591 break;
592 }
593 } else if ((*lease)->state_ == Lease::STATE_DECLINED) {
594 // In theory only NAs can be declined
595 if (((*lease)->type_) == Lease::TYPE_NA) {
596 ++declined;
597 }
598 }
599 }
600
601 // Make the rows for last subnet, unless there were no rows
602 if (assigned > 0) {
603 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
604 Lease::STATE_DEFAULT, assigned));
605 }
606
607 if (declined > 0) {
608 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_NA,
609 Lease::STATE_DECLINED, declined));
610 }
611
612 if (assigned_pds > 0) {
613 rows_.push_back(LeaseStatsRow(cur_id, Lease::TYPE_PD,
614 Lease::STATE_DEFAULT, assigned_pds));
615 }
616
617 // Set the next row position to the beginning of the rows.
618 next_pos_ = rows_.begin();
619 }
620
621private:
623 Lease6Storage& storage6_;
624};
625
626// Explicit definition of class static constants. Values are given in the
627// declaration so they're not needed here.
630
632 : LeaseMgr(), lfc_setup_(), conn_(parameters), mutex_(new std::mutex) {
633 bool conversion_needed = false;
634
635 // Check the universe and use v4 file or v6 file.
636 std::string universe = conn_.getParameter("universe");
637 if (universe == "4") {
638 std::string file4 = initLeaseFilePath(V4);
639 if (!file4.empty()) {
640 conversion_needed = loadLeasesFromFiles<Lease4,
641 CSVLeaseFile4>(file4,
642 lease_file4_,
643 storage4_);
644 }
645 } else {
646 std::string file6 = initLeaseFilePath(V6);
647 if (!file6.empty()) {
648 conversion_needed = loadLeasesFromFiles<Lease6,
649 CSVLeaseFile6>(file6,
650 lease_file6_,
651 storage6_);
652 }
653 }
654
655 // If lease persistence have been disabled for both v4 and v6,
656 // issue a warning. It is ok not to write leases to disk when
657 // doing testing, but it should not be done in normal server
658 // operation.
659 if (!persistLeases(V4) && !persistLeases(V6)) {
661 } else {
662 if (conversion_needed) {
664 .arg(MAJOR_VERSION).arg(MINOR_VERSION);
665 }
666 lfcSetup(conversion_needed);
667 }
668}
669
671 if (lease_file4_) {
672 lease_file4_->close();
673 lease_file4_.reset();
674 }
675 if (lease_file6_) {
676 lease_file6_->close();
677 lease_file6_.reset();
678 }
679}
680
681std::string
683 std::stringstream tmp;
684 tmp << "Memfile backend " << MAJOR_VERSION;
685 tmp << "." << MINOR_VERSION;
686 return (tmp.str());
687}
688
689bool
690Memfile_LeaseMgr::addLeaseInternal(const Lease4Ptr& lease) {
691 if (getLease4Internal(lease->addr_)) {
692 // there is a lease with specified address already
693 return (false);
694 }
695
696 // Try to write a lease to disk first. If this fails, the lease will
697 // not be inserted to the memory and the disk and in-memory data will
698 // remain consistent.
699 if (persistLeases(V4)) {
700 lease_file4_->append(*lease);
701 }
702
703 storage4_.insert(lease);
704
705 // Update lease current expiration time (allows update between the creation
706 // of the Lease up to the point of insertion in the database).
707 lease->updateCurrentExpirationTime();
708
709 return (true);
710}
711
712bool
715 DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
716
717 if (MultiThreadingMgr::instance().getMode()) {
718 std::lock_guard<std::mutex> lock(*mutex_);
719 return (addLeaseInternal(lease));
720 } else {
721 return (addLeaseInternal(lease));
722 }
723}
724
725bool
726Memfile_LeaseMgr::addLeaseInternal(const Lease6Ptr& lease) {
727 if (getLease6Internal(lease->type_, lease->addr_)) {
728 // there is a lease with specified address already
729 return (false);
730 }
731
732 // Try to write a lease to disk first. If this fails, the lease will
733 // not be inserted to the memory and the disk and in-memory data will
734 // remain consistent.
735 if (persistLeases(V6)) {
736 lease_file6_->append(*lease);
737 }
738
739 storage6_.insert(lease);
740
741 // Update lease current expiration time (allows update between the creation
742 // of the Lease up to the point of insertion in the database).
743 lease->updateCurrentExpirationTime();
744
745 return (true);
746}
747
748bool
751 DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
752
753 if (MultiThreadingMgr::instance().getMode()) {
754 std::lock_guard<std::mutex> lock(*mutex_);
755 return (addLeaseInternal(lease));
756 } else {
757 return (addLeaseInternal(lease));
758 }
759}
760
762Memfile_LeaseMgr::getLease4Internal(const isc::asiolink::IOAddress& addr) const {
763 const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
764 Lease4StorageAddressIndex::iterator l = idx.find(addr);
765 if (l == idx.end()) {
766 return (Lease4Ptr());
767 } else {
768 return (Lease4Ptr(new Lease4(**l)));
769 }
770}
771
776
777 if (MultiThreadingMgr::instance().getMode()) {
778 std::lock_guard<std::mutex> lock(*mutex_);
779 return (getLease4Internal(addr));
780 } else {
781 return (getLease4Internal(addr));
782 }
783}
784
785void
786Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
787 Lease4Collection& collection) const {
788 // Using composite index by 'hw address' and 'subnet id'. It is
789 // ok to use it for searching by the 'hw address' only.
791 storage4_.get<HWAddressSubnetIdIndexTag>();
792 std::pair<Lease4StorageHWAddressSubnetIdIndex::const_iterator,
793 Lease4StorageHWAddressSubnetIdIndex::const_iterator> l
794 = idx.equal_range(boost::make_tuple(hwaddr.hwaddr_));
795
796 for (auto lease = l.first; lease != l.second; ++lease) {
797 collection.push_back(Lease4Ptr(new Lease4(**lease)));
798 }
799}
800
804 DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.toText());
805
806 Lease4Collection collection;
807 if (MultiThreadingMgr::instance().getMode()) {
808 std::lock_guard<std::mutex> lock(*mutex_);
809 getLease4Internal(hwaddr, collection);
810 } else {
811 getLease4Internal(hwaddr, collection);
812 }
813
814 return (collection);
815}
816
818Memfile_LeaseMgr::getLease4Internal(const HWAddr& hwaddr,
819 SubnetID subnet_id) const {
820 // Get the index by HW Address and Subnet Identifier.
822 storage4_.get<HWAddressSubnetIdIndexTag>();
823 // Try to find the lease using HWAddr and subnet id.
824 Lease4StorageHWAddressSubnetIdIndex::const_iterator lease =
825 idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
826 // Lease was not found. Return empty pointer to the caller.
827 if (lease == idx.end()) {
828 return (Lease4Ptr());
829 }
830
831 // Lease was found. Return it to the caller.
832 return (Lease4Ptr(new Lease4(**lease)));
833}
834
837 SubnetID subnet_id) const {
840 .arg(hwaddr.toText());
841
842 if (MultiThreadingMgr::instance().getMode()) {
843 std::lock_guard<std::mutex> lock(*mutex_);
844 return (getLease4Internal(hwaddr, subnet_id));
845 } else {
846 return (getLease4Internal(hwaddr, subnet_id));
847 }
848}
849
850void
851Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
852 Lease4Collection& collection) const {
853 // Using composite index by 'client id' and 'subnet id'. It is ok
854 // to use it to search by 'client id' only.
856 storage4_.get<ClientIdSubnetIdIndexTag>();
857 std::pair<Lease4StorageClientIdSubnetIdIndex::const_iterator,
858 Lease4StorageClientIdSubnetIdIndex::const_iterator> l
859 = idx.equal_range(boost::make_tuple(client_id.getClientId()));
860
861 for (auto lease = l.first; lease != l.second; ++lease) {
862 collection.push_back(Lease4Ptr(new Lease4(**lease)));
863 }
864}
865
867Memfile_LeaseMgr::getLease4(const ClientId& client_id) const {
869 DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.toText());
870
871 Lease4Collection collection;
872 if (MultiThreadingMgr::instance().getMode()) {
873 std::lock_guard<std::mutex> lock(*mutex_);
874 getLease4Internal(client_id, collection);
875 } else {
876 getLease4Internal(client_id, collection);
877 }
878
879 return (collection);
880}
881
883Memfile_LeaseMgr::getLease4Internal(const ClientId& client_id,
884 SubnetID subnet_id) const {
885 // Get the index by client and subnet id.
887 storage4_.get<ClientIdSubnetIdIndexTag>();
888 // Try to get the lease using client id and subnet id.
889 Lease4StorageClientIdSubnetIdIndex::const_iterator lease =
890 idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
891 // Lease was not found. Return empty pointer to the caller.
892 if (lease == idx.end()) {
893 return (Lease4Ptr());
894 }
895 // Lease was found. Return it to the caller.
896 return (Lease4Ptr(new Lease4(**lease)));
897}
898
901 SubnetID subnet_id) const {
904 .arg(client_id.toText());
905
906 if (MultiThreadingMgr::instance().getMode()) {
907 std::lock_guard<std::mutex> lock(*mutex_);
908 return (getLease4Internal(client_id, subnet_id));
909 } else {
910 return (getLease4Internal(client_id, subnet_id));
911 }
912}
913
914void
915Memfile_LeaseMgr::getLeases4Internal(SubnetID subnet_id,
916 Lease4Collection& collection) const {
917 const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
918 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
919 Lease4StorageSubnetIdIndex::const_iterator> l =
920 idx.equal_range(subnet_id);
921
922 for (auto lease = l.first; lease != l.second; ++lease) {
923 collection.push_back(Lease4Ptr(new Lease4(**lease)));
924 }
925}
926
930 .arg(subnet_id);
931
932 Lease4Collection collection;
933 if (MultiThreadingMgr::instance().getMode()) {
934 std::lock_guard<std::mutex> lock(*mutex_);
935 getLeases4Internal(subnet_id, collection);
936 } else {
937 getLeases4Internal(subnet_id, collection);
938 }
939
940 return (collection);
941}
942
943void
944Memfile_LeaseMgr::getLeases4Internal(const std::string& hostname,
945 Lease4Collection& collection) const {
946 const Lease4StorageHostnameIndex& idx = storage4_.get<HostnameIndexTag>();
947 std::pair<Lease4StorageHostnameIndex::const_iterator,
948 Lease4StorageHostnameIndex::const_iterator> l =
949 idx.equal_range(hostname);
950
951 for (auto lease = l.first; lease != l.second; ++lease) {
952 collection.push_back(Lease4Ptr(new Lease4(**lease)));
953 }
954}
955
957Memfile_LeaseMgr::getLeases4(const std::string& hostname) const {
959 .arg(hostname);
960
961 Lease4Collection collection;
962 if (MultiThreadingMgr::instance().getMode()) {
963 std::lock_guard<std::mutex> lock(*mutex_);
964 getLeases4Internal(hostname, collection);
965 } else {
966 getLeases4Internal(hostname, collection);
967 }
968
969 return (collection);
970}
971
972void
973Memfile_LeaseMgr::getLeases4Internal(Lease4Collection& collection) const {
974 for (auto lease = storage4_.begin(); lease != storage4_.end(); ++lease) {
975 collection.push_back(Lease4Ptr(new Lease4(**lease)));
976 }
977}
978
982
983 Lease4Collection collection;
984 if (MultiThreadingMgr::instance().getMode()) {
985 std::lock_guard<std::mutex> lock(*mutex_);
986 getLeases4Internal(collection);
987 } else {
988 getLeases4Internal(collection);
989 }
990
991 return (collection);
992}
993
994void
995Memfile_LeaseMgr::getLeases4Internal(const asiolink::IOAddress& lower_bound_address,
996 const LeasePageSize& page_size,
997 Lease4Collection& collection) const {
998 const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
999 Lease4StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1000
1001 // Exclude the lower bound address specified by the caller.
1002 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1003 ++lb;
1004 }
1005
1006 // Return all other leases being within the page size.
1007 for (auto lease = lb;
1008 (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1009 ++lease) {
1010 collection.push_back(Lease4Ptr(new Lease4(**lease)));
1011 }
1012}
1013
1016 const LeasePageSize& page_size) const {
1017 // Expecting IPv4 address.
1018 if (!lower_bound_address.isV4()) {
1019 isc_throw(InvalidAddressFamily, "expected IPv4 address while "
1020 "retrieving leases from the lease database, got "
1021 << lower_bound_address);
1022 }
1023
1025 .arg(page_size.page_size_)
1026 .arg(lower_bound_address.toText());
1027
1028 Lease4Collection collection;
1029 if (MultiThreadingMgr::instance().getMode()) {
1030 std::lock_guard<std::mutex> lock(*mutex_);
1031 getLeases4Internal(lower_bound_address, page_size, collection);
1032 } else {
1033 getLeases4Internal(lower_bound_address, page_size, collection);
1034 }
1035
1036 return (collection);
1037}
1038
1040Memfile_LeaseMgr::getLease6Internal(Lease::Type type,
1041 const isc::asiolink::IOAddress& addr) const {
1042 Lease6Storage::iterator l = storage6_.find(addr);
1043 if (l == storage6_.end() || !(*l) || ((*l)->type_ != type)) {
1044 return (Lease6Ptr());
1045 } else {
1046 return (Lease6Ptr(new Lease6(**l)));
1047 }
1048}
1049
1052 const isc::asiolink::IOAddress& addr) const {
1055 .arg(addr.toText())
1056 .arg(Lease::typeToText(type));
1057
1058 if (MultiThreadingMgr::instance().getMode()) {
1059 std::lock_guard<std::mutex> lock(*mutex_);
1060 return (getLease6Internal(type, addr));
1061 } else {
1062 return (getLease6Internal(type, addr));
1063 }
1064}
1065
1066void
1067Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1068 const DUID& duid,
1069 uint32_t iaid,
1070 Lease6Collection& collection) const {
1071 // Get the index by DUID, IAID, lease type.
1072 const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1073 // Try to get the lease using the DUID, IAID and lease type.
1074 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1075 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1076 idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1077
1078 for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1079 l.first; lease != l.second; ++lease) {
1080 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1081 }
1082}
1083
1086 const DUID& duid,
1087 uint32_t iaid) const {
1090 .arg(iaid)
1091 .arg(duid.toText())
1092 .arg(Lease::typeToText(type));
1093
1094 Lease6Collection collection;
1095 if (MultiThreadingMgr::instance().getMode()) {
1096 std::lock_guard<std::mutex> lock(*mutex_);
1097 getLeases6Internal(type, duid, iaid, collection);
1098 } else {
1099 getLeases6Internal(type, duid, iaid, collection);
1100 }
1101
1102 return (collection);
1103}
1104
1105void
1106Memfile_LeaseMgr::getLeases6Internal(Lease::Type type,
1107 const DUID& duid,
1108 uint32_t iaid,
1109 SubnetID subnet_id,
1110 Lease6Collection& collection) const {
1111 // Get the index by DUID, IAID, lease type.
1112 const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
1113 // Try to get the lease using the DUID, IAID and lease type.
1114 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
1115 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
1116 idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
1117
1118 for (Lease6StorageDuidIaidTypeIndex::const_iterator lease =
1119 l.first; lease != l.second; ++lease) {
1120 // Filter out the leases which subnet id doesn't match.
1121 if ((*lease)->subnet_id_ == subnet_id) {
1122 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1123 }
1124 }
1125}
1126
1129 const DUID& duid,
1130 uint32_t iaid,
1131 SubnetID subnet_id) const {
1134 .arg(iaid)
1135 .arg(subnet_id)
1136 .arg(duid.toText())
1137 .arg(Lease::typeToText(type));
1138
1139 Lease6Collection collection;
1140 if (MultiThreadingMgr::instance().getMode()) {
1141 std::lock_guard<std::mutex> lock(*mutex_);
1142 getLeases6Internal(type, duid, iaid, subnet_id, collection);
1143 } else {
1144 getLeases6Internal(type, duid, iaid, subnet_id, collection);
1145 }
1146
1147 return (collection);
1148}
1149
1150void
1151Memfile_LeaseMgr::getLeases6Internal(SubnetID subnet_id,
1152 Lease6Collection& collection) const {
1153 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
1154 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
1155 Lease6StorageSubnetIdIndex::const_iterator> l =
1156 idx.equal_range(subnet_id);
1157
1158 for (auto lease = l.first; lease != l.second; ++lease) {
1159 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1160 }
1161}
1162
1166 .arg(subnet_id);
1167
1168 Lease6Collection collection;
1169 if (MultiThreadingMgr::instance().getMode()) {
1170 std::lock_guard<std::mutex> lock(*mutex_);
1171 getLeases6Internal(subnet_id, collection);
1172 } else {
1173 getLeases6Internal(subnet_id, collection);
1174 }
1175
1176 return (collection);
1177}
1178
1179void
1180Memfile_LeaseMgr::getLeases6Internal(const std::string& hostname,
1181 Lease6Collection& collection) const {
1182 const Lease6StorageHostnameIndex& idx = storage6_.get<HostnameIndexTag>();
1183 std::pair<Lease6StorageHostnameIndex::const_iterator,
1184 Lease6StorageHostnameIndex::const_iterator> l =
1185 idx.equal_range(hostname);
1186
1187 for (auto lease = l.first; lease != l.second; ++lease) {
1188 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1189 }
1190}
1191
1193Memfile_LeaseMgr::getLeases6(const std::string& hostname) const {
1195 .arg(hostname);
1196
1197 Lease6Collection collection;
1198 if (MultiThreadingMgr::instance().getMode()) {
1199 std::lock_guard<std::mutex> lock(*mutex_);
1200 getLeases6Internal(hostname, collection);
1201 } else {
1202 getLeases6Internal(hostname, collection);
1203 }
1204
1205 return (collection);
1206}
1207
1208void
1209Memfile_LeaseMgr::getLeases6Internal(Lease6Collection& collection) const {
1210 for (auto lease = storage6_.begin(); lease != storage6_.end(); ++lease) {
1211 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1212 }
1213}
1214
1218
1219 Lease6Collection collection;
1220 if (MultiThreadingMgr::instance().getMode()) {
1221 std::lock_guard<std::mutex> lock(*mutex_);
1222 getLeases6Internal(collection);
1223 } else {
1224 getLeases6Internal(collection);
1225 }
1226
1227 return (collection);
1228}
1229
1230void
1231Memfile_LeaseMgr::getLeases6Internal(const DUID& duid,
1232 Lease6Collection& collection) const {
1233 const Lease6StorageDuidIndex& idx = storage6_.get<DuidIndexTag>();
1234 std::pair<Lease6StorageDuidIndex::const_iterator,
1235 Lease6StorageDuidIndex::const_iterator> l =
1236 idx.equal_range(duid.getDuid());
1237
1238 for (auto lease = l.first; lease != l.second; ++lease) {
1239 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1240 }
1241}
1242
1246 .arg(duid.toText());
1247
1248 Lease6Collection collection;
1249 if (MultiThreadingMgr::instance().getMode()) {
1250 std::lock_guard<std::mutex> lock(*mutex_);
1251 getLeases6Internal(duid, collection);
1252 } else {
1253 getLeases6Internal(duid, collection);
1254 }
1255
1256 return (collection);
1257}
1258
1259void
1260Memfile_LeaseMgr::getLeases6Internal(const asiolink::IOAddress& lower_bound_address,
1261 const LeasePageSize& page_size,
1262 Lease6Collection& collection) const {
1263 const Lease6StorageAddressIndex& idx = storage6_.get<AddressIndexTag>();
1264 Lease6StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1265
1266 // Exclude the lower bound address specified by the caller.
1267 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1268 ++lb;
1269 }
1270
1271 // Return all other leases being within the page size.
1272 for (auto lease = lb;
1273 (lease != idx.end()) && (std::distance(lb, lease) < page_size.page_size_);
1274 ++lease) {
1275 collection.push_back(Lease6Ptr(new Lease6(**lease)));
1276 }
1277}
1278
1281 const LeasePageSize& page_size) const {
1282 // Expecting IPv6 address.
1283 if (!lower_bound_address.isV6()) {
1284 isc_throw(InvalidAddressFamily, "expected IPv6 address while "
1285 "retrieving leases from the lease database, got "
1286 << lower_bound_address);
1287 }
1288
1290 .arg(page_size.page_size_)
1291 .arg(lower_bound_address.toText());
1292
1293 Lease6Collection collection;
1294 if (MultiThreadingMgr::instance().getMode()) {
1295 std::lock_guard<std::mutex> lock(*mutex_);
1296 getLeases6Internal(lower_bound_address, page_size, collection);
1297 } else {
1298 getLeases6Internal(lower_bound_address, page_size, collection);
1299 }
1300
1301 return (collection);
1302}
1303
1304void
1305Memfile_LeaseMgr::getExpiredLeases4Internal(Lease4Collection& expired_leases,
1306 const size_t max_leases) const {
1307 // Obtain the index which segragates leases by state and time.
1308 const Lease4StorageExpirationIndex& index = storage4_.get<ExpirationIndexTag>();
1309
1310 // Retrieve leases which are not reclaimed and which haven't expired. The
1311 // 'less-than' operator will be used for both components of the index. So,
1312 // for the 'state' 'false' is less than 'true'. Also the leases with
1313 // expiration time lower than current time will be returned.
1314 Lease4StorageExpirationIndex::const_iterator ub =
1315 index.upper_bound(boost::make_tuple(false, time(NULL)));
1316
1317 // Copy only the number of leases indicated by the max_leases parameter.
1318 for (Lease4StorageExpirationIndex::const_iterator lease = index.begin();
1319 (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1320 max_leases));
1321 ++lease) {
1322 expired_leases.push_back(Lease4Ptr(new Lease4(**lease)));
1323 }
1324}
1325
1326void
1328 const size_t max_leases) const {
1330 .arg(max_leases);
1331
1332 if (MultiThreadingMgr::instance().getMode()) {
1333 std::lock_guard<std::mutex> lock(*mutex_);
1334 getExpiredLeases4Internal(expired_leases, max_leases);
1335 } else {
1336 getExpiredLeases4Internal(expired_leases, max_leases);
1337 }
1338}
1339
1340void
1341Memfile_LeaseMgr::getExpiredLeases6Internal(Lease6Collection& expired_leases,
1342 const size_t max_leases) const {
1343 // Obtain the index which segragates leases by state and time.
1344 const Lease6StorageExpirationIndex& index = storage6_.get<ExpirationIndexTag>();
1345
1346 // Retrieve leases which are not reclaimed and which haven't expired. The
1347 // 'less-than' operator will be used for both components of the index. So,
1348 // for the 'state' 'false' is less than 'true'. Also the leases with
1349 // expiration time lower than current time will be returned.
1350 Lease6StorageExpirationIndex::const_iterator ub =
1351 index.upper_bound(boost::make_tuple(false, time(NULL)));
1352
1353 // Copy only the number of leases indicated by the max_leases parameter.
1354 for (Lease6StorageExpirationIndex::const_iterator lease = index.begin();
1355 (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1356 max_leases));
1357 ++lease) {
1358 expired_leases.push_back(Lease6Ptr(new Lease6(**lease)));
1359 }
1360}
1361
1362void
1364 const size_t max_leases) const {
1366 .arg(max_leases);
1367
1368 if (MultiThreadingMgr::instance().getMode()) {
1369 std::lock_guard<std::mutex> lock(*mutex_);
1370 getExpiredLeases6Internal(expired_leases, max_leases);
1371 } else {
1372 getExpiredLeases6Internal(expired_leases, max_leases);
1373 }
1374}
1375
1376void
1377Memfile_LeaseMgr::updateLease4Internal(const Lease4Ptr& lease) {
1378 // Obtain 'by address' index.
1379 Lease4StorageAddressIndex& index = storage4_.get<AddressIndexTag>();
1380
1381 bool persist = persistLeases(V4);
1382
1383 // Lease must exist if it is to be updated.
1384 Lease4StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1385 if (lease_it == index.end()) {
1386 isc_throw(NoSuchLease, "failed to update the lease with address "
1387 << lease->addr_ << " - no such lease");
1388 } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1389 ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1390 // For test purpose only: check that the lease has not changed in
1391 // the database.
1392 isc_throw(NoSuchLease, "failed to update the lease with address "
1393 << lease->addr_ << " - lease has changed in database");
1394 }
1395
1396 // Try to write a lease to disk first. If this fails, the lease will
1397 // not be inserted to the memory and the disk and in-memory data will
1398 // remain consistent.
1399 if (persist) {
1400 lease_file4_->append(*lease);
1401 }
1402
1403 // Update lease current expiration time.
1404 lease->updateCurrentExpirationTime();
1405
1406 // Use replace() to re-index leases.
1407 index.replace(lease_it, Lease4Ptr(new Lease4(*lease)));
1408}
1409
1410void
1413 DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
1414
1415 if (MultiThreadingMgr::instance().getMode()) {
1416 std::lock_guard<std::mutex> lock(*mutex_);
1417 updateLease4Internal(lease);
1418 } else {
1419 updateLease4Internal(lease);
1420 }
1421}
1422
1423void
1424Memfile_LeaseMgr::updateLease6Internal(const Lease6Ptr& lease) {
1425 // Obtain 'by address' index.
1426 Lease6StorageAddressIndex& index = storage6_.get<AddressIndexTag>();
1427
1428 bool persist = persistLeases(V6);
1429
1430 // Lease must exist if it is to be updated.
1431 Lease6StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1432 if (lease_it == index.end()) {
1433 isc_throw(NoSuchLease, "failed to update the lease with address "
1434 << lease->addr_ << " - no such lease");
1435 } else if ((!persist) && (((*lease_it)->cltt_ != lease->current_cltt_) ||
1436 ((*lease_it)->valid_lft_ != lease->current_valid_lft_))) {
1437 // For test purpose only: check that the lease has not changed in
1438 // the database.
1439 isc_throw(NoSuchLease, "failed to update the lease with address "
1440 << lease->addr_ << " - lease has changed in database");
1441 }
1442
1443 // Try to write a lease to disk first. If this fails, the lease will
1444 // not be inserted to the memory and the disk and in-memory data will
1445 // remain consistent.
1446 if (persist) {
1447 lease_file6_->append(*lease);
1448 }
1449
1450 // Update lease current expiration time.
1451 lease->updateCurrentExpirationTime();
1452
1453 // Use replace() to re-index leases.
1454 index.replace(lease_it, Lease6Ptr(new Lease6(*lease)));
1455}
1456
1457void
1460 DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
1461
1462 if (MultiThreadingMgr::instance().getMode()) {
1463 std::lock_guard<std::mutex> lock(*mutex_);
1464 updateLease6Internal(lease);
1465 } else {
1466 updateLease6Internal(lease);
1467 }
1468}
1469
1470bool
1471Memfile_LeaseMgr::deleteLeaseInternal(const Lease4Ptr& lease) {
1472 const isc::asiolink::IOAddress& addr = lease->addr_;
1473 Lease4Storage::iterator l = storage4_.find(addr);
1474 if (l == storage4_.end()) {
1475 // No such lease
1476 return (false);
1477 } else {
1478 if (persistLeases(V4)) {
1479 // Copy the lease. The valid lifetime needs to be modified and
1480 // we don't modify the original lease.
1481 Lease4 lease_copy = **l;
1482 // Setting valid lifetime to 0 means that lease is being
1483 // removed.
1484 lease_copy.valid_lft_ = 0;
1485 lease_file4_->append(lease_copy);
1486 } else {
1487 // For test purpose only: check that the lease has not changed in
1488 // the database.
1489 if (((*l)->cltt_ != lease->current_cltt_) ||
1490 ((*l)->valid_lft_ != lease->current_valid_lft_)) {
1491 return false;
1492 }
1493 }
1494 storage4_.erase(l);
1495 return (true);
1496 }
1497}
1498
1499bool
1502 DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
1503
1504 if (MultiThreadingMgr::instance().getMode()) {
1505 std::lock_guard<std::mutex> lock(*mutex_);
1506 return (deleteLeaseInternal(lease));
1507 } else {
1508 return (deleteLeaseInternal(lease));
1509 }
1510}
1511
1512bool
1513Memfile_LeaseMgr::deleteLeaseInternal(const Lease6Ptr& lease) {
1514 const isc::asiolink::IOAddress& addr = lease->addr_;
1515 Lease6Storage::iterator l = storage6_.find(addr);
1516 if (l == storage6_.end()) {
1517 // No such lease
1518 return (false);
1519 } else {
1520 if (persistLeases(V6)) {
1521 // Copy the lease. The lifetimes need to be modified and we
1522 // don't modify the original lease.
1523 Lease6 lease_copy = **l;
1524 // Setting lifetimes to 0 means that lease is being removed.
1525 lease_copy.valid_lft_ = 0;
1526 lease_copy.preferred_lft_ = 0;
1527 lease_file6_->append(lease_copy);
1528 } else {
1529 // For test purpose only: check that the lease has not changed in
1530 // the database.
1531 if (((*l)->cltt_ != lease->current_cltt_) ||
1532 ((*l)->valid_lft_ != lease->current_valid_lft_)) {
1533 return false;
1534 }
1535 }
1536 storage6_.erase(l);
1537 return (true);
1538 }
1539}
1540
1541bool
1544 DHCPSRV_MEMFILE_DELETE_ADDR).arg(lease->addr_.toText());
1545
1546 if (MultiThreadingMgr::instance().getMode()) {
1547 std::lock_guard<std::mutex> lock(*mutex_);
1548 return (deleteLeaseInternal(lease));
1549 } else {
1550 return (deleteLeaseInternal(lease));
1551 }
1552}
1553
1554uint64_t
1558 .arg(secs);
1559
1560 if (MultiThreadingMgr::instance().getMode()) {
1561 std::lock_guard<std::mutex> lock(*mutex_);
1562 return (deleteExpiredReclaimedLeases<
1564 >(secs, V4, storage4_, lease_file4_));
1565 } else {
1566 return (deleteExpiredReclaimedLeases<
1568 >(secs, V4, storage4_, lease_file4_));
1569 }
1570}
1571
1572uint64_t
1576 .arg(secs);
1577
1578 if (MultiThreadingMgr::instance().getMode()) {
1579 std::lock_guard<std::mutex> lock(*mutex_);
1580 return (deleteExpiredReclaimedLeases<
1582 >(secs, V6, storage6_, lease_file6_));
1583 } else {
1584 return (deleteExpiredReclaimedLeases<
1586 >(secs, V6, storage6_, lease_file6_));
1587 }
1588}
1589
1590template<typename IndexType, typename LeaseType, typename StorageType,
1591 typename LeaseFileType>
1592uint64_t
1593Memfile_LeaseMgr::deleteExpiredReclaimedLeases(const uint32_t secs,
1594 const Universe& universe,
1595 StorageType& storage,
1596 LeaseFileType& lease_file) const {
1597 // Obtain the index which segragates leases by state and time.
1598 IndexType& index = storage.template get<ExpirationIndexTag>();
1599
1600 // This returns the first element which is greater than the specified
1601 // tuple (true, time(NULL) - secs). However, the range between the
1602 // beginning of the index and returned element also includes all the
1603 // elements for which the first value is false (lease state is NOT
1604 // reclaimed), because false < true. All elements between the
1605 // beginning of the index and the element returned, for which the
1606 // first value is true, represent the reclaimed leases which should
1607 // be deleted, because their expiration time + secs has occurred earlier
1608 // than current time.
1609 typename IndexType::const_iterator upper_limit =
1610 index.upper_bound(boost::make_tuple(true, time(NULL) - secs));
1611
1612 // Now, we have to exclude all elements of the index which represent
1613 // leases in the state other than reclaimed - with the first value
1614 // in the index equal to false. Note that elements in the index are
1615 // ordered from the lower to the higher ones. So, all elements with
1616 // the first value of false are placed before the elements with the
1617 // value of true. Hence, we have to find the first element which
1618 // contains value of true. The time value is the lowest possible.
1619 typename IndexType::const_iterator lower_limit =
1620 index.upper_bound(boost::make_tuple(true, std::numeric_limits<int64_t>::min()));
1621
1622 // If there are some elements in this range, delete them.
1623 uint64_t num_leases = static_cast<uint64_t>(std::distance(lower_limit, upper_limit));
1624 if (num_leases > 0) {
1625
1628 .arg(num_leases);
1629
1630 // If lease persistence is enabled, we also have to mark leases
1631 // as deleted in the lease file. We do this by setting the
1632 // lifetime to 0.
1633 if (persistLeases(universe)) {
1634 for (typename IndexType::const_iterator lease = lower_limit;
1635 lease != upper_limit; ++lease) {
1636 // Copy lease to not affect the lease in the container.
1637 LeaseType lease_copy(**lease);
1638 // Set the valid lifetime to 0 to indicate the removal
1639 // of the lease.
1640 lease_copy.valid_lft_ = 0;
1641 lease_file->append(lease_copy);
1642 }
1643 }
1644
1645 // Erase leases from memory.
1646 index.erase(lower_limit, upper_limit);
1647 }
1648 // Return number of leases deleted.
1649 return (num_leases);
1650}
1651
1652
1653std::string
1655 return (std::string("In memory database with leases stored in a CSV file."));
1656}
1657
1658void
1661}
1662
1663void
1667}
1668
1669std::string
1670Memfile_LeaseMgr::appendSuffix(const std::string& file_name,
1671 const LFCFileType& file_type) {
1672 std::string name(file_name);
1673 switch (file_type) {
1674 case FILE_INPUT:
1675 name += ".1";
1676 break;
1677 case FILE_PREVIOUS:
1678 name += ".2";
1679 break;
1680 case FILE_OUTPUT:
1681 name += ".output";
1682 break;
1683 case FILE_FINISH:
1684 name += ".completed";
1685 break;
1686 case FILE_PID:
1687 name += ".pid";
1688 break;
1689 default:
1690 // Do not append any suffix for the FILE_CURRENT.
1691 ;
1692 }
1693
1694 return (name);
1695}
1696
1697std::string
1699 std::ostringstream s;
1700 s << CfgMgr::instance().getDataDir() << "/kea-leases";
1701 s << (u == V4 ? "4" : "6");
1702 s << ".csv";
1703 return (s.str());
1704}
1705
1706std::string
1708 if (u == V4) {
1709 return (lease_file4_ ? lease_file4_->getFilename() : "");
1710 }
1711
1712 return (lease_file6_ ? lease_file6_->getFilename() : "");
1713}
1714
1715bool
1717 // Currently, if the lease file IO is not created, it means that writes to
1718 // disk have been explicitly disabled by the administrator. At some point,
1719 // there may be a dedicated ON/OFF flag implemented to control this.
1720 if (u == V4 && lease_file4_) {
1721 return (true);
1722 }
1723
1724 return (u == V6 && lease_file6_);
1725}
1726
1727std::string
1728Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
1729 std::string persist_val;
1730 try {
1731 persist_val = conn_.getParameter("persist");
1732 } catch (const Exception&) {
1733 // If parameter persist hasn't been specified, we use a default value
1734 // 'yes'.
1735 persist_val = "true";
1736 }
1737 // If persist_val is 'false' we will not store leases to disk, so let's
1738 // return empty file name.
1739 if (persist_val == "false") {
1740 return ("");
1741
1742 } else if (persist_val != "true") {
1743 isc_throw(isc::BadValue, "invalid value 'persist="
1744 << persist_val << "'");
1745 }
1746
1747 std::string lease_file;
1748 try {
1749 lease_file = conn_.getParameter("name");
1750 } catch (const Exception&) {
1751 lease_file = getDefaultLeaseFilePath(u);
1752 }
1753 return (lease_file);
1754}
1755
1756template<typename LeaseObjectType, typename LeaseFileType, typename StorageType>
1757bool
1758Memfile_LeaseMgr::loadLeasesFromFiles(const std::string& filename,
1759 boost::shared_ptr<LeaseFileType>& lease_file,
1760 StorageType& storage) {
1761 // Check if the instance of the LFC is running right now. If it is
1762 // running, we refuse to load leases as the LFC may be writing to the
1763 // lease files right now. When the user retries server configuration
1764 // it should go through.
1767 PIDFile pid_file(appendSuffix(filename, FILE_PID));
1768 if (pid_file.check()) {
1769 isc_throw(DbOpenError, "unable to load leases from files while the "
1770 "lease file cleanup is in progress");
1771 }
1772
1773 storage.clear();
1774
1775 std::string max_row_errors_str = "0";
1776 try {
1777 max_row_errors_str = conn_.getParameter("max-row-errors");
1778 } catch (const std::exception&) {
1779 // Ignore and default to 0.
1780 }
1781
1782 uint32_t max_row_errors = 0;
1783 try {
1784 max_row_errors = boost::lexical_cast<uint32_t>(max_row_errors_str);
1785 } catch (const boost::bad_lexical_cast&) {
1786 isc_throw(isc::BadValue, "invalid value of the max-row-errors "
1787 << max_row_errors_str << " specified");
1788 }
1789
1790 // Load the leasefile.completed, if exists.
1791 bool conversion_needed = false;
1792 lease_file.reset(new LeaseFileType(std::string(filename + ".completed")));
1793 if (lease_file->exists()) {
1794 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1795 max_row_errors);
1796 conversion_needed = conversion_needed || lease_file->needsConversion();
1797 } else {
1798 // If the leasefile.completed doesn't exist, let's load the leases
1799 // from leasefile.2 and leasefile.1, if they exist.
1800 lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_PREVIOUS)));
1801 if (lease_file->exists()) {
1802 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1803 max_row_errors);
1804 conversion_needed = conversion_needed || lease_file->needsConversion();
1805 }
1806
1807 lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_INPUT)));
1808 if (lease_file->exists()) {
1809 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1810 max_row_errors);
1811 conversion_needed = conversion_needed || lease_file->needsConversion();
1812 }
1813 }
1814
1815 // Always load leases from the primary lease file. If the lease file
1816 // doesn't exist it will be created by the LeaseFileLoader. Note
1817 // that the false value passed as the last parameter to load
1818 // function causes the function to leave the file open after
1819 // it is parsed. This file will be used by the backend to record
1820 // future lease updates.
1821 lease_file.reset(new LeaseFileType(filename));
1822 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1823 max_row_errors, false);
1824 conversion_needed = conversion_needed || lease_file->needsConversion();
1825
1826 return (conversion_needed);
1827}
1828
1829
1830bool
1832 return (lfc_setup_->isRunning());
1833}
1834
1835int
1837 return (lfc_setup_->getExitStatus());
1838}
1839
1840void
1843
1844 // Check if we're in the v4 or v6 space and use the appropriate file.
1845 if (lease_file4_) {
1847 lfcExecute(lease_file4_);
1848 } else if (lease_file6_) {
1850 lfcExecute(lease_file6_);
1851 }
1852}
1853
1854void
1855Memfile_LeaseMgr::lfcSetup(bool conversion_needed) {
1856 std::string lfc_interval_str = "3600";
1857 try {
1858 lfc_interval_str = conn_.getParameter("lfc-interval");
1859 } catch (const std::exception&) {
1860 // Ignore and default to 3600.
1861 }
1862
1863 uint32_t lfc_interval = 0;
1864 try {
1865 lfc_interval = boost::lexical_cast<uint32_t>(lfc_interval_str);
1866 } catch (const boost::bad_lexical_cast&) {
1867 isc_throw(isc::BadValue, "invalid value of the lfc-interval "
1868 << lfc_interval_str << " specified");
1869 }
1870
1871 if (lfc_interval > 0 || conversion_needed) {
1872 lfc_setup_.reset(new LFCSetup(std::bind(&Memfile_LeaseMgr::lfcCallback, this)));
1873 lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_, conversion_needed);
1874 }
1875}
1876
1877template<typename LeaseFileType>
1878void
1879Memfile_LeaseMgr::lfcExecute(boost::shared_ptr<LeaseFileType>& lease_file) {
1880 bool do_lfc = true;
1881
1882 // Check the status of the LFC instance.
1883 // If the finish file exists or the copy of the lease file exists it
1884 // is an indication that another LFC instance may be in progress or
1885 // may be stalled. In that case we don't want to rotate the current
1886 // lease file to avoid overriding the contents of the existing file.
1887 CSVFile lease_file_finish(appendSuffix(lease_file->getFilename(), FILE_FINISH));
1888 CSVFile lease_file_copy(appendSuffix(lease_file->getFilename(), FILE_INPUT));
1889 if (!lease_file_finish.exists() && !lease_file_copy.exists()) {
1890 // Close the current file so as we can move it to the copy file.
1891 lease_file->close();
1892 // Move the current file to the copy file. Remember the result
1893 // because we don't want to run LFC if the rename failed.
1894 do_lfc = (rename(lease_file->getFilename().c_str(),
1895 lease_file_copy.getFilename().c_str()) == 0);
1896
1897 if (!do_lfc) {
1899 .arg(lease_file->getFilename())
1900 .arg(lease_file_copy.getFilename())
1901 .arg(strerror(errno));
1902 }
1903
1904 // Regardless if we successfully moved the current file or not,
1905 // we need to re-open the current file for the server to write
1906 // new lease updates. If the file has been successfully moved,
1907 // this will result in creation of the new file. Otherwise,
1908 // an existing file will be opened.
1909 try {
1910 lease_file->open(true);
1911
1912 } catch (const CSVFileError& ex) {
1913 // If we're unable to open the lease file this is a serious
1914 // error because the server will not be able to persist
1915 // leases.
1923 .arg(lease_file->getFilename())
1924 .arg(ex.what());
1925 // Reset the pointer to the file so as the backend doesn't
1926 // try to write leases to disk.
1927 lease_file.reset();
1928 do_lfc = false;
1929 }
1930 }
1931 // Once the files have been rotated, or untouched if another LFC had
1932 // not finished, a new process is started.
1933 if (do_lfc) {
1934 lfc_setup_->execute();
1935 }
1936}
1937
1940 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_));
1941 query->start();
1942 return(query);
1943}
1944
1947 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, subnet_id));
1948 query->start();
1949 return(query);
1950}
1951
1954 const SubnetID& last_subnet_id) {
1955 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_, first_subnet_id,
1956 last_subnet_id));
1957 query->start();
1958 return(query);
1959}
1960
1963 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_));
1964 query->start();
1965 return(query);
1966}
1967
1970 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, subnet_id));
1971 query->start();
1972 return(query);
1973}
1974
1977 const SubnetID& last_subnet_id) {
1978 LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery6(storage6_, first_subnet_id,
1979 last_subnet_id));
1980 query->start();
1981 return(query);
1982}
1983
1984size_t
1987 .arg(subnet_id);
1988
1989 // Get the index by DUID, IAID, lease type.
1990 const Lease4StorageSubnetIdIndex& idx = storage4_.get<SubnetIdIndexTag>();
1991
1992 // Try to get the lease using the DUID, IAID and lease type.
1993 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
1994 Lease4StorageSubnetIdIndex::const_iterator> l =
1995 idx.equal_range(subnet_id);
1996
1997 // Let's collect all leases.
1998 Lease4Collection leases;
1999 for (auto lease = l.first; lease != l.second; ++lease) {
2000 leases.push_back(*lease);
2001 }
2002
2003 size_t num = leases.size();
2004 for (auto l = leases.begin(); l != leases.end(); ++l) {
2005 deleteLease(*l);
2006 }
2008 .arg(subnet_id).arg(num);
2009
2010 return (num);
2011}
2012
2013size_t
2016 .arg(subnet_id);
2017
2018 // Get the index by DUID, IAID, lease type.
2019 const Lease6StorageSubnetIdIndex& idx = storage6_.get<SubnetIdIndexTag>();
2020
2021 // Try to get the lease using the DUID, IAID and lease type.
2022 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
2023 Lease6StorageSubnetIdIndex::const_iterator> l =
2024 idx.equal_range(subnet_id);
2025
2026 // Let's collect all leases.
2027 Lease6Collection leases;
2028 for (auto lease = l.first; lease != l.second; ++lease) {
2029 leases.push_back(*lease);
2030 }
2031
2032 size_t num = leases.size();
2033 for (auto l = leases.begin(); l != leases.end(); ++l) {
2034 deleteLease(*l);
2035 }
2037 .arg(subnet_id).arg(num);
2038
2039 return (num);
2040}
2041
2042} // namespace dhcp
2043} // namespace isc
2044
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:71
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
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:222
static isc::asiolink::IOServicePtr & getIOService()
Returns pointer to the IO service.
Definition: lease_mgr.h:758
Wraps value holding size of the page with leases.
Definition: lease_mgr.h:43
const size_t page_size_
Holds page size.
Definition: lease_mgr.h:53
Base class for fulfilling a statistical lease data query.
Definition: lease_mgr.h:128
SubnetID getLastSubnetID() const
Returns the value of last subnet ID specified (or zero)
Definition: lease_mgr.h:183
SubnetID getFirstSubnetID() const
Returns the value of first subnet ID specified (or zero)
Definition: lease_mgr.h:178
SelectMode getSelectMode() const
Returns the selection criteria mode The value returned is based upon the constructor variant used and...
Definition: lease_mgr.h:190
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 Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const
Returns existing IPv4 lease for specified IPv4 address.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery6(const SubnetID &subnet_id)
Creates and runs the IPv6 lease stats query for a single subnet.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs)
Deletes all expired-reclaimed DHCPv6 leases.
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 size_t wipeLeases4(const SubnetID &subnet_id)
Removes specified IPv4 leases.
virtual size_t wipeLeases6(const SubnetID &subnet_id)
Removed specified IPv6 leases.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs)
Deletes all expired-reclaimed DHCPv4 leases.
virtual void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const
Returns a collection of expired DHCPv6 leases.
Universe
Specifies universe (V4, V6)
virtual std::string getDescription() const
Returns description of the backend.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery4(const SubnetID &subnet_id)
Creates and runs the IPv4 lease stats query for a single subnet.
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery4(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Creates and runs the IPv4 lease stats query for a single subnet.
LFCFileType
Types of the lease files used by the Lease File Cleanup.
@ FILE_PREVIOUS
Previous Lease File.
virtual void commit()
Commit Transactions.
virtual bool deleteLease(const Lease4Ptr &lease)
Deletes an IPv4 lease.
virtual bool addLease(const Lease4Ptr &lease)
Adds an IPv4 lease.
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.
static std::string getDBVersion()
Local version of getDBVersion() class method.
virtual LeaseStatsQueryPtr startLeaseStatsQuery6()
Creates and runs the IPv6 lease stats query.
virtual void rollback()
Rollback Transactions.
virtual LeaseStatsQueryPtr startLeaseStatsQuery4()
Creates and runs the IPv4 lease stats query.
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const
Returns a collection of expired DHCPv4 leases.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const
Returns existing IPv6 lease for a given IPv6 address.
virtual Lease6Collection getLeases6() const
Returns all IPv6 leases.
std::string getLeaseFilePath(Universe u) const
Returns an absolute path to the lease file.
virtual void lfcCallback()
A callback function triggering Lease File Cleanup (LFC).
virtual void updateLease4(const Lease4Ptr &lease4)
Updates IPv4 lease.
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery6(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Creates and runs the IPv6 lease stats query for a single subnet.
virtual Lease4Collection getLeases4() const
Returns all IPv4 leases.
static std::string appendSuffix(const std::string &file_name, const LFCFileType &file_type)
Appends appropriate suffix to the file name.
virtual void updateLease6(const Lease6Ptr &lease6)
Updates IPv6 lease.
virtual ~Memfile_LeaseMgr()
Destructor (closes file)
std::string getDefaultLeaseFilePath(Universe u) const
Returns default path to the lease file.
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 MINOR_VERSION
Defines minor version of the 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
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_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:492
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:640
boost::shared_ptr< LeaseStatsQuery > LeaseStatsQueryPtr
Defines a pointer to a LeaseStatsQuery.
Definition: lease_mgr.h:207
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
Unique identifier for a subnet (both v4 and v6)
Definition: lease.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:487
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:283
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:294
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:503
Contains a single row of lease statistical data.
Definition: lease_mgr.h:61
static const uint32_t STATE_DEFAULT
A lease in the default state.
Definition: lease.h:73
static const uint32_t STATE_DECLINED
Declined lease.
Definition: lease.h:76
Type
Type of lease or pool.
Definition: lease.h:50
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
Definition: lease.h:53
@ TYPE_NA
the lease contains non-temporary IPv6 address
Definition: lease.h:51
static std::string typeToText(Type type)
returns text representation of a lease type
Definition: lease.cc:52
Tag for indexes by subnet-id.