zone_loader.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // Copyright (C) 2012 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 DATASRC_ZONE_LOADER_H
  15. #define DATASRC_ZONE_LOADER_H
  16. #include <datasrc/exceptions.h>
  17. #include <dns/master_loader.h>
  18. #include <cstdlib> // For size_t
  19. #include <boost/shared_ptr.hpp>
  20. #include <boost/scoped_ptr.hpp>
  21. namespace isc {
  22. namespace dns {
  23. // Forward declaration
  24. class Name;
  25. }
  26. namespace datasrc {
  27. // Forward declarations
  28. class DataSourceClient;
  29. class ZoneIterator;
  30. typedef boost::shared_ptr<ZoneIterator> ZoneIteratorPtr;
  31. class ZoneUpdater;
  32. typedef boost::shared_ptr<ZoneUpdater> ZoneUpdaterPtr;
  33. /// \brief Exception thrown when there's a problem with master file.
  34. ///
  35. /// This is thrown by the ZoneLoader when there's a fatal problem with
  36. /// a master file being loaded.
  37. class MasterFileError : public DataSourceError {
  38. public:
  39. MasterFileError(const char* file, size_t line, const char* what) :
  40. DataSourceError(file, line, what)
  41. {}
  42. };
  43. /// \brief Exception thrown when the zone doesn't pass post-load check.
  44. ///
  45. /// This is thrown by the ZoneLoader when the zone is loaded, but it
  46. /// doesn't pass basic sanity checks.
  47. class ZoneContentError : public DataSourceError {
  48. public:
  49. ZoneContentError(const char* file, size_t line, const char* what) :
  50. DataSourceError(file, line, what)
  51. {}
  52. };
  53. /// \brief Class to load data into a data source client.
  54. ///
  55. /// This is a small wrapper class that is able to load data into a data source.
  56. /// It can load either from another data source or from a master file. The
  57. /// purpose of the class is only to hold the state for incremental loading.
  58. ///
  59. /// The old content of zone is discarded and no journal is stored.
  60. class ZoneLoader {
  61. public:
  62. /// \brief Constructor from master file.
  63. ///
  64. /// This initializes the zone loader to load from a master file.
  65. ///
  66. /// \param destination The data source into which the loaded data should
  67. /// go.
  68. /// \param zone_name The origin of the zone. The class is implicit in the
  69. /// destination.
  70. /// \param master_file Path to the master file to read data from.
  71. /// \throw DataSourceError in case the zone does not exist in destination.
  72. /// This class does not support creating brand new zones, only loading
  73. /// data into them. In case a new zone is needed, it must be created
  74. /// beforehand.
  75. /// \throw DataSourceError in case of other (possibly low-level) errors,
  76. /// such as read-only data source or database error.
  77. ZoneLoader(DataSourceClient& destination, const isc::dns::Name& zone_name,
  78. const char* master_file);
  79. /// \brief Constructor from another data source.
  80. ///
  81. /// This initializes the zone loader to read from another data source.
  82. /// It'll effectively copy data from one data source to another.
  83. ///
  84. /// \param destination The data source into which the loaded data should
  85. /// go.
  86. /// \param zone_name The origin of the zone.
  87. /// \param source The data source from which the data would be read.
  88. /// \throw InvalidParameter in case the class of destination and source
  89. /// differs.
  90. /// \throw NotImplemented in case the source data source client doesn't
  91. /// provide an iterator.
  92. /// \throw DataSourceError in case the zone does not exist in destination.
  93. /// This class does not support creating brand new zones, only loading
  94. /// data into them. In case a new zone is needed, it must be created
  95. /// beforehand.
  96. /// \throw DataSourceError in case the zone does not exist in the source.
  97. /// \throw DataSourceError in case of other (possibly low-level) errors,
  98. /// such as read-only data source or database error.
  99. ZoneLoader(DataSourceClient& destination, const isc::dns::Name& zone_name,
  100. DataSourceClient& source);
  101. /// \brief Perform the whole load.
  102. ///
  103. /// This performs the whole loading operation. It may take a long time.
  104. ///
  105. /// \throw InvalidOperation in case the loading was already completed
  106. /// before this call.
  107. /// \throw DataSourceError in case some error (possibly low-level) happens.
  108. /// \throw MasterFileError when the master_file is badly formatted or some
  109. /// similar problem is found when loading the master file.
  110. /// \throw ZoneContentError when the zone doesn't pass sanity check.
  111. void load() {
  112. while (!loadIncremental(1000)) { // 1000 is arbitrary largish number
  113. // Body intentionally left blank.
  114. }
  115. }
  116. /// \brief Load up to limit RRs.
  117. ///
  118. /// This performs a part of the loading. In case there's enough data in the
  119. /// source, it copies limit RRs. It can copy less RRs during the final call
  120. /// (when there's less than limit left).
  121. ///
  122. /// This can be called repeatedly until the whole zone is loaded, having
  123. /// pauses in the loading for some purposes (for example reporting
  124. /// progress).
  125. ///
  126. /// After the last RR is loaded, a sanity check of the zone is performed by
  127. /// isc::dns::validateZone. It reports errors and warnings by logging them
  128. /// directly. If there are any errors, a ZoneContentError exception is
  129. /// thrown and the load is aborted (preserving the old version of zone, if
  130. /// any).
  131. ///
  132. /// \param limit The maximum allowed number of RRs to be loaded during this
  133. /// call.
  134. /// \return True in case the loading is completed, false if there's more
  135. /// to load.
  136. /// \throw InvalidOperation in case the loading was already completed
  137. /// before this call (by load() or by a loadIncremental that returned
  138. /// true).
  139. /// \throw DataSourceError in case some error (possibly low-level) happens.
  140. /// \throw MasterFileError when the master_file is badly formatted or some
  141. /// similar problem is found when loading the master file.
  142. /// \throw ZoneContentError when the zone doesn't pass sanity check.
  143. /// \note If the limit is exactly the number of RRs available to be loaded,
  144. /// the method still returns false and true'll be returned on the next
  145. /// call (which will load 0 RRs). This is because the end of iterator
  146. /// or master file is detected when reading past the end, not when the
  147. /// last one is read.
  148. bool loadIncremental(size_t limit);
  149. /// \brief Return the number of RRs loaded.
  150. ///
  151. /// This method returns the number of RRs loaded via this loader by the
  152. /// time of the call. Before starting the load it will return 0.
  153. /// It will return the total number of RRs of the zone on and after
  154. /// completing the load.
  155. ///
  156. /// \throw None
  157. size_t getRRCount() const;
  158. /// \brief Return the current progress of the loader.
  159. ///
  160. /// This method returns the current estimated progress of loader as a
  161. /// value between 0 and 1 (inclusive); it's 0 before starting the load,
  162. /// and 1 at the completion, and a value between these (exclusive) in the
  163. /// middle of loading. It's an implementation detail how to calculate
  164. /// the progress, which may vary depending on how the loader is
  165. /// constructed and may even be impossible to detect effectively.
  166. ///
  167. /// If the progress cannot be determined, this method returns a special
  168. /// value of PROGRESS_UNKNOWN, which is not included in the range between
  169. /// 0 and 1.
  170. ///
  171. /// As such, the application should use the return value only for
  172. /// informational purposes such as logging. For example, it shouldn't
  173. /// be used to determine whether loading is completed by comparing it
  174. /// to 1. It should also expect the possibility of getting
  175. /// \c PROGRESS_UNKNOWN at any call to this method; it shouldn't assume
  176. /// the specific way of internal implementation as described below (which
  177. /// is provided for informational purposes only).
  178. ///
  179. /// In this implementation, if the loader is constructed with a file
  180. /// name, the progress value is measured by the number of characters
  181. /// read from the zone file divided by the size of the zone file
  182. /// (with taking into account any included files). Note that due to
  183. /// the possibility of intermediate included files, the total file size
  184. /// cannot be fully fixed until the completion of the load. And, due to
  185. /// this possibility, return values from this method may not always
  186. /// increase monotonically.
  187. ///
  188. /// If it's constructed with another data source client, this method
  189. /// always returns \c PROGRESS_UNKNOWN; in future, however, it may become
  190. /// possible to return something more useful, e.g, based on the result
  191. /// of \c getRRCount() and the total number of RRs if the underlying data
  192. /// source can provide the latter value efficiently.
  193. ///
  194. /// \throw None
  195. double getProgress() const;
  196. /// \brief A special value for \c getProgress, meaning the progress is
  197. /// unknown.
  198. ///
  199. /// See the method description for details.
  200. static const double PROGRESS_UNKNOWN;
  201. private:
  202. /// \brief The iterator used as source of data in case of the copy mode.
  203. const ZoneIteratorPtr iterator_;
  204. /// \brief The destination zone updater
  205. const ZoneUpdaterPtr updater_;
  206. /// \brief The master loader (for the master file mode)
  207. boost::scoped_ptr<isc::dns::MasterLoader> loader_;
  208. /// \brief Indicator if loading was completed
  209. bool complete_;
  210. /// \brief Was the loading successful?
  211. bool loaded_ok_;
  212. size_t rr_count_;
  213. };
  214. }
  215. }
  216. #endif // DATASRC_ZONE_LOADER_H
  217. // Local Variables:
  218. // mode: c++
  219. // End: