1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright (C) 2015-2023 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef HOST_DATA_SOURCE_FACTORY_H
#define HOST_DATA_SOURCE_FACTORY_H

#include <database/database_connection.h>
#include <dhcpsrv/base_host_data_source.h>
#include <exceptions/exceptions.h>

#include <functional><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <string><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <vector><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <map><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace isc {
namespace dhcp {

/// @brief No host data source instance exception
///
/// Thrown if an attempt is made to get a reference to the current
/// host data source instance and none is currently available.
class NoHostDataSourceManager : public Exception {
public:
    NoHostDataSourceManager(const char* file, size_t line, const char* what) :
        isc::Exception(file, line, what) {}
};

/// @brief Host Data Source Factory
///
/// This class comprises nothing but static methods used to create a host data
/// source object. It analyzes the database information passed to the creation
/// function and instantiates an appropriate host data source object based on
/// the type requested.
///
/// Strictly speaking these functions could be stand-alone functions.  However,
/// it is convenient to encapsulate them in a class for naming purposes.

class HostDataSourceFactory {
public:
    /// @brief Create and add an instance of a host data source.
    ///
    /// Each database backend has its own host data source type. This static
    /// method adds an object of the appropriate type to a list of
    /// host data sources.
    ///
    /// dbaccess is a generic way of passing parameters. Parameters are passed
    /// in the "name=value" format, separated by spaces.  The data MUST include
    /// a keyword/value pair of the form "type=dbtype" giving the database
    /// type, e.q. "mysql" or "sqlite3".
    ///
    /// @param sources host data source list (new backend will be added here)
    /// @param dbaccess Database access parameters.  These are in the form of
    ///        "keyword=value" pairs, separated by spaces. They are backend-
    ///        -end specific, although must include the "type" keyword which
    ///        gives the backend in use.
    ///
    /// @throw isc::InvalidParameter dbaccess string does not contain the "type"
    ///        keyword.
    /// @throw isc::dhcp::InvalidType The "type" keyword in dbaccess does not
    ///        identify a supported backend.
    static void add(HostDataSourceList& sources, const std::string& dbaccess);

    /// @brief Delete a host data source.
    ///
    /// Delete the first instance of a host data source of the given type.
    /// This should have the effect of closing the database connection.
    ///
    /// @param sources host data source list.
    /// @param db_type database backend type.
    /// @return true when found and removed, false when not found.
    static bool del(HostDataSourceList& sources, const std::string& db_type);

    /// @brief Delete a host data source.
    ///
    /// Delete the first instance of a host data source which matches specific
    /// parameters.
    /// This should have the effect of closing the database connection.
    ///
    /// @param sources host data source list.
    /// @param db_type database backend type.
    /// @param dbaccess Database access parameters.  These are in the form of
    ///        "keyword=value" pairs, separated by spaces. They are backend-
    ///        -end specific, although must include the "type" keyword which
    ///        gives the backend in use.
    /// @param if_unusable flag which indicates if the host data source should
    ///        be deleted only if it is unusable.
    /// @return false when not removed because it is not found or because it is
    /// still usable (if_unusable is true), true otherwise.
    static bool del(HostDataSourceList& sources, const std::string& db_type,
                    const std::string& dbaccess, bool if_unusable = true);

    /// @brief Type of host data source factory
    ///
    /// A factory takes a parameter map and returns a pointer to a host
    /// data source. In case of failure it must throw and not return NULL.
    typedef std::function<HostDataSourcePtr (const db::DatabaseConnection::ParameterMap&)> Factory;

    /// @brief Register a host data source factory
    ///
    /// Associate the factory to a database type in the map.
    /// The no_log is to avoid logging before the logger is initialized
    /// as when called at global object initialization.
    ///
    /// @param db_type database type
    /// @param factory host data source factory
    /// @param no_log do not log (default false)
    /// @return true if the factory was successfully added to the map, false
    /// if it already exists.
    static bool registerFactory(const std::string& db_type,
                                const Factory& factory, bool no_log = false);

    /// @brief Deregister a host data source factory
    ///
    /// Disassociate the factory to a database type in the map.
    /// The no_log is to avoid logging during global object deinitialization.
    ///
    /// @param db_type database type
    /// @param no_log do not log (default false)
    /// @return true if the factory was successfully removed from the map,
    /// false if it was not found.
    static bool deregisterFactory(const std::string& db_type,
                                  bool no_log = false);

    /// @brief Check if a host data source factory was registered
    ///
    /// @param db_type database type
    /// @return true if a factory was registered for db_type, false if not.
    static bool registeredFactory(const std::string& db_type);

    /// @brief Prints out all registered backends.
    ///
    /// We need a dedicated method for this, because we sometimes can't log
    /// the backend type when doing early initialization for backends
    /// initialized statically.
    static void printRegistered();

private:
    /// @brief Factory map
    static std::map<std::string, Factory> map_;
};

} // end of isc::dhcp namespace
} // end of isc namespace

#endif