#pragma once #include #include #include #include #include namespace nanodbc { static constexpr inline auto ODBC_CONNECT_TIMEOUT = 100; using ConnectionPtr = std::shared_ptr; using Pool = BorrowedObjectPool; using PoolPtr = std::shared_ptr; class ConnectionHolder { public: ConnectionHolder(const std::string & connection_string_, PoolPtr pool_) : connection_string(connection_string_), pool(pool_) {} ~ConnectionHolder() { pool->returnObject(std::move(connection)); } nanodbc::connection & operator*() { if (!connection || !connection->connected()) { pool->borrowObject(connection, [&]() { return std::make_shared(connection_string, ODBC_CONNECT_TIMEOUT); }); } return *connection; } private: std::string connection_string; PoolPtr pool; ConnectionPtr connection; }; } namespace DB { static constexpr inline auto ODBC_DEFAULT_POOL_SIZE = 16; class ODBCConnectionFactory final : private boost::noncopyable { public: static ODBCConnectionFactory & instance() { static ODBCConnectionFactory ret; return ret; } nanodbc::ConnectionHolder get(const std::string & connection_string, size_t pool_size = ODBC_DEFAULT_POOL_SIZE) { std::lock_guard lock(mutex); if (!factory.count(connection_string)) factory.emplace(std::make_pair(connection_string, std::make_shared(pool_size))); return nanodbc::ConnectionHolder(connection_string, factory[connection_string]); } private: /// [connection_string] -> [connection_pool] using PoolFactory = std::unordered_map; PoolFactory factory; std::mutex mutex; }; }