读书人

Linux上C++访问MySQL连接池lt;二gt

发布时间: 2012-12-27 10:17:10 作者: rapoo

Linux下C++访问MySQL连接池<二>

实现是基于mysql connector C++ api的

connpool.h文件

?/**
? *数据库连接池(单例模式)
? **/
#ifndef CONN_POOL_H
#define CONN_POOL_H

#include <mysql_connection.h>
#include <mysql_driver.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include "push.h"
#include "mutex.h"
?? ?
using namespace std;

class ConnPool{
?? ?private:
?? ??? ?deque<sql::Connection *> conns;//连接队列
?? ??? ?int curSize;//当前队列中路连接数目
?? ??? ?int maxSize;//最大连接数目
?? ??? ?sql::ConnectOptionsMap connectionProperties;
?? ??? ?Mutex *lock;//连接队列互斥锁
?? ??? ?static ConnPool * connPool;
?? ??? ?sql::Driver * driver;//mysql connector C++ driver
?? ??? ?sql::Connection * CreateConnection();//创建一个连接
?? ??? ?void TerminateConnection(sql::Connection * conn);//终止一个连接
?? ??? ?void Init(int initialSize);//初始化连接池
?? ??? ?void Destroy();//销毁连接池
?? ?protected:
?? ??? ?ConnPool(string host,string user,string password,int maxSize);
?? ?public:
?? ??? ?~ConnPool();
?? ??? ?sql::Connection * GetConnection();//获取一个连接
?? ??? ?void ReleaseConnection(sql::Connection * conn);//释放一个连接
?? ??? ?sql::Connection * GetConnectionTry(int maxNum);//GetConnection的加强版,maxNum代表重试次数
?? ??? ?static ConnPool * GetInstance();//获取一个ConnPool对象实例
};

#endif
???

connpool.cpp文件

/**
? *数据库连接池
? *? **/
#include <stdexcept>
#include "connpool.h"
#include "config.h"
?? ??? ??? ?
using namespace std;
extern Config *config;

ConnPool * ConnPool::connPool = NULL;

ConnPool::ConnPool(string host,string user,string password,int maxSize){
?? ?connectionProperties["hostName"] = host;
?? ?connectionProperties["userName"] = user;
?? ?connectionProperties["password"] = password;
?? ?connectionProperties["OPT_CONNECT_TIMEOUT"] = 600;
?? ?connectionProperties["OPT_RECONNECT"] = true;
?? ?
?? ?this->maxSize = maxSize;
?? ?this->lock = new Mutex();
?? ?this->curSize = 0;
?? ?//初始化driver
?? ?try{
?? ??? ?this->driver = sql::mysql::get_driver_instance();? //这里不是线程安全的
?? ?}
?? ?catch(sql::SQLException &e){
?? ??? ?string errorMsg = string("SQLException: ") + e.what() + string(" MySQL error code: ") + int_to_string(e.getErrorCode()) + string(" SQLState ") +? e.getSQLState();
?? ??? ?Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);
?? ?}
?? ?catch(std::runtime_error &e){
?? ??? ?string errorMsg = string("runtime_error: ") + e.what();
?? ??? ?Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);
?? ?}
?? ?//初始化连接池
?? ?this->Init(maxSize/2);
}

ConnPool::~ConnPool(){?? ?
?? ?this->Destroy();
?? ?delete lock;
}

ConnPool *ConnPool::GetInstance(){
?? ?if(connPool == NULL) {
?? ??? ?connPool = new ConnPool(config->GetVar("db_host"),config->GetVar("db_user"),config->GetVar("db_password"),string_to_int(config->GetVar("max_db_conn_size")));
?? ?}
?? ?
?? ?return connPool;
}

void ConnPool::Init(int size){
?? ?sql::Connection * conn ;
?? ?lock->Lock();
?? ?
?? ?for(int i = 0; i < size ;){
?? ??? ?conn = this->CreateConnection();
?? ??? ?if(conn){
?? ??? ??? ?i++;?? ??? ??? ?
?? ??? ??? ?conns.push_back(conn);
?? ??? ??? ?++curSize;
?? ??? ?}
?? ??? ?else{
?? ??? ??? ?Log::Write(__FILE__,__FUNCTION__,__LINE__,"Init connpooo fail one");
?? ??? ?}
?? ?}
?? ?
?? ?lock->UnLock();?? ?
}

void ConnPool::Destroy(){
?? ?deque<sql::Connection *>::iterator pos;
?? ?
?? ?lock->Lock();
?? ?
?? ?for(pos = conns.begin(); pos != conns.end();++pos){
?? ??? ?this->TerminateConnection(*pos);
?? ?}
?? ?
?? ?curSize = 0;
?? ?conns.clear();
?? ?
?? ?lock->UnLock();?? ?
}

sql::Connection * ConnPool::CreateConnection(){//这里不负责curSize的增加
?? ?sql::Connection *conn;
?? ?
?? ?try{
?? ??? ?conn = driver->connect(connectionProperties);
?? ??? ?Log::Write(__FILE__,__FUNCTION__,__LINE__,"create a mysql conn");
?? ??? ?return conn;
?? ?}
?? ?catch(sql::SQLException &e){
?? ??? ?string errorMsg = string("SQLException:") + e.what() + string(" MySQL error code: ") + int_to_string(e.getErrorCode()) + string(" SQLState ") +? e.getSQLState();
?? ??? ?Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);
?? ??? ?return NULL;
?? ?}
?? ?catch(std::runtime_error &e){
?? ??? ?string errorMsg = string("runtime_error: ") + e.what();
?? ??? ?Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);
?? ??? ?return NULL;
?? ?}
}

void ConnPool::TerminateConnection(sql::Connection * conn){
?? ?if(conn){
?? ??? ?try{
?? ??? ??? ?conn->close();
?? ??? ?}
?? ??? ?catch(sql::SQLException &e){
?? ??? ??? ?string errorMsg = string("SQLException:") + e.what() + string(" MySQL error code: ") + int_to_string(e.getErrorCode()) + string(" SQLState ") +? e.getSQLState();
?? ??? ??? ?Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);
?? ??? ?}
?? ??? ?catch(std::runtime_error &e){
?? ??? ??? ?string errorMsg = string("runtime_error: ") + e.what();
?? ??? ??? ?Log::Write(__FILE__,__FUNCTION__,__LINE__,errorMsg);
?? ??? ?}
?? ??? ?
?? ??? ?delete conn;
?? ?}
}

sql::Connection * ConnPool::GetConnection(){
?? ?sql::Connection * conn;
?? ?
?? ?lock->Lock();
?? ?
?? ?if(conns.size() > 0){//有空闲连接,则返回
?? ??? ?conn = conns.front();
?? ??? ?conns.pop_front();
?? ??? ?
?? ??? ?if(conn->isClosed()){ //如果连接关闭,则重新打开一个连接
?? ??? ??? ?Log::Write(__FILE__,__FUNCTION__,__LINE__,"a mysql conn has been closed");
?? ??? ??? ?delete conn;
?? ??? ??? ?conn = this->CreateConnection();
?? ??? ?}
?? ??? ?
?? ??? ?if(conn == NULL){ //创建连接不成功
?? ??? ??? ?--curSize;
?? ??? ?}
?? ??? ?lock->UnLock();
?? ??? ?
?? ??? ?return conn;
?? ?}
?? ?else{
?? ??? ?if(curSize < maxSize){//还可以创建新的连接
?? ??? ??? ?conn = this->CreateConnection();
?? ??? ??? ?if(conn){
?? ??? ??? ??? ?++curSize;
?? ??? ??? ??? ?lock->UnLock();
?? ??? ??? ??? ?return conn;
?? ??? ??? ?}
?? ??? ??? ?else{
?? ??? ??? ??? ?lock->UnLock();
?? ??? ??? ??? ?return NULL;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?else{//连接池已经满了
?? ??? ??? ?lock->UnLock();
?? ??? ??? ?return NULL;
?? ??? ?}
?? ?}?? ?
}

void ConnPool::ReleaseConnection(sql::Connection * conn){
?? ?if(conn){
?? ??? ?lock->Lock();
?? ??? ?
?? ??? ?conns.push_back(conn);
?? ??? ?
?? ??? ?lock->UnLock();
?? ?}
}

sql::Connection * ConnPool::GetConnectionTry(int maxNum){
?? ?sql::Connection * conn;
?? ?
?? ?for(int i = 0; i < maxNum; ++i){
?? ??? ?conn = this->GetConnection();
?? ??? ?if(conn){
?? ??? ??? ?return conn;
?? ??? ?}
?? ??? ?else {
?? ??? ??? ?sleep(2);
?? ??? ?}
?? ?}
?? ?
?? ?return NULL;
}

1 楼 wxqhbw2008 2012-10-26 我刚学c++,这个connpool.h文件copy过去就报错,报以下这些头文件无法打开,这些头文件是怎么回事呀,不太懂
#include <mysql_connection.h>
#include <mysql_driver.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include "push.h"
#include "mutex.h"
谢谢提点

读书人网 >C++

热点推荐