C++DB is the database layer that was designed to work with C++CMS. This customized version is used within Ye Ol' Pi Shack.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

162 lines
3.4 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2010-2011 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
  4. //
  5. // Distributed under:
  6. //
  7. // the Boost Software License, Version 1.0.
  8. // (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // or (at your opinion) under:
  12. //
  13. // The MIT License
  14. // (See accompanying file MIT.txt or a copy at
  15. // http://www.opensource.org/licenses/mit-license.php)
  16. //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #define CPPDB_SOURCE
  19. #include <cppdb/pool.h>
  20. #include <cppdb/backend.h>
  21. #include <cppdb/utils.h>
  22. #include <cppdb/driver_manager.h>
  23. #include <stdlib.h>
  24. namespace cppdb {
  25. struct pool::data {};
  26. ref_ptr<pool> pool::create(connection_info const &ci)
  27. {
  28. ref_ptr<pool> p = new pool(ci);
  29. return p;
  30. }
  31. ref_ptr<pool> pool::create(std::string const &cs)
  32. {
  33. connection_info ci(cs);
  34. ref_ptr<pool> p = new pool(ci);
  35. return p;
  36. }
  37. pool::pool(connection_info const &ci) :
  38. limit_(0),
  39. life_time_(0),
  40. ci_(ci),
  41. size_(0)
  42. {
  43. limit_ = ci_.get("@pool_size",16);
  44. life_time_ = ci_.get("@pool_max_idle",600);
  45. }
  46. pool::~pool()
  47. {
  48. }
  49. ref_ptr<backend::connection> pool::open()
  50. {
  51. if(limit_ == 0)
  52. return driver_manager::instance().connect(ci_);
  53. ref_ptr<backend::connection> p = get();
  54. if(!p) {
  55. p=driver_manager::instance().connect(ci_);
  56. }
  57. p->set_pool(this);
  58. return p;
  59. }
  60. // this is thread safe member function
  61. ref_ptr<backend::connection> pool::get()
  62. {
  63. if(limit_ == 0)
  64. return 0;
  65. ref_ptr<backend::connection> c;
  66. pool_type garbage;
  67. std::time_t now = time(0);
  68. {
  69. mutex::guard l(lock_);
  70. // Nothing there should throw so it is safe
  71. pool_type::iterator p = pool_.begin(),tmp;
  72. while(p!=pool_.end()) {
  73. if(p->last_used + life_time_ < now) {
  74. tmp=p;
  75. p++;
  76. garbage.splice(garbage.begin(),pool_,tmp);
  77. size_ --;
  78. }
  79. else {
  80. // all is sorted by time
  81. break;
  82. }
  83. }
  84. if(!pool_.empty()) {
  85. c = pool_.back().conn;
  86. pool_.pop_back();
  87. size_ --;
  88. }
  89. }
  90. return c;
  91. }
  92. // this is thread safe member function
  93. void pool::put(backend::connection *c_in)
  94. {
  95. std::auto_ptr<backend::connection> c(c_in);
  96. if(limit_ == 0)
  97. return;
  98. pool_type garbage;
  99. std::time_t now = time(0);
  100. {
  101. mutex::guard l(lock_);
  102. // under lock do all very fast
  103. if(c.get()) {
  104. pool_.push_back(entry());
  105. pool_.back().last_used = now;
  106. pool_.back().conn = c.release();
  107. size_ ++;
  108. }
  109. // Nothing there should throw so it is safe
  110. pool_type::iterator p = pool_.begin(),tmp;
  111. while(p!=pool_.end()) {
  112. if(p->last_used + life_time_ < now) {
  113. tmp=p;
  114. p++;
  115. garbage.splice(garbage.begin(),pool_,tmp);
  116. size_ --;
  117. }
  118. else {
  119. // all is sorted by time
  120. break;
  121. }
  122. }
  123. // can be at most 1 entry bigger then limit
  124. if(size_ > limit_) {
  125. garbage.splice(garbage.begin(),pool_,pool_.begin());
  126. size_--;
  127. }
  128. }
  129. }
  130. void pool::gc()
  131. {
  132. put(0);
  133. }
  134. void pool::clear()
  135. {
  136. pool_type garbage;
  137. {
  138. mutex::guard l(lock_);
  139. garbage.swap(pool_);
  140. size_ = 0;
  141. } // destroy outside mutex scope
  142. }
  143. }