// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. #ifndef MASTER_LOADER_H #define MASTER_LOADER_H #include #include namespace isc { namespace dns { class Name; class RRClass; /// \brief Error while loading by MasterLoader without specifying the /// MANY_ERRORS option. class MasterLoaderError : public isc::Exception { public: MasterLoaderError(const char* file, size_t line, const char* what) : Exception(file, line, what) {} }; /// \brief A class able to load DNS master files /// /// This class is able to produce a stream of RRs from a master file. /// It is able to load all of the master file at once, or by blocks /// incrementally. /// /// It reports the loaded RRs and encountered errors by callbacks. class MasterLoader : boost::noncopyable { public: /// \brief Options how the parsing should work. enum Options { DEFAULT = 0, ///< Nothing special. MANY_ERRORS = 1 ///< Lenient mode (see documentation of MasterLoader /// constructor). }; /// \brief Constructor /// /// This creates a master loader and provides it with all /// relevant information. /// /// Except for the exceptions listed below, the constructor doesn't /// throw. Most errors (like non-existent master file) are reported /// by the callbacks during load() or loadIncremental(). /// /// \param master_file Path to the file to load. /// \param zone_origin The origin of zone to be expected inside /// the master file. Currently unused, but it is expected to /// be used for some validation. /// \param zone_class The class of zone to be expected inside the /// master file. /// \param callbacks The callbacks by which it should report problems. /// Usually, the callback carries a filename and line number of the /// input where the problem happens. There's a special case of empty /// filename and zero line in case the opening of the top-level master /// file fails. /// \param add_callback The callback which would be called with each /// loaded RR. /// \param options Options for the parsing, which is bitwise-or of /// the Options values or DEFAULT. If the MANY_ERRORS option is /// included, the parser tries to continue past errors. If it /// is not included, it stops at first encountered error. /// \throw std::bad_alloc when there's not enough memory. /// \throw isc::InvalidParameter if add_callback is empty. MasterLoader(const char* master_file, const Name& zone_origin, const RRClass& zone_class, const MasterLoaderCallbacks& callbacks, const AddRRCallback& add_callback, Options options = DEFAULT); /// \brief Constructor from a stream /// /// This is a constructor very similar to the previous one. The only /// difference is it doesn't take a filename, but an input stream /// to read the data from. It is expected to be mostly used in tests, /// but it is public as it may possibly be useful for other currently /// unknown purposes. MasterLoader(std::istream& input, const Name& zone_origin, const RRClass& zone_class, const MasterLoaderCallbacks& callbacks, const AddRRCallback& add_callback, Options options = DEFAULT); /// \brief Destructor ~MasterLoader(); /// \brief Load some RRs /// /// This method loads at most count_limit RRs and reports them. In case /// an error (either fatal or without MANY_ERRORS) or end of file is /// encountered, they may be less. /// /// \param count_limit Upper limit on the number of RRs loaded. /// \return In case it stops because of the count limit, it returns false. /// It returns true if the loading is done. /// \throw isc::InvalidOperation when called after loading was done /// already. /// \throw MasterLoaderError when there's an error in the input master /// file and the MANY_ERRORS is not specified. It never throws this /// in case MANY_ERRORS is specified. bool loadIncremental(size_t count_limit); /// \brief Load everything /// /// This simply calls loadIncremental until the loading is done. /// \throw isc::InvalidOperation when called after loading was done /// already. /// \throw MasterLoaderError when there's an error in the input master /// file and the MANY_ERRORS is not specified. It never throws this /// in case MANY_ERRORS is specified. void load() { while (!loadIncremental(1000)) { // 1000 = arbitrary largish number // Body intentionally left blank } } /// \brief Was the loading successful? /// /// \return true if and only if the loading was complete (after a call of /// load or after loadIncremental returned true) and there was no /// error. In other cases, return false. /// \note While this method works even before the loading is complete (by /// returning false in that case), it is meant to be called only after /// finishing the load. bool loadedSucessfully() const; /// \brief Return the total size of the zone files and streams. /// /// This method returns the size of the source of the zone to be loaded /// (master zone files or streams) that is known at the time of the call. /// For a zone file, it's the size of the file; for a stream, it's the /// size of the data (in bytes) available at the start of the load. /// If separate zone files are included via the $INCLUDE directive, the /// sum of the sizes of these files are added. /// /// If the loader is constructed with a stream, the size can be /// "unknown" as described for \c MasterLexer::getTotalSourceSize(). /// In this case this method always returns /// \c MasterLexer::SOURCE_SIZE_UNKNOWN. /// /// If the loader is constructed with a zone file, this method /// initially returns 0. So until either \c load() or \c loadIncremental() /// is called, the value is meaningless. /// /// Note that when the source includes separate files, this method /// cannot take into account the included files that the loader has not /// recognized at the time of call. So it's possible that this method /// returns different values at different times of call. /// /// \throw None size_t getSize() const; /// \brief Return the position of the loader in zone. /// /// This method returns a conceptual "position" of the loader in the /// zone to be loaded. Specifically, it returns the total number of /// characters contained in the zone files and streams and recognized /// by the loader. Before starting the load it returns 0; on successful /// completion it will be equal to the return value of \c getSize() /// (unless the latter returns \c MasterLexer::SOURCE_SIZE_UNKNOWN). /// /// \throw None size_t getPosition() const; private: class MasterLoaderImpl; MasterLoaderImpl* impl_; }; } // end namespace dns } // end namespace isc #endif // MASTER_LOADER_H // Local Variables: // mode: c++ // End: