Commit 455dc3f7 authored by Marcin Siodelski's avatar Marcin Siodelski

[#28,!20] Added commentary to the BaseConfigBackendMgr.

parent ac2de9f5
......@@ -7,8 +7,8 @@
#ifndef BASE_CONFIG_BACKEND_MGR_H
#define BASE_CONFIG_BACKEND_MGR_H
#include <database/database_connection.h>
#include <config_backend/base_config_backend.h>
#include <database/database_connection.h>
#include <exceptions/exceptions.h>
#include <boost/shared_ptr.hpp>
#include <functional>
......@@ -18,40 +18,116 @@
namespace isc {
namespace cb {
/// @brief Base class for Configuration Backend Managers (CBM).
///
/// Each Kea server supporting Configuration Backend feature implements
/// a "manager" class which holds information about supported and
/// configured backends and provides access to the backends. This is
/// similar to @c HostMgr and @c LeaseMgr singletons being used by the
/// DHCP servers.
///
/// The Config Backend Managers are typically implemented as singletons
/// which can be accessed from any place within the server code. This
/// includes server configuration, data fetching during normal server
/// operation and data management, including processing of control
/// commands implemented within hooks libraries.
///
/// The @c BaseConfigBackendMgr is a base class for all CBMs implemented
/// for respective Kea servers. It includes mechanisms to register config
/// backend factory functions and to create instances of the backends using
/// those factory functions as a result of server configuration. The mechanism
/// of factory functions registration is useful in cases when the config
/// backend is implemented within the hook library. Such hook library
/// registers factory function in its @c load function and the server
/// simply calls this function to create the instance of this backend when
/// instructed to do so via configuration. Similar mechanism exists in
/// DHCP @c HostMgr.
///
/// Unlike @c HostMgr, the CBMs do not directly expose API to fetch and
/// manipulate the data in the database. This is done via, so called,
/// Configuration Backends Pools. See @c BaseConfigBackendPool for
/// details. The @c BaseConfigBackendMgr is provided with the pool type
/// via class template parameter. Respective CBM implementations
/// use their own pools, which provide APIs appropriate for those
/// implementation.
///
/// @tparam ConfgBackendPoolType Type of the configuration backend pool
/// to be used by the manager. It must derive from @c BaseConfigBackendPool
/// template class.
template<typename ConfigBackendPoolType>
class BaseConfigBackendMgr {
public:
/// @brief Pointer to the configuration backend pool.
typedef boost::shared_ptr<ConfigBackendPoolType> ConfigBackendPoolPtr;
/// @brief Type of the backend factory function.
///
/// Factory function returns a pointer to the instance of the configuration
/// backend created.
typedef std::function<typename ConfigBackendPoolType::ConfigBackendTypePtr
(const db::DatabaseConnection::ParameterMap&)> Factory;
/// @brief Constructor.
BaseConfigBackendMgr()
: factories_(), backends_(new ConfigBackendPoolType()) {
: factories_(), pool_(new ConfigBackendPoolType()) {
}
/// @brief Registers new backend factory function for a given backend type.
///
/// The typical usage of this function is to make the CBM aware of a
/// configuration backend implementation. This implementation may exist
/// in a hooks library. In such case, this function should be called from
/// the @c load function in this library. When the backend is registered,
/// the server will use it when required by the configuration, i.e. a
/// user includes configuration backend of that type in the
/// "config-databases" list.
///
/// If the backend of the given type has already been registered, perhaps
/// by another hooks library, the CBM will refuse to register another
/// backend of the same type.
///
/// @param db_type Backend type, e.g. "mysql".
/// @param factory Pointer to the backend factory function.
///
/// @return true if the backend has been successfully registered, false
/// if another backend of this type already exists.
bool registerBackendFactory(const std::string& db_type,
const Factory& factory) {
// Check if this backend has been already registered.
if (factories_.count(db_type)) {
return (false);
}
// Register the new backend.
factories_.insert(std::make_pair(db_type, factory));
return (true);
}
/// @brief Create an instance of a configuration backend.
///
/// This method uses provided @c dbaccess string representing database
/// connection information to create an instance of the database
/// backend. If the specified backend type is not supported, i.e. there
/// is no relevant factory function registered, an exception is thrown.
///
/// @param dbaccess Database access string being a collection of
/// key=value pairs.
///
/// @throw InvalidParameter if access string lacks database type value.
/// @throw db::InvalidType if the type of the database backend is not
/// supported.
/// @throw Unexpected if the backend factory function returned NULL.
void addBackend(const std::string& dbaccess) {
// Parse the access string and create a redacted string for logging.
// Parse the access string into a map of parameters.
db::DatabaseConnection::ParameterMap parameters =
db::DatabaseConnection::parse(dbaccess);
// Get the database type and open the corresponding database
// Get the database type to locate a factory function.
db::DatabaseConnection::ParameterMap::iterator it = parameters.find("type");
if (it == parameters.end()) {
isc_throw(InvalidParameter, "Host database configuration does not "
"contain the 'type' keyword");
isc_throw(InvalidParameter, "Config backend specification lacks the "
"'type' keyword");
}
std::string db_type = it->second;
......@@ -59,8 +135,8 @@ public:
// No match?
if (index == factories_.end()) {
isc_throw(db::InvalidType, "The type of host backend: '" <<
db_type << "' is not currently supported");
isc_throw(db::InvalidType, "The type of the configuration backend: '" <<
db_type << "' is not supported");
}
// Call the factory and push the pointer on sources.
......@@ -70,23 +146,27 @@ public:
" factory returned NULL");
}
backends_->addBackend(backend);
// Backend instance created successfully.
pool_->addBackend(backend);
}
/// @brief Removes all backends from the pool.
void delAllBackends() {
backends_->delAllBackends();
pool_->delAllBackends();
}
/// @brief Returns underlying config backend pool.
ConfigBackendPoolPtr getPool() const {
return (backends_);
return (pool_);
}
protected:
/// @brief A map holding registered backend factory functions.
std::map<std::string, Factory> factories_;
ConfigBackendPoolPtr backends_;
/// @brief Pointer to the configuration backends pool.
ConfigBackendPoolPtr pool_;
};
} // end of namespace isc::cb
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment