123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #ifndef DATASRC_SQLITE3_ACCESSOR_H
- #define DATASRC_SQLITE3_ACCESSOR_H
- #include <datasrc/database.h>
- #include <datasrc/exceptions.h>
- #include <exceptions/exceptions.h>
- #include <boost/enable_shared_from_this.hpp>
- #include <boost/scoped_ptr.hpp>
- #include <string>
- #include <cc/data.h>
- namespace isc {
- namespace dns {
- class RRClass;
- }
- namespace datasrc {
- /// \brief Low-level database error
- ///
- /// This exception is thrown when the SQLite library complains about something.
- /// It might mean corrupt database file, invalid request or that something is
- /// rotten in the library.
- class SQLite3Error : public DataSourceError {
- public:
- SQLite3Error(const char* file, size_t line, const char* what) :
- DataSourceError(file, line, what) {}
- };
- class IncompatibleDbVersion : public Exception {
- public:
- IncompatibleDbVersion(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
- };
- /// \brief Too Much Data
- ///
- /// Thrown if a query expecting a certain number of rows back returned too
- /// many rows.
- class TooMuchData : public DataSourceError {
- public:
- TooMuchData(const char* file, size_t line, const char* what) :
- DataSourceError(file, line, what) {}
- };
- /// \brief Too Little Data
- ///
- /// Thrown if a query expecting a certain number of rows back returned too
- /// few rows (including none).
- class TooLittleData : public DataSourceError {
- public:
- TooLittleData(const char* file, size_t line, const char* what) :
- DataSourceError(file, line, what) {}
- };
- struct SQLite3Parameters;
- /// \brief Concrete implementation of DatabaseAccessor for SQLite3 databases
- ///
- /// This opens one database file with our schema and serves data from there.
- /// According to the design, it doesn't interpret the data in any way, it just
- /// provides unified access to the DB.
- class SQLite3Accessor : public DatabaseAccessor,
- public boost::enable_shared_from_this<SQLite3Accessor> {
- public:
- /// \brief Constructor
- ///
- /// This opens the database and becomes ready to serve data from there.
- ///
- /// \exception SQLite3Error will be thrown if the given database file
- /// doesn't work (it is broken, doesn't exist and can't be created, etc).
- ///
- /// \param filename The database file to be used.
- /// \param rrclass Textual representation of RR class ("IN", "CH", etc),
- /// specifying which class of data it should serve (while the database
- /// file can contain multiple classes of data, a single accessor can
- /// work with only one class).
- SQLite3Accessor(const std::string& filename, const std::string& rrclass);
- /// \brief Destructor
- ///
- /// Closes the database.
- virtual ~SQLite3Accessor();
- /// This implementation internally opens a new sqlite3 database for the
- /// same file name specified in the constructor of the original accessor.
- virtual boost::shared_ptr<DatabaseAccessor> clone();
- /// \brief Look up a zone
- ///
- /// This implements the getZone from DatabaseAccessor and looks up a zone
- /// in the data. It looks for a zone with the exact given origin and class
- /// passed to the constructor.
- ///
- /// \exception SQLite3Error if something about the database is broken.
- ///
- /// \param name The (fully qualified) domain name of zone to look up
- /// \return The pair contains if the lookup was successful in the first
- /// element and the zone id in the second if it was.
- virtual std::pair<bool, int> getZone(const std::string& name) const;
- /// \brief Add a zone
- ///
- /// This implements the addZone from DatabaseAccessor and adds a zone
- /// into the zones table. If the zone exists already, it is still added,
- /// so the caller should make sure this does not happen (by making
- /// sure the zone does not exist). In the case of duplicate addition,
- /// it is undefined which zone id is returned.
- ///
- /// The class of the newly created zone is the class passed at construction
- /// time of the accessor.
- ///
- /// This method requires a transaction has been started (with
- /// \c beginTransaction) by the caller.
- ///
- /// \exception DataSourceError if no transaction is active, or if there
- /// is an SQLite3 error when performing the
- /// queries.
- ///
- /// \param name The origin name of the zone to add
- /// \return the id of the zone that has been added
- virtual int addZone(const std::string& name);
- // Nothing special to add for this implementation (the base class
- // description is sufficient).
- virtual void deleteZone(int zone_id);
- /// \brief Look up all resource records for a name
- ///
- /// This implements the getRecords() method from DatabaseAccessor
- ///
- /// \exception SQLite3Error if there is an sqlite3 error when performing
- /// the query
- ///
- /// \param name the name to look up
- /// \param id the zone id, as returned by getZone()
- /// \param subdomains Match subdomains instead of the name.
- /// \return Iterator that contains all records with the given name
- virtual IteratorContextPtr getRecords(const std::string& name,
- int id,
- bool subdomains = false) const;
- /// \brief Look up NSEC3 records for the given hash
- ///
- /// This implements the getNSEC3Records of DatabaseAccessor.
- ///
- /// \todo Actually implement, currently throws NotImplemented.
- virtual IteratorContextPtr getNSEC3Records(const std::string& hash,
- int id) const;
- /// \brief Look up all resource records for a zone
- ///
- /// This implements the getRecords() method from DatabaseAccessor
- ///
- /// \exception SQLite3Error if there is an sqlite3 error when performing
- /// the query
- ///
- /// \param id the zone id, as returned by getZone()
- /// \return Iterator that contains all records in the given zone
- virtual IteratorContextPtr getAllRecords(int id) const;
- /// \brief Creates an iterator context for a set of differences.
- ///
- /// Implements the getDiffs() method from DatabaseAccessor
- ///
- /// \exception NoSuchSerial if either of the versions do not exist in
- /// the difference table.
- /// \exception SQLite3Error if there is an sqlite3 error when performing
- /// the query
- ///
- /// \param id The ID of the zone, returned from getZone().
- /// \param start The SOA serial number of the version of the zone from
- /// which the difference sequence should start.
- /// \param end The SOA serial number of the version of the zone at which
- /// the difference sequence should end.
- ///
- /// \return Iterator containing difference records.
- virtual IteratorContextPtr
- getDiffs(int id, uint32_t start, uint32_t end) const;
- virtual std::pair<bool, int> startUpdateZone(const std::string& zone_name,
- bool replace);
- virtual void startTransaction();
- /// \note we are quite impatient here: it's quite possible that the COMMIT
- /// fails due to other process performing SELECT on the same database
- /// (consider the case where COMMIT is done by xfrin or dynamic update
- /// server while an authoritative server is busy reading the DB).
- /// In a future version we should probably need to introduce some retry
- /// attempt and/or increase timeout before giving up the COMMIT, even
- /// if it still doesn't guarantee 100% success. Right now this
- /// implementation throws a \c DataSourceError exception in such a case.
- virtual void commit();
- /// \note In SQLite3 rollback can fail if there's another unfinished
- /// statement is performed for the same database structure.
- /// Although it's not expected to happen in our expected usage, it's not
- /// guaranteed to be prevented at the API level. If it ever happens, this
- /// method throws a \c DataSourceError exception. It should be
- /// considered a bug of the higher level application program.
- virtual void rollback();
- virtual void addRecordToZone(
- const std::string (&columns)[ADD_COLUMN_COUNT]);
- virtual void addNSEC3RecordToZone(
- const std::string (&columns)[ADD_NSEC3_COLUMN_COUNT]);
- virtual void deleteRecordInZone(
- const std::string (¶ms)[DEL_PARAM_COUNT]);
- virtual void deleteNSEC3RecordInZone(
- const std::string (¶ms)[DEL_NSEC3_PARAM_COUNT]);
- /// This derived version of the method prepares an SQLite3 statement
- /// for adding the diff first time it's called, and if it fails throws
- // an \c SQLite3Error exception.
- virtual void addRecordDiff(
- int zone_id, uint32_t serial, DiffOperation operation,
- const std::string (¶ms)[DIFF_PARAM_COUNT]);
- /// The SQLite3 implementation of this method returns a string starting
- /// with a fixed prefix of "sqlite3_" followed by the DB file name
- /// removing any path name. For example, for the DB file
- /// /somewhere/in/the/system/bind10.sqlite3, this method will return
- /// "sqlite3_bind10.sqlite3".
- virtual const std::string& getDBName() const { return (database_name_); }
- /// \brief Concrete implementation of the pure virtual method
- virtual std::string findPreviousName(int zone_id, const std::string& rname)
- const;
- /// \brief Concrete implementation of the pure virtual method of
- /// DatabaseAccessor
- virtual std::string findPreviousNSEC3Hash(int zone_id,
- const std::string& hash) const;
- private:
- /// \brief Private database data
- boost::scoped_ptr<SQLite3Parameters> dbparameters_;
- /// \brief The filename of the DB (necessary for clone())
- const std::string filename_;
- /// \brief The class for which the queries are done
- const std::string class_;
- /// \brief Database name
- const std::string database_name_;
- /// \brief Opens the database
- void open(const std::string& filename);
- /// \brief Closes the database
- void close();
- /// \brief SQLite3 implementation of IteratorContext for all records
- class Context;
- friend class Context;
- /// \brief SQLite3 implementation of IteratorContext for differences
- class DiffContext;
- friend class DiffContext;
- };
- /// \brief Creates an instance of the SQlite3 datasource client
- ///
- /// Currently the configuration passed here must be a MapElement, containing
- /// one item called "database_file", whose value is a string
- ///
- /// This configuration setup is currently under discussion and will change in
- /// the near future.
- ///
- /// \param config The configuration for the datasource instance
- /// \param error This string will be set to an error message if an error occurs
- /// during initialization
- /// \return An instance of the sqlite3 datasource client, or NULL if there was
- /// an error
- extern "C" DataSourceClient* createInstance(isc::data::ConstElementPtr config,
- std::string& error);
- /// \brief Destroy the instance created by createInstance()
- extern "C" void destroyInstance(DataSourceClient* instance);
- }
- }
- #endif // DATASRC_SQLITE3_ACCESSOR_H
- // Local Variables:
- // mode: c++
- // End:
|