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>
11 #include <database/db_exceptions.h>
12 #include <database/db_log.h>
13 #include <database/db_messages.h>
14 #include <exceptions/exceptions.h>
15 
16 #include <boost/algorithm/string.hpp>
17 #include <boost/foreach.hpp>
18 #include <vector>
19 
20 using namespace std;
21 
22 namespace isc {
23 namespace db {
24 
25 const time_t DatabaseConnection::MAX_DB_TIME = 2147483647;
26 
27 std::string
28 DatabaseConnection::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 
37 DatabaseConnection::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 
65 std::string
66 DatabaseConnection::redactedAccessString(const ParameterMap& parameters) {
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 
94 bool
95 DatabaseConnection::configuredReadOnly() const {
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 
114 DatabaseConnection::makeReconnectCtl() const {
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 
146 bool
147 DatabaseConnection::invokeDbLostCallback() const {
148  if (DatabaseConnection::db_lost_callback) {
149  // Invoke the callback, passing in a new instance of ReconnectCtl
150  return (DatabaseConnection::db_lost_callback)(makeReconnectCtl());
151  }
152 
153  return (false);
154 }
155 
157 DatabaseConnection::toElement(const ParameterMap& params) {
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 
211 DatabaseConnection::toElementDbAccessString(const std::string& dbaccess) {
212  ParameterMap params = parse(dbaccess);
213  return (toElement(params));
214 }
215 
217 DatabaseConnection::db_lost_callback = 0;
218 
219 };
220 };
isc::util::str::tokens
vector< string > tokens(const std::string &text, const std::string &delim, bool escape)
Split String into Tokens.
Definition: strutil.cc:77
LOG_ERROR
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
isc::db::DB_INVALID_ACCESS
@ DB_INVALID_ACCESS
Definition: db_log.h:52
db_log.h
db_exceptions.h
isc::data::Element::createMap
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition: data.cc:268
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:192
isc::InvalidParameter
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
Definition: exceptions/exceptions.h:124
isc::BadValue
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition: exceptions/exceptions.h:132
isc::db::DbInvalidReadOnly
Invalid 'readonly' value specification.
Definition: database_connection.h:63
isc::db::database_logger
isc::log::Logger database_logger("database")
Common database library logger.
Definition: db_log.h:45
isc::db::ReconnectCtl
Warehouses DB reconnect control values.
Definition: database_connection.h:76
cfg_to_element.h
database_connection.h
DB_LOG_ERROR
#define DB_LOG_ERROR(MESSAGE)
Definition: db_log.h:137
exceptions.h
isc::db::DatabaseConnection::DbLostCallback
boost::function< bool(ReconnectCtlPtr db_retry)> DbLostCallback
Defines a callback prototype for propogating events upward.
Definition: database_connection.h:206
isc::data::ElementPtr
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
isc::db::ReconnectCtlPtr
boost::shared_ptr< ReconnectCtl > ReconnectCtlPtr
Pointer to an instance of ReconnectCtl.
Definition: database_connection.h:130
isc::data::Element::create
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition: data.cc:223
isc::db::DatabaseConnection::ParameterMap
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Definition: database_connection.h:152