00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #pragma once
00019
00020 #include <stack>
00021 #include "dbclient.h"
00022 #include "redef_macros.h"
00023
00024 namespace mongo {
00025
00026 class Shard;
00027
00032 class PoolForHost {
00033 public:
00034 PoolForHost()
00035 : _created(0) {}
00036
00037 PoolForHost( const PoolForHost& other ) {
00038 assert(other._pool.size() == 0);
00039 _created = other._created;
00040 assert( _created == 0 );
00041 }
00042
00043 ~PoolForHost();
00044
00045 int numAvailable() const { return (int)_pool.size(); }
00046
00047 void createdOne( DBClientBase * base);
00048 long long numCreated() const { return _created; }
00049
00050 ConnectionString::ConnectionType type() const { assert(_created); return _type; }
00051
00055 DBClientBase * get();
00056
00057 void done( DBClientBase * c );
00058
00059 void flush();
00060
00061 static void setMaxPerHost( unsigned max ) { _maxPerHost = max; }
00062 static unsigned getMaxPerHost() { return _maxPerHost; }
00063 private:
00064
00065 struct StoredConnection {
00066 StoredConnection( DBClientBase * c );
00067
00068 bool ok( time_t now );
00069
00070 DBClientBase* conn;
00071 time_t when;
00072 };
00073
00074 std::stack<StoredConnection> _pool;
00075 long long _created;
00076 ConnectionString::ConnectionType _type;
00077
00078 static unsigned _maxPerHost;
00079 };
00080
00081 class DBConnectionHook {
00082 public:
00083 virtual ~DBConnectionHook() {}
00084 virtual void onCreate( DBClientBase * conn ) {}
00085 virtual void onHandedOut( DBClientBase * conn ) {}
00086 };
00087
00103 class DBConnectionPool {
00104
00105 public:
00106
00108 struct serverNameCompare {
00109 bool operator()( const string& a , const string& b ) const;
00110 };
00111
00112 private:
00113
00114 mongo::mutex _mutex;
00115 typedef map<string,PoolForHost,serverNameCompare> PoolMap;
00116 PoolMap _pools;
00117 list<DBConnectionHook*> _hooks;
00118 string _name;
00119
00120 DBClientBase* _get( const string& ident );
00121
00122 DBClientBase* _finishCreate( const string& ident , DBClientBase* conn );
00123
00124 public:
00125 DBConnectionPool() : _mutex("DBConnectionPool") , _name( "dbconnectionpool" ) { }
00126 ~DBConnectionPool();
00127
00129 void setName( const string& name ) { _name = name; }
00130
00131 void onCreate( DBClientBase * conn );
00132 void onHandedOut( DBClientBase * conn );
00133
00134 void flush();
00135
00136 DBClientBase *get(const string& host);
00137 DBClientBase *get(const ConnectionString& host);
00138
00139 void release(const string& host, DBClientBase *c) {
00140 if ( c->isFailed() ) {
00141 delete c;
00142 return;
00143 }
00144 scoped_lock L(_mutex);
00145 _pools[host].done(c);
00146 }
00147 void addHook( DBConnectionHook * hook );
00148 void appendInfo( BSONObjBuilder& b );
00149 };
00150
00151 extern DBConnectionPool pool;
00152
00153 class AScopedConnection : boost::noncopyable {
00154 public:
00155 AScopedConnection() { _numConnections++; }
00156 virtual ~AScopedConnection() { _numConnections--; }
00157 virtual DBClientBase* get() = 0;
00158 virtual void done() = 0;
00159 virtual string getHost() const = 0;
00160
00164 static int getNumConnections() { return _numConnections; }
00165
00166 private:
00167 static AtomicUInt _numConnections;
00168 };
00169
00174 class ScopedDbConnection : public AScopedConnection {
00175 public:
00179 explicit ScopedDbConnection(const string& host) : _host(host), _conn( pool.get(host) ) {}
00180
00181 ScopedDbConnection() : _host( "" ) , _conn(0) {}
00182
00183
00184 ScopedDbConnection(const string& host, DBClientBase* conn ) : _host( host ) , _conn( conn ) {}
00185
00187 explicit ScopedDbConnection(const ConnectionString& url ) : _host(url.toString()), _conn( pool.get(url) ) {}
00188
00190 explicit ScopedDbConnection(const Shard& shard );
00191 explicit ScopedDbConnection(const Shard* shard );
00192
00193 ~ScopedDbConnection();
00194
00196 DBClientBase* operator->() {
00197 uassert( 11004 , "connection was returned to the pool already" , _conn );
00198 return _conn;
00199 }
00200
00202 DBClientBase& conn() {
00203 uassert( 11005 , "connection was returned to the pool already" , _conn );
00204 return *_conn;
00205 }
00206
00208 DBClientBase* get() {
00209 uassert( 13102 , "connection was returned to the pool already" , _conn );
00210 return _conn;
00211 }
00212
00213 string getHost() const { return _host; }
00214
00218 void kill() {
00219 delete _conn;
00220 _conn = 0;
00221 }
00222
00229 void done() {
00230 if ( ! _conn )
00231 return;
00232
00233
00234
00235
00236
00237
00238 pool.release(_host, _conn);
00239 _conn = 0;
00240 }
00241
00242 ScopedDbConnection * steal();
00243
00244 private:
00245 const string _host;
00246 DBClientBase *_conn;
00247
00248 };
00249
00250 }
00251
00252 #include "undef_macros.h"