LCOV - code coverage report
Current view: top level - datasrc - database.h (source / functions) Hit Total Coverage
Test: report.info Lines: 8 9 88.9 %
Date: 2012-05-15 Functions: 5 10 50.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2011  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                 :            : 
      15                 :            : #ifndef __DATABASE_DATASRC_H
      16                 :            : #define __DATABASE_DATASRC_H
      17                 :            : 
      18                 :            : #include <string>
      19                 :            : 
      20                 :            : #include <boost/scoped_ptr.hpp>
      21                 :            : #include <boost/tuple/tuple.hpp>
      22                 :            : 
      23                 :            : #include <dns/rrclass.h>
      24                 :            : #include <dns/rrset.h>
      25                 :            : #include <dns/rrtype.h>
      26                 :            : 
      27                 :            : #include <datasrc/data_source.h>
      28                 :            : #include <datasrc/client.h>
      29                 :            : #include <datasrc/zone.h>
      30                 :            : #include <datasrc/logger.h>
      31                 :            : 
      32                 :            : #include <dns/name.h>
      33                 :            : #include <exceptions/exceptions.h>
      34                 :            : 
      35                 :            : #include <map>
      36                 :            : #include <set>
      37                 :            : 
      38                 :            : namespace isc {
      39                 :            : namespace datasrc {
      40                 :            : 
      41                 :            : /// \brief Abstraction of lowlevel database with DNS data
      42                 :            : ///
      43                 :            : /// This class is defines interface to databases. Each supported database
      44                 :            : /// will provide methods for accessing the data stored there in a generic
      45                 :            : /// manner. The methods are meant to be low-level, without much or any knowledge
      46                 :            : /// about DNS and should be possible to translate directly to queries.
      47                 :            : ///
      48                 :            : /// On the other hand, how the communication with database is done and in what
      49                 :            : /// schema (in case of relational/SQL database) is up to the concrete classes.
      50                 :            : ///
      51                 :            : /// This class is non-copyable, as copying connections to database makes little
      52                 :            : /// sense and will not be needed.
      53                 :            : ///
      54                 :            : /// \todo Is it true this does not need to be copied? For example the zone
      55                 :            : ///     iterator might need it's own copy. But a virtual clone() method might
      56                 :            : ///     be better for that than copy constructor.
      57                 :            : ///
      58                 :            : /// \note The same application may create multiple connections to the same
      59                 :            : ///     database, having multiple instances of this class. If the database
      60                 :            : ///     allows having multiple open queries at one connection, the connection
      61                 :            : ///     class may share it.
      62                 :        603 : class DatabaseAccessor : boost::noncopyable {
      63                 :            : public:
      64                 :            :     /// \brief Data columns for by IteratorContext::getNext()
      65                 :            :     ///
      66                 :            :     /// When implementing getNext(), the columns array should be filled with
      67                 :            :     /// the values as described in this enumeration, in this order, i.e.
      68                 :            :     /// - TYPE_COLUMN should be the first element (index 0) of the array,
      69                 :            :     /// - TTL_COLUMN should be the second element (index 1),
      70                 :            :     /// - etc.
      71                 :            :     enum RecordColumns {
      72                 :            :         TYPE_COLUMN = 0,    ///< The RRType of the record (A/NS/TXT etc.)
      73                 :            :         TTL_COLUMN = 1,     ///< The TTL of the record (a
      74                 :            :         SIGTYPE_COLUMN = 2, ///< For RRSIG records, this contains the RRTYPEs
      75                 :            :                             ///< the RRSIG cover. In the current implementation,
      76                 :            :                             ///< this field is ignored.
      77                 :            :         RDATA_COLUMN = 3,   ///< Full text representation of the record's RDATA
      78                 :            :         NAME_COLUMN = 4,    ///< The domain name of this RR
      79                 :            :         COLUMN_COUNT = 5    ///< The total number of columns, MUST be value of
      80                 :            :                             ///< the largest other element in this enum plus 1.
      81                 :            :     };
      82                 :            : 
      83                 :            :     /// \brief Definitions of the fields to be passed to addRecordToZone()
      84                 :            :     ///
      85                 :            :     /// Each derived implementation of addRecordToZone() should expect
      86                 :            :     /// the "columns" array to be filled with the values as described in this
      87                 :            :     /// enumeration, in this order.
      88                 :            :     enum AddRecordColumns {
      89                 :            :         ADD_NAME = 0,       ///< The owner name of the record (a domain name)
      90                 :            :         ADD_REV_NAME = 1,   ///< Reversed name of NAME (used for DNSSEC)
      91                 :            :         ADD_TTL = 2,        ///< The TTL of the record (in numeric form)
      92                 :            :         ADD_TYPE = 3,       ///< The RRType of the record (A/NS/TXT etc.)
      93                 :            :         ADD_SIGTYPE = 4,    ///< RRSIGs only: RRTYPEs the RRSIG covers.
      94                 :            :         ADD_RDATA = 5,      ///< Full text representation of the record's RDATA
      95                 :            :         ADD_COLUMN_COUNT = 6 ///< Number of columns
      96                 :            :     };
      97                 :            : 
      98                 :            :     /// \brief Definitions of the fields to be passed to addNSEC3RecordToZone()
      99                 :            :     ///
     100                 :            :     /// Each derived implementation of addNSEC3RecordToZone() should expect
     101                 :            :     /// the "columns" array to be filled with the values as described in this
     102                 :            :     /// enumeration, in this order.
     103                 :            :     ///
     104                 :            :     /// Note that there is no "reversed name" column.  Since the conceptual
     105                 :            :     /// separate namespace for NSEC3 is very simplified and essentially only
     106                 :            :     /// consists of a single-label names, there is no need for using reversed
     107                 :            :     /// names to identify the "previous hash".
     108                 :            :     enum AddNSEC3RecordColumns {
     109                 :            :         ADD_NSEC3_HASH = 0, ///< The hash (1st) label of the owner name,
     110                 :            :                             ///< excluding the dot character
     111                 :            :         ADD_NSEC3_TTL = 1,  ///< The TTL of the record (in numeric form)
     112                 :            :         ADD_NSEC3_TYPE = 2, ///< The RRType of the record (either NSEC3 or
     113                 :            :                             ///< RRSIG for NSEC3)
     114                 :            :         ADD_NSEC3_RDATA = 3, ///< Full text representation of the record's
     115                 :            :                              ///< RDATA
     116                 :            :         ADD_NSEC3_COLUMN_COUNT = 4 ///< Number of columns
     117                 :            :     };
     118                 :            : 
     119                 :            :     /// \brief Definitions of the fields to be passed to deleteRecordInZone()
     120                 :            :     /// and deleteNSEC3RecordInZone()
     121                 :            :     ///
     122                 :            :     /// Each derived implementation of deleteRecordInZone() should expect
     123                 :            :     /// the "params" array to be filled with the values as described in this
     124                 :            :     /// enumeration, in this order.
     125                 :            :     enum DeleteRecordParams {
     126                 :            :         DEL_NAME = 0, ///< The owner name of the record (a domain name)
     127                 :            :                       ///< or the hash label for deleteNSEC3RecordInZone()
     128                 :            :         DEL_TYPE = 1, ///< The RRType of the record (A/NS/TXT etc.)
     129                 :            :         DEL_RDATA = 2, ///< Full text representation of the record's RDATA
     130                 :            :         DEL_PARAM_COUNT = 3 ///< Number of parameters
     131                 :            :     };
     132                 :            : 
     133                 :            :     /// \brief Operation mode when adding a record diff.
     134                 :            :     ///
     135                 :            :     /// This is used as the "operation" parameter value of addRecordDiff().
     136                 :            :     enum DiffOperation {
     137                 :            :         DIFF_ADD = 0,           ///< This diff is for adding an RR
     138                 :            :         DIFF_DELETE = 1         ///< This diff is for deleting an RR
     139                 :            :     };
     140                 :            : 
     141                 :            :     /// \brief Definitions of the fields to be passed to addRecordDiff().
     142                 :            :     ///
     143                 :            :     /// Each derived implementation of addRecordDiff() should expect
     144                 :            :     /// the "params" array to be filled with the values as described in this
     145                 :            :     /// enumeration, in this order.
     146                 :            :     enum DiffRecordParams {
     147                 :            :         DIFF_NAME = 0,          ///< Owner name of the record (a domain name)
     148                 :            :         DIFF_TYPE = 1,          ///< The RRType of the record (A/NS/TXT etc.)
     149                 :            :         DIFF_TTL = 2,           ///< The TTL of the record (in numeric form)
     150                 :            :         DIFF_RDATA = 3,         ///< Full text representation of record's RDATA
     151                 :            :         DIFF_PARAM_COUNT = 4    ///< Number of parameters
     152                 :            :     };
     153                 :            : 
     154                 :            :     /// \brief Destructor
     155                 :            :     ///
     156                 :            :     /// It is empty, but needs a virtual one, since we will use the derived
     157                 :            :     /// classes in polymorphic way.
     158                 :        603 :     virtual ~DatabaseAccessor() { }
     159                 :            : 
     160                 :            :     /// \brief Retrieve a zone identifier
     161                 :            :     ///
     162                 :            :     /// This method looks up a zone for the given name in the database. It
     163                 :            :     /// should match only exact zone name (eg. name is equal to the zone's
     164                 :            :     /// apex), as the DatabaseClient will loop trough the labels itself and
     165                 :            :     /// find the most suitable zone.
     166                 :            :     ///
     167                 :            :     /// It is not specified if and what implementation of this method may throw,
     168                 :            :     /// so code should expect anything.
     169                 :            :     ///
     170                 :            :     /// \param name The (fully qualified) domain name of the zone's apex to be
     171                 :            :     ///             looked up.
     172                 :            :     /// \return The first part of the result indicates if a matching zone
     173                 :            :     ///     was found. In case it was, the second part is internal zone ID.
     174                 :            :     ///     This one will be passed to methods finding data in the zone.
     175                 :            :     ///     It is not required to keep them, in which case whatever might
     176                 :            :     ///     be returned - the ID is only passed back to the database as
     177                 :            :     ///     an opaque handle.
     178                 :            :     virtual std::pair<bool, int> getZone(const std::string& name) const = 0;
     179                 :            : 
     180                 :            :     /// \brief This holds the internal context of ZoneIterator for databases
     181                 :            :     ///
     182                 :            :     /// While the ZoneIterator implementation from DatabaseClient does all the
     183                 :            :     /// translation from strings to DNS classes and validation, this class
     184                 :            :     /// holds the pointer to where the database is at reading the data.
     185                 :            :     ///
     186                 :            :     /// It can either hold shared pointer to the connection which created it
     187                 :            :     /// and have some kind of statement inside (in case single database
     188                 :            :     /// connection can handle multiple concurrent SQL statements) or it can
     189                 :            :     /// create a new connection (or, if it is more convenient, the connection
     190                 :            :     /// itself can inherit both from DatabaseConnection and IteratorContext
     191                 :            :     /// and just clone itself).
     192                 :       2797 :     class IteratorContext : public boost::noncopyable {
     193                 :            :     public:
     194                 :            :         /// \brief Destructor
     195                 :            :         ///
     196                 :            :         /// Virtual destructor, so any descendand class is destroyed correctly.
     197                 :       2797 :         virtual ~IteratorContext() { }
     198                 :            : 
     199                 :            :         /// \brief Function to provide next resource record
     200                 :            :         ///
     201                 :            :         /// This function should provide data about the next resource record
     202                 :            :         /// from the data that is searched. The data is not converted yet.
     203                 :            :         ///
     204                 :            :         /// Depending on how the iterator was constructed, there is a difference
     205                 :            :         /// in behaviour; for a 'full zone iterator', created with
     206                 :            :         /// getAllRecords(), all COLUMN_COUNT elements of the array are
     207                 :            :         /// overwritten.
     208                 :            :         /// For a 'name iterator', created with getRecords(), the column
     209                 :            :         /// NAME_COLUMN is untouched, since what would be added here is by
     210                 :            :         /// definition already known to the caller (it already passes it as
     211                 :            :         /// an argument to getRecords()).
     212                 :            :         ///
     213                 :            :         /// Once this function returns false, any subsequent call to it should
     214                 :            :         /// result in false.  The implementation of a derived class must ensure
     215                 :            :         /// it doesn't cause any disruption due to that such as a crash or
     216                 :            :         /// exception.
     217                 :            :         ///
     218                 :            :         /// \note The order of RRs is not strictly set, but the RRs for single
     219                 :            :         /// RRset must not be interleaved with any other RRs (eg. RRsets must be
     220                 :            :         /// "together").
     221                 :            :         ///
     222                 :            :         /// \param columns The data will be returned through here. The order
     223                 :            :         ///     is specified by the RecordColumns enum, and the size must be
     224                 :            :         ///     COLUMN_COUNT
     225                 :            :         /// \todo Do we consider databases where it is stored in binary blob
     226                 :            :         ///     format?
     227                 :            :         /// \throw DataSourceError if there's database-related error. If the
     228                 :            :         ///     exception (or any other in case of derived class) is thrown,
     229                 :            :         ///     the iterator can't be safely used any more.
     230                 :            :         /// \return true if a record was found, and the columns array was
     231                 :            :         ///         updated. false if there was no more data, in which case
     232                 :            :         ///         the columns array is untouched.
     233                 :            :         virtual bool getNext(std::string (&columns)[COLUMN_COUNT]) = 0;
     234                 :            :     };
     235                 :            : 
     236                 :            :     typedef boost::shared_ptr<IteratorContext> IteratorContextPtr;
     237                 :            : 
     238                 :            :     /// \brief Creates an iterator context for a specific name.
     239                 :            :     ///
     240                 :            :     /// Returns an IteratorContextPtr that contains all records of the
     241                 :            :     /// given name from the given zone.
     242                 :            :     ///
     243                 :            :     /// The implementation of the iterator that is returned may leave the
     244                 :            :     /// NAME_COLUMN column of the array passed to getNext() untouched, as that
     245                 :            :     /// data is already known (it is the same as the name argument here)
     246                 :            :     ///
     247                 :            :     /// \exception any Since any implementation can be used, the caller should
     248                 :            :     ///            expect any exception to be thrown.
     249                 :            :     ///
     250                 :            :     /// \param name The name to search for. This should be a FQDN.
     251                 :            :     /// \param id The ID of the zone, returned from getZone().
     252                 :            :     /// \param subdomains If set to true, match subdomains of name instead
     253                 :            :     ///     of name itself. It is used to find empty domains and match
     254                 :            :     ///     wildcards.
     255                 :            :     /// \return Newly created iterator context. Must not be NULL.
     256                 :            :     virtual IteratorContextPtr getRecords(const std::string& name,
     257                 :            :                                           int id,
     258                 :            :                                           bool subdomains = false) const = 0;
     259                 :            : 
     260                 :            :     /// \brief Creates an iterator context for the records of NSEC3 namespace
     261                 :            :     ///     for the given hash
     262                 :            :     ///
     263                 :            :     /// Returns an Iteratorcontextptr that contains all the records of the given
     264                 :            :     /// hash in the NSEC3 namespace of the given zone.
     265                 :            :     ///
     266                 :            :     /// The implementation of the iterator that is returned may leave the
     267                 :            :     /// NAME_COLUMN column of the array passed to getNext() untouched,
     268                 :            :     /// as that name is easy to construct on the caller side (both the
     269                 :            :     /// hash and the name of the zone is known). The SIGTYPE_COLUMN can
     270                 :            :     /// be omitted as well, as it would be always empty for NSEC3 RRs or
     271                 :            :     /// contained "NSEC3" in case of RRSIG RRs.
     272                 :            :     ///
     273                 :            :     /// The iterator will contain both the NSEC3 records and the corresponding
     274                 :            :     /// RRSIGs, in arbitrary order.
     275                 :            :     ///
     276                 :            :     /// The iterator might be empty (containing no RRs) in case the zone is not
     277                 :            :     /// signed by NSEC3.
     278                 :            :     ///
     279                 :            :     /// \note In case there are multiple NSEC3 chains and they collide
     280                 :            :     ///     (unlikely, but it can happen), this can return multiple NSEC3
     281                 :            :     ///     records.
     282                 :            :     /// \exception any Since any implementaion can be used, the caller should
     283                 :            :     ///     expect any exception to be thrown.
     284                 :            :     /// \exception isc::NotImplemented in case the database does not support
     285                 :            :     ///     NSEC3
     286                 :            :     ///
     287                 :            :     /// \param hash The hash part of the NSEC3 name (eg. for a name of NSEC3
     288                 :            :     ///     RKBUCQT8T78GV6QBCGBHCHC019LG73SJ.example.com., we the hash would be
     289                 :            :     ///     RKBUCQT8T78GV6QBCGBHCHC019LG73SJ).
     290                 :            :     /// \param id The id of te zone, as returned from getZone().
     291                 :            :     /// \return Newly created iterator context. Must not be NULL.
     292                 :            :     virtual IteratorContextPtr getNSEC3Records(const std::string& hash,
     293                 :            :                                                int id) const = 0;
     294                 :            : 
     295                 :            :     /// \brief Creates an iterator context for the whole zone.
     296                 :            :     ///
     297                 :            :     /// Returns an IteratorContextPtr that contains all records of the
     298                 :            :     /// zone with the given zone id.
     299                 :            :     ///
     300                 :            :     /// Each call to getNext() on the returned iterator should copy all
     301                 :            :     /// column fields of the array that is passed, as defined in the
     302                 :            :     /// RecordColumns enum.
     303                 :            :     ///
     304                 :            :     /// \exception any Since any implementation can be used, the caller should
     305                 :            :     ///            expect any exception to be thrown.
     306                 :            :     ///
     307                 :            :     /// \param id The ID of the zone, returned from getZone().
     308                 :            :     /// \return Newly created iterator context. Must not be NULL.
     309                 :            :     virtual IteratorContextPtr getAllRecords(int id) const = 0;
     310                 :            : 
     311                 :            :     /// \brief Creates an iterator context for a set of differences.
     312                 :            :     ///
     313                 :            :     /// Returns an IteratorContextPtr that contains all difference records for
     314                 :            :     /// the given zone between two versions of a zone.
     315                 :            :     ///
     316                 :            :     /// The difference records are the set of records that would appear in an
     317                 :            :     /// IXFR serving a request for the difference between two versions of a
     318                 :            :     /// zone.  The records are returned in the same order as they would be in
     319                 :            :     /// the IXFR.  This means that if the the difference between versions of a
     320                 :            :     /// zone with SOA serial numbers of "start" and "end" is required, and the
     321                 :            :     /// zone contains the differences between serial number "start" to serial
     322                 :            :     /// number "intermediate" and from serial number "intermediate" to serial
     323                 :            :     /// number "end", the returned records will be (in order):
     324                 :            :     ///
     325                 :            :     /// \li SOA for serial "start"
     326                 :            :     /// \li Records removed from the zone between versions "start" and
     327                 :            :     ///     "intermediate" of the zone.  The order of these is not guaranteed.
     328                 :            :     /// \li SOA for serial "intermediate"
     329                 :            :     /// \li Records added to the zone between versions "start" and
     330                 :            :     ///     "intermediate" of the zone.  The order of these is not guaranteed.
     331                 :            :     /// \li SOA for serial "intermediate"
     332                 :            :     /// \li Records removed from the zone between versions "intermediate" and
     333                 :            :     ///     "end" of the zone.  The order of these is not guaranteed.
     334                 :            :     /// \li SOA for serial "end"
     335                 :            :     /// \li Records added to the zone between versions "intermediate" and "end"
     336                 :            :     ///     of the zone. The order of these is not guaranteed.
     337                 :            :     ///
     338                 :            :     /// Note that there is no requirement that "start" be less than "end".
     339                 :            :     /// Owing to serial number arithmetic, it is entirely possible that a later
     340                 :            :     /// version of a zone will have a smaller SOA serial number than an earlier
     341                 :            :     /// version.
     342                 :            :     ///
     343                 :            :     /// Each call to getNext() on the returned iterator should copy all column
     344                 :            :     /// fields of the array that is passed, as defined in the RecordColumns
     345                 :            :     /// enum.
     346                 :            :     ///
     347                 :            :     /// \exception any Since any implementation can be used, the caller should
     348                 :            :     ///                expect any exception to be thrown.
     349                 :            :     ///
     350                 :            :     /// \param id The ID of the zone, returned from getZone().
     351                 :            :     /// \param start The SOA serial number of the version of the zone from
     352                 :            :     ///        which the difference sequence should start.
     353                 :            :     /// \param end The SOA serial number of the version of the zone at which
     354                 :            :     ///        the difference sequence should end.
     355                 :            :     ///
     356                 :            :     /// \return Newly created iterator context. Must not be NULL.
     357                 :            :     virtual IteratorContextPtr
     358                 :            :     getDiffs(int id, uint32_t start, uint32_t end) const = 0;
     359                 :            : 
     360                 :            :     /// \brief Start a transaction for updating a zone.
     361                 :            :     ///
     362                 :            :     /// Each derived class version of this method starts a database
     363                 :            :     /// transaction to make updates to the given name of zone (whose class was
     364                 :            :     /// specified at the construction of the class).
     365                 :            :     ///
     366                 :            :     /// If \c replace is true, any existing records of the zone will be
     367                 :            :     /// deleted on successful completion of updates (after
     368                 :            :     /// \c commitUpdateZone()); if it's false, the existing records will be
     369                 :            :     /// intact unless explicitly deleted by \c deleteRecordInZone().
     370                 :            :     ///
     371                 :            :     /// A single \c DatabaseAccessor instance can perform at most one
     372                 :            :     /// transaction; a duplicate call to this method before
     373                 :            :     /// \c commitUpdateZone() or \c rollbackUpdateZone(), or a call to this
     374                 :            :     /// method within another transaction started by \c startTransaction()
     375                 :            :     /// will result in a \c DataSourceError exception.
     376                 :            :     /// If multiple update attempts need to be performed concurrently (and
     377                 :            :     /// if the underlying database allows such operation), separate
     378                 :            :     /// \c DatabaseAccessor instance must be created.
     379                 :            :     ///
     380                 :            :     /// \note The underlying database may not allow concurrent updates to
     381                 :            :     /// the same database instance even if different "connections" (or
     382                 :            :     /// something similar specific to the database implementation) are used
     383                 :            :     /// for different sets of updates.  For example, it doesn't seem to be
     384                 :            :     /// possible for SQLite3 unless different databases are used.  MySQL
     385                 :            :     /// allows concurrent updates to different tables of the same database,
     386                 :            :     /// but a specific operation may block others.  As such, this interface
     387                 :            :     /// doesn't require derived classes to allow concurrent updates with
     388                 :            :     /// multiple \c DatabaseAccessor instances; however, the implementation
     389                 :            :     /// is encouraged to do the best for making it more likely to succeed
     390                 :            :     /// as long as the underlying database system allows concurrent updates.
     391                 :            :     ///
     392                 :            :     /// This method returns a pair of \c bool and \c int.  Its first element
     393                 :            :     /// indicates whether the given name of zone is found.  If it's false,
     394                 :            :     /// the transaction isn't considered to be started; a subsequent call to
     395                 :            :     /// this method with an existing zone name should succeed.  Likewise,
     396                 :            :     /// if a call to this method results in an exception, the transaction
     397                 :            :     /// isn't considered to be started.  Note also that if the zone is not
     398                 :            :     /// found this method doesn't try to create a new one in the database.
     399                 :            :     /// It must have been created by some other means beforehand.
     400                 :            :     ///
     401                 :            :     /// The second element is the internal zone ID used for subsequent
     402                 :            :     /// updates.  Depending on implementation details of the actual derived
     403                 :            :     /// class method, it may be different from the one returned by
     404                 :            :     /// \c getZone(); for example, a specific implementation may use a
     405                 :            :     /// completely new zone ID when \c replace is true.
     406                 :            :     ///
     407                 :            :     /// \exception DataSourceError Duplicate call to this method, call to
     408                 :            :     /// this method within another transaction, or some internal database
     409                 :            :     /// related error.
     410                 :            :     ///
     411                 :            :     /// \param zone_name A string representation of the zone name to be updated
     412                 :            :     /// \param replace Whether to replace the entire zone (see above)
     413                 :            :     ///
     414                 :            :     /// \return A pair of bool and int, indicating whether the specified zone
     415                 :            :     /// exists and (if so) the zone ID to be used for the update, respectively.
     416                 :            :     virtual std::pair<bool, int> startUpdateZone(const std::string& zone_name,
     417                 :            :                                                  bool replace) = 0;
     418                 :            : 
     419                 :            :     /// \brief Add a single record to the zone to be updated.
     420                 :            :     ///
     421                 :            :     /// This method provides a simple interface to insert a new record
     422                 :            :     /// (a database "row") to the zone in the update context started by
     423                 :            :     /// \c startUpdateZone().  The zone to which the record to be added
     424                 :            :     /// is the one specified at the time of the \c startUpdateZone() call.
     425                 :            :     ///
     426                 :            :     /// A successful call to \c startUpdateZone() must have preceded to
     427                 :            :     /// this call; otherwise a \c DataSourceError exception will be thrown.
     428                 :            :     ///
     429                 :            :     /// The row is defined as a vector of strings that has exactly
     430                 :            :     /// ADD_COLUMN_COUNT number of elements.  See AddRecordColumns for
     431                 :            :     /// the semantics of each element.
     432                 :            :     ///
     433                 :            :     /// Derived class methods are not required to check whether the given
     434                 :            :     /// values in \c columns are valid in terms of the expected semantics;
     435                 :            :     /// in general, it's the caller's responsibility.
     436                 :            :     /// For example, TTLs would normally be expected to be a textual
     437                 :            :     /// representation of decimal numbers, but this interface doesn't require
     438                 :            :     /// the implementation to perform this level of validation.  It may check
     439                 :            :     /// the values, however, and in that case if it detects an error it
     440                 :            :     /// should throw a \c DataSourceError exception.
     441                 :            :     ///
     442                 :            :     /// Likewise, derived class methods are not required to detect any
     443                 :            :     /// duplicate record that is already in the zone.
     444                 :            :     ///
     445                 :            :     /// \note The underlying database schema may not have a trivial mapping
     446                 :            :     /// from this style of definition of rows to actual database records.
     447                 :            :     /// It's the implementation's responsibility to implement the mapping
     448                 :            :     /// in the actual derived method.
     449                 :            :     ///
     450                 :            :     /// \exception DataSourceError Invalid call without starting a transaction,
     451                 :            :     /// or other internal database error.
     452                 :            :     ///
     453                 :            :     /// \param columns An array of strings that defines a record to be added
     454                 :            :     /// to the zone.
     455                 :            :     virtual void addRecordToZone(
     456                 :            :         const std::string (&columns)[ADD_COLUMN_COUNT]) = 0;
     457                 :            : 
     458                 :            :     /// \brief Add a single NSEC3-related record to the zone to be updated.
     459                 :            :     ///
     460                 :            :     /// This method is similar to \c addRecordToZone(), but is expected to
     461                 :            :     /// be only used for NSEC3 RRs or RRSIG RRs that cover NSEC3.  In terms
     462                 :            :     /// of the DNS protocol, these types of RRs reside in a separate space
     463                 :            :     /// of the zone.  While this interface does not mandate a specific way
     464                 :            :     /// of implementing the separate namespaces in the underlying database,
     465                 :            :     /// it would be more convenient for the underlying implementation if the
     466                 :            :     /// interfaces are separated; for example, the implementation does not
     467                 :            :     /// have to examine the given data to identify the appropriate namespace.
     468                 :            :     ///
     469                 :            :     /// An implementation may choose to skip providing this interface if the
     470                 :            :     /// zones managed by that data source are known to not support NSEC3.
     471                 :            :     /// In that case the implementation should throw the
     472                 :            :     /// \c isc::NotImplemented exception.
     473                 :            :     ///
     474                 :            :     /// Note that the \c ADD_NSEC3_HASH column of \c columns is expected to
     475                 :            :     /// store only the hash label, not the entire owner name.  This is similar
     476                 :            :     /// to the \c hash parameter of \c getNSEC3Records().
     477                 :            :     ///
     478                 :            :     /// The RRs to be added using this method are expected to be limited to
     479                 :            :     /// NSEC3 or RRSIG RRs that cover NSEC3, but it's generally assumed to
     480                 :            :     /// be the caller's responsibility to ensure that; the implementation
     481                 :            :     /// is not required to check that condition.  The result of adding
     482                 :            :     /// unexpected type of RRs (and the result of subsequent lookups) is
     483                 :            :     /// undefined.
     484                 :            :     ///
     485                 :            :     /// Other general notes for \c addRecordToZone() also apply to this
     486                 :            :     /// method.
     487                 :            :     ///
     488                 :            :     /// \exception DataSourceError Invalid call without starting a transaction,
     489                 :            :     /// or other internal database error.
     490                 :            :     /// \exception isc::NotImplemented in case the database does not support
     491                 :            :     ///     NSEC3
     492                 :            :     ///
     493                 :            :     /// \param columns An array of strings that defines a record to be added
     494                 :            :     /// to the NSEC3 namespace of the zone.
     495                 :            :     virtual void addNSEC3RecordToZone(
     496                 :            :         const std::string (&columns)[ADD_NSEC3_COLUMN_COUNT]) = 0;
     497                 :            : 
     498                 :            :     /// \brief Delete a single record from the zone to be updated.
     499                 :            :     ///
     500                 :            :     /// This method provides a simple interface to delete a record
     501                 :            :     /// (a database "row") from the zone in the update context started by
     502                 :            :     /// \c startUpdateZone().  The zone from which the record to be deleted
     503                 :            :     /// is the one specified at the time of the \c startUpdateZone() call.
     504                 :            :     ///
     505                 :            :     /// A successful call to \c startUpdateZone() must have preceded to
     506                 :            :     /// this call; otherwise a \c DataSourceError exception will be thrown.
     507                 :            :     ///
     508                 :            :     /// The record to be deleted is specified by a vector of strings that has
     509                 :            :     /// exactly DEL_PARAM_COUNT number of elements.  See DeleteRecordParams
     510                 :            :     /// for the semantics of each element.
     511                 :            :     ///
     512                 :            :     /// \note In IXFR, TTL may also be specified, but we intentionally
     513                 :            :     /// ignore that in this interface, because it's not guaranteed
     514                 :            :     /// that all records have the same TTL (unlike the RRset
     515                 :            :     /// assumption) and there can even be multiple records for the
     516                 :            :     /// same name, type and rdata with different TTLs.  If we only
     517                 :            :     /// delete one of them, subsequent lookup will still return a
     518                 :            :     /// positive answer, which would be confusing.  It's a higher
     519                 :            :     /// layer's responsibility to check if there is at least one
     520                 :            :     /// record in the database that has the given TTL.
     521                 :            :     ///
     522                 :            :     /// Like \c addRecordToZone, derived class methods are not required to
     523                 :            :     /// validate the semantics of the given parameters or to check if there
     524                 :            :     /// is a record that matches the specified parameter; if there isn't
     525                 :            :     /// it simply ignores the result.
     526                 :            :     ///
     527                 :            :     /// \exception DataSourceError Invalid call without starting a transaction,
     528                 :            :     /// or other internal database error.
     529                 :            :     ///
     530                 :            :     /// \param params An array of strings that defines a record to be deleted
     531                 :            :     /// from the zone.
     532                 :            :     virtual void deleteRecordInZone(
     533                 :            :         const std::string (&params)[DEL_PARAM_COUNT]) = 0;
     534                 :            : 
     535                 :            :     /// \brief Delete a single NSEC3-related record from the zone to be
     536                 :            :     /// updated.
     537                 :            :     ///
     538                 :            :     /// This method is similar to \c deleteRecordInZone(), but is expected to
     539                 :            :     /// be only used for NSEC3 RRs or RRSIG RRs that cover NSEC3.  The
     540                 :            :     /// relationship between these two methods is similar to that between
     541                 :            :     /// \c addRecordToZone() and \c addNSEC3RecordToZone(), and the same
     542                 :            :     /// notes apply to this method.
     543                 :            :     ///
     544                 :            :     /// This method uses the same set of parameters to specify the record
     545                 :            :     /// to be deleted as \c deleteRecordInZone(), but the \c DEL_NAME column
     546                 :            :     /// is expected to only store the hash label of the owner name.
     547                 :            :     /// This is the same as \c ADD_NSEC3_HASH column for
     548                 :            :     /// \c addNSEC3RecordToZone().
     549                 :            :     ///
     550                 :            :     /// \exception DataSourceError Invalid call without starting a transaction,
     551                 :            :     /// or other internal database error.
     552                 :            :     /// \exception isc::NotImplemented in case the database does not support
     553                 :            :     ///     NSEC3
     554                 :            :     ///
     555                 :            :     /// \param params An array of strings that defines a record to be deleted
     556                 :            :     /// from the NSEC3 namespace of the zone.
     557                 :            :     virtual void deleteNSEC3RecordInZone(
     558                 :            :         const std::string (&params)[DEL_PARAM_COUNT]) = 0;
     559                 :            : 
     560                 :            :     /// \brief Start a general transaction.
     561                 :            :     ///
     562                 :            :     /// Each derived class version of this method starts a database
     563                 :            :     /// transaction in a way specific to the database details.  Any subsequent
     564                 :            :     /// operations on the accessor are guaranteed to be not susceptible to
     565                 :            :     /// any update attempts made during the transaction.  The transaction
     566                 :            :     /// must be terminated by either \c commit() or \c rollback().
     567                 :            :     ///
     568                 :            :     /// In practice, this transaction is intended to be used to perform
     569                 :            :     /// a set of atomic reads and work as a read-only lock.  So, in many
     570                 :            :     /// cases \c commit() and \c rollback() will have the same effect.
     571                 :            :     ///
     572                 :            :     /// This transaction cannot coexist with an update transaction started
     573                 :            :     /// by \c startUpdateZone().  Such an attempt will result in
     574                 :            :     /// \c DataSourceError.
     575                 :            :     ///
     576                 :            :     /// \exception DataSourceError An attempt of nested transaction, or some
     577                 :            :     /// internal database related error.
     578                 :            :     virtual void startTransaction() = 0;
     579                 :            : 
     580                 :            :     /// \brief Commit a transaction.
     581                 :            :     ///
     582                 :            :     /// This method completes a transaction started by \c startTransaction
     583                 :            :     /// or \c startUpdateZone.
     584                 :            :     ///
     585                 :            :     /// A successful call to one of the "start" methods must have preceded to
     586                 :            :     /// this call; otherwise a \c DataSourceError exception will be thrown.
     587                 :            :     /// Once this method successfully completes, the transaction isn't
     588                 :            :     /// considered to exist any more.  So a new transaction can now be
     589                 :            :     /// started.  On the other hand, a duplicate call to this method after
     590                 :            :     /// a successful completion of it is invalid and should result in
     591                 :            :     /// a \c DataSourceError exception.
     592                 :            :     ///
     593                 :            :     /// If some internal database error happens, a \c DataSourceError
     594                 :            :     /// exception must be thrown.  In that case the transaction is still
     595                 :            :     /// considered to be valid; the caller must explicitly rollback it
     596                 :            :     /// or (if it's confident that the error is temporary) try to commit it
     597                 :            :     /// again.
     598                 :            :     ///
     599                 :            :     /// \exception DataSourceError Call without a transaction, duplicate call
     600                 :            :     /// to the method or internal database error.
     601                 :            :     virtual void commit() = 0;
     602                 :            : 
     603                 :            :     /// \brief Rollback any changes in a transaction made so far.
     604                 :            :     ///
     605                 :            :     /// This method rollbacks a transaction started by \c startTransaction or
     606                 :            :     /// \c startUpdateZone.  When it succeeds (it normally should, but see
     607                 :            :     /// below), the underlying database should be reverted to the point
     608                 :            :     /// before performing the corresponding "start" method.
     609                 :            :     ///
     610                 :            :     /// A successful call to one of the "start" method must have preceded to
     611                 :            :     /// this call; otherwise a \c DataSourceError exception will be thrown.
     612                 :            :     /// Once this method successfully completes, the transaction isn't
     613                 :            :     /// considered to exist any more.  So a new transaction can now be
     614                 :            :     /// started.  On the other hand, a duplicate call to this method after
     615                 :            :     /// a successful completion of it is invalid and should result in
     616                 :            :     /// a \c DataSourceError exception.
     617                 :            :     ///
     618                 :            :     /// Normally this method should not fail.  But it may not always be
     619                 :            :     /// possible to guarantee it depending on the characteristics of the
     620                 :            :     /// underlying database system.  So this interface doesn't require the
     621                 :            :     /// actual implementation for the error free property.  But if a specific
     622                 :            :     /// implementation of this method can fail, it is encouraged to document
     623                 :            :     /// when that can happen with its implication.
     624                 :            :     ///
     625                 :            :     /// \exception DataSourceError Call without a transaction, duplicate call
     626                 :            :     /// to the method or internal database error.
     627                 :            :     virtual void rollback() = 0;
     628                 :            : 
     629                 :            :     /// \brief Install a single RR diff in difference sequences for zone update.
     630                 :            :     ///
     631                 :            :     /// This method inserts parameters of an update operation for a single RR
     632                 :            :     /// (either adding or deleting one) in the underlying database.
     633                 :            :     /// (These parameters would normally be a separate database table, but
     634                 :            :     /// actual realization can differ in specific implementations).
     635                 :            :     /// The information given via this method generally corresponds to either
     636                 :            :     /// a single call to \c addRecordToZone() or \c deleteRecordInZone(),
     637                 :            :     /// and this method is expected to be called immediately after (or before)
     638                 :            :     /// a call to either of those methods.
     639                 :            :     ///
     640                 :            :     /// Note, however, that this method passes more detailed information
     641                 :            :     /// than those update methods: it passes "serial", even if the diff
     642                 :            :     /// is not for the SOA RR; it passes TTL for a diff that deletes an RR
     643                 :            :     /// while in \c deleteRecordInZone() it's omitted.  This is because
     644                 :            :     /// the stored diffs are expected to be retrieved in the form that
     645                 :            :     /// \c getDiffs() is expected to meet.  This means if the caller
     646                 :            :     /// wants to use this method with other update operations, it must
     647                 :            :     /// ensure the additional information is ready when this method is called.
     648                 :            :     ///
     649                 :            :     /// The caller of this method must ensure that the added diffs via
     650                 :            :     /// this method in a single transaction form an IXFR-style difference
     651                 :            :     /// sequences: Each difference sequence is a sequence of RRs:
     652                 :            :     /// an older version of SOA (to be deleted), zero or more other deleted
     653                 :            :     /// RRs, the post-transaction SOA (to be added), and zero or more other
     654                 :            :     /// added RRs.  So, for example, the first call to this method in a
     655                 :            :     /// transaction must always be deleting an SOA.  Also, the \c serial
     656                 :            :     /// parameter must be equal to the value of the serial field of the
     657                 :            :     /// SOA that was last added or deleted (if the call is to add or delete
     658                 :            :     /// an SOA RR, \c serial must be identical to the serial of that SOA).
     659                 :            :     /// The underlying derived class implementation may or may not check
     660                 :            :     /// this condition, but if the caller doesn't meet the condition
     661                 :            :     /// a subsequent call to \c getDiffs() will not work as expected.
     662                 :            :     ///
     663                 :            :     /// Any call to this method must be in a transaction, and, for now,
     664                 :            :     /// it must be a transaction triggered by \c startUpdateZone() (that is,
     665                 :            :     /// it cannot be a transaction started by \c startTransaction()).
     666                 :            :     /// All calls to this method are considered to be part of an atomic
     667                 :            :     /// transaction: Until \c commit() is performed, the added diffs are
     668                 :            :     /// not visible outside the transaction; if \c rollback() is performed,
     669                 :            :     /// all added diffs are canceled; and the added sequences are not
     670                 :            :     /// affected by any concurrent attempt of adding diffs (conflict resolution
     671                 :            :     /// is up to the database implementation).
     672                 :            :     ///
     673                 :            :     /// Also for now, all diffs are assumed to be for the zone that is
     674                 :            :     /// being updated in the context of \c startUpdateZone().  So the
     675                 :            :     /// \c zone_id parameter must be identical to the zone ID returned by
     676                 :            :     /// \c startUpdateZone().
     677                 :            :     ///
     678                 :            :     /// In a future version we may loosen this condition so that diffs can be
     679                 :            :     /// added in a generic transaction and may not even have to belong to
     680                 :            :     /// a single zone.  For this possible extension \c zone_id parameter is
     681                 :            :     /// included even if it's redundant under the current restriction.
     682                 :            :     ///
     683                 :            :     /// The support for adding (or retrieving) diffs is optional; if it's
     684                 :            :     /// not supported in a specific data source, this method for the
     685                 :            :     /// corresponding derived class will throw an \c NotImplemented exception.
     686                 :            :     ///
     687                 :            :     /// \exception DataSourceError Invalid call without starting a transaction,
     688                 :            :     /// zone ID doesn't match the zone being updated, or other internal
     689                 :            :     /// database error.
     690                 :            :     /// \exception NotImplemented Adding diffs is not supported in the
     691                 :            :     /// data source.
     692                 :            :     /// \exception Other The concrete derived method may throw other
     693                 :            :     /// data source specific exceptions.
     694                 :            :     ///
     695                 :            :     /// \param zone_id The zone for the diff to be added.
     696                 :            :     /// \param serial The SOA serial to which the diff belongs.
     697                 :            :     /// \param operation Either \c DIFF_ADD or \c DIFF_DELETE.
     698                 :            :     /// \param params An array of strings that defines a record for the diff.
     699                 :            :     virtual void addRecordDiff(
     700                 :            :         int zone_id, uint32_t serial, DiffOperation operation,
     701                 :            :         const std::string (&params)[DIFF_PARAM_COUNT]) = 0;
     702                 :            : 
     703                 :            :     /// \brief Clone the accessor with the same configuration.
     704                 :            :     ///
     705                 :            :     /// Each derived class implementation of this method will create a new
     706                 :            :     /// accessor of the same derived class with the same configuration
     707                 :            :     /// (such as the database server address) as that of the caller object
     708                 :            :     /// and return it.
     709                 :            :     ///
     710                 :            :     /// Note that other internal states won't be copied to the new accessor
     711                 :            :     /// even though the name of "clone" may indicate so.  For example, even
     712                 :            :     /// if the calling accessor is in the middle of a update transaction,
     713                 :            :     /// the new accessor will not start a transaction to trace the same
     714                 :            :     /// updates.
     715                 :            :     ///
     716                 :            :     /// The intended use case of cloning is to create a separate context
     717                 :            :     /// where a specific set of database operations can be performed
     718                 :            :     /// independently from the original accessor.  The updater will use it
     719                 :            :     /// so that multiple updaters can be created concurrently even if the
     720                 :            :     /// underlying database system doesn't allow running multiple transactions
     721                 :            :     /// in a single database connection.
     722                 :            :     ///
     723                 :            :     /// The underlying database system may not support the functionality
     724                 :            :     /// that would be needed to implement this method.  For example, it
     725                 :            :     /// may not allow a single thread (or process) to have more than one
     726                 :            :     /// database connections.  In such a case the derived class implementation
     727                 :            :     /// should throw a \c DataSourceError exception.
     728                 :            :     ///
     729                 :            :     /// \return A shared pointer to the cloned accessor.
     730                 :            :     virtual boost::shared_ptr<DatabaseAccessor> clone() = 0;
     731                 :            : 
     732                 :            :     /// \brief Returns a string identifying this dabase backend
     733                 :            :     ///
     734                 :            :     /// The returned string is mainly intended to be used for
     735                 :            :     /// debugging/logging purposes.
     736                 :            :     ///
     737                 :            :     /// Any implementation is free to choose the exact string content,
     738                 :            :     /// but it is advisable to make it a name that is distinguishable
     739                 :            :     /// from the others.
     740                 :            :     ///
     741                 :            :     /// \return the name of the database
     742                 :            :     virtual const std::string& getDBName() const = 0;
     743                 :            : 
     744                 :            :     /// \brief It returns the previous name in DNSSEC order.
     745                 :            :     ///
     746                 :            :     /// This is used in DatabaseClient::findPreviousName and does more
     747                 :            :     /// or less the real work, except for working on strings.
     748                 :            :     ///
     749                 :            :     /// \param rname The name to ask for previous of, in reversed form.
     750                 :            :     ///     We use the reversed form (see isc::dns::Name::reverse),
     751                 :            :     ///     because then the case insensitive order of string representation
     752                 :            :     ///     and the DNSSEC order correspond (eg. org.example.a is followed
     753                 :            :     ///     by org.example.a.b which is followed by org.example.b, etc).
     754                 :            :     /// \param zone_id The zone to look through.
     755                 :            :     /// \return The previous name.
     756                 :            :     /// \note This function must return previous name even in case
     757                 :            :     ///     the queried rname does not exist in the zone.
     758                 :            :     /// \note This method must skip under-the-zone-cut data (glue data).
     759                 :            :     ///     This might be implemented by looking for NSEC records (as glue
     760                 :            :     ///     data don't have them) in the zone or in some other way.
     761                 :            :     ///
     762                 :            :     /// \throw DataSourceError if there's a problem with the database.
     763                 :            :     /// \throw NotImplemented if this database doesn't support DNSSEC
     764                 :            :     ///     or there's no previous name for the queried one (the NSECs
     765                 :            :     ///     might be missing or the queried name is less or equal the
     766                 :            :     ///     apex of the zone).
     767                 :            :     virtual std::string findPreviousName(int zone_id,
     768                 :            :                                          const std::string& rname) const = 0;
     769                 :            : 
     770                 :            :     /// \brief It returns the previous hash in the NSEC3 chain.
     771                 :            :     ///
     772                 :            :     /// This is used to find previous NSEC3 hashes, to find covering NSEC3 in
     773                 :            :     /// case none match exactly.
     774                 :            :     ///
     775                 :            :     /// In case a hash before the lowest or the lowest is provided,
     776                 :            :     /// this should return the largest one in the zone (NSEC3 needs a
     777                 :            :     /// wrap-around semantics).
     778                 :            :     ///
     779                 :            :     /// \param zone_id Specifies the zone to look into, as returned by getZone.
     780                 :            :     /// \param hash The hash to look before.
     781                 :            :     /// \return The nearest smaller hash than the provided one, or the largest
     782                 :            :     ///     hash in the zone if something smaller or equal to the lowest one
     783                 :            :     ///     is provided.
     784                 :            :     /// \note If the zone contains multiple NSEC3 chains, you should check that
     785                 :            :     ///     the returned result contains the NSEC3 for correct parameters. If
     786                 :            :     ///     not, query again and get something smaller - this will eventually
     787                 :            :     ///     get to the correct one. This interface and semantics might change
     788                 :            :     ///     in future.
     789                 :            :     ///
     790                 :            :     /// \throw DataSourceError if there's a problem with the database or if
     791                 :            :     ///     this zone is not signed with NSEC3.
     792                 :            :     /// \throw NotImplemented if this database doesn't support NSEC3.
     793                 :            :     /// \throw anything else, as this might be any implementation.
     794                 :            :     virtual std::string findPreviousNSEC3Hash(int zone_id,
     795                 :            :                                               const std::string& hash)
     796                 :            :         const = 0;
     797                 :            : };
     798                 :            : 
     799                 :            : /// \brief Concrete data source client oriented at database backends.
     800                 :            : ///
     801                 :            : /// This class (together with corresponding versions of ZoneFinder,
     802                 :            : /// ZoneIterator, etc.) translates high-level data source queries to
     803                 :            : /// low-level calls on DatabaseAccessor. It calls multiple queries
     804                 :            : /// if necessary and validates data from the database, allowing the
     805                 :            : /// DatabaseAccessor to be just simple translation to SQL/other
     806                 :            : /// queries to database.
     807                 :            : ///
     808                 :            : /// While it is possible to subclass it for specific database in case
     809                 :            : /// of special needs, it is not expected to be needed. This should just
     810                 :            : /// work as it is with whatever DatabaseAccessor.
     811                 :        490 : class DatabaseClient : public DataSourceClient {
     812                 :            : public:
     813                 :            :     /// \brief Constructor
     814                 :            :     ///
     815                 :            :     /// It initializes the client with a database via the given accessor.
     816                 :            :     ///
     817                 :            :     /// \exception isc::InvalidParameter if accessor is NULL. It might throw
     818                 :            :     /// standard allocation exception as well, but doesn't throw anything else.
     819                 :            :     ///
     820                 :            :     /// \param rrclass The RR class of the zones that this client will handle.
     821                 :            :     /// \param accessor The accessor to the database to use to get data.
     822                 :            :     ///  As the parameter suggests, the client takes ownership of the accessor
     823                 :            :     ///  and will delete it when itself deleted.
     824                 :            :     DatabaseClient(isc::dns::RRClass rrclass,
     825                 :            :                    boost::shared_ptr<DatabaseAccessor> accessor);
     826                 :            : 
     827                 :            : 
     828                 :            :     /// \brief Corresponding ZoneFinder implementation
     829                 :            :     ///
     830                 :            :     /// The zone finder implementation for database data sources. Similarly
     831                 :            :     /// to the DatabaseClient, it translates the queries to methods of the
     832                 :            :     /// database.
     833                 :            :     ///
     834                 :            :     /// Application should not come directly in contact with this class
     835                 :            :     /// (it should handle it trough generic ZoneFinder pointer), therefore
     836                 :            :     /// it could be completely hidden in the .cc file. But it is provided
     837                 :            :     /// to allow testing and for rare cases when a database needs slightly
     838                 :            :     /// different handling, so it can be subclassed.
     839                 :            :     ///
     840                 :            :     /// Methods directly corresponds to the ones in ZoneFinder.
     841                 :       1549 :     class Finder : public ZoneFinder {
     842                 :            :     public:
     843                 :            :         /// \brief Constructor
     844                 :            :         ///
     845                 :            :         /// \param database The database (shared with DatabaseClient) to
     846                 :            :         ///     be used for queries (the one asked for ID before).
     847                 :            :         /// \param zone_id The zone ID which was returned from
     848                 :            :         ///     DatabaseAccessor::getZone and which will be passed to further
     849                 :            :         ///     calls to the database.
     850                 :            :         /// \param origin The name of the origin of this zone. It could query
     851                 :            :         ///     it from database, but as the DatabaseClient just searched for
     852                 :            :         ///     the zone using the name, it should have it.
     853                 :            :         Finder(boost::shared_ptr<DatabaseAccessor> database, int zone_id,
     854                 :            :                const isc::dns::Name& origin);
     855                 :            : 
     856                 :            :         // The following three methods are just implementations of inherited
     857                 :            :         // ZoneFinder's pure virtual methods.
     858                 :            :         virtual isc::dns::Name getOrigin() const;
     859                 :            :         virtual isc::dns::RRClass getClass() const;
     860                 :            : 
     861                 :            :         /// \brief Find an RRset in the datasource
     862                 :            :         ///
     863                 :            :         /// Searches the datasource for an RRset of the given name and
     864                 :            :         /// type. If there is a CNAME at the given name, the CNAME rrset
     865                 :            :         /// is returned.
     866                 :            :         /// (this implementation is not complete, and currently only
     867                 :            :         /// does full matches, CNAMES, and the signatures for matches and
     868                 :            :         /// CNAMEs)
     869                 :            :         ///
     870                 :            :         /// \note Maybe counter intuitively, this method is not a const member
     871                 :            :         /// function.  This is intentional; some of the underlying
     872                 :            :         /// implementations are expected to use a database backend, and would
     873                 :            :         /// internally contain some abstraction of "database connection".  In
     874                 :            :         /// the most strict sense any (even read only) operation might change
     875                 :            :         /// the internal state of such a connection, and in that sense the
     876                 :            :         /// operation cannot be considered "const".  In order to avoid giving a
     877                 :            :         /// false sense of safety to the caller, we indicate a call to this
     878                 :            :         /// method may have a surprising side effect.  That said, this view may
     879                 :            :         /// be too strict and it may make sense to say the internal database
     880                 :            :         /// connection doesn't affect external behavior in terms of the
     881                 :            :         /// interface of this method.  As we gain more experiences with various
     882                 :            :         /// kinds of backends we may revisit the constness.
     883                 :            :         ///
     884                 :            :         /// \exception DataSourceError when there is a problem reading
     885                 :            :         ///                            the data from the dabase backend.
     886                 :            :         ///                            This can be a connection, code, or
     887                 :            :         ///                            data (parse) error.
     888                 :            :         ///
     889                 :            :         /// \param name The name to find
     890                 :            :         /// \param type The RRType to find
     891                 :            :         /// \param options Options about how to search.
     892                 :            :         ///     See ZoneFinder::FindOptions.
     893                 :            :         virtual ZoneFinderContextPtr find(const isc::dns::Name& name,
     894                 :            :                                           const isc::dns::RRType& type,
     895                 :            :                                           const FindOptions options =
     896                 :            :                                           FIND_DEFAULT);
     897                 :            :         /// \brief Implementation of the ZoneFinder::findAll method.
     898                 :            :         ///
     899                 :            :         /// In short, it is mostly the same thing as find, but it returns all
     900                 :            :         /// RRsets in the named node through the target parameter in successful
     901                 :            :         /// case. It acts the same in the unsuccessful one.
     902                 :            :         virtual ZoneFinderContextPtr findAll(
     903                 :            :             const isc::dns::Name& name,
     904                 :            :             std::vector<isc::dns::ConstRRsetPtr>& target,
     905                 :            :             const FindOptions options = FIND_DEFAULT);
     906                 :            : 
     907                 :            :         /// \brief Implementation of ZoneFinder::findPreviousName method.
     908                 :            :         virtual isc::dns::Name findPreviousName(const isc::dns::Name& query)
     909                 :            :             const;
     910                 :            : 
     911                 :            :         /// Look for NSEC3 for proving (non)existence of given name.
     912                 :            :         ///
     913                 :            :         /// See documentation in \c Zone.
     914                 :            :         virtual FindNSEC3Result
     915                 :            :         findNSEC3(const isc::dns::Name& name, bool recursive);
     916                 :            : 
     917                 :            :         /// \brief The zone ID
     918                 :            :         ///
     919                 :            :         /// This function provides the stored zone ID as passed to the
     920                 :            :         /// constructor. This is meant for testing purposes and normal
     921                 :            :         /// applications shouldn't need it.
     922                 :          0 :         int zone_id() const { return (zone_id_); }
     923                 :            : 
     924                 :            :         /// \brief The database accessor.
     925                 :            :         ///
     926                 :            :         /// This function provides the database accessor stored inside as
     927                 :            :         /// passed to the constructor. This is meant for testing purposes and
     928                 :            :         /// normal applications shouldn't need it.
     929                 :            :         const DatabaseAccessor& getAccessor() const {
     930                 :            :             return (*accessor_);
     931                 :            :         }
     932                 :            : 
     933                 :            :     private:
     934                 :            :         boost::shared_ptr<DatabaseAccessor> accessor_;
     935                 :            :         const int zone_id_;
     936                 :            :         const isc::dns::Name origin_;
     937                 :            : 
     938                 :            :         /// \brief Shortcut name for the result of getRRsets
     939                 :            :         typedef std::pair<bool, std::map<dns::RRType, dns::RRsetPtr> >
     940                 :            :             FoundRRsets;
     941                 :            :         /// \brief Just shortcut for set of types
     942                 :            :         typedef std::set<dns::RRType> WantedTypes;
     943                 :            : 
     944                 :            :         /// \brief Internal logit of find and findAll methods.
     945                 :            :         ///
     946                 :            :         /// Most of their handling is in the "error" cases and delegations
     947                 :            :         /// and so on. So they share the logic here and find and findAll provide
     948                 :            :         /// just an interface for it.
     949                 :            :         ///
     950                 :            :         /// Parameters and behaviour is like of those combined together.
     951                 :            :         /// Unexpected parameters, like type != ANY and having the target, are
     952                 :            :         /// just that - unexpected and not checked.
     953                 :            :         ResultContext findInternal(const isc::dns::Name& name,
     954                 :            :                                    const isc::dns::RRType& type,
     955                 :            :                                    std::vector<isc::dns::ConstRRsetPtr>*
     956                 :            :                                    target,
     957                 :            :                                    const FindOptions options = FIND_DEFAULT);
     958                 :            : 
     959                 :            :         /// \brief Searches database for RRsets of one domain.
     960                 :            :         ///
     961                 :            :         /// This method scans RRs of single domain specified by name and
     962                 :            :         /// extracts any RRsets found and requested by parameters.
     963                 :            :         ///
     964                 :            :         /// It is used internally by find(), because it is called multiple
     965                 :            :         /// times (usually with different domains).
     966                 :            :         ///
     967                 :            :         /// \param name Which domain name should be scanned.
     968                 :            :         /// \param types List of types the caller is interested in.
     969                 :            :         /// \param check_ns If this is set to true, it checks nothing lives
     970                 :            :         ///     together with NS record (with few little exceptions, like RRSIG
     971                 :            :         ///     or NSEC). This check is meant for non-apex NS records.
     972                 :            :         /// \param construct_name If this is NULL, the resulting RRsets have
     973                 :            :         ///     their name set to name. If it is not NULL, it overrides the name
     974                 :            :         ///     and uses this one (this can be used for wildcard synthesized
     975                 :            :         ///     records).
     976                 :            :         /// \param any If this is true, it records all the types, not only the
     977                 :            :         ///     ones requested by types. It also puts a NULL pointer under the
     978                 :            :         ///     ANY type into the result, if it finds any RRs at all, to easy the
     979                 :            :         ///     identification of success.
     980                 :            :         /// \param srcContext This can be set to non-NULL value to override the
     981                 :            :         ///     iterator context used for obtaining the data. This can be used,
     982                 :            :         ///     for example, to get data from the NSEC3 namespace.
     983                 :            :         /// \return A pair, where the first element indicates if the domain
     984                 :            :         ///     contains any RRs at all (not only the requested, it may happen
     985                 :            :         ///     this is set to true, but the second part is empty). The second
     986                 :            :         ///     part is map from RRtypes to RRsets of the corresponding types.
     987                 :            :         ///     If the RRset is not present in DB, the RRtype is not there at
     988                 :            :         ///     all (so you'll not find NULL pointer in the result).
     989                 :            :         /// \throw DataSourceError If there's a low-level error with the
     990                 :            :         ///     database or the database contains bad data.
     991                 :            :         FoundRRsets getRRsets(const std::string& name,
     992                 :            :                               const WantedTypes& types, bool check_ns,
     993                 :            :                               const std::string* construct_name = NULL,
     994                 :            :                               bool any = false,
     995                 :            :                               DatabaseAccessor::IteratorContextPtr srcContext =
     996                 :            :                               DatabaseAccessor::IteratorContextPtr());
     997                 :            : 
     998                 :            :         /// \brief DNSSEC related context for ZoneFinder::findInternal.
     999                 :            :         ///
    1000                 :            :         /// This class is a helper for the ZoneFinder::findInternal method,
    1001                 :            :         /// encapsulating DNSSEC related information and processing logic.
    1002                 :            :         /// Specifically, it tells the finder whether the zone under search
    1003                 :            :         /// is DNSSEC signed or not, and if it is, whether it's with NSEC or
    1004                 :            :         /// with NSEC3.  It also provides a RRset DNSSEC proof RRset for some
    1005                 :            :         /// specific situations (in practice, this means an NSEC RRs for
    1006                 :            :         /// negative proof when they are needed and expected).
    1007                 :            :         ///
    1008                 :            :         /// The purpose of this class is to keep the main finder implementation
    1009                 :            :         /// unaware of DNSSEC related details.  It's also intended to help
    1010                 :            :         /// avoid unnecessary lookup for DNSSEC proof RRsets; this class
    1011                 :            :         /// doesn't look into the DB for these RRsets unless it's known to
    1012                 :            :         /// be needed.  The same optimization could be implemented in the
    1013                 :            :         /// main code, but it will result in duplicate similar code logic
    1014                 :            :         /// and make the code more complicated.  By encapsulating and unifying
    1015                 :            :         /// the logic in a single separate class, we can keep the main
    1016                 :            :         /// search logic readable.
    1017                 :            :         class FindDNSSECContext {
    1018                 :            :         public:
    1019                 :            :             /// \brief Constructor for FindDNSSECContext class.
    1020                 :            :             ///
    1021                 :            :             /// This constructor doesn't involve any expensive operation such
    1022                 :            :             /// as database lookups.  It only initializes some internal
    1023                 :            :             /// states (in a cheap way) and remembers if DNSSEC proof
    1024                 :            :             /// is requested.
    1025                 :            :             ///
    1026                 :            :             /// \param finder The Finder for the findInternal that uses this
    1027                 :            :             /// context.
    1028                 :            :             /// \param options Find options given to the finder.
    1029                 :            :             FindDNSSECContext(Finder& finder, const FindOptions options);
    1030                 :            : 
    1031                 :            :             /// \brief Return DNSSEC related result flags for the context.
    1032                 :            :             ///
    1033                 :            :             /// This method returns a FindResultFlags value related to
    1034                 :            :             /// DNSSEC, based on the context.  If DNSSEC proof is requested
    1035                 :            :             /// and the zone is signed with NSEC/NSEC3, it returns
    1036                 :            :             /// RESULT_NSEC_SIGNED/RESULT_NSEC3_SIGNED, respectively;
    1037                 :            :             /// otherwise it returns RESULT_DEFAULT.  So the caller can simply
    1038                 :            :             /// take a logical OR for the returned value of this method and
    1039                 :            :             /// whatever other flags it's going to set, without knowing
    1040                 :            :             /// DNSSEC specific information.
    1041                 :            :             ///
    1042                 :            :             /// If it's not yet identified whether and how the zone is DNSSEC
    1043                 :            :             /// signed at the time of the call, it now detects that via
    1044                 :            :             /// database lookups (if necessary).  (And this is because why
    1045                 :            :             /// this method cannot be a const member function).
    1046                 :            :             ZoneFinder::FindResultFlags getResultFlags();
    1047                 :            : 
    1048                 :            :             /// \brief Get DNSSEC negative proof for a given name.
    1049                 :            :             ///
    1050                 :            :             /// If the zone is considered NSEC-signed and the context
    1051                 :            :             /// requested DNSSEC proofs, this method tries to find NSEC RRs
    1052                 :            :             /// for the give name.  If \c covering is true, it means a
    1053                 :            :             /// "no name" proof is requested, so it calls findPreviousName on
    1054                 :            :             /// the given name and extracts an NSEC record on the result;
    1055                 :            :             /// otherwise it tries to get NSEC RRs for the given name.  If
    1056                 :            :             /// the NSEC is found, this method returns it; otherwise it returns
    1057                 :            :             /// NULL.
    1058                 :            :             ///
    1059                 :            :             /// In all other cases this method simply returns NULL.
    1060                 :            :             ///
    1061                 :            :             /// \param name The name which the NSEC RRset belong to.
    1062                 :            :             /// \param covering true if a covering NSEC is required; false if
    1063                 :            :             /// a matching NSEC is required.
    1064                 :            :             /// \return Any found DNSSEC proof RRset or NULL
    1065                 :            :             isc::dns::ConstRRsetPtr getDNSSECRRset(
    1066                 :            :                 const isc::dns::Name& name, bool covering);
    1067                 :            : 
    1068                 :            :             /// \brief Get DNSSEC negative proof for a given name.
    1069                 :            :             ///
    1070                 :            :             /// If the zone is considered NSEC-signed and the context
    1071                 :            :             /// requested DNSSEC proofs, this method tries to find NSEC RRset
    1072                 :            :             /// from the given set (\c found_set) and returns it if found;
    1073                 :            :             /// in other cases this method simply returns NULL.
    1074                 :            :             ///
    1075                 :            :             /// \param found_set The RRset which may contain an NSEC RRset.
    1076                 :            :             /// \return Any found DNSSEC proof RRset or NULL
    1077                 :            :             isc::dns::ConstRRsetPtr getDNSSECRRset(const FoundRRsets&
    1078                 :            :                                                    found_set);
    1079                 :            : 
    1080                 :            :         private:
    1081                 :            :             /// \brief Returns whether the zone is signed with NSEC3.
    1082                 :            :             ///
    1083                 :            :             /// This method returns true if the zone for the finder that
    1084                 :            :             /// uses this context is considered DNSSEC signed with NSEC3;
    1085                 :            :             /// otherwise it returns false.  If it's not yet detected,
    1086                 :            :             /// this method now detects that via database lookups (if
    1087                 :            :             /// necessary).
    1088                 :            :             bool isNSEC3();
    1089                 :            : 
    1090                 :            :             /// \brief Returns whether the zone is signed with NSEC.
    1091                 :            :             ///
    1092                 :            :             /// This is similar to isNSEC3(), but works for NSEC.
    1093                 :            :             bool isNSEC();
    1094                 :            : 
    1095                 :            :             /// \brief Probe into the database to see if/how the zone is
    1096                 :            :             /// signed.
    1097                 :            :             ///
    1098                 :            :             /// This is a subroutine of isNSEC3() and isNSEC(), and performs
    1099                 :            :             /// delayed database probe to detect whether the zone used by
    1100                 :            :             /// the finder is DNSSEC signed, and if it is, with NSEC or NSEC3.
    1101                 :            :             void probe();
    1102                 :            : 
    1103                 :            :             DatabaseClient::Finder& finder_;
    1104                 :            :             const bool need_dnssec_;
    1105                 :            : 
    1106                 :            :             bool is_nsec3_;
    1107                 :            :             bool is_nsec_;
    1108                 :            :             bool probed_;
    1109                 :            :         };
    1110                 :            : 
    1111                 :            :         /// \brief Search result of \c findDelegationPoint().
    1112                 :            :         ///
    1113                 :            :         /// This is a tuple combining the result of the search - a status code
    1114                 :            :         /// and a pointer to the RRset found - together with additional
    1115                 :            :         /// information needed for subsequent processing, an indication of
    1116                 :            :         /// the first NS RRset found in the search and the number of labels
    1117                 :            :         /// in the last non-empty domain encountered in the search.  It is
    1118                 :            :         /// used by \c findDelegationPoint().
    1119                 :            :         ///
    1120                 :            :         /// The last two items are located naturally in the search and although
    1121                 :            :         /// not strictly part of the result, they are passed back to avoid
    1122                 :            :         /// another (duplicate) search later in the processing.
    1123                 :            :         ///
    1124                 :            :         /// Note that the code and rrset elements are the same as that in
    1125                 :            :         /// the \c ZoneFinder::FindResult struct: this structure could be
    1126                 :            :         /// derived from that one, but as it is used just once in the code and
    1127                 :            :         /// will never be treated as a \c FindResult, the obscurity involved in
    1128                 :            :         /// deriving it from a parent class was deemed not worthwhile.
    1129                 :        726 :         struct DelegationSearchResult {
    1130                 :            :             DelegationSearchResult(const ZoneFinder::Result param_code,
    1131                 :            :                                    const isc::dns::ConstRRsetPtr param_rrset,
    1132                 :            :                                    const isc::dns::ConstRRsetPtr param_ns,
    1133                 :            :                                    size_t param_last_known) :
    1134                 :            :                                    code(param_code), rrset(param_rrset),
    1135                 :            :                                    first_ns(param_ns),
    1136                 :       2178 :                                    last_known(param_last_known)
    1137                 :            :             {}
    1138                 :            :             const ZoneFinder::Result code;          ///< Result code
    1139                 :            :             const isc::dns::ConstRRsetPtr rrset;    ///< RRset found
    1140                 :            :             const isc::dns::ConstRRsetPtr first_ns; ///< First NS found
    1141                 :            :             const size_t last_known; ///< No. labels in last non-empty domain
    1142                 :            :         };
    1143                 :            : 
    1144                 :            :         /// \brief Find delegation point
    1145                 :            :         ///
    1146                 :            :         /// Given a name, searches through the superdomains from the origin
    1147                 :            :         /// down, searching for a point that indicates a delegation (i.e. an
    1148                 :            :         /// NS record or a DNAME).
    1149                 :            :         ///
    1150                 :            :         /// The method operates in two modes, non-glue-ok and glue-ok modes:
    1151                 :            :         ///
    1152                 :            :         /// In non-glue-ok mode, the search is made purely for the NS or DNAME
    1153                 :            :         /// RR.  The zone is searched from the origin down looking  for one
    1154                 :            :         /// of these RRTypes (and ignoring the NS records at the zone origin).
    1155                 :            :         /// A status is returned indicating what is found: DNAME, DELEGATION
    1156                 :            :         /// of SUCCESS, the last indicating that nothing was found, together
    1157                 :            :         /// with a pointer to the relevant RR.
    1158                 :            :         ///
    1159                 :            :         /// In glue-ok mode, the first NS encountered in the search (apart from
    1160                 :            :         /// the NS at the zone apex) is remembered but otherwise NS records are
    1161                 :            :         /// ignored and the search attempts to find a DNAME.  The result is
    1162                 :            :         /// returned in the same format, along with a pointer to the first non-
    1163                 :            :         /// apex NS (if found).
    1164                 :            :         ///
    1165                 :            :         /// \param name The name to find
    1166                 :            :         /// \param options Options about how to search. See the documentation
    1167                 :            :         ///        for ZoneFinder::FindOptions.
    1168                 :            :         ///
    1169                 :            :         /// \return Tuple holding the result of the search - the RRset of the
    1170                 :            :         ///         delegation point and the type of the point (DELEGATION or
    1171                 :            :         ///         DNAME) - and associated information.  This latter item
    1172                 :            :         ///         comprises two pieces of data: a pointer to the highest
    1173                 :            :         ///         encountered NS, and the number of labels in the last known
    1174                 :            :         ///         non-empty domain.  The associated information is found as
    1175                 :            :         ///         a natural part of the search for the delegation point and
    1176                 :            :         ///         is used later in the find() processing; it is passed back
    1177                 :            :         ///         to avoid the need to perform a second search to obtain it.
    1178                 :            :         DelegationSearchResult
    1179                 :            :         findDelegationPoint(const isc::dns::Name& name,
    1180                 :            :                             const FindOptions options);
    1181                 :            : 
    1182                 :            :         /// \brief Find wildcard match
    1183                 :            :         ///
    1184                 :            :         /// Having found that the name is not an empty non-terminal, this
    1185                 :            :         /// searches the zone for for wildcards that match the name.
    1186                 :            :         ///
    1187                 :            :         /// It searches superdomains of the name from the zone origin down
    1188                 :            :         /// looking for a wildcard in the zone that matches the name.  There
    1189                 :            :         /// are several cases to consider:
    1190                 :            :         ///
    1191                 :            :         /// - If the previous search for a delegation point has found that
    1192                 :            :         ///   there is an NS at the superdomain of the point at which the
    1193                 :            :         ///   wildcard is found, the delegation is returned.
    1194                 :            :         /// - If there is a match to the name, an appropriate status is
    1195                 :            :         ///   returned (match on requested type, delegation, cname, or just
    1196                 :            :         ///   the indication of a match but no RRs relevant to the query).
    1197                 :            :         /// - If the match is to an non-empty non-terminal wildcard, a
    1198                 :            :         ///   wildcard NXRRSET is returned.
    1199                 :            :         ///
    1200                 :            :         /// Note that if DNSSEC is enabled for the search and the zone uses
    1201                 :            :         /// NSEC for authenticated denial of existence, the search may
    1202                 :            :         /// return NSEC records.
    1203                 :            :         ///
    1204                 :            :         /// \param name The name to find
    1205                 :            :         /// \param type The RRType to find
    1206                 :            :         /// \param options Options about how to search. See the documentation
    1207                 :            :         ///        for ZoneFinder::FindOptions.
    1208                 :            :         /// \param dresult Result of the search through the zone for a
    1209                 :            :         ///        delegation.
    1210                 :            :         /// \param target If the type happens to be ANY, it will insert all
    1211                 :            :         ///        the RRsets of the found name (if any is found) here instead
    1212                 :            :         ///        of being returned by the result.
    1213                 :            :         /// \param dnssec_ctx The dnssec context, it is a DNSSEC wrapper for
    1214                 :            :         ///        find function.
    1215                 :            :         /// \return Tuple holding the result of the search - the RRset of the
    1216                 :            :         ///         wildcard records matching the name, together with a status
    1217                 :            :         ///         indicating the match type (e.g. CNAME at the wildcard
    1218                 :            :         ///         match, no RRs of the requested type at the wildcard,
    1219                 :            :         ///         success due to an exact match).  Also returned if there
    1220                 :            :         ///         is no match is an indication as to whether there was an
    1221                 :            :         ///         NXDOMAIN or an NXRRSET.
    1222                 :            :         ResultContext findWildcardMatch(const isc::dns::Name& name,
    1223                 :            :                                         const isc::dns::RRType& type,
    1224                 :            :                                         const FindOptions options,
    1225                 :            :                                         const DelegationSearchResult& dresult,
    1226                 :            :                                         std::vector<isc::dns::ConstRRsetPtr>*
    1227                 :            :                                         target, FindDNSSECContext& dnssec_ctx);
    1228                 :            : 
    1229                 :            :         /// \brief Handle matching results for name
    1230                 :            :         ///
    1231                 :            :         /// This is called when something is found in the underlying database
    1232                 :            :         /// whose domain name is an exact match of the name to be searched for.
    1233                 :            :         /// It explores four possible cases to decide the final lookup result:
    1234                 :            :         /// - The name is a zone cut due to an NS RR.
    1235                 :            :         /// - CNAME is found (while the requested RR type is not CNAME).
    1236                 :            :         ///   In this case multiple CNAMEs are checked and rejected with
    1237                 :            :         ///   a \c DataSourceError exception.
    1238                 :            :         /// - Requested type is not found at that name.
    1239                 :            :         /// - A record of the requested type is found, or the query is ANY and
    1240                 :            :         ///   some records were found.
    1241                 :            :         /// and returns a corresponding find result.
    1242                 :            :         ///
    1243                 :            :         /// This method is commonly used for normal (non wildcard) and wildcard
    1244                 :            :         /// matches.
    1245                 :            :         ///
    1246                 :            :         /// \param name The name to find
    1247                 :            :         /// \param type The RRType to find
    1248                 :            :         /// \param options Options about how to search. See the documentation
    1249                 :            :         ///        for ZoneFinder::FindOptions.
    1250                 :            :         /// \param is_origin If name is the zone's origin name.
    1251                 :            :         /// \param found A set of found RRsets in the search for the name
    1252                 :            :         ///        and type.  It could contain one or more of the requested
    1253                 :            :         ///        type, CNAME, NS, and NSEC RRsets of the name.
    1254                 :            :         /// \param wildname If non NULL, the method is called on a wildcard
    1255                 :            :         ///                 match, and points to a string object representing
    1256                 :            :         ///                 a textual form of the matched wildcard name;
    1257                 :            :         ///                 it's NULL in the case of non wildcard match.
    1258                 :            :         /// \param target When the query is any, this must be set to a vector
    1259                 :            :         ///    where the result will be stored.
    1260                 :            :         /// \param dnssec_ctx The dnssec context, it is a DNSSEC wrapper for
    1261                 :            :         ///        find function.
    1262                 :            : 
    1263                 :            :         /// \return Tuple holding the result of the search - the RRset of the
    1264                 :            :         ///         wildcard records matching the name, together with a status
    1265                 :            :         ///         indicating the match type (corresponding to the each of
    1266                 :            :         ///         the above 4 cases).  The return value is intended to be
    1267                 :            :         ///         usable as a return value of the caller of this helper
    1268                 :            :         ///         method.
    1269                 :            :         ResultContext findOnNameResult(const isc::dns::Name& name,
    1270                 :            :                                        const isc::dns::RRType& type,
    1271                 :            :                                        const FindOptions options,
    1272                 :            :                                        const bool is_origin,
    1273                 :            :                                        const FoundRRsets& found,
    1274                 :            :                                        const std::string* wildname,
    1275                 :            :                                        std::vector<isc::dns::ConstRRsetPtr>*
    1276                 :            :                                        target, FindDNSSECContext& dnssec_ctx);
    1277                 :            : 
    1278                 :            :         /// \brief Handle no match for name
    1279                 :            :         ///
    1280                 :            :         /// This is called when it is known that there is no delegation and
    1281                 :            :         /// there is no exact match for the name (regardless of RR types
    1282                 :            :         /// requested).  Before returning NXDOMAIN, we need to check two
    1283                 :            :         /// cases:
    1284                 :            :         /// - Empty non-terminal: if the name has subdomains in the database,
    1285                 :            :         ///   flag the fact.  An NXRRSET will be returned (along with the
    1286                 :            :         ///   NSEC record covering the requested domain name if DNSSEC data
    1287                 :            :         ///   is being returned).
    1288                 :            :         /// - Wildcard: is there a wildcard record in the zone that matches
    1289                 :            :         ///   requested name? If so, return it.  If not, return the relevant
    1290                 :            :         ///   NSEC records (if requested).
    1291                 :            :         ///
    1292                 :            :         /// \param name The name to find
    1293                 :            :         /// \param type The RRType to find
    1294                 :            :         /// \param options Options about how to search. See the documentation
    1295                 :            :         ///        for ZoneFinder::FindOptions.
    1296                 :            :         /// \param dresult Result of the search through the zone for a
    1297                 :            :         ///        delegation.
    1298                 :            :         /// \param target If the query is for type ANY, the successfull result,
    1299                 :            :         ///        if there happens to be one, will be returned through the
    1300                 :            :         ///        parameter, as it doesn't fit into the result.
    1301                 :            :         /// \param dnssec_ctx The dnssec context, it is a DNSSEC wrapper for
    1302                 :            :         ///        find function.
    1303                 :            :         /// \return Tuple holding the result of the search - the RRset of the
    1304                 :            :         ///         wildcard records matching the name, together with a status
    1305                 :            :         ///         indicating the match type (e.g. CNAME at the wildcard
    1306                 :            :         ///         match, no RRs of the requested type at the wildcard,
    1307                 :            :         ///         success due to an exact match).
    1308                 :            :         ResultContext findNoNameResult(const isc::dns::Name& name,
    1309                 :            :                                        const isc::dns::RRType& type,
    1310                 :            :                                        FindOptions options,
    1311                 :            :                                        const DelegationSearchResult& dresult,
    1312                 :            :                                        std::vector<isc::dns::ConstRRsetPtr>*
    1313                 :            :                                        target, FindDNSSECContext& dnssec_ctx);
    1314                 :            : 
    1315                 :            :         /// Logs condition and creates result
    1316                 :            :         ///
    1317                 :            :         /// A convenience function used by findOnNameResult(), it both creates
    1318                 :            :         /// the FindResult object that find() will return to its caller as well
    1319                 :            :         /// as logging a debug message for the information being returned.
    1320                 :            :         ///
    1321                 :            :         /// \param name Domain name of the RR that was being sought.
    1322                 :            :         /// \param wildname Domain name string of a matched wildcard name or
    1323                 :            :         /// NULL for non wildcard match.
    1324                 :            :         /// \param type Type of RR being sought.
    1325                 :            :         /// \param code Result of the find operation
    1326                 :            :         /// \param rrset RRset found as a result of the find (which may be
    1327                 :            :         ///        null).
    1328                 :            :         /// \param log_id ID of the message being logged.  Up to five
    1329                 :            :         ///        parameters are available to the message: data source name,
    1330                 :            :         ///        requested domain name, requested class, requested type
    1331                 :            :         ///        and (but only if the search was successful and returned
    1332                 :            :         ///        an RRset) details of the RRset found.
    1333                 :            :         ///
    1334                 :            :         /// \return FindResult object constructed from the code and rrset
    1335                 :            :         ///         arguments.
    1336                 :            :         ResultContext logAndCreateResult(const isc::dns::Name& name,
    1337                 :            :                                          const std::string* wildname,
    1338                 :            :                                          const isc::dns::RRType& type,
    1339                 :            :                                          ZoneFinder::Result code,
    1340                 :            :                                          isc::dns::ConstRRsetPtr rrset,
    1341                 :            :                                          const isc::log::MessageID& log_id,
    1342                 :            :                                          FindResultFlags flags) const;
    1343                 :            : 
    1344                 :            :         /// \brief Checks if something lives below this domain.
    1345                 :            :         ///
    1346                 :            :         /// This looks if there's any subdomain of the given name. It can be
    1347                 :            :         /// used to test if domain is empty non-terminal.
    1348                 :            :         ///
    1349                 :            :         /// \param name The domain to check.
    1350                 :            :         ///
    1351                 :            :         /// \return true if the name has subdomains, false if not.
    1352                 :            :         bool hasSubdomains(const std::string& name);
    1353                 :            : 
    1354                 :            :         /// \brief Convenience type shortcut.
    1355                 :            :         ///
    1356                 :            :         /// To find stuff in the result of getRRsets.
    1357                 :            :         typedef std::map<dns::RRType, dns::RRsetPtr>::const_iterator
    1358                 :            :             FoundIterator;
    1359                 :            :     };
    1360                 :            : 
    1361                 :            :     /// \brief Find a zone in the database
    1362                 :            :     ///
    1363                 :            :     /// This queries database's getZone to find the best matching zone.
    1364                 :            :     /// It will propagate whatever exceptions are thrown from that method
    1365                 :            :     /// (which is not restricted in any way).
    1366                 :            :     ///
    1367                 :            :     /// \param name Name of the zone or data contained there.
    1368                 :            :     /// \return FindResult containing the code and an instance of Finder, if
    1369                 :            :     ///     anything is found. However, application should not rely on the
    1370                 :            :     ///     ZoneFinder being instance of Finder (possible subclass of this class
    1371                 :            :     ///     may return something else and it may change in future versions), it
    1372                 :            :     ///     should use it as a ZoneFinder only.
    1373                 :            :     virtual FindResult findZone(const isc::dns::Name& name) const;
    1374                 :            : 
    1375                 :            :     /// \brief Get the zone iterator
    1376                 :            :     ///
    1377                 :            :     /// The iterator allows going through the whole zone content. If the
    1378                 :            :     /// underlying DatabaseConnection is implemented correctly, it should
    1379                 :            :     /// be possible to have multiple ZoneIterators at once and query data
    1380                 :            :     /// at the same time.
    1381                 :            :     ///
    1382                 :            :     /// \exception DataSourceError if the zone doesn't exist.
    1383                 :            :     /// \exception isc::NotImplemented if the underlying DatabaseConnection
    1384                 :            :     ///     doesn't implement iteration. But in case it is not implemented
    1385                 :            :     ///     and the zone doesn't exist, DataSourceError is thrown.
    1386                 :            :     /// \exception Anything else the underlying DatabaseConnection might
    1387                 :            :     ///     want to throw.
    1388                 :            :     /// \param name The origin of the zone to iterate.
    1389                 :            :     /// \param separate_rrs If true, the iterator will return each RR as a
    1390                 :            :     ///                     new RRset object. If false, the iterator will
    1391                 :            :     ///                     combine consecutive RRs with the name and type
    1392                 :            :     ///                     into 1 RRset. The capitalization of the RRset will
    1393                 :            :     ///                     be that of the first RR read, and TTLs will be
    1394                 :            :     ///                     adjusted to the lowest one found.
    1395                 :            :     /// \return Shared pointer to the iterator (it will never be NULL)
    1396                 :            :     virtual ZoneIteratorPtr getIterator(const isc::dns::Name& name,
    1397                 :            :                                         bool separate_rrs = false) const;
    1398                 :            : 
    1399                 :            :     /// This implementation internally clones the accessor from the one
    1400                 :            :     /// used in the client and starts a separate transaction using the cloned
    1401                 :            :     /// accessor.  The returned updater will be able to work separately from
    1402                 :            :     /// the original client.
    1403                 :            :     virtual ZoneUpdaterPtr getUpdater(const isc::dns::Name& name,
    1404                 :            :                                       bool replace,
    1405                 :            :                                       bool journaling = false) const;
    1406                 :            : 
    1407                 :            : 
    1408                 :            :     /// This implementation internally clones the accessor from the one
    1409                 :            :     /// used in the client for retrieving diffs and iterating over them.
    1410                 :            :     /// The returned reader object will be able to work separately from
    1411                 :            :     /// the original client.
    1412                 :            :     virtual std::pair<ZoneJournalReader::Result, ZoneJournalReaderPtr>
    1413                 :            :     getJournalReader(const isc::dns::Name& zone, uint32_t begin_serial,
    1414                 :            :                      uint32_t end_serial) const;
    1415                 :            : 
    1416                 :            : private:
    1417                 :            :     /// \brief The RR class that this client handles.
    1418                 :            :     const isc::dns::RRClass rrclass_;
    1419                 :            : 
    1420                 :            :     /// \brief The accessor to our database.
    1421                 :            :     const boost::shared_ptr<DatabaseAccessor> accessor_;
    1422                 :            : };
    1423                 :            : 
    1424                 :            : }
    1425                 :            : }
    1426                 :            : 
    1427                 :            : #endif  // __DATABASE_DATASRC_H
    1428                 :            : 
    1429                 :            : // Local Variables:
    1430                 :            : // mode: c++
    1431                 :            : // End:

Generated by: LCOV version 1.9