diff options
Diffstat (limited to 'src/mongo/client/connpool.h')
-rw-r--r-- | src/mongo/client/connpool.h | 525 |
1 files changed, 275 insertions, 250 deletions
diff --git a/src/mongo/client/connpool.h b/src/mongo/client/connpool.h index 0324a5be080..04beed0d33d 100644 --- a/src/mongo/client/connpool.h +++ b/src/mongo/client/connpool.h @@ -39,324 +39,349 @@ namespace mongo { - class DBConnectionPool; +class DBConnectionPool; + +/** + * not thread safe + * thread safety is handled by DBConnectionPool + */ +class PoolForHost { +public: + // Sentinel value indicating pool has no cleanup limit + static const int kPoolSizeUnlimited; + + PoolForHost() + : _created(0), + _minValidCreationTimeMicroSec(0), + _type(ConnectionString::INVALID), + _maxPoolSize(kPoolSizeUnlimited) {} + + PoolForHost(const PoolForHost& other) + : _created(other._created), + _minValidCreationTimeMicroSec(other._minValidCreationTimeMicroSec), + _type(other._type), + _maxPoolSize(other._maxPoolSize) { + verify(_created == 0); + verify(other._pool.size() == 0); + } + + ~PoolForHost(); /** - * not thread safe - * thread safety is handled by DBConnectionPool + * Returns the maximum number of connections stored in the pool */ - class PoolForHost { - public: - - // Sentinel value indicating pool has no cleanup limit - static const int kPoolSizeUnlimited; - - PoolForHost() : - _created(0), - _minValidCreationTimeMicroSec(0), - _type(ConnectionString::INVALID), - _maxPoolSize(kPoolSizeUnlimited) { - } - - PoolForHost(const PoolForHost& other) : - _created(other._created), - _minValidCreationTimeMicroSec(other._minValidCreationTimeMicroSec), - _type(other._type), - _maxPoolSize(other._maxPoolSize) { - verify(_created == 0); - verify(other._pool.size() == 0); - } - - ~PoolForHost(); - - /** - * Returns the maximum number of connections stored in the pool - */ - int getMaxPoolSize() { return _maxPoolSize; } - - /** - * Sets the maximum number of connections stored in the pool - */ - void setMaxPoolSize( int maxPoolSize ) { _maxPoolSize = maxPoolSize; } - - int numAvailable() const { return (int)_pool.size(); } - - void createdOne( DBClientBase * base ); - long long numCreated() const { return _created; } - - ConnectionString::ConnectionType type() const { verify(_created); return _type; } - - /** - * gets a connection or return NULL - */ - DBClientBase * get( DBConnectionPool * pool , double socketTimeout ); + int getMaxPoolSize() { + return _maxPoolSize; + } - // Deletes all connections in the pool - void clear(); + /** + * Sets the maximum number of connections stored in the pool + */ + void setMaxPoolSize(int maxPoolSize) { + _maxPoolSize = maxPoolSize; + } - void done( DBConnectionPool * pool , DBClientBase * c ); + int numAvailable() const { + return (int)_pool.size(); + } - void flush(); + void createdOne(DBClientBase* base); + long long numCreated() const { + return _created; + } - void getStaleConnections( std::vector<DBClientBase*>& stale ); + ConnectionString::ConnectionType type() const { + verify(_created); + return _type; + } - /** - * Sets the lower bound for creation times that can be considered as - * good connections. - */ - void reportBadConnectionAt(uint64_t microSec); + /** + * gets a connection or return NULL + */ + DBClientBase* get(DBConnectionPool* pool, double socketTimeout); - /** - * @return true if the given creation time is considered to be not - * good for use. - */ - bool isBadSocketCreationTime(uint64_t microSec); + // Deletes all connections in the pool + void clear(); - /** - * Sets the host name to a new one, only if it is currently empty. - */ - void initializeHostName(const std::string& hostName); + void done(DBConnectionPool* pool, DBClientBase* c); - private: + void flush(); - struct StoredConnection { - StoredConnection( DBClientBase * c ); + void getStaleConnections(std::vector<DBClientBase*>& stale); - bool ok( time_t now ); + /** + * Sets the lower bound for creation times that can be considered as + * good connections. + */ + void reportBadConnectionAt(uint64_t microSec); - DBClientBase* conn; - time_t when; - }; + /** + * @return true if the given creation time is considered to be not + * good for use. + */ + bool isBadSocketCreationTime(uint64_t microSec); - std::string _hostName; - std::stack<StoredConnection> _pool; + /** + * Sets the host name to a new one, only if it is currently empty. + */ + void initializeHostName(const std::string& hostName); - int64_t _created; - uint64_t _minValidCreationTimeMicroSec; - ConnectionString::ConnectionType _type; +private: + struct StoredConnection { + StoredConnection(DBClientBase* c); - // The maximum number of connections we'll save in the pool - int _maxPoolSize; - }; + bool ok(time_t now); - class DBConnectionHook { - public: - virtual ~DBConnectionHook() {} - virtual void onCreate( DBClientBase * conn ) {} - virtual void onHandedOut( DBClientBase * conn ) {} - virtual void onRelease(DBClientBase* conn) {} - virtual void onDestroy( DBClientBase * conn ) {} + DBClientBase* conn; + time_t when; }; - /** Database connection pool. + std::string _hostName; + std::stack<StoredConnection> _pool; - Generally, use ScopedDbConnection and do not call these directly. + int64_t _created; + uint64_t _minValidCreationTimeMicroSec; + ConnectionString::ConnectionType _type; - This class, so far, is suitable for use with unauthenticated connections. - Support for authenticated connections requires some adjustments: please - request... + // The maximum number of connections we'll save in the pool + int _maxPoolSize; +}; - Usage: +class DBConnectionHook { +public: + virtual ~DBConnectionHook() {} + virtual void onCreate(DBClientBase* conn) {} + virtual void onHandedOut(DBClientBase* conn) {} + virtual void onRelease(DBClientBase* conn) {} + virtual void onDestroy(DBClientBase* conn) {} +}; - { - ScopedDbConnection c("myserver"); - c.conn()... - } - */ - class DBConnectionPool : public PeriodicTask { - public: +/** Database connection pool. - DBConnectionPool(); - ~DBConnectionPool(); + Generally, use ScopedDbConnection and do not call these directly. - /** right now just controls some asserts. defaults to "dbconnectionpool" */ - void setName( const std::string& name ) { _name = name; } + This class, so far, is suitable for use with unauthenticated connections. + Support for authenticated connections requires some adjustments: please + request... - /** - * Returns the maximum number of connections pooled per-host - * - * This setting only applies to new host connection pools, previously-pooled host pools are - * unaffected. - */ - int getMaxPoolSize() { return _maxPoolSize; } + Usage: - /** - * Sets the maximum number of connections pooled per-host. - * - * This setting only applies to new host connection pools, previously-pooled host pools are - * unaffected. - */ - void setMaxPoolSize( int maxPoolSize ) { _maxPoolSize = maxPoolSize; } + { + ScopedDbConnection c("myserver"); + c.conn()... + } +*/ +class DBConnectionPool : public PeriodicTask { +public: + DBConnectionPool(); + ~DBConnectionPool(); - void onCreate( DBClientBase * conn ); - void onHandedOut( DBClientBase * conn ); - void onDestroy( DBClientBase * conn ); - void onRelease(DBClientBase* conn); + /** right now just controls some asserts. defaults to "dbconnectionpool" */ + void setName(const std::string& name) { + _name = name; + } - void flush(); + /** + * Returns the maximum number of connections pooled per-host + * + * This setting only applies to new host connection pools, previously-pooled host pools are + * unaffected. + */ + int getMaxPoolSize() { + return _maxPoolSize; + } - DBClientBase *get(const std::string& host, double socketTimeout = 0); - DBClientBase *get(const ConnectionString& host, double socketTimeout = 0); + /** + * Sets the maximum number of connections pooled per-host. + * + * This setting only applies to new host connection pools, previously-pooled host pools are + * unaffected. + */ + void setMaxPoolSize(int maxPoolSize) { + _maxPoolSize = maxPoolSize; + } - void release(const std::string& host, DBClientBase *c); + void onCreate(DBClientBase* conn); + void onHandedOut(DBClientBase* conn); + void onDestroy(DBClientBase* conn); + void onRelease(DBClientBase* conn); - void addHook( DBConnectionHook * hook ); // we take ownership - void appendInfo( BSONObjBuilder& b ); + void flush(); - /** - * Clears all connections for all host. - */ - void clear(); + DBClientBase* get(const std::string& host, double socketTimeout = 0); + DBClientBase* get(const ConnectionString& host, double socketTimeout = 0); - /** - * Checks whether the connection for a given host is black listed or not. - * - * @param hostName the name of the host the connection connects to. - * @param conn the connection to check. - * - * @return true if the connection is not bad, meaning, it is good to keep it for - * future use. - */ - bool isConnectionGood(const std::string& host, DBClientBase* conn); + void release(const std::string& host, DBClientBase* c); - // Removes and deletes all connections from the pool for the host (regardless of timeout) - void removeHost( const std::string& host ); + void addHook(DBConnectionHook* hook); // we take ownership + void appendInfo(BSONObjBuilder& b); - /** compares server namees, but is smart about replica set names */ - struct serverNameCompare { - bool operator()( const std::string& a , const std::string& b ) const; - }; + /** + * Clears all connections for all host. + */ + void clear(); - virtual std::string taskName() const { return "DBConnectionPool-cleaner"; } - virtual void taskDoWork(); + /** + * Checks whether the connection for a given host is black listed or not. + * + * @param hostName the name of the host the connection connects to. + * @param conn the connection to check. + * + * @return true if the connection is not bad, meaning, it is good to keep it for + * future use. + */ + bool isConnectionGood(const std::string& host, DBClientBase* conn); - private: - DBConnectionPool( DBConnectionPool& p ); + // Removes and deletes all connections from the pool for the host (regardless of timeout) + void removeHost(const std::string& host); - DBClientBase* _get( const std::string& ident , double socketTimeout ); + /** compares server namees, but is smart about replica set names */ + struct serverNameCompare { + bool operator()(const std::string& a, const std::string& b) const; + }; - DBClientBase* _finishCreate( const std::string& ident , double socketTimeout, DBClientBase* conn ); + virtual std::string taskName() const { + return "DBConnectionPool-cleaner"; + } + virtual void taskDoWork(); - struct PoolKey { - PoolKey( const std::string& i , double t ) : ident( i ) , timeout( t ) {} - std::string ident; - double timeout; - }; +private: + DBConnectionPool(DBConnectionPool& p); - struct poolKeyCompare { - bool operator()( const PoolKey& a , const PoolKey& b ) const; - }; + DBClientBase* _get(const std::string& ident, double socketTimeout); - typedef std::map<PoolKey,PoolForHost,poolKeyCompare> PoolMap; // servername -> pool + DBClientBase* _finishCreate(const std::string& ident, double socketTimeout, DBClientBase* conn); - stdx::mutex _mutex; - std::string _name; + struct PoolKey { + PoolKey(const std::string& i, double t) : ident(i), timeout(t) {} + std::string ident; + double timeout; + }; - // The maximum number of connections we'll save in the pool per-host - // PoolForHost::kPoolSizeUnlimited is a sentinel value meaning "no limit" - // 0 effectively disables the pool - int _maxPoolSize; + struct poolKeyCompare { + bool operator()(const PoolKey& a, const PoolKey& b) const; + }; - PoolMap _pools; + typedef std::map<PoolKey, PoolForHost, poolKeyCompare> PoolMap; // servername -> pool - // pointers owned by me, right now they leak on shutdown - // _hooks itself also leaks because it creates a shutdown race condition - std::list<DBConnectionHook*> * _hooks; + stdx::mutex _mutex; + std::string _name; - }; + // The maximum number of connections we'll save in the pool per-host + // PoolForHost::kPoolSizeUnlimited is a sentinel value meaning "no limit" + // 0 effectively disables the pool + int _maxPoolSize; - class AScopedConnection { - MONGO_DISALLOW_COPYING(AScopedConnection); - public: - AScopedConnection() { _numConnections.fetchAndAdd(1); } - virtual ~AScopedConnection() { _numConnections.fetchAndAdd(-1); } + PoolMap _pools; - virtual DBClientBase* get() = 0; - virtual void done() = 0; - virtual std::string getHost() const = 0; + // pointers owned by me, right now they leak on shutdown + // _hooks itself also leaks because it creates a shutdown race condition + std::list<DBConnectionHook*>* _hooks; +}; - /** - * @return true iff this has a connection to the db - */ - virtual bool ok() const = 0; +class AScopedConnection { + MONGO_DISALLOW_COPYING(AScopedConnection); - /** - * @return total number of current instances of AScopedConnection - */ - static int getNumConnections() { return _numConnections.load(); } +public: + AScopedConnection() { + _numConnections.fetchAndAdd(1); + } + virtual ~AScopedConnection() { + _numConnections.fetchAndAdd(-1); + } - private: - static AtomicInt32 _numConnections; - }; + virtual DBClientBase* get() = 0; + virtual void done() = 0; + virtual std::string getHost() const = 0; - /** Use to get a connection from the pool. On exceptions things - clean up nicely (i.e. the socket gets closed automatically when the - scopeddbconnection goes out of scope). - */ - class ScopedDbConnection : public AScopedConnection { - public: - /** the main constructor you want to use - throws UserException if can't connect - */ - explicit ScopedDbConnection(const std::string& host, double socketTimeout = 0); - explicit ScopedDbConnection(const ConnectionString& host, double socketTimeout = 0); + /** + * @return true iff this has a connection to the db + */ + virtual bool ok() const = 0; - ScopedDbConnection() : _host( "" ) , _conn(0), _socketTimeout( 0 ) {} + /** + * @return total number of current instances of AScopedConnection + */ + static int getNumConnections() { + return _numConnections.load(); + } + +private: + static AtomicInt32 _numConnections; +}; + +/** Use to get a connection from the pool. On exceptions things + clean up nicely (i.e. the socket gets closed automatically when the + scopeddbconnection goes out of scope). +*/ +class ScopedDbConnection : public AScopedConnection { +public: + /** the main constructor you want to use + throws UserException if can't connect + */ + explicit ScopedDbConnection(const std::string& host, double socketTimeout = 0); + explicit ScopedDbConnection(const ConnectionString& host, double socketTimeout = 0); - /* @param conn - bind to an existing connection */ - ScopedDbConnection(const std::string& host, DBClientBase* conn, double socketTimeout = 0 ) : _host( host ) , _conn( conn ), _socketTimeout( socketTimeout ) { - _setSocketTimeout(); - } + ScopedDbConnection() : _host(""), _conn(0), _socketTimeout(0) {} - ~ScopedDbConnection(); + /* @param conn - bind to an existing connection */ + ScopedDbConnection(const std::string& host, DBClientBase* conn, double socketTimeout = 0) + : _host(host), _conn(conn), _socketTimeout(socketTimeout) { + _setSocketTimeout(); + } - static void clearPool(); + ~ScopedDbConnection(); - /** get the associated connection object */ - DBClientBase* operator->() { - uassert( 11004 , "connection was returned to the pool already" , _conn ); - return _conn; - } + static void clearPool(); - /** get the associated connection object */ - DBClientBase& conn() { - uassert( 11005 , "connection was returned to the pool already" , _conn ); - return *_conn; - } + /** get the associated connection object */ + DBClientBase* operator->() { + uassert(11004, "connection was returned to the pool already", _conn); + return _conn; + } - /** get the associated connection object */ - DBClientBase* get() { - uassert( 13102 , "connection was returned to the pool already" , _conn ); - return _conn; - } + /** get the associated connection object */ + DBClientBase& conn() { + uassert(11005, "connection was returned to the pool already", _conn); + return *_conn; + } - bool ok() const { return _conn != NULL; } + /** get the associated connection object */ + DBClientBase* get() { + uassert(13102, "connection was returned to the pool already", _conn); + return _conn; + } - std::string getHost() const { return _host; } + bool ok() const { + return _conn != NULL; + } - /** Force closure of the connection. You should call this if you leave it in - a bad state. Destructor will do this too, but it is verbose. - */ - void kill() { - delete _conn; - _conn = 0; - } + std::string getHost() const { + return _host; + } - /** Call this when you are done with the connection. + /** Force closure of the connection. You should call this if you leave it in + a bad state. Destructor will do this too, but it is verbose. + */ + void kill() { + delete _conn; + _conn = 0; + } - If you do not call done() before this object goes out of scope, - we can't be sure we fully read all expected data of a reply on the socket. so - we don't try to reuse the connection in that situation. - */ - void done(); + /** Call this when you are done with the connection. - private: + If you do not call done() before this object goes out of scope, + we can't be sure we fully read all expected data of a reply on the socket. so + we don't try to reuse the connection in that situation. + */ + void done(); - void _setSocketTimeout(); +private: + void _setSocketTimeout(); - const std::string _host; - DBClientBase *_conn; - const double _socketTimeout; - }; + const std::string _host; + DBClientBase* _conn; + const double _socketTimeout; +}; -} // namespace mongo +} // namespace mongo |