29 const uint32_t MAX_LEASE_ERRORS = 100;
38 const char* KEA_LFC_EXECUTABLE_ENV_NAME =
"KEA_LFC_EXECUTABLE";
91 void setup(
const uint32_t lfc_interval,
92 const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
93 const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
94 bool run_once_now =
false);
102 bool isRunning()
const;
105 int getExitStatus()
const;
111 boost::scoped_ptr<util::ProcessSpawn> process_;
127 : process_(), callback_(callback), pid_(0),
143 timer_mgr_->unregisterTimer(
"memfile-lfc");
145 }
catch (
const std::exception& ex) {
150 DHCPSRV_MEMFILE_LFC_UNREGISTER_TIMER_FAILED).arg(ex.what());
156 const boost::shared_ptr<CSVLeaseFile4>& lease_file4,
157 const boost::shared_ptr<CSVLeaseFile6>& lease_file6,
161 if (lfc_interval == 0 && !run_once_now) {
166 std::string executable;
167 char* c_executable = getenv(KEA_LFC_EXECUTABLE_ENV_NAME);
168 if (c_executable == NULL) {
169 executable = KEA_LFC_EXECUTABLE;
171 executable = c_executable;
175 std::string lease_file = lease_file4 ? lease_file4->getFilename() :
176 lease_file6->getFilename();
181 args.push_back(lease_file4 ?
"-4" :
"-6");
184 args.push_back(
"-x");
188 args.push_back(
"-i");
192 args.push_back(
"-o");
196 args.push_back(
"-f");
200 args.push_back(
"-p");
205 args.push_back(
"-c");
206 args.push_back(
"ignored-path");
217 if (lfc_interval > 0) {
224 timer_mgr_->registerTimer(
"memfile-lfc", callback_, lfc_interval * 1000,
226 timer_mgr_->setup(
"memfile-lfc");
234 .arg(process_->getCommandLine());
235 pid_ = process_->spawn();
244 return (process_ && process_->isRunning(pid_));
251 " the process is NULL");
253 return (process_->getExitStatus(pid_));
310 return (
rows_.size());
379 Lease4StorageSubnetIdIndex::const_iterator lower;
380 Lease4StorageSubnetIdIndex::const_iterator upper;
399 if (lower == upper) {
407 int64_t assigned = 0;
408 int64_t declined = 0;
409 for(Lease4StorageSubnetIdIndex::const_iterator lease = lower;
410 lease != upper; ++lease) {
413 if ((*lease)->subnet_id_ != cur_id) {
431 cur_id = (*lease)->subnet_id_;
521 Lease6StorageSubnetIdIndex::const_iterator lower;
522 Lease6StorageSubnetIdIndex::const_iterator upper;
541 if (lower == upper) {
549 int64_t assigned = 0;
550 int64_t declined = 0;
551 int64_t assigned_pds = 0;
552 for(Lease6StorageSubnetIdIndex::const_iterator lease = lower;
553 lease != upper; ++lease) {
556 if ((*lease)->subnet_id_ != cur_id) {
572 if (assigned_pds > 0) {
581 cur_id = (*lease)->subnet_id_;
586 switch((*lease)->type_) {
615 if (assigned_pds > 0) {
635 :
LeaseMgr(), lfc_setup_(), conn_(parameters)
637 bool conversion_needed =
false;
641 if (universe ==
"4") {
642 std::string file4 = initLeaseFilePath(
V4);
643 if (!file4.empty()) {
644 conversion_needed = loadLeasesFromFiles<
Lease4,
650 std::string file6 = initLeaseFilePath(
V6);
651 if (!file6.empty()) {
652 conversion_needed = loadLeasesFromFiles<
Lease6,
666 if (conversion_needed) {
670 lfcSetup(conversion_needed);
677 lease_file4_->close();
678 lease_file4_.reset();
681 lease_file6_->close();
682 lease_file6_.reset();
688 std::stringstream tmp;
697 DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
708 lease_file4_->append(*lease);
711 storage4_.insert(lease);
718 DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
720 if (
getLease6(lease->type_, lease->addr_)) {
729 lease_file6_->append(*lease);
732 storage6_.insert(lease);
739 DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.
toText());
742 Lease4StorageAddressIndex::iterator l = idx.find(addr);
743 if (l == idx.end()) {
753 DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.
toText());
760 std::pair<Lease4StorageHWAddressSubnetIdIndex::const_iterator,
761 Lease4StorageHWAddressSubnetIdIndex::const_iterator> l
762 = idx.equal_range(boost::make_tuple(hwaddr.
hwaddr_));
764 for(
auto lease = l.first; lease != l.second; ++lease) {
774 DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
781 Lease4StorageHWAddressSubnetIdIndex::const_iterator lease =
782 idx.find(boost::make_tuple(hwaddr.
hwaddr_, subnet_id));
784 if (lease == idx.end()) {
795 DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.
toText());
801 std::pair<Lease4StorageClientIdSubnetIdIndex::const_iterator,
802 Lease4StorageClientIdSubnetIdIndex::const_iterator> l
803 = idx.equal_range(boost::make_tuple(client_id.
getClientId()));
805 for(
auto lease = l.first; lease != l.second; ++lease) {
817 DHCPSRV_MEMFILE_GET_CLIENTID_HWADDR_SUBID).arg(client_id.
toText())
825 Lease4StorageClientIdHWAddressSubnetIdIndex::const_iterator lease =
829 if (lease == idx.end()) {
842 DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id)
849 Lease4StorageClientIdSubnetIdIndex::const_iterator lease =
850 idx.find(boost::make_tuple(client_id.
getClientId(), subnet_id));
852 if (lease == idx.end()) {
866 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
867 Lease4StorageSubnetIdIndex::const_iterator> l =
868 idx.equal_range(subnet_id);
870 for (
auto lease = l.first; lease != l.second; ++lease) {
882 for (
auto lease = storage4_.begin(); lease != storage4_.end(); ++lease ) {
893 if (!lower_bound_address.
isV4()) {
895 "retrieving leases from the lease database, got "
896 << lower_bound_address);
901 .arg(lower_bound_address.
toText());
905 Lease4StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
908 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
913 for (
auto lease = lb;
914 (lease != idx.end()) && (std::distance(lb, lease) < page_size.
page_size_);
926 DHCPSRV_MEMFILE_GET_ADDR6)
929 Lease6Storage::iterator l = storage6_.find(addr);
930 if (l == storage6_.end() || !(*l) || ((*l)->type_ != type)) {
939 const DUID& duid, uint32_t iaid)
const {
941 DHCPSRV_MEMFILE_GET_IAID_DUID)
949 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
950 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
951 idx.equal_range(boost::make_tuple(duid.
getDuid(), iaid, type));
953 for(Lease6StorageDuidIaidTypeIndex::const_iterator lease =
954 l.first; lease != l.second; ++lease) {
963 const DUID& duid, uint32_t iaid,
966 DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID)
975 std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
976 Lease6StorageDuidIaidTypeIndex::const_iterator> l =
977 idx.equal_range(boost::make_tuple(duid.
getDuid(), iaid, type));
979 for(Lease6StorageDuidIaidTypeIndex::const_iterator lease =
980 l.first; lease != l.second; ++lease) {
982 if((*lease)->subnet_id_ == subnet_id) {
997 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
998 Lease6StorageSubnetIdIndex::const_iterator> l =
999 idx.equal_range(subnet_id);
1001 for (
auto lease = l.first; lease != l.second; ++lease) {
1005 return (collection);
1013 for (
auto lease = storage6_.begin(); lease != storage6_.end(); ++lease ) {
1017 return (collection);
1027 std::pair<Lease6StorageDuidIndex::const_iterator,
1028 Lease6StorageDuidIndex::const_iterator> l =
1029 idx.equal_range(duid.
getDuid());
1031 for (
auto lease = l.first; lease != l.second; ++lease) {
1035 return (collection);
1042 if (!lower_bound_address.
isV6()) {
1044 "retrieving leases from the lease database, got "
1045 << lower_bound_address);
1050 .arg(lower_bound_address.
toText());
1054 Lease6StorageAddressIndex::const_iterator lb = idx.lower_bound(lower_bound_address);
1057 if ((lb != idx.end()) && ((*lb)->addr_ == lower_bound_address)) {
1062 for (
auto lease = lb;
1063 (lease != idx.end()) && (std::distance(lb, lease) < page_size.
page_size_);
1068 return (collection);
1073 const size_t max_leases)
const {
1084 Lease4StorageExpirationIndex::const_iterator ub =
1085 index.upper_bound(boost::make_tuple(
false, time(NULL)));
1088 for (Lease4StorageExpirationIndex::const_iterator lease = index.begin();
1089 (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1098 const size_t max_leases)
const {
1109 Lease6StorageExpirationIndex::const_iterator ub =
1110 index.upper_bound(boost::make_tuple(
false, time(NULL)));
1113 for (Lease6StorageExpirationIndex::const_iterator lease = index.begin();
1114 (lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
1124 DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
1130 Lease4StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1131 if (lease_it == index.end()) {
1133 << lease->addr_ <<
" - no such lease");
1140 lease_file4_->append(*lease);
1150 DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
1156 Lease6StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
1157 if (lease_it == index.end()) {
1159 << lease->addr_ <<
" - no such lease");
1166 lease_file6_->append(*lease);
1176 DHCPSRV_MEMFILE_DELETE_ADDR).arg(addr.
toText());
1179 Lease4Storage::iterator l = storage4_.find(addr);
1180 if (l == storage4_.end()) {
1191 lease_file4_->append(lease_copy);
1199 Lease6Storage::iterator l = storage6_.find(addr);
1200 if (l == storage6_.end()) {
1211 lease_file6_->append(lease_copy);
1223 DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED4)
1225 return (deleteExpiredReclaimedLeases<
1227 >(secs,
V4, storage4_, lease_file4_));
1233 DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED6)
1235 return (deleteExpiredReclaimedLeases<
1237 >(secs,
V6, storage6_, lease_file6_));
1240 template<
typename IndexType,
typename LeaseType,
typename StorageType,
1241 typename LeaseFileType>
1243 Memfile_LeaseMgr::deleteExpiredReclaimedLeases(
const uint32_t secs,
1244 const Universe& universe,
1245 StorageType& storage,
1246 LeaseFileType& lease_file)
const {
1248 IndexType& index = storage.template get<ExpirationIndexTag>();
1259 typename IndexType::const_iterator upper_limit =
1260 index.upper_bound(boost::make_tuple(
true, time(NULL) - secs));
1269 typename IndexType::const_iterator lower_limit =
1270 index.upper_bound(boost::make_tuple(
true, std::numeric_limits<int64_t>::min()));
1273 uint64_t num_leases =
static_cast<uint64_t
>(std::distance(lower_limit, upper_limit));
1274 if (num_leases > 0) {
1277 DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START)
1284 for (
typename IndexType::const_iterator lease = lower_limit;
1285 lease != upper_limit; ++lease) {
1287 LeaseType lease_copy(**lease);
1290 lease_copy.valid_lft_ = 0;
1291 lease_file->append(lease_copy);
1296 index.erase(lower_limit, upper_limit);
1299 return (num_leases);
1305 return (std::string(
"In memory database with leases stored in a CSV file."));
1316 DHCPSRV_MEMFILE_ROLLBACK);
1322 std::string name(file_name);
1323 switch (file_type) {
1334 name +=
".completed";
1349 std::ostringstream s;
1351 s << (u ==
V4 ?
"4" :
"6");
1359 return (lease_file4_ ? lease_file4_->getFilename() :
"");
1362 return (lease_file6_ ? lease_file6_->getFilename() :
"");
1370 if (u ==
V4 && lease_file4_) {
1374 return (u ==
V6 && lease_file6_);
1378 Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
1379 std::string persist_val;
1385 persist_val =
"true";
1389 if (persist_val ==
"false") {
1392 }
else if (persist_val !=
"true") {
1394 << persist_val <<
"'");
1397 std::string lease_file;
1400 }
catch (
const Exception&) {
1403 return (lease_file);
1406 template<
typename LeaseObjectType,
typename LeaseFileType,
typename StorageType>
1407 bool Memfile_LeaseMgr::loadLeasesFromFiles(
const std::string& filename,
1408 boost::shared_ptr<LeaseFileType>& lease_file,
1409 StorageType& storage) {
1417 if (pid_file.check()) {
1419 "lease file cleanup is in progress");
1425 bool conversion_needed =
false;
1426 lease_file.reset(
new LeaseFileType(std::string(filename +
".completed")));
1427 if (lease_file->exists()) {
1428 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1430 conversion_needed = conversion_needed || lease_file->needsConversion();
1435 if (lease_file->exists()) {
1436 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1438 conversion_needed = conversion_needed || lease_file->needsConversion();
1442 if (lease_file->exists()) {
1443 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1445 conversion_needed = conversion_needed || lease_file->needsConversion();
1455 lease_file.reset(
new LeaseFileType(filename));
1456 LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
1457 MAX_LEASE_ERRORS,
false);
1458 conversion_needed = conversion_needed || lease_file->needsConversion();
1460 return (conversion_needed);
1466 return (lfc_setup_->isRunning());
1471 return (lfc_setup_->getExitStatus());
1480 lfcExecute(lease_file4_);
1482 }
else if (lease_file6_) {
1483 lfcExecute(lease_file6_);
1488 Memfile_LeaseMgr::lfcSetup(
bool conversion_needed) {
1489 std::string lfc_interval_str =
"3600";
1492 }
catch (
const std::exception&) {
1496 uint32_t lfc_interval = 0;
1498 lfc_interval = boost::lexical_cast<uint32_t>(lfc_interval_str);
1499 }
catch (boost::bad_lexical_cast&) {
1501 << lfc_interval_str <<
" specified");
1504 if (lfc_interval > 0 || conversion_needed) {
1506 lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_, conversion_needed);
1510 template<
typename LeaseFileType>
1511 void Memfile_LeaseMgr::lfcExecute(boost::shared_ptr<LeaseFileType>& lease_file) {
1521 if (!lease_file_finish.exists() && !lease_file_copy.exists()) {
1523 lease_file->close();
1526 do_lfc = (rename(lease_file->getFilename().c_str(),
1527 lease_file_copy.getFilename().c_str()) == 0);
1531 .arg(lease_file->getFilename())
1532 .arg(lease_file_copy.getFilename())
1533 .arg(strerror(errno));
1542 lease_file->open(
true);
1555 .arg(lease_file->getFilename())
1566 lfc_setup_->execute();
1624 std::pair<Lease4StorageSubnetIdIndex::const_iterator,
1625 Lease4StorageSubnetIdIndex::const_iterator> l =
1626 idx.equal_range(subnet_id);
1630 for(
auto lease = l.first; lease != l.second; ++lease) {
1631 leases.push_back(*lease);
1634 size_t num = leases.size();
1635 for (
auto l = leases.begin(); l != leases.end(); ++l) {
1639 .arg(subnet_id).arg(num);
1652 std::pair<Lease6StorageSubnetIdIndex::const_iterator,
1653 Lease6StorageSubnetIdIndex::const_iterator> l =
1654 idx.equal_range(subnet_id);
1658 for(
auto lease = l.first; lease != l.second; ++lease) {
1659 leases.push_back(*lease);
1662 size_t num = leases.size();
1663 for (
auto l = leases.begin(); l != leases.end(); ++l) {
1667 .arg(subnet_id).arg(num);