|
- ///////////////////////////////////////////////////////////////////////////////
- //
- // 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/pool.h>
- #include <cppdb/backend.h>
- #include <cppdb/utils.h>
- #include <cppdb/driver_manager.h>
-
- #include <stdlib.h>
-
- namespace cppdb {
-
- struct pool::data {};
-
- ref_ptr<pool> pool::create(connection_info const &ci)
- {
- ref_ptr<pool> p = new pool(ci);
- return p;
- }
- ref_ptr<pool> pool::create(std::string const &cs)
- {
- connection_info ci(cs);
- ref_ptr<pool> p = new pool(ci);
- return p;
- }
-
- pool::pool(connection_info const &ci) :
- limit_(0),
- life_time_(0),
- ci_(ci),
- size_(0)
- {
- limit_ = ci_.get("@pool_size",16);
- life_time_ = ci_.get("@pool_max_idle",600);
- }
-
- pool::~pool()
- {
- }
-
- ref_ptr<backend::connection> pool::open()
- {
- if(limit_ == 0)
- return driver_manager::instance().connect(ci_);
-
- ref_ptr<backend::connection> p = get();
-
- if(!p) {
- p=driver_manager::instance().connect(ci_);
- }
- p->set_pool(this);
- return p;
- }
-
- // this is thread safe member function
- ref_ptr<backend::connection> pool::get()
- {
- if(limit_ == 0)
- return 0;
- ref_ptr<backend::connection> c;
- pool_type garbage;
- std::time_t now = time(0);
- {
- mutex::guard l(lock_);
- // Nothing there should throw so it is safe
- pool_type::iterator p = pool_.begin(),tmp;
- while(p!=pool_.end()) {
- if(p->last_used + life_time_ < now) {
- tmp=p;
- p++;
- garbage.splice(garbage.begin(),pool_,tmp);
- size_ --;
- }
- else {
- // all is sorted by time
- break;
- }
- }
- if(!pool_.empty()) {
- c = pool_.back().conn;
- pool_.pop_back();
- size_ --;
- }
- }
- return c;
- }
-
- // this is thread safe member function
- void pool::put(backend::connection *c_in)
- {
- std::auto_ptr<backend::connection> c(c_in);
- if(limit_ == 0)
- return;
- pool_type garbage;
- std::time_t now = time(0);
- {
- mutex::guard l(lock_);
- // under lock do all very fast
- if(c.get()) {
- pool_.push_back(entry());
- pool_.back().last_used = now;
- pool_.back().conn = c.release();
- size_ ++;
- }
-
- // Nothing there should throw so it is safe
-
- pool_type::iterator p = pool_.begin(),tmp;
- while(p!=pool_.end()) {
- if(p->last_used + life_time_ < now) {
- tmp=p;
- p++;
- garbage.splice(garbage.begin(),pool_,tmp);
- size_ --;
- }
- else {
- // all is sorted by time
- break;
- }
- }
- // can be at most 1 entry bigger then limit
- if(size_ > limit_) {
- garbage.splice(garbage.begin(),pool_,pool_.begin());
- size_--;
- }
- }
- }
-
- void pool::gc()
- {
- put(0);
- }
-
- void pool::clear()
- {
- pool_type garbage;
- {
- mutex::guard l(lock_);
- garbage.swap(pool_);
- size_ = 0;
- } // destroy outside mutex scope
- }
- }
-
-
|