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
|
// 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/.
#include <config.h>
#include <database/database_connection.h>
#include <database/db_exceptions.h>
#include <database/db_log.h>
#include <exceptions/exceptions.h>
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <vector>
using namespace std;
namespace isc {
namespace db {
const time_t DatabaseConnection::MAX_DB_TIME = 2147483647;
std::string
DatabaseConnection::getParameter(const std::string& name) const {
ParameterMap::const_iterator param = parameters_.find(name);
if (param == parameters_.end()) {
isc_throw(BadValue, "Parameter " << name << " not found");
}
return (param->second);
}
DatabaseConnection::ParameterMap
DatabaseConnection::parse(const std::string& dbaccess) {
DatabaseConnection::ParameterMap mapped_tokens;
if (!dbaccess.empty()) {
vector<string> tokens;
// We need to pass a string to is_any_of, not just char*. Otherwise
// there are cryptic warnings on Debian6 running g++ 4.4 in
// /usr/include/c++/4.4/bits/stl_algo.h:2178 "array subscript is above
// array bounds"
boost::split(tokens, dbaccess, boost::is_any_of(string("\t ")));
BOOST_FOREACH(std::string token, tokens) {
size_t pos = token.find("=");
if (pos != string::npos) {
string name = token.substr(0, pos);
string value = token.substr(pos + 1);
mapped_tokens.insert(make_pair(name, value));
} else {
DB_LOG_ERROR(DB_INVALID_ACCESS).arg(dbaccess);
isc_throw(InvalidParameter, "Cannot parse " << token
<< ", expected format is name=value");
}
}
}
return (mapped_tokens);
}
std::string
DatabaseConnection::redactedAccessString(const ParameterMap& parameters) {
// Reconstruct the access string: start of with an empty string, then
// work through all the parameters in the original string and add them.
std::string access;
for (DatabaseConnection::ParameterMap::const_iterator i = parameters.begin();
i != parameters.end(); ++i) {
// Separate second and subsequent tokens are preceded by a space.
if (!access.empty()) {
access += " ";
}
// Append name of parameter...
access += i->first;
access += "=";
// ... and the value, except in the case of the password, where a
// redacted value is appended.
if (i->first == std::string("password")) {
access += "*****";
} else {
access += i->second;
}
}
return (access);
}
bool
DatabaseConnection::configuredReadOnly() const {
std::string readonly_value = "false";
try {
readonly_value = getParameter("readonly");
boost::algorithm::to_lower(readonly_value);
} catch (...) {
// Parameter "readonly" hasn't been specified so we simply use
// the default value of "false".
}
if ((readonly_value != "false") && (readonly_value != "true")) {
isc_throw(DbInvalidReadOnly, "invalid value '" << readonly_value
<< "' specified for boolean parameter 'readonly'");
}
return (readonly_value == "true");
}
ReconnectCtlPtr
DatabaseConnection::makeReconnectCtl() const {
ReconnectCtlPtr retry;
string type = "unknown";
unsigned int retries = 0;
unsigned int interval = 0;
// Assumes that parsing ensurse only valid values are present
try {
type = getParameter("type");
} catch (...) {
// Wasn't specified so we'll use default of "unknown".
}
std::string parm_str;
try {
parm_str = getParameter("max-reconnect-tries");
retries = boost::lexical_cast<unsigned int>(parm_str);
} catch (...) {
// Wasn't specified so we'll use default of 0;
}
try {
parm_str = getParameter("reconnect-wait-time");
interval = boost::lexical_cast<unsigned int>(parm_str);
} catch (...) {
// Wasn't specified so we'll use default of 0;
}
retry.reset(new ReconnectCtl(type, retries, interval));
return (retry);
}
bool
DatabaseConnection::invokeDbLostCallback() const {
if (DatabaseConnection::db_lost_callback) {
// Invoke the callback, passing in a new instance of ReconnectCtl
return (DatabaseConnection::db_lost_callback)(makeReconnectCtl());
}
return (false);
}
DatabaseConnection::DbLostCallback
DatabaseConnection::db_lost_callback = 0;
};
};
|