3D Repo Bouncer  1.4
repo_connection_pool_mongo.h
1 
18 #pragma once
19 
20 #include "../../../lib/repo_stack.h"
21 #include "../../../lib/repo_log.h"
22 
23 #if defined(_WIN32) || defined(_WIN64)
24 #include <WinSock2.h>
25 #include <Windows.h>
26 
27 #define strcasecmp _stricmp
28 #endif
29 
30 #include <mongo/client/dbclient.h>
31 
32 namespace repo{
33  namespace core{
34  namespace handler {
35  namespace connectionPool{
36  class MongoConnectionPool : repo::lib::RepoStack < mongo::DBClientBase * >
37  {
38  public:
44  const int &numConnections,
45  mongo::ConnectionString dbAddress,
46  mongo::BSONObj* auth) :
47  maxSize(numConnections),
48  dbAddress(dbAddress),
49  auth(auth? new mongo::BSONObj(*auth) : nullptr)
50  {
51  repoDebug << "Instantiating Mongo connection pool with " << maxSize << " connections...";
52  //push one connected worker to ensure valid connection
53  //so the caller can handle the exceptions appropriately
54  std::string errMsg;
55 
56  mongo::DBClientBase *worker = dbAddress.connect(errMsg);
57 
58  if (worker)
59  {
60  repoDebug << "Connected to database, trying authentication..";
61  for (int i = 0; i < numConnections; i++)
62  {
63  mongo::DBClientBase *worker = dbAddress.connect(errMsg);
64  if (auth)
65  {
66  repoTrace << auth->toString();
67  if (!worker->auth(auth->getStringField("db"), auth->getStringField("user"), auth->getStringField("pwd"), errMsg, auth->getField("digestPassword").boolean()))
68  {
69  throw mongo::DBException(errMsg, mongo::ErrorCodes::AuthenticationFailed);
70  }
71  }
72  else
73  {
74  repoWarning << "No credentials found. User is not authenticated against the database!";
75  }
76  push(worker);
77  }
78  }
79  else
80  {
81  repoDebug << "Failed to connect: " << errMsg;
82  throw mongo::DBException(errMsg, 1000);
83  }
84  }
85 
86  MongoConnectionPool() :maxSize(0){}
87 
88  ~MongoConnectionPool()
89  {
90  delete auth;
91  //free workers within the pool
92  std::vector<mongo::DBClientBase*> workers = empty();
93  std::vector<mongo::DBClientBase*>::iterator it;
94  for (it = workers.begin(); it != workers.end(); ++it)
95  {
96  mongo::DBClientBase* worker = *it;
97  if (worker)
98  delete worker;
99  }
100  }
101 
102  mongo::DBClientBase* getWorker()
103  {
104  return pop();
105  }
106 
107  void returnWorker(mongo::DBClientBase *worker)
108  {
109  push(worker);
110  }
111 
112  mongo::DBClientBase* pop()
113  {
114  mongo::DBClientBase* worker = RepoStack::pop();
115 
116  if (!worker)
117  {
118  //worker was never used, instantiate it with a connection
119  std::string tmp;
120  worker = connectWorker(tmp);
121  }
122  else
123  {
124  //check worker is still connected
125  if (!worker->isStillConnected())
126  {
127  std::string tmp;
128  worker = connectWorker(tmp);
129  }
130  }
131 
132  return worker;
133  }
134 
135  void push(mongo::DBClientBase *worker)
136  {
137  if (worker)
138  RepoStack::push(worker);
139  }
140  private:
141  mongo::DBClientBase* connectWorker(std::string &errMsg)
142  {
143  mongo::DBClientBase *worker = dbAddress.connect(errMsg);
144  if (auth && !worker->auth(auth->getStringField("db"), auth->getStringField("user"), auth->getStringField("pwd"), errMsg, auth->getField("digestPassword").boolean()))
145  {
146  throw mongo::DBException(errMsg, mongo::ErrorCodes::AuthenticationFailed);
147  }
148  return worker;
149  }
150 
151  const uint32_t maxSize;
152  const mongo::ConnectionString dbAddress;
153  const mongo::BSONObj *auth;
154  };
155  }
156  } /* namespace handler */
157  }
158 }
Definition: repo_connection_pool_mongo.h:36
Definition: repo_connection_pool_mongo.h:32
std::vector< mongo::DBClientBase * > empty()
Definition: repo_stack.h:64
MongoConnectionPool(const int &numConnections, mongo::ConnectionString dbAddress, mongo::BSONObj *auth)
Definition: repo_connection_pool_mongo.h:43
Definition: repo_stack.h:32