/***************************************************************************** * * This file is part of Mapnik (c++ mapping toolkit) * * Copyright (C) 2021 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #ifndef POSTGIS_CONNECTION_MANAGER_HPP #define POSTGIS_CONNECTION_MANAGER_HPP #include "connection.hpp" // mapnik #include #include #include // boost #include // stl #include #include using mapnik::CreateStatic; using mapnik::Pool; using mapnik::singleton; template class ConnectionCreator { public: ConnectionCreator(mapnik::parameters const& params) : host_{params.get("host")} , port_{params.get("port")} , dbname_{params.get("dbname")} , user_{params.get("user")} , password_{params.get("password")} , connect_timeout_{params.get("connect_timeout", "4")} , application_name_{params.get("application_name")} {} T* operator()() const { return new T(connection_string_safe(), password_); } inline std::string id() const { return connection_string_safe(); } inline std::string connection_string() const { std::string connect_str = connection_string_safe(); append_param(connect_str, "password=", password_); return connect_str; } inline std::string connection_string_safe() const { std::string connect_str; append_param(connect_str, "host=", host_); append_param(connect_str, "port=", port_); append_param(connect_str, "dbname=", dbname_); append_param(connect_str, "user=", user_); append_param(connect_str, "connect_timeout=", connect_timeout_); if (!append_param(connect_str, "application_name=", application_name_)) { // only set fallback_application_name, so that application_name // can still be overriden with PGAPPNAME environment variable append_param(connect_str, "fallback_application_name=", "mapnik"); } return connect_str; } private: static bool append_param(std::string& dest, char const* key, std::string const& val) { if (val.empty()) return false; if (!dest.empty()) dest += ' '; dest += key; dest += val; return true; } static bool append_param(std::string& dest, char const* key, boost::optional const& opt) { return opt && append_param(dest, key, *opt); } boost::optional host_; boost::optional port_; boost::optional dbname_; boost::optional user_; boost::optional password_; boost::optional connect_timeout_; boost::optional application_name_; }; class ConnectionManager : public singleton { public: using PoolType = Pool; private: friend class CreateStatic; using ContType = std::map>; using HolderType = std::shared_ptr; ContType pools_; public: bool registerPool(ConnectionCreator const& creator, unsigned initialSize, unsigned maxSize) { #ifdef MAPNIK_THREADSAFE std::lock_guard lock(mutex_); #endif ContType::const_iterator itr = pools_.find(creator.id()); if (itr != pools_.end()) { itr->second->set_initial_size(initialSize); itr->second->set_max_size(maxSize); } else { return pools_ .insert(std::make_pair(creator.id(), std::make_shared(creator, initialSize, maxSize))) .second; } return false; } std::shared_ptr getPool(std::string const& key) { #ifdef MAPNIK_THREADSAFE std::lock_guard lock(mutex_); #endif ContType::const_iterator itr = pools_.find(key); if (itr != pools_.end()) { return itr->second; } static const std::shared_ptr emptyPool; return emptyPool; } ConnectionManager() {} private: ConnectionManager(const ConnectionManager&); ConnectionManager& operator=(const ConnectionManager); }; #endif // POSTGIS_CONNECTION_MANAGER_HPP