Kea 1.5.0
database_connection.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <cc/cfg_to_element.h>
12#include <database/db_log.h>
13#include <database/db_messages.h>
15
16#include <boost/algorithm/string.hpp>
17#include <boost/foreach.hpp>
18#include <vector>
19
20using namespace std;
21
22namespace isc {
23namespace db {
24
25const time_t DatabaseConnection::MAX_DB_TIME = 2147483647;
26
27std::string
28DatabaseConnection::getParameter(const std::string& name) const {
29 ParameterMap::const_iterator param = parameters_.find(name);
30 if (param == parameters_.end()) {
31 isc_throw(BadValue, "Parameter " << name << " not found");
32 }
33 return (param->second);
34}
35
37DatabaseConnection::parse(const std::string& dbaccess) {
39
40 if (!dbaccess.empty()) {
41 vector<string> tokens;
42
43 // We need to pass a string to is_any_of, not just char*. Otherwise
44 // there are cryptic warnings on Debian6 running g++ 4.4 in
45 // /usr/include/c++/4.4/bits/stl_algo.h:2178 "array subscript is above
46 // array bounds"
47 boost::split(tokens, dbaccess, boost::is_any_of(string("\t ")));
48 BOOST_FOREACH(std::string token, tokens) {
49 size_t pos = token.find("=");
50 if (pos != string::npos) {
51 string name = token.substr(0, pos);
52 string value = token.substr(pos + 1);
53 mapped_tokens.insert(make_pair(name, value));
54 } else {
55 DB_LOG_ERROR(DB_INVALID_ACCESS).arg(dbaccess);
56 isc_throw(InvalidParameter, "Cannot parse " << token
57 << ", expected format is name=value");
58 }
59 }
60 }
61
62 return (mapped_tokens);
63}
64
65std::string
67 // Reconstruct the access string: start of with an empty string, then
68 // work through all the parameters in the original string and add them.
69 std::string access;
70 for (DatabaseConnection::ParameterMap::const_iterator i = parameters.begin();
71 i != parameters.end(); ++i) {
72
73 // Separate second and subsequent tokens are preceded by a space.
74 if (!access.empty()) {
75 access += " ";
76 }
77
78 // Append name of parameter...
79 access += i->first;
80 access += "=";
81
82 // ... and the value, except in the case of the password, where a
83 // redacted value is appended.
84 if (i->first == std::string("password")) {
85 access += "*****";
86 } else {
87 access += i->second;
88 }
89 }
90
91 return (access);
92}
93
94bool
96 std::string readonly_value = "false";
97 try {
98 readonly_value = getParameter("readonly");
99 boost::algorithm::to_lower(readonly_value);
100 } catch (...) {
101 // Parameter "readonly" hasn't been specified so we simply use
102 // the default value of "false".
103 }
104
105 if ((readonly_value != "false") && (readonly_value != "true")) {
106 isc_throw(DbInvalidReadOnly, "invalid value '" << readonly_value
107 << "' specified for boolean parameter 'readonly'");
108 }
109
110 return (readonly_value == "true");
111}
112
115 ReconnectCtlPtr retry;
116 string type = "unknown";
117 unsigned int retries = 0;
118 unsigned int interval = 0;
119
120 // Assumes that parsing ensurse only valid values are present
121 try {
122 type = getParameter("type");
123 } catch (...) {
124 // Wasn't specified so we'll use default of "unknown".
125 }
126
127 std::string parm_str;
128 try {
129 parm_str = getParameter("max-reconnect-tries");
130 retries = boost::lexical_cast<unsigned int>(parm_str);
131 } catch (...) {
132 // Wasn't specified so we'll use default of 0;
133 }
134
135 try {
136 parm_str = getParameter("reconnect-wait-time");
137 interval = boost::lexical_cast<unsigned int>(parm_str);
138 } catch (...) {
139 // Wasn't specified so we'll use default of 0;
140 }
141
142 retry.reset(new ReconnectCtl(type, retries, interval));
143 return (retry);
144}
145
146bool
149 // Invoke the callback, passing in a new instance of ReconnectCtl
151 }
152
153 return (false);
154}
155
159
160 for (auto param: params) {
161 std::string keyword = param.first;
162 std::string value = param.second;
163
164 if ((keyword == "lfc-interval") ||
165 (keyword == "connect-timeout") ||
166 (keyword == "request-timeout") ||
167 (keyword == "port") ||
168 (keyword == "max-reconnect-tries") ||
169 (keyword == "reconnect-wait-time") ||
170 (keyword == "tcp-keepalive")) {
171
172 // integer parameters
173 int64_t int_value;
174 try {
175 int_value = boost::lexical_cast<int64_t>(value);
176 result->set(keyword, isc::data::Element::create(int_value));
177 } catch (...) {
178 LOG_ERROR(database_logger, DATABASE_TO_JSON_ERROR)
179 .arg("integer").arg(keyword).arg(value);
180 }
181 } else if ((keyword == "persist") ||
182 (keyword == "readonly") ||
183 (keyword == "tcp-nodelay")) {
184
185 if (value == "true") {
186 result->set(keyword, isc::data::Element::create(true));
187 } else if (value == "false") {
188 result->set(keyword, isc::data::Element::create(false));
189 } else {
190 LOG_ERROR(database_logger, DATABASE_TO_JSON_ERROR)
191 .arg("boolean").arg(keyword).arg(value);
192 }
193 } else if ((keyword == "type") ||
194 (keyword == "user") ||
195 (keyword == "password") ||
196 (keyword == "host") ||
197 (keyword == "name") ||
198 (keyword == "contact-points") ||
199 (keyword == "keyspace")) {
200 result->set(keyword, isc::data::Element::create(value));
201 } else {
202 LOG_ERROR(database_logger, DATABASE_TO_JSON_ERROR)
203 .arg("unknown").arg(keyword).arg(value);
204 }
205 }
206
207 return (result);
208}
209
212 ParameterMap params = parse(dbaccess);
213 return (toElement(params));
214}
215
218
219};
220};
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition: data.cc:223
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition: data.cc:268
bool configuredReadOnly() const
Convenience method checking if database should be opened with read only access.
boost::function< bool(ReconnectCtlPtr db_retry)> DbLostCallback
Defines a callback prototype for propogating events upward.
std::string getParameter(const std::string &name) const
Returns value of a connection parameter.
static std::string redactedAccessString(const ParameterMap &parameters)
Redact database access string.
static isc::data::ElementPtr toElement(const ParameterMap &params)
Unparse a parameter map.
static isc::data::ElementPtr toElementDbAccessString(const std::string &dbaccess)
Unparse an access string.
static DbLostCallback db_lost_callback
Optional call back function to invoke if a successfully open connection subsequently fails.
static ParameterMap parse(const std::string &dbaccess)
Parse database access string.
bool invokeDbLostCallback() const
Invokes the connection's lost connectivity callback.
virtual ReconnectCtlPtr makeReconnectCtl() const
Instantiates a ReconnectCtl based on the connection's reconnect parameters.
static const time_t MAX_DB_TIME
Defines maximum value for time that can be reliably stored.
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Invalid 'readonly' value specification.
Warehouses DB reconnect control values.
We want to reuse the database backend connection and exchange code for other uses,...
#define DB_LOG_ERROR(MESSAGE)
Definition: db_log.h:137
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
boost::shared_ptr< Element > ElementPtr
Definition: data.h:22
isc::log::Logger database_logger("database")
Common database library logger.
Definition: db_log.h:45
@ DB_INVALID_ACCESS
Definition: db_log.h:52
boost::shared_ptr< ReconnectCtl > ReconnectCtlPtr
Pointer to an instance of ReconnectCtl.
Defines the logger used by the top-level component of kea-dhcp-ddns.