MongoDB  2.7.0
connpool.h
Go to the documentation of this file.
1 
3 /* Copyright 2009 10gen Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #pragma once
19 
20 #include <stack>
21 
23 #include "mongo/client/export_macros.h"
24 #include "mongo/platform/cstdint.h"
25 #include "mongo/util/background.h"
26 
27 namespace mongo {
28 
29  class Shard;
30  class DBConnectionPool;
31 
36  class MONGO_CLIENT_API PoolForHost {
37  public:
38 
39  // Sentinel value indicating pool has no cleanup limit
40  static const int kPoolSizeUnlimited;
41 
42  PoolForHost() :
43  _created(0),
44  _minValidCreationTimeMicroSec(0),
45  _type(ConnectionString::INVALID),
46  _maxPoolSize(kPoolSizeUnlimited) {
47  }
48 
49  PoolForHost(const PoolForHost& other) :
50  _created(other._created),
51  _minValidCreationTimeMicroSec(other._minValidCreationTimeMicroSec),
52  _type(other._type),
53  _maxPoolSize(other._maxPoolSize) {
54  verify(_created == 0);
55  verify(other._pool.size() == 0);
56  }
57 
58  ~PoolForHost();
59 
63  int getMaxPoolSize() { return _maxPoolSize; }
64 
68  void setMaxPoolSize( int maxPoolSize ) { _maxPoolSize = maxPoolSize; }
69 
70  int numAvailable() const { return (int)_pool.size(); }
71 
72  void createdOne( DBClientBase * base );
73  long long numCreated() const { return _created; }
74 
75  ConnectionString::ConnectionType type() const { verify(_created); return _type; }
76 
80  DBClientBase * get( DBConnectionPool * pool , double socketTimeout );
81 
82  // Deletes all connections in the pool
83  void clear();
84 
85  void done( DBConnectionPool * pool , DBClientBase * c );
86 
87  void flush();
88 
89  void getStaleConnections( vector<DBClientBase*>& stale );
90 
95  void reportBadConnectionAt(uint64_t microSec);
96 
101  bool isBadSocketCreationTime(uint64_t microSec);
102 
106  void initializeHostName(const std::string& hostName);
107 
108  private:
109 
110  struct StoredConnection {
111  StoredConnection( DBClientBase * c );
112 
113  bool ok( time_t now );
114 
115  DBClientBase* conn;
116  time_t when;
117  };
118 
119  std::string _hostName;
120  std::stack<StoredConnection> _pool;
121 
122  int64_t _created;
123  uint64_t _minValidCreationTimeMicroSec;
124  ConnectionString::ConnectionType _type;
125 
126  // The maximum number of connections we'll save in the pool
127  int _maxPoolSize;
128  };
129 
131  public:
132  virtual ~DBConnectionHook() {}
133  virtual void onCreate( DBClientBase * conn ) {}
134  virtual void onHandedOut( DBClientBase * conn ) {}
135  virtual void onDestroy( DBClientBase * conn ) {}
136  };
137 
153  class MONGO_CLIENT_API DBConnectionPool : public PeriodicTask {
154 
155  public:
156 
158  ~DBConnectionPool();
159 
161  void setName( const string& name ) { _name = name; }
162 
169  int getMaxPoolSize() { return _maxPoolSize; }
170 
177  void setMaxPoolSize( int maxPoolSize ) { _maxPoolSize = maxPoolSize; }
178 
179  void onCreate( DBClientBase * conn );
180  void onHandedOut( DBClientBase * conn );
181  void onDestroy( DBClientBase * conn );
182 
183  void flush();
184 
185  DBClientBase *get(const string& host, double socketTimeout = 0);
186  DBClientBase *get(const ConnectionString& host, double socketTimeout = 0);
187 
188  void release(const string& host, DBClientBase *c);
189 
190  void addHook( DBConnectionHook * hook ); // we take ownership
191  void appendInfo( BSONObjBuilder& b );
192 
196  void clear();
197 
207  bool isConnectionGood(const string& host, DBClientBase* conn);
208 
209  // Removes and deletes all connections from the pool for the host (regardless of timeout)
210  void removeHost( const string& host );
211 
214  bool operator()( const string& a , const string& b ) const;
215  };
216 
217  virtual string taskName() const { return "DBConnectionPool-cleaner"; }
218  virtual void taskDoWork();
219 
220  private:
222 
223  DBClientBase* _get( const string& ident , double socketTimeout );
224 
225  DBClientBase* _finishCreate( const string& ident , double socketTimeout, DBClientBase* conn );
226 
227  struct PoolKey {
228  PoolKey( const std::string& i , double t ) : ident( i ) , timeout( t ) {}
229  string ident;
230  double timeout;
231  };
232 
233  struct poolKeyCompare {
234  bool operator()( const PoolKey& a , const PoolKey& b ) const;
235  };
236 
237  typedef map<PoolKey,PoolForHost,poolKeyCompare> PoolMap; // servername -> pool
238 
239  mongo::mutex _mutex;
240  string _name;
241 
242  // The maximum number of connections we'll save in the pool per-host
243  // PoolForHost::kPoolSizeUnlimited is a sentinel value meaning "no limit"
244  // 0 effectively disables the pool
245  int _maxPoolSize;
246 
247  PoolMap _pools;
248 
249  // pointers owned by me, right now they leak on shutdown
250  // _hooks itself also leaks because it creates a shutdown race condition
251  list<DBConnectionHook*> * _hooks;
252 
253  };
254 
255  extern MONGO_CLIENT_API DBConnectionPool pool;
256 
257  class MONGO_CLIENT_API AScopedConnection : boost::noncopyable {
258  public:
259  AScopedConnection() { _numConnections++; }
260  virtual ~AScopedConnection() { _numConnections--; }
261 
262  virtual DBClientBase* get() = 0;
263  virtual void done() = 0;
264  virtual string getHost() const = 0;
265 
269  virtual bool ok() const = 0;
270 
274  static int getNumConnections() { return _numConnections; }
275 
276  private:
277  static AtomicUInt _numConnections;
278  };
279 
284  class MONGO_CLIENT_API ScopedDbConnection : public AScopedConnection {
285  public:
289  explicit ScopedDbConnection(const string& host, double socketTimeout = 0) : _host(host), _conn( pool.get(host, socketTimeout) ), _socketTimeout( socketTimeout ) {
290  _setSocketTimeout();
291  }
292 
293  explicit ScopedDbConnection(const ConnectionString& host, double socketTimeout = 0) : _host(host.toString()), _conn( pool.get(host, socketTimeout) ), _socketTimeout( socketTimeout ) {
294  _setSocketTimeout();
295  }
296 
297  ScopedDbConnection() : _host( "" ) , _conn(0), _socketTimeout( 0 ) {}
298 
299  /* @param conn - bind to an existing connection */
300  ScopedDbConnection(const string& host, DBClientBase* conn, double socketTimeout = 0 ) : _host( host ) , _conn( conn ), _socketTimeout( socketTimeout ) {
301  _setSocketTimeout();
302  }
303 
304  static void clearPool();
305 
306  ~ScopedDbConnection();
307 
310  uassert( 11004 , "connection was returned to the pool already" , _conn );
311  return _conn;
312  }
313 
316  uassert( 11005 , "connection was returned to the pool already" , _conn );
317  return *_conn;
318  }
319 
321  DBClientBase* get() {
322  uassert( 13102 , "connection was returned to the pool already" , _conn );
323  return _conn;
324  }
325 
326  bool ok() const { return _conn != NULL; }
327 
328  string getHost() const { return _host; }
329 
333  void kill() {
334  delete _conn;
335  _conn = 0;
336  }
337 
344  void done() {
345  if ( ! _conn )
346  return;
347 
348  /* we could do this, but instead of assume one is using autoreconnect mode on the connection
349  if ( _conn->isFailed() )
350  kill();
351  else
352  */
353  pool.release(_host, _conn);
354  _conn = 0;
355  }
356 
357  private:
358 
359  void _setSocketTimeout();
360 
361  const string _host;
362  DBClientBase *_conn;
363  const double _socketTimeout;
364 
365  };
366 
367 } // namespace mongo
Utility for creating a BSONObj.
Definition: bsonobjbuilder.h:52
compares server namees, but is smart about replica set names
Definition: connpool.h:213
static int getNumConnections()
Definition: connpool.h:274
void kill()
Force closure of the connection.
Definition: connpool.h:333
void setMaxPoolSize(int maxPoolSize)
Sets the maximum number of connections pooled per-host.
Definition: connpool.h:177
DBClientBase * operator->()
get the associated connection object
Definition: connpool.h:309
Use to get a connection from the pool.
Definition: connpool.h:284
abstract class that implements the core db operations
Definition: dbclientinterface.h:1058
bool ok() const
Definition: connpool.h:326
DBClientBase & conn()
get the associated connection object
Definition: connpool.h:315
int getMaxPoolSize()
Returns the maximum number of connections stored in the pool.
Definition: connpool.h:63
Definition: connpool.h:130
void setName(const string &name)
right now just controls some asserts.
Definition: connpool.h:161
void done()
Call this when you are done with the connection.
Definition: connpool.h:344
Core MongoDB C++ driver interfaces are defined here.
On pthread systems, it is an error to destroy a mutex while held (boost mutex may use pthread)...
Definition: mutex.h:74
not thread safe thread safety is handled by DBConnectionPool
Definition: connpool.h:36
these run "roughly" every minute instantiate statically class MyTask : public PeriodicTask { public: ...
Definition: background.h:131
int getMaxPoolSize()
Returns the maximum number of connections pooled per-host.
Definition: connpool.h:169
ScopedDbConnection(const string &host, double socketTimeout=0)
the main constructor you want to use throws UserException if can't connect
Definition: connpool.h:289
Database connection pool.
Definition: connpool.h:153
void setMaxPoolSize(int maxPoolSize)
Sets the maximum number of connections stored in the pool.
Definition: connpool.h:68
Definition: connpool.h:257
ConnectionString handles parsing different ways to connect to mongo and determining method samples: s...
Definition: dbclientinterface.h:192