|
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Copyright (C) 2010-2011 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
- //
- // Distributed under:
- //
- // the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- //
- // or (at your opinion) under:
- //
- // The MIT License
- // (See accompanying file MIT.txt or a copy at
- // http://www.opensource.org/licenses/mit-license.php)
- //
- ///////////////////////////////////////////////////////////////////////////////
- #define CPPDB_SOURCE
- #include <cppdb/driver_manager.h>
- #include <cppdb/shared_object.h>
- #include <cppdb/backend.h>
- #include <cppdb/utils.h>
- #include <cppdb/mutex.h>
-
- #include <vector>
- #include <list>
-
- extern "C" {
- #ifdef CPPDB_WITH_SQLITE3
- cppdb::backend::connection *cppdb_sqlite3_get_connection(cppdb::connection_info const &cs);
- #endif
- #ifdef CPPDB_WITH_PQ
- cppdb::backend::connection *cppdb_postgresql_get_connection(cppdb::connection_info const &cs);
- #endif
- #ifdef CPPDB_WITH_ODBC
- cppdb::backend::connection *cppdb_odbc_get_connection(cppdb::connection_info const &cs);
- #endif
- #ifdef CPPDB_WITH_MYSQL
- cppdb::backend::connection *cppdb_mysql_get_connection(cppdb::connection_info const &cs);
- #endif
- }
-
-
- namespace cppdb {
-
- typedef backend::static_driver::connect_function_type connect_function_type;
-
- class so_driver : public backend::loadable_driver {
- public:
- so_driver(std::string const &name,std::vector<std::string> const &so_list) :
- connect_(0)
- {
- std::string symbol_name = "cppdb_" + name + "_get_connection";
- for(unsigned i=0;i<so_list.size();i++) {
- so_ = shared_object::open(so_list[i]);
- if(so_) {
- so_->safe_resolve(symbol_name,connect_);
- break;
- }
- }
- if(!so_ || !connect_) {
- throw cppdb_error("cppdb::driver failed to load driver " + name + " - no module found");
- }
- }
- virtual backend::connection *open(connection_info const &ci)
- {
- return connect_(ci);
- }
- private:
- connect_function_type connect_;
- ref_ptr<shared_object> so_;
- };
-
- backend::connection *driver_manager::connect(std::string const &str)
- {
- connection_info conn(str);
- return connect(conn);
- }
-
- backend::connection *driver_manager::connect(connection_info const &conn)
- {
- ref_ptr<backend::driver> drv_ptr;
- drivers_type::iterator p;
- { // get driver
- mutex::guard lock(lock_);
- p=drivers_.find(conn.driver);
- if(p!=drivers_.end()) {
- drv_ptr = p->second;
- }
- else {
- drv_ptr = load_driver(conn);
- drivers_[conn.driver] = drv_ptr;
- }
- }
- return drv_ptr->connect(conn);
- }
- void driver_manager::collect_unused()
- {
- std::list<ref_ptr<backend::driver> > garbage;
- {
- mutex::guard lock(lock_);
- drivers_type::iterator p=drivers_.begin(),tmp;
- while(p!=drivers_.end()) {
- if(!p->second->in_use()) {
- garbage.push_back(p->second);
- tmp=p;
- ++p;
- drivers_.erase(tmp);
- }
- else {
- ++p;
- }
- }
- }
- garbage.clear();
- }
-
- #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__CYGWIN__)
-
- # define CPPDB_LIBRARY_SUFFIX_V1 "-" CPPDB_SOVERSION CPPDB_LIBRARY_SUFFIX
- # define CPPDB_LIBRARY_SUFFIX_V2 CPPDB_LIBRARY_SUFFIX
-
- #elif defined(__APPLE__)
-
- # define CPPDB_LIBRARY_SUFFIX_V1 "." CPPDB_SOVERSION CPPDB_LIBRARY_SUFFIX
- # define CPPDB_LIBRARY_SUFFIX_V2 CPPDB_LIBRARY_SUFFIX
-
- #else
-
- # define CPPDB_LIBRARY_SUFFIX_V1 CPPDB_LIBRARY_SUFFIX "." CPPDB_SOVERSION
- # define CPPDB_LIBRARY_SUFFIX_V2 CPPDB_LIBRARY_SUFFIX
-
- #endif
-
- #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
-
- # define PATH_SEPARATOR ';'
-
- #else
-
- # define PATH_SEPARATOR ':'
-
- #endif
-
-
- ref_ptr<backend::driver> driver_manager::load_driver(connection_info const &conn)
- {
- std::vector<std::string> so_names;
- std::string module;
- std::vector<std::string> search_paths = search_paths_;
- std::string mpath=conn.get("@modules_path");
- if(!mpath.empty()) {
- size_t sep = mpath.find(PATH_SEPARATOR);
- search_paths.push_back(mpath.substr(0,sep));
- while(sep<mpath.size()) {
- size_t next = mpath.find(PATH_SEPARATOR,sep+1);
- search_paths.push_back(mpath.substr(sep+1,next - sep+1));
- sep = next;
- }
- }
- if(!(module=conn.get("@module")).empty()) {
- so_names.push_back(module);
- }
- else {
- std::string so_name1 = CPPDB_LIBRARY_PREFIX "cppdb_" + conn.driver + CPPDB_LIBRARY_SUFFIX_V1;
- std::string so_name2 = CPPDB_LIBRARY_PREFIX "cppdb_" + conn.driver + CPPDB_LIBRARY_SUFFIX_V2;
-
- for(unsigned i=0;i<search_paths.size();i++) {
- so_names.push_back(search_paths[i]+"/" + so_name1);
- so_names.push_back(search_paths[i]+"/" + so_name2);
- }
- if(!no_default_directory_) {
- so_names.push_back(so_name1);
- so_names.push_back(so_name2);
- }
- }
- ref_ptr<backend::driver> drv=new so_driver(conn.driver,so_names);
- return drv;
- }
-
- void driver_manager::install_driver(std::string const &name,ref_ptr<backend::driver> drv)
- {
- if(!drv) {
- throw cppdb_error("cppdb::driver_manager::install_driver: Can't install empty driver");
- }
- mutex::guard lock(lock_);
- drivers_[name]=drv;
- }
-
- driver_manager::driver_manager() :
- no_default_directory_(false)
- {
- }
- // Borland erros on hidden destructors in classes without only static methods.
- #ifndef __BORLANDC__
- driver_manager::~driver_manager()
- {
- }
- #endif
-
- void driver_manager::add_search_path(std::string const &p)
- {
- mutex::guard l(lock_);
- search_paths_.push_back(p);
- }
- void driver_manager::clear_search_paths()
- {
- mutex::guard l(lock_);
- search_paths_.clear();
- }
- void driver_manager::use_default_search_path(bool v)
- {
- mutex::guard l(lock_);
- no_default_directory_ = !v;
- }
- driver_manager &driver_manager::instance()
- {
- static driver_manager instance;
- return instance;
- }
- namespace {
- struct initializer {
- initializer() {
- driver_manager::instance();
- #ifdef CPPDB_WITH_SQLITE3
- driver_manager::instance().install_driver(
- "sqlite3",new backend::static_driver(cppdb_sqlite3_get_connection)
- );
- #endif
- #ifdef CPPDB_WITH_ODBC
- driver_manager::instance().install_driver(
- "odbc",new backend::static_driver(cppdb_odbc_get_connection)
- );
- #endif
- #ifdef CPPDB_WITH_PQ
- driver_manager::instance().install_driver(
- "postgresql",new backend::static_driver(cppdb_postgresql_get_connection)
- );
- #endif
- #ifdef CPPDB_WITH_MYSQL
- driver_manager::instance().install_driver(
- "mysql",new backend::static_driver(cppdb_mysql_get_connection)
- );
- #endif
- }
-
- } init;
- }
- } // cppdb
|