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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
|
// Copyright (C) 2015-2018 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 DATABASE_CONNECTION_H
#define DATABASE_CONNECTION_H
#include <boost/noncopyable.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <exceptions/exceptions.h>
#include <map>
#include <string>
namespace isc {
namespace db {
/// @brief Exception thrown if name of database is not specified
class NoDatabaseName : public Exception {
public:
NoDatabaseName(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
/// @brief Exception thrown on failure to open database
class DbOpenError : public Exception {
public:
DbOpenError(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
/// @brief Exception thrown on failure to execute a database function
class DbOperationError : public Exception {
public:
DbOperationError(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
/// @brief Invalid type exception
///
/// Thrown when the factory doesn't recognize the type of the backend.
class InvalidType : public Exception {
public:
InvalidType(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
/// @brief Invalid Timeout
///
/// Thrown when the timeout specified for the database connection is invalid.
class DbInvalidTimeout : public Exception {
public:
DbInvalidTimeout(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
/// @brief Invalid 'readonly' value specification.
///
/// Thrown when the value of the 'readonly' boolean parameter is invalid.
class DbInvalidReadOnly : public Exception {
public:
DbInvalidReadOnly(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
/// @brief Warehouses DB reconnect control values
///
/// When a DatabaseConnection loses connectivity to its backend, it
/// creates an instance of this class based on its configuration parameters and
/// passes the instance into connection's DB lost callback. This allows
/// the layer(s) above the connection to know how to proceed.
///
class ReconnectCtl {
public:
/// @brief Constructor
/// @param backend_type type of the caller backend.
/// @param max_retries maximum number of reconnect attempts to make
/// @param retry_interval amount of time to between reconnect attempts
ReconnectCtl(const std::string& backend_type, unsigned int max_retries,
unsigned int retry_interval)
: backend_type_(backend_type), max_retries_(max_retries),
retries_left_(max_retries), retry_interval_(retry_interval) {}
/// @brief Returns the type of the caller backend.
std::string backendType() const {
return (backend_type_);
}
/// @brief Decrements the number of retries remaining
///
/// Each call decrements the number of retries by one until zero is reached.
/// @return true the number of retries remaining is greater than zero.
bool checkRetries() {
return (retries_left_ ? --retries_left_ : false);
}
/// @brief Returns the maximum number for retries allowed
unsigned int maxRetries() {
return (max_retries_);
}
/// @brief Returns the number for retries remaining
unsigned int retriesLeft() {
return (retries_left_);
}
/// @brief Returns the amount of time to wait between reconnect attempts
unsigned int retryInterval() {
return (retry_interval_);
}
private:
/// @brief Caller backend type.
const std::string backend_type_;
/// @brief Maximum number of retry attempts to make
unsigned int max_retries_;
/// @brief Number of attempts remaining
unsigned int retries_left_;
/// @brief The amount of time to wait between reconnect attempts
unsigned int retry_interval_;
};
/// @brief Pointer to an instance of ReconnectCtl
typedef boost::shared_ptr<ReconnectCtl> ReconnectCtlPtr;
/// @brief Common database connection class.
///
/// This class provides functions that are common for establishing
/// connection with different types of databases; enables operations
/// on access parameters strings. In particular, it provides a way
/// to parse parameters in key=value format. This class is expected
/// to be a base class for all @ref LeaseMgr and possibly
/// @ref BaseHostDataSource derived classes.
class DatabaseConnection : public boost::noncopyable {
public:
/// @brief Defines maximum value for time that can be reliably stored.
///
/// @todo: Is this common for MySQL and Postgres? Maybe we should have
/// specific values for each backend?
///
/// If I'm still alive I'll be too old to care. You fix it.
static const time_t MAX_DB_TIME;
/// @brief Database configuration parameter map
typedef std::map<std::string, std::string> ParameterMap;
/// @brief Constructor
///
/// @param parameters A data structure relating keywords and values
/// concerned with the database.
DatabaseConnection(const ParameterMap& parameters)
:parameters_(parameters) {
}
/// @brief Destructor
virtual ~DatabaseConnection(){};
/// @brief Instantiates a ReconnectCtl based on the connection's
/// reconnect parameters
/// @return pointer to the new ReconnectCtl object
virtual ReconnectCtlPtr makeReconnectCtl() const;
/// @brief Returns value of a connection parameter.
///
/// @param name Name of the parameter which value should be returned.
/// @return Value of one of the connection parameters.
/// @throw BadValue if parameter is not found
std::string getParameter(const std::string& name) const;
/// @brief Parse database access string
///
/// Parses the string of "keyword=value" pairs and separates them
/// out into the map.
///
/// @param dbaccess Database access string.
///
/// @return @ref ParameterMap of keyword/value pairs.
static ParameterMap parse(const std::string& dbaccess);
/// @brief Redact database access string
///
/// Takes the database parameters and returns a database access string
/// passwords replaced by asterisks. This string is used in log messages.
///
/// @param parameters Database access parameters (output of "parse").
///
/// @return Redacted database access string.
static std::string redactedAccessString(const ParameterMap& parameters);
/// @brief Convenience method checking if database should be opened with
/// read only access.
///
/// @return true if "readonly" parameter is specified and set to true;
/// false if "readonly" parameter is not specified or it is specified
/// and set to false.
bool configuredReadOnly() const;
/// @brief Defines a callback prototype for propogating events upward
typedef boost::function<bool (ReconnectCtlPtr db_retry)> DbLostCallback;
/// @brief Invokes the connection's lost connectivity callback
///
/// This function may be called by derivations when the connectivity
/// to their data server is lost. If connectivity callback was specified,
/// this function will instantiate a ReconnectCtl and pass it to the
/// callback.
///
/// @return Returns the result of the callback or false if there is no
/// callback.
bool invokeDbLostCallback() const;
/// @brief Optional call back function to invoke if a successfully
/// open connection subsequently fails
static DbLostCallback db_lost_callback;
private:
/// @brief List of parameters passed in dbconfig
///
/// That will be mostly used for storing database name, username,
/// password and other parameters required for DB access. It is not
/// intended to keep any DHCP-related parameters.
ParameterMap parameters_;
};
}; // end of isc::db namespace
}; // end of isc namespace
#endif // DATABASE_CONNECTION_H
|