| | |
| | | #include "stdafx.h" |
| | | #include "ConnectionPool.h" |
| | | |
| | | #include <fstream> |
| | | #include <iostream> |
| | | #include <thread> |
| | | |
| | | ConnectionPool* ConnectionPool::getInstance() { |
| | | static ConnectionPool connPool; |
| | | return &connPool; |
| | | } |
| | | |
| | | ConnectionPool::ConnectionPool() { |
| | | // å è½½é
ç½®æä»¶ |
| | | if (!parseJsonFile()) { |
| | | std::cout << "parseJsonFile is failed!" << std::endl; |
| | | return; |
| | | } |
| | | for ( int i = 0 ; i < m_min_conn ; i++ ) { |
| | | addConnection( ); |
| | | } |
| | | // å建ä¸ä¸ªçº¿ç¨ï¼å¯¹è¿æ¥æ°è¿è¡çæ§ ï¼è¿æ¥æ°ä¸è¶³å°±åç»§ç»å建 |
| | | std::thread producer(&ConnectionPool::produce, this); |
| | | // å¯¹è¿æ¥æ°è¿è¡çæ§ ï¼å¦ææå¤ªå¤ç©ºé²å¾çº¿ç¨ ï¼é£ä¹å°±å¯¹å
¶è¿è¡éæ¯ |
| | | std::thread recycler( &ConnectionPool::recycle, this); |
| | | |
| | | // 线ç¨å离 |
| | | producer.detach(); |
| | | recycler.detach(); |
| | | |
| | | m_min_conn = 5; // å设æå°è¿æ¥æ°ä¸º 5 |
| | | m_max_conn = 10; // å设æå¤§è¿æ¥æ°ä¸º 10 |
| | | m_timeout = 1000; // åè®¾è¿æ¥è¶
æ¶æ¶é´ä¸º 1000 æ¯«ç§ |
| | | max_del_time = 60000; // å设æå¤§ç©ºé²æ¶é´ä¸º 60000 æ¯«ç§ |
| | | |
| | | for (int i = 0; i < m_min_conn; i++) { |
| | | addConnection(); |
| | | } |
| | | // å建ä¸ä¸ªçº¿ç¨ï¼å¯¹è¿æ¥æ°è¿è¡çæ§ ï¼è¿æ¥æ°ä¸è¶³å°±åç»§ç»å建 |
| | | thread producer(&ConnectionPool::produce, this); |
| | | // å¯¹è¿æ¥æ°è¿è¡çæ§ ï¼å¦ææå¤ªå¤ç©ºé²å¾çº¿ç¨ ï¼é£ä¹å°±å¯¹å
¶è¿è¡éæ¯ |
| | | thread recycler(&ConnectionPool::recycle, this); |
| | | |
| | | // 线ç¨å离 |
| | | producer.detach(); |
| | | recycler.detach(); |
| | | } |
| | | |
| | | bool ConnectionPool::parseJsonFile() { |
| | | |
| | | std::ifstream ifs("dbconf.json"); |
| | | Reader rd; |
| | | Value root; |
| | | rd.parse(ifs, root); |
| | | if ( root.isObject( ) ) { |
| | | m_ip = root["ip"].asString(); |
| | | m_port = root["port"].asInt(); |
| | | m_userName = root["userName"].asString(); |
| | | m_passwd = root["password"].asString(); |
| | | m_db = root["dbName"].asString(); |
| | | m_min_conn = root["minSize"].asInt(); |
| | | m_max_conn = root["maxSize"].asInt(); |
| | | max_del_time = root["maxDleTime"].asInt(); |
| | | m_timeout = root["timeout"].asInt(); |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | void ConnectionPool::description() { |
| | | std::cout << m_ip << ". " << m_userName << ". " << m_passwd << ". " << m_db << ". " |
| | | << m_port << ". " << m_max_conn << ". " << m_min_conn << ". " << m_timeout << ". " |
| | | << max_del_time << std::endl; |
| | | } |
| | | |
| | | ConnectionPool::~ConnectionPool() { |
| | | while (!m_connkQueue.empty()) { |
| | | MysqlConn* conn = m_connkQueue.front(); |
| | | m_connkQueue.pop(); |
| | | delete conn; |
| | | } |
| | | |
| | | while (!m_connkQueue.empty()) { |
| | | MysqlConn* conn = m_connkQueue.front(); |
| | | m_connkQueue.pop(); |
| | | delete conn; |
| | | } |
| | | } |
| | | |
| | | void ConnectionPool::addConnection() { |
| | | MysqlConn* conn = new MysqlConn(); |
| | | if ( !conn->connect( m_ip, m_userName, m_passwd, m_db, m_port ) ) { |
| | | std::cout << "ConnectionPool connect to mysql is failed!" << std::endl; |
| | | delete conn; |
| | | return; |
| | | } |
| | | conn->refreshActiveTime( ); |
| | | m_connkQueue.push(conn); |
| | | m_cond.notify_one(); // å¤éä¸ä¸ªçº¿ç¨ |
| | | MysqlConn* conn = new MysqlConn(); |
| | | if (!conn->isConnected()) { |
| | | cout << "ConnectionPool connect to mysql is failed!" << endl; |
| | | delete conn; |
| | | return; |
| | | } |
| | | conn->refreshActiveTime(); |
| | | m_connkQueue.push(conn); |
| | | m_cond.notify_one(); // å¤éä¸ä¸ªçº¿ç¨ |
| | | } |
| | | |
| | | void ConnectionPool::produce(){ |
| | | while (true) { |
| | | std::unique_lock<std::mutex> lock(m_mutex); |
| | | while (m_connkQueue.size() >= m_min_conn) { // è¿æ¥éåçæ°éå¤§äºæå°çè¿æ¥æ° |
| | | m_cond.wait(lock); |
| | | } |
| | | addConnection(); |
| | | } |
| | | void ConnectionPool::produce() { |
| | | while (true) { |
| | | unique_lock<mutex> lock(m_mutex); |
| | | while (m_connkQueue.size() >= m_min_conn) { // è¿æ¥éåçæ°éå¤§äºæå°çè¿æ¥æ° |
| | | m_cond.wait(lock); |
| | | } |
| | | addConnection(); |
| | | } |
| | | } |
| | | |
| | | // å é¤ç©ºé²è¿æ¥ |
| | | void ConnectionPool::recycle() { |
| | | while ( true ) { |
| | | std::this_thread::sleep_for( std::chrono::milliseconds(500)); // ä¼ç 500 ms |
| | | std::unique_lock<std::mutex>lock(m_mutex); |
| | | while ( m_connkQueue.size() > m_min_conn ) { |
| | | MysqlConn* conn = m_connkQueue.front( ); |
| | | if (conn->getActiveTime() >= max_del_time) { |
| | | m_connkQueue.pop(); |
| | | delete conn; |
| | | } |
| | | else { |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | while (true) { |
| | | this_thread::sleep_for(chrono::milliseconds(500)); // ä¼ç 500 ms |
| | | unique_lock<mutex> lock(m_mutex); |
| | | while (m_connkQueue.size() > m_min_conn) { |
| | | MysqlConn* conn = m_connkQueue.front(); |
| | | if (conn->getActiveTime() >= max_del_time) { |
| | | m_connkQueue.pop(); |
| | | delete conn; |
| | | } |
| | | else { |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | std::shared_ptr<MysqlConn> ConnectionPool::getMysqlConn() { |
| | | |
| | | std::unique_lock<std::mutex>lock(m_mutex); |
| | | while ( m_connkQueue.empty()) { |
| | | // 妿çå¾
䏿®µæ¶é´å,éåè¿æ¯ä¸ºç©º,è¿åä¸ä¸ª null |
| | | if ( std::cv_status::timeout == m_cond.wait_for(lock, std::chrono::milliseconds(m_timeout)) ) { |
| | | if( m_connkQueue.empty( ) ) return nullptr; |
| | | } |
| | | } |
| | | std::shared_ptr<MysqlConn> connPtr(std::move(m_connkQueue.front()), [this](MysqlConn* conn) { |
| | | std::unique_lock <std::mutex>lock(m_mutex) ; |
| | | conn->refreshActiveTime(); |
| | | m_connkQueue.push(conn); |
| | | }); |
| | | m_connkQueue.pop(); |
| | | m_cond.notify_one(); // å¤éé»å¡çç产è
线ç¨,å¼å§ç产 |
| | | return connPtr; |
| | | shared_ptr<MysqlConn> ConnectionPool::getMysqlConn() { |
| | | unique_lock<mutex> lock(m_mutex); |
| | | while (m_connkQueue.empty()) { |
| | | // 妿çå¾
䏿®µæ¶é´å,éåè¿æ¯ä¸ºç©º,è¿åä¸ä¸ª null |
| | | if (cv_status::timeout == m_cond.wait_for(lock, chrono::milliseconds(m_timeout))) { |
| | | if (m_connkQueue.empty()) return nullptr; |
| | | } |
| | | } |
| | | shared_ptr<MysqlConn> connPtr(move(m_connkQueue.front()), [this](MysqlConn* conn) { |
| | | unique_lock<mutex> lock(m_mutex); |
| | | conn->refreshActiveTime(); |
| | | m_connkQueue.push(conn); |
| | | }); |
| | | m_connkQueue.pop(); |
| | | m_cond.notify_one(); // å¤éé»å¡çç产è
线ç¨,å¼å§ç产 |
| | | return connPtr; |
| | | } |
| | | void ConnectionPool::description() { |
| | | cout << m_ip << ". " << m_userName << ". " << m_passwd << ". " << m_db << ". " |
| | | << m_port << ". " << m_max_conn << ". " << m_min_conn << ". " << m_timeout << ". " |
| | | << max_del_time << endl; |
| | | } |
| | | |
| | | ConnectionPool* ConnectionPool::getInstance() { |
| | | static ConnectionPool connPool; |
| | | return &connPool; |
| | | } |