lease_file_loader.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef LEASE_FILE_LOADER_H
  15. #define LEASE_FILE_LOADER_H
  16. #include <dhcpsrv/dhcpsrv_log.h>
  17. #include <dhcpsrv/inmemory_lease_storage.h>
  18. #include <util/csv_file.h>
  19. #include <boost/shared_ptr.hpp>
  20. namespace isc {
  21. namespace dhcp {
  22. /// @brief Utility class to manage bulk of leases in the lease files.
  23. ///
  24. /// This class exposes methods which allow for bulk loading leases from
  25. /// the lease file and dumping the leases held in memory into the
  26. /// lease file. There are two major use cases for this class:
  27. /// - load leases by the DHCP server when the server starts up or
  28. /// reloads configuration,
  29. /// - an application performing a lease file cleanup rewrites the whole
  30. /// lease file to remove the redundant lease entries.
  31. ///
  32. /// In the former case, this class is used by the @c MemFile_LeaseMgr.
  33. /// In the latter case, this class is used by the standalone application
  34. /// which reads the whole lease file into memory (storage) and then
  35. /// dumps the leases held in the storage to another file.
  36. ///
  37. /// The methods in this class are templated so as they can be used both
  38. /// with the @c Lease4Storage and @c Lease6Storage to process the DHCPv4
  39. /// and DHCPv6 leases respectively.
  40. ///
  41. /// @todo Add a method which dumps all leases from the storage to a
  42. /// specified lease file.
  43. class LeaseFileLoader {
  44. public:
  45. /// @brief Load leases from the lease file into the specified storage.
  46. ///
  47. /// This method iterates over the entries in the lease file in the
  48. /// CSV format, creates @c Lease4 or @c Lease6 objects and inserts
  49. /// them into the storage to which reference is specified as an
  50. /// argument. If there are multiple entries for the particular lease
  51. /// in the lease file the entries further in the lease file override
  52. /// the previous entries.
  53. ///
  54. /// If the method finds the entry with the valid lifetime of 0 it
  55. /// means that the particular lease was released and the method
  56. /// removes an existing lease from the container.
  57. ///
  58. /// @param lease_file A reference to the @c CSVLeaseFile4 or
  59. /// @c CSVLeaseFile6 object representing the lease file. The
  60. /// lease file must be opened and the internal file pointer should
  61. /// be set to the beginning of the file.
  62. /// @param storage A reference to the container to which leases
  63. /// should be inserted.
  64. /// @param max_errors Maximum number of corrupted leases in the
  65. /// lease file. The method will skip corrupted leases but after
  66. /// exceeding the specified number of errors it will throw an
  67. /// exception.
  68. /// @tparam LeaseObjectType A @c Lease4 or @c Lease6.
  69. /// @tparam LeaseFileType A @c CSVLeaseFile4 or @c CSVLeaseFile6.
  70. /// @tparam StorageType A @c Lease4Storage or @c Lease6Storage.
  71. ///
  72. /// @throw isc::util::CSVFileError when the maximum number of errors
  73. /// has been exceeded.
  74. template<typename LeaseObjectType, typename LeaseFileType,
  75. typename StorageType>
  76. static void load(LeaseFileType& lease_file, StorageType& storage,
  77. const uint32_t max_errors = 0xFFFFFFFF) {
  78. LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LEASE_FILE_LOAD)
  79. .arg(lease_file.getFilename());
  80. boost::shared_ptr<LeaseObjectType> lease;
  81. // Track the number of corrupted leases.
  82. uint32_t errcnt = 0;
  83. while (true) {
  84. // Unable to parse the lease.
  85. if (!lease_file.next(lease)) {
  86. // A value of 0xFFFFFFFF indicates that we don't return
  87. // until the whole file is parsed, even if errors occur.
  88. // Otherwise, check if we have exceeded the maximum number
  89. // of errors and throw an exception if we have.
  90. if ((max_errors < 0xFFFFFFFF) && (++errcnt > max_errors)) {
  91. isc_throw(util::CSVFileError, "exceeded maximum number of"
  92. " failures " << max_errors << " to read a lease"
  93. " from the lease file "
  94. << lease_file.getFilename());
  95. }
  96. // Skip the corrupted lease.
  97. continue;
  98. }
  99. // Lease was found and we successfully parsed it.
  100. if (lease) {
  101. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL_DATA,
  102. DHCPSRV_MEMFILE_LEASE_LOAD)
  103. .arg(lease->toText());
  104. // Check if this lease exists.
  105. typename StorageType::iterator lease_it =
  106. storage.find(lease->addr_);
  107. // The lease doesn't exist yet. Insert the lease if
  108. // it has a positive valid lifetime.
  109. if (lease_it == storage.end()) {
  110. if (lease->valid_lft_ > 0) {
  111. storage.insert(lease);
  112. }
  113. } else {
  114. // The lease exists. If the new entry has a valid
  115. // lifetime of 0 it is an indication to remove the
  116. // existing entry. Otherwise, we update the lease.
  117. if (lease->valid_lft_ == 0) {
  118. storage.erase(lease_it);
  119. } else {
  120. **lease_it = *lease;
  121. }
  122. }
  123. } else {
  124. // Being here means that we hit the end of file.
  125. break;
  126. }
  127. }
  128. }
  129. };
  130. }
  131. }
  132. #endif // LEASE_FILE_LOADER_H