Server/王琨元/code/ConnectionPool.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Server/王琨元/code/ConnectionPool.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Server/王琨元/code/MysqlConn.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Server/王琨元/code/MysqlConn.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
Server/ÍõçûÔª/code/ConnectionPool.cpp
New file @@ -0,0 +1,131 @@ #include "ConnectionPool.h" ConnectionPool::ConnectionPool() { if (!parseXmlFile()) return; for (m_num = 0; m_num < m_minSize;) { bool flag = addConnection(); if (!flag) { return; } } // 妿å线ç¨çä»»å¡å½æ°æ¯ç±»çééæå½æ°ï¼æä»¬éè¦æå®ä»»å¡å½æ°çå°ååä»»å¡å½æ°çææè thread producer(&ConnectionPool::productConnection, this); // åå»ºè¿æ¥ thread recycler(&ConnectionPool::recycleConnection, this); // æ£æµå¹¶éæ¯è¿æ¥ // 线ç¨å离ï¼é²æ¢é»å¡ä¸»çº¿ç¨ producer.detach(); recycler.detach(); } ConnectionPool::~ConnectionPool() { while (!m_connections.empty()) { MysqlConn* conn = m_connections.front(); m_connections.pop(); delete conn; } } bool ConnectionPool::parseXmlFile() { TiXmlDocument xml("mysql.xml"); // å è½½æä»¶ bool res = xml.LoadFile(); if (!res) { return false; // æç¤º } // æ ¹ TiXmlElement* rootElement = xml.RootElement(); TiXmlElement* childElement = rootElement->FirstChildElement("mysql"); // 读åä¿¡æ¯ m_ip = childElement->FirstChildElement("ip")->GetText(); m_port = static_cast<unsigned short>(stoi(string(childElement->FirstChildElement("port")->GetText()))); m_user = childElement->FirstChildElement("username")->GetText(); m_passwd = childElement->FirstChildElement("password")->GetText(); m_dbName = childElement->FirstChildElement("dbName")->GetText(); m_minSize = static_cast<int>(stoi(string(childElement->FirstChildElement("minSize")->GetText()))); m_maxSize = static_cast<int>(stoi(string(childElement->FirstChildElement("maxSize")->GetText()))); m_maxIdleTime = static_cast<int>(stoi(string(childElement->FirstChildElement("maxIdleTime")->GetText()))); m_timeout = static_cast<int>(stoi(string(childElement->FirstChildElement("timeout")->GetText()))); return true; } bool ConnectionPool::addConnection() { MysqlConn* conn = new MysqlConn; bool res = conn->connect(m_user, m_passwd, m_dbName, m_ip, m_port); if (res) { // å·æ°ç©ºé²æ¶é´ conn->refreashAliveTime(); m_connections.push(conn); ++m_num; return true; } else { delete conn; return false; // æç¤º } } void ConnectionPool::productConnection() { while (true) { unique_lock<mutex> lc(m_mutex); m_cond.wait(lc, [this]() {return m_connections.empty(); }); if (m_num < m_maxSize) { bool flag = addConnection(); if (!flag) { return; } } // å¤é m_cond1.notify_all(); } } void ConnectionPool::recycleConnection() { while (true) { // ä¼ç 䏿®µæ¶é´ 0.5s this_thread::sleep_for(milliseconds(500)); lock_guard<mutex> lc(m_mutex); while (!m_connections.empty() && m_num > m_minSize) { MysqlConn* conn = m_connections.front(); if (conn->getAliveTime() >= m_maxIdleTime) { m_connections.pop(); delete conn; --m_num; } else { break; } } } } ConnectionPool* ConnectionPool::getConnectPool() { // ä¸ä½¿ç¨äºæ¥éç线ç¨å®å ¨çææ±æ¨¡å¼ static ConnectionPool pool; // åªå¨ç¬¬ä¸æ¬¡è°ç¨å½æ°æ¶åå§å return &pool; } shared_ptr<MysqlConn> ConnectionPool::getConnection() { unique_lock<mutex> lc(m_mutex); while (m_connections.empty()) { if (cv_status::timeout == m_cond1.wait_for(lc, chrono::milliseconds(m_timeout))) { if (m_connections.empty()) { // cout << "out of time" << endl; return nullptr; // ç»æ // æç¤º // continue; // å©ç¨whileé åcontinue ç»§ç»é»å¡ } } } // è¦æå®å é¤å¨destructorï¼æ¥ä¿è¯è¿æ¥çå½è¿ shared_ptr<MysqlConn> conn(m_connections.front(), [this](MysqlConn* conn) { // å éä¿è¯éå线ç¨å®å ¨ // m_mutex.lock(); // 1 unique_lock<mutex> lc(m_mutex); // 2 // lock_guard<mutex> lc(m_mutex); // 3 conn->refreashAliveTime(); m_connections.push(conn); // m_mutex.unlock(); // 1 }); m_connections.pop(); m_cond.notify_all(); return conn; } Server/ÍõçûÔª/code/ConnectionPool.h
New file @@ -0,0 +1,54 @@ #pragma once #include "MysqlConn.h" #include "./tinyxml/tinyxml.h" #include <queue> #include <mutex> #include <thread> #include <atomic> #include <condition_variable> #pragma comment(lib, "./tinyxml/x64/Debug/tinyxml.lib") // åºç¨-å便¨¡å¼ï¼ææ±æ¨¡å¼[éè¦èèå¤çº¿ç¨å®å ¨é®é¢] class ConnectionPool { private: ConnectionPool(); // ç§»å¨æ·è´æç»è¿æ¯æä¸ä» æä¸ä¸ªå¯¹è±¡ï¼æä»¥ä¾æ§æ¯å±äºå便¨¡å¼ã // delete 黿¢æ·è´æé åæ·è´èµå¼çç±»å¯¹è±¡çæ ConnectionPool(ConnectionPool&) = delete; ConnectionPool& operator=(ConnectionPool&) = delete; ~ConnectionPool(); // è§£æxmlé ç½®æä»¶ è¯»åæ°æ®åºåè¿æ¥æ± çç¸å ³ä¿¡æ¯ bool parseXmlFile(); // æ·»å è¿æ¥ bool addConnection(); // 线ç¨å½æ° void productConnection(); void recycleConnection(); // åæ¾æ°æ®åºè¿æ¥æ± 建ç«çè¿æ¥ queue<MysqlConn*> m_connections; // ä¸äºåºæ¬ä¿¡æ¯ string m_ip; // IP unsigned short m_port; // ç«¯å£ string m_user; // ç¨æ·å string m_passwd; // å¯ç string m_dbName; // æ°æ®åºåç§° int m_minSize; // åå§è¿æ¥é(æå°è¿æ¥é) int m_maxSize; // æå¤§è¿æ¥é int m_timeout; // è¶ æ¶æ¶é¿ int m_maxIdleTime; // æå¤§ç©ºé²æ¶é¿ // 线ç¨å®å ¨ç¸å ³ mutex m_mutex; condition_variable m_cond; // ä» ç¨ä¸ä¸ªæ¡ä»¶å鿥å¤é线ç¨ï¼ä½å¹¶ä¸å½±å线ç¨è¿è¡ condition_variable m_cond1; // è¿æ¥æ°é atomic_int m_num; // è¿æ¥çæ»æ°é public: // è·ååä¾å¯¹è±¡çæ¥å£ static ConnectionPool* getConnectPool(); // ç¨æ·è·åè¿æ¥çæ¥å£, 妿è·å失败ï¼ä¼è¿ånullptr shared_ptr<MysqlConn> getConnection(); }; Server/ÍõçûÔª/code/MysqlConn.cpp
New file @@ -0,0 +1,174 @@ #include "MysqlConn.h" MysqlConn::MysqlConn()//åå§åæ°æ®åº { m_result = nullptr; m_mysqlRow = nullptr; // ä¼ å ¥nullptr空æéæ¶ï¼ä¼èªå¨åé ä¸ä¸ªMYSQL对象 m_conn = mysql_init(nullptr); } MysqlConn::~MysqlConn()//éæ¾æ°æ®åºè¿æ¥ { freeRes(); // éæ¾ç»æé if (m_conn != nullptr) { mysql_close(m_conn); m_conn = nullptr; } } void MysqlConn::freeRes()//ç»æééæ¾ { if (m_result) { mysql_free_result(m_result); m_result = nullptr; } } bool MysqlConn::connect(const string user, const string passwd, \ const string dbName, string ip, \ const unsigned short port)//è¿æ¥æ°æ®åº { MYSQL* res = mysql_real_connect(m_conn, ip.c_str(), user.c_str(), \ passwd.c_str(), dbName.c_str(), port, nullptr, 0); // ä¿®æ¹ç¼ç mysql_set_character_set(m_conn, "gb2312"); return res != nullptr; } bool MysqlConn::update(const string sql) const { // æ§è¡æåè¿å0ï¼ int res = mysql_real_query(m_conn, sql.c_str(), static_cast<unsigned int>(sql.size())); if (res != 0) { return false; // æç¤º } return true; } bool MysqlConn::query(const string sql) { freeRes(); int res = mysql_real_query(m_conn, sql.c_str(), static_cast<unsigned int>(sql.size())); if (res != 0) { return false; // æç¤º } m_result = mysql_store_result(m_conn); return true; } bool MysqlConn::getRes() { if (m_result != nullptr) { // char** è·ååè¡è®°å½ m_mysqlRow = mysql_fetch_row(m_result); if (m_mysqlRow != nullptr) { return true; } freeRes(); } return false; } string MysqlConn::getValue(const int fieldIndex) const { int fieldCount = mysql_num_fields(m_result); if (fieldIndex >= fieldCount || fieldIndex < 0) { return string(); // æç¤º } char* value = m_mysqlRow[fieldIndex]; // å¾å°ä¸ä¸ªä¿åååæ®µå¼é¿åº¦çæ°ç» unsigned long* len = mysql_fetch_lengths(m_result); unsigned long length = len[fieldIndex]; // 鲿¢ç»æä¸åå¨\0å¯¼è´æ°æ®ä¸¢å¤± return string(value, length); } bool MysqlConn::selectDB(const string dbName) const { int res = mysql_select_db(m_conn, dbName.c_str()); if (res != 0) { return false; // æç¤º } return true; } void MysqlConn::backupCurrentDB(const string path) { string sql = "show tables"; int r = mysql_real_query(m_conn, sql.c_str(), static_cast<unsigned long>(sql.size())); if (r != 0) { return; // æç¤º } MYSQL_RES* tableRes = mysql_store_result(m_conn); for (int i = 0; i < mysql_num_rows(tableRes); ++i) { MYSQL_ROW tableName = mysql_fetch_row(tableRes); backupCurrentTable(path, tableName[0]); } } void MysqlConn::backupCurrentTable(const string path, const string tableName) { string file = path + tableName + ".sql"; ofstream ofs(file); if (!ofs.is_open()) { return; // æç¤º } // è¡¨ç»æåå ¥ string showCreate = "show create table " + tableName + ";"; bool res = query(showCreate); if (!res) { return; // æç¤º } if (getRes()) { string writeSQL = getValue(1) + ";\n"; ofs.write(writeSQL.c_str(), writeSQL.size()); // cout << writeSQL << endl; } // è¡¨æ°æ®åå ¥ string sql = "select * from " + tableName + ";"; res = query(sql); if (!res) { return; // æç¤º } while (getRes()) { string writeSQL = "insert into `" + tableName + "` values("; for (int i = 0; !getValue(i).empty(); ++i) { if (i != 0) { writeSQL += ","; } MYSQL_FIELD* valueType = mysql_fetch_field_direct(m_result, i); if (valueType->type == MYSQL_TYPE_DECIMAL || valueType->type == MYSQL_TYPE_TINY || valueType->type == MYSQL_TYPE_SHORT || valueType->type == MYSQL_TYPE_LONG || valueType->type == MYSQL_TYPE_FLOAT || valueType->type == MYSQL_TYPE_DOUBLE || valueType->type == MYSQL_TYPE_TIMESTAMP || valueType->type == MYSQL_TYPE_LONGLONG || valueType->type == MYSQL_TYPE_INT24) { writeSQL += getValue(i); } else { writeSQL += "'" + getValue(i) + "'"; } } writeSQL += ");\n"; ofs.write(writeSQL.c_str(), writeSQL.size()); } ofs.close(); } bool MysqlConn::transaction() const { // å°äºå¡æäº¤è®¾ç½®ä¸ºæå¨æäº¤ return mysql_autocommit(m_conn, false); } bool MysqlConn::commit() const { return mysql_commit(m_conn); } bool MysqlConn::rollback() const { return mysql_rollback(m_conn); } void MysqlConn::refreashAliveTime() { m_alivetime = steady_clock::now(); } ll MysqlConn::getAliveTime() { // æ¯«ç§ <<= 纳ç§:精度éä½ milliseconds res = duration_cast<milliseconds>(steady_clock::now() - m_alivetime); return res.count(); } Server/ÍõçûÔª/code/MysqlConn.h
New file @@ -0,0 +1,63 @@ #pragma once #include<iostream> #include <memory> #include <string> #include <mysql.h> #include <chrono> // æ¶é #include <fstream> #pragma comment(lib, "./lib/libmysql.lib") // å è½½æ°æ®åºåºæä»¶ using namespace std; using namespace chrono; typedef long long ll; class MysqlConn { private: // ç»å¯¹æ¶é steady_clock::time_point m_alivetime; // è¿æ¥ MYSQL* m_conn; // æ¥è¯¢çç»æé MYSQL_RES* m_result; // åè®°å½ç»æé MYSQL_ROW m_mysqlRow; // ç»æééæ¾ void freeRes(); // å¯¼åºæä¸å¼ 表ä¸çæ°æ® void backupCurrentTable(const string path, const string tableName); public: // åå§åæ°æ®åº MysqlConn(); // æ°æ®åºè¿æ¥éæ¾ ~MysqlConn(); // è¿æ¥æ°æ®åº, éæä¾ç¨æ· å¯ç æ°æ®åºåç§° ip ç«¯å£ bool connect(const string user, const string passwd, \ const string dbName, string ip, \ const unsigned short port = 3306U); // æ´æ°æ°æ®åº:å¢å æ¹æä½ bool update(const string sql) const; // æ¥è¯¢æ°æ®åº bool query(const string sql); // éåæ¥è¯¢ç»æé bool getRes(); // è·åç»æéä¸çåæ®µå¼ string getValue(const int fieldIndex) const; // åæ¢æ°æ®åº bool selectDB(const string dbName) const; // å»ºåº //bool createDB(const string dbName) const; // å¤ä»½æä¸ªåº void backupCurrentDB(const string path); // äºå¡æä½ bool transaction() const; // æäº¤äºå¡ bool commit() const; // äºå¡åæ» bool rollback() const; // å·æ°èµ·å§çç©ºé²æ¶é´ç¹ void refreashAliveTime(); // 计ç®åæ´»æ»æ¶é¿ ll getAliveTime(); };