22 #include "mongodb_thread.h" 24 #ifdef HAVE_MONGODB_VERSION_H 25 # include <mongo/client/init.h> 28 using namespace mongo;
42 std::string cfgname, std::string prefix);
43 mongo::DBClientBase * create_client();
50 void log(
Logger *logger,
const char *component,
const char *indent);
54 std::string cfgname, std::string prefix);
57 std::string __logcomp;
59 ConnectionMode __mode;
60 mongo::HostAndPort __conn_hostport;
61 std::vector<mongo::HostAndPort> __replicaset_hostports;
64 typedef struct _AuthInfo {
65 _AuthInfo(std::string dbname, std::string username, std::string clearpwd)
66 { this->dbname = dbname; this->username = username;
67 this->clearpwd = clearpwd; }
74 std::list<AuthInfo> __auth_infos;
91 __mongodb_aspect_inifin(this)
105 #ifdef HAVE_MONGODB_VERSION_H 106 mongo::client::initialize();
109 std::set<std::string> ignored_configs;
111 std::string prefix =
"/plugins/mongodb/clients/";
113 #if __cplusplus >= 201103L || (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 4) 114 std::unique_ptr<Configuration::ValueIterator> i(
config->
search(prefix.c_str()));
116 std::auto_ptr<Configuration::ValueIterator> i(
config->
search(prefix.c_str()));
119 std::string cfg_name = std::string(i->
path()).substr(prefix.length());
120 cfg_name = cfg_name.substr(0, cfg_name.find(
"/"));
122 if ( (__configs.find(cfg_name) == __configs.end()) &&
123 (ignored_configs.find(cfg_name) == ignored_configs.end()) ) {
125 std::string cfg_prefix = prefix + cfg_name +
"/";
130 __configs[cfg_name] = conf;
136 "configuration %s", cfg_name.c_str());
138 ignored_configs.insert(cfg_name);
142 "exception follows.", cfg_name.c_str());
143 ignored_configs.insert(cfg_name);
148 if (__configs.empty()) {
149 throw Exception(
"No active MongoDB configurations found");
157 std::map<std::string, ClientConf *>::iterator i;
158 for (i = __configs.begin(); i != __configs.end(); ++i) {
170 mongo::DBClientBase *
173 const char *cname = config_name ? config_name :
"default";
175 if (__configs.find(cname) != __configs.end()) {
176 if (! __configs[cname]->is_active()) {
177 throw Exception(
"MongoDB config '%s' is not marked active", cname);
179 return __configs[cname]->create_client();
181 throw Exception(
"No MongoDB config named '%s' exists", cname);
203 std::string cfgname, std::string prefix)
205 std::set<std::string> authinfos;
208 std::string dbname = config->
get_string((prefix +
"auth_dbname").c_str());
209 std::string username = config->
get_string((prefix +
"auth_username").c_str());
210 std::string password = config->
get_string((prefix +
"auth_password").c_str());
211 __auth_infos.push_back(AuthInfo(dbname, username, password));
213 logger->
log_info(__logcomp.c_str(),
"No default authentication info for " 214 "MongoDB client '%s'", cfgname.c_str());
217 #if __cplusplus >= 201103L 218 std::unique_ptr<Configuration::ValueIterator>
220 std::auto_ptr<Configuration::ValueIterator>
222 i(config->
search((prefix +
"auth/").c_str()));
224 std::string auth_name = std::string(i->
path()).substr(prefix.length());
225 auth_name = auth_name.substr(0, auth_name.find(
"/"));
227 if (authinfos.find(auth_name) == authinfos.end()) {
229 std::string ap = prefix + auth_name +
"/";
230 std::string dbname = config->
get_string((ap +
"auth_dbname").c_str());
231 std::string username = config->
get_string((ap +
"auth_username").c_str());
232 std::string password = config->
get_string((ap +
"auth_password").c_str());
233 __auth_infos.push_back(AuthInfo(dbname, username, password));
235 logger->
log_info(__logcomp.c_str(),
"Incomplete extended auth info '%s' " 236 "for MongoDB client '%s'",
237 auth_name.c_str(), cfgname.c_str());
251 std::string cfgname, std::string prefix)
253 __logcomp =
"MongoDB ClientConf " + cfgname;
257 __active = config->
get_bool((prefix +
"active").c_str());
260 std::string mode =
"connection";
262 mode = config->
get_string((prefix +
"mode").c_str());
264 logger->
log_info(__logcomp.c_str(),
"MongoDB config '%s' specifies no client " 265 "mode, assuming 'connection'.", cfgname.c_str());
268 if (mode ==
"replica_set" || mode ==
"replicaset") {
269 __mode = REPLICA_SET;
271 #if __cplusplus >= 201103L || (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 4) 272 std::unique_ptr<Configuration::ValueIterator>
274 std::auto_ptr<Configuration::ValueIterator>
276 i(config->
search((prefix +
"hosts/").c_str()));
279 __replicaset_hostports.push_back(HostAndPort(i->
get_string()));
283 }
else if (mode ==
"sync_cluster" || mode ==
"synccluster") {
284 throw Exception(
"sync_cluster connections are no longer supported");
290 HostAndPort(config->
get_string((prefix +
"hostport").c_str()));
297 mongo::DBClientBase *
300 mongo::DBClientBase *client;
306 std::string noname =
"";
307 DBClientReplicaSet *repset =
308 new DBClientReplicaSet(noname, __replicaset_hostports);
310 if (! repset->connect())
throw Exception(
"Cannot connect to database");
311 std::list<AuthInfo>::iterator ai;
312 for (ai = __auth_infos.begin(); ai != __auth_infos.end(); ++ai) {
313 if (!repset->auth(ai->dbname, ai->username, ai->clearpwd, errmsg,
false)) {
314 throw Exception(
"Authenticating for %s as %s failed: %s",
315 ai->dbname.c_str(), ai->username.c_str(),
324 DBClientConnection *clconn =
325 new DBClientConnection(
true);
328 if (! clconn->connect(__conn_hostport, errmsg)) {
329 throw Exception(
"Could not connect to MongoDB at %s: %s",
330 __conn_hostport.toString().c_str(), errmsg.c_str());
332 std::list<AuthInfo>::iterator ai;
333 for (ai = __auth_infos.begin(); ai != __auth_infos.end(); ++ai) {
334 if (!clconn->auth(ai->dbname, ai->username, ai->clearpwd, errmsg,
false)) {
335 throw Exception(
"Authenticating for %s as %s failed: %s",
336 ai->dbname.c_str(), ai->username.c_str(),
360 logger->
log_info(component,
"%smode: replica set", indent);
361 logger->
log_info(component,
"%shosts:", indent);
362 std::vector<mongo::HostAndPort>::iterator i;
363 for (i = __replicaset_hostports.begin();
364 i != __replicaset_hostports.end();
367 logger->
log_info(component,
"%s - %s:", indent, i->toString().c_str());
370 if (! __auth_infos.empty()) {
371 logger->
log_info(component,
"%sauth infos:", indent);
372 std::list<AuthInfo>::iterator a;
373 for (a = __auth_infos.begin(); a != __auth_infos.end(); ++a) {
374 logger->
log_info(component,
"%s - %s @ %s", indent, a->username.c_str(),
383 logger->
log_info(component,
"%smode: connection", indent);
384 logger->
log_info(component,
"%shost: %s", indent,
385 __conn_hostport.toString().c_str());
386 if (! __auth_infos.empty()) {
387 logger->
log_info(component,
"%sauth infos:", indent);
388 std::list<AuthInfo>::iterator a;
389 for (a = __auth_infos.begin(); a != __auth_infos.end(); ++a) {
390 logger->
log_info(component,
"%s - %s @ %s", indent, a->username.c_str(),
bool is_active() const
Check if configuration is active.
virtual void log_info(const char *component, const char *format,...)=0
Log informational message.
ClientConf(fawkes::Configuration *config, fawkes::Logger *logger, std::string cfgname, std::string prefix)
Constructor.
Fawkes library namespace.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
virtual void finalize()
Finalize the thread.
virtual ValueIterator * search(const char *path)=0
Iterator with search results.
virtual bool next()=0
Check if there is another element and advance to this if possible.
Thread class encapsulation of pthreads.
Logger * logger
This is the Logger member used to access the logger.
virtual ~MongoDBThread()
Destructor.
virtual void loop()
Code to execute in the thread.
ConnectionMode
Connection mode enumeration.
virtual bool is_string() const =0
Check if current value is a string.
Base class for exceptions in Fawkes.
virtual std::string get_string() const =0
Get string value.
const char * name() const
Get name of thread.
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual const char * path() const =0
Path of value.
Thread aspect provide a new aspect.
virtual mongo::DBClientBase * create_client(const char *config_name=0)
Create a new MongoDB client.
MongoDBThread()
Constructor.
virtual void delete_client(mongo::DBClientBase *client)
Delete a client.
Configuration * config
This is the Configuration member used to access the configuration.
Interface for configuration handling.
void log(Logger *logger, const char *component, const char *indent)
Write client configuration information to log.
mongo::DBClientBase * create_client()
Create MongoDB client for this configuration.
virtual void init()
Initialize the thread.
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.