ConnectionManager.cpp
Go to the documentation of this file.
1 #include "ConnectionManager.h"
2 
3 #include <algorithm>
4 #include <fstream>
5 #include <iostream>
6 
8 {
9  std::mutex ConnectionManager::initializationMutex;
10  bool ConnectionManager::initialized = false;
11  std::map<std::string, std::unique_ptr<mongocxx::pool>> ConnectionManager::Connections = {};
12 
14  {
15  std::string armarx_home = std::string(getenv("HOME")) + "/.armarx";
16  if (getenv("ARMARX_DEFAULTS_DIR"))
17  {
18  armarx_home = getenv("ARMARX_DEFAULTS_DIR");
19  }
20  std::ifstream cFile(armarx_home + "/default.cfg");
21  if (cFile.is_open())
22  {
23  std::string line;
24  while (getline(cFile, line))
25  {
26  line.erase(std::remove_if(line.begin(), line.end(), isspace), line.end());
27  if (line[0] == '#' || line.empty())
28  {
29  continue;
30  }
31  auto delimiterPos = line.find("=");
32  const auto name = line.substr(0, delimiterPos);
33  const auto value = line.substr(delimiterPos + 1);
34  if (name == "ArmarX.MongoHost")
35  {
36  host = value;
37  }
38  if (name == "ArmarX.MongoPort")
39  {
40  port = (unsigned int)std::stoi(value);
41  }
42  if (name == "ArmarX.MongoUser")
43  {
44  user = value;
45  }
46  if (name == "ArmarX.MongoPassword")
47  {
48  password = value;
49  }
50  }
51  }
52  }
53 
54  bool
56  {
57  // we always need a host and a port
58  return !host.empty() and port != 0;
59  }
60 
61  std::string
63  {
64  std::stringstream ss;
65  ss << "mongodb://";
66 
67  if (!user.empty())
68  {
69  ss << user;
70  if (!password.empty())
71  {
72  ss << ":" << password;
73  }
74  ss << "@";
75  }
76  ss << host;
77  return ss.str();
78  }
79 
80  std::string
82  {
83  // TODO: What happens if a connection exists and you would like to open another one with a different user (e.g. that sees different things)?
84  return "mongodb://" + host + ":" + std::to_string(port);
85  }
86 
87  std::string
89  {
90  return baseUri() + ":" + std::to_string(port) +
91  "/?minPoolSize=" + std::to_string(minPoolSize) +
92  "&maxPoolSize=" + std::to_string(maxPoolSize);
93  }
94 
95  std::string
97  {
98  return uri() + "&database=" + database;
99  }
100 
101  void
102  ConnectionManager::initialize_if()
103  {
104  std::lock_guard l(
105  initializationMutex); // all others have to wait until the initialization is complete
106  if (!initialized)
107  {
108  initialized = true;
109  mongocxx::instance instance{}; // This should be done only once.
110  }
111  }
112 
113  mongocxx::pool&
115  {
116  initialize_if();
117 
118  const auto uri_str = settings.uri();
119  auto it = Connections.find(uri_str);
120  if (it == Connections.end())
121  {
122  mongocxx::uri uri(uri_str);
123  auto pool = std::make_unique<mongocxx::pool>(uri);
124  auto con = Connections.emplace(settings.key(), std::move(pool));
125  return *con.first->second;
126  }
127  else
128  {
129  // A connection already exists. We do not need to open another one.
130  return *it->second;
131  }
132  }
133 
134  bool
135  ConnectionManager::ConnectionIsValid(const MongoDBSettings& settings, bool forceNewConnection)
136  {
137  initialize_if();
138 
139  try
140  {
141  if (!forceNewConnection)
142  {
143  auto it = Connections.find(settings.key());
144  if (it != Connections.end())
145  {
146  auto client = it->second->acquire();
147  auto admin = client->database("admin");
148  auto result = admin.run_command(bsoncxx::builder::basic::make_document(
149  bsoncxx::builder::basic::kvp("isMaster", 1)));
150  return true;
151  }
152  }
153 
154  mongocxx::uri uri(settings.uri());
155  auto client = mongocxx::client(uri);
156  auto admin = client["admin"];
157  auto result = admin.run_command(bsoncxx::builder::basic::make_document(
158  bsoncxx::builder::basic::kvp("isMaster", 1)));
159  return true;
160  }
161  catch (const std::exception& xcp)
162  {
163  return false;
164  }
165  }
166 
167  bool
169  {
170  initialize_if();
171 
172  auto it = Connections.find(settings.key());
173  return it != Connections.end();
174  }
175 } // namespace armarx::armem::server::ltm::mongodb
armarx::armem::server::ltm::mongodb::ConnectionManager::MongoDBSettings::key
std::string key() const
Definition: ConnectionManager.cpp:81
armarx::armem::server::ltm::mongodb::ConnectionManager::MongoDBSettings::isSet
bool isSet() const
Definition: ConnectionManager.cpp:55
armarx::armem::server::ltm::mongodb::ConnectionManager::MongoDBSettings
Definition: ConnectionManager.h:32
armarx::armem::server::ltm::mongodb::ConnectionManager::MongoDBSettings::port
unsigned int port
Definition: ConnectionManager.h:35
armarx::armem::server::ltm::mongodb::ConnectionManager::ConnectionExists
static bool ConnectionExists(const MongoDBSettings &settings)
Definition: ConnectionManager.cpp:168
armarx::armem::server::ltm::mongodb::ConnectionManager::MongoDBSettings::uri
std::string uri() const
Definition: ConnectionManager.cpp:88
armarx::armem::server::ltm::mongodb::ConnectionManager::Connect
static mongocxx::pool & Connect(const MongoDBSettings &settings)
Definition: ConnectionManager.cpp:114
armarx::armem::server::ltm::mongodb::ConnectionManager::MongoDBSettings::user
std::string user
Definition: ConnectionManager.h:36
armarx::armem::server::ltm::mongodb::ConnectionManager::MongoDBSettings::toString
std::string toString() const
Definition: ConnectionManager.cpp:96
armarx::armem::server::ltm::mongodb
Definition: ConnectionManager.cpp:7
armarx::armem::server::ltm::mongodb::ConnectionManager::MongoDBSettings::baseUri
std::string baseUri() const
Definition: ConnectionManager.cpp:62
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:855
armarx::armem::server::ltm::mongodb::ConnectionManager::MongoDBSettings::MongoDBSettings
MongoDBSettings()
Definition: ConnectionManager.cpp:13
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:41
armarx::armem::server::ltm::mongodb::ConnectionManager::MongoDBSettings::host
std::string host
Definition: ConnectionManager.h:34
armarx::armem::server::ltm::mongodb::ConnectionManager::ConnectionIsValid
static bool ConnectionIsValid(const MongoDBSettings &settings, bool forceNewConnection=false)
Definition: ConnectionManager.cpp:135
ConnectionManager.h
armarx::armem::server::ltm::mongodb::ConnectionManager::MongoDBSettings::password
std::string password
Definition: ConnectionManager.h:37