这个class的设计和MysqlObj不一样了,不会像MysqlObj提供Connect函数来进行连接,这里我直接就在构造函数当中创建好池,因为如果再提供一个init之类的函数来创建池的话我觉得与这个class的设计语意违背,毕竟池创建好就能直接使用了。
在构造函数当中使用到了boost的property_tree,目的就是从config里面读取database.xml或者database.json配置文件,从配置文件当中获取到host,user,dbname等等。
做的工作只有一件事情,从配置文件当中读取出的max_connections,说明了池的容量,需要建立这么多的连接数目,然后使用map来保存这个连接,map的first是连接指针,second指的是Mysql连接是否可用,true为可用,false为已经被其他的占用了。
析构函数的话直接轮询map,然后删除掉对应的指针,我现在正在想用shared_ptr来代替掉指针。
getConnection()函数就是说从池当中取出一个连接,就是轮询map,然后查找有用的连接。
这里为了应对多线程使用了锁,使用并非简单的mutex.lock()和mutex.unlock()。我更加喜欢使用RAII方式的unique_lock和lock_guard,但是unique_lock提供了更好的上锁和解锁机制。
releaseConnection()正好和getConnection()是相反的,也是用了unique_lock机制。
#include
#include
#include
#include "mysql_obj.h"
using std::string;
using std::vector;
using std::mutex;
using std::unique_lock;
using std::map;
using std::make_pair;
// 这个pool只做了一件事情,那就是创建poolsize个的连接,Mysql的最大连接数目是151
class MysqlPool
{
public:
// 批量创建连接在构造函数当中进行
MysqlPool();
// 析构函数就是顺序销毁MysqlObj指针
// 最后清空map
virtual ~MysqlPool();
// 从map当中选取一个连接
MysqlObj* getConnection();
// 释放特定的连接就是把map当中的bool值置为false
int releaseConnection(MysqlObj*);
// 构造函数创建poolsize个连接错误时候用来打印错误信息
string ErrorMessage() const;
private:
mutex resource_mutex;
public:
// 之所以要把这里设置成为public,是因为使用insert的方式来插入连接和是否可用的pair
// bool值为false的时候说明mysql连接被占用
map mysql_map;
private:
string host_ ;
string user_ ;
string password_ ;
string dbname_;
unsigned port_;
//Mysql的最大连接数为151,从database.xml或者database.json当中读取max_connections
int poolSize_;
//错误信息
string m_strErrorMessage;
};
#include "../include/mysql_connection_pool.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
using std::cout;
using std::endl;
MysqlPool::MysqlPool()
{
// 从配置文件database.xml当中读入mysql的ip, 用户, 密码, 数据库名称,
boost::property_tree::ptree pt;
const char* xml_path = "../config/database.xml";
boost::property_tree::read_xml(xml_path, pt);
//这段注释的代码是读取json配置文件的
// const char* json_path = "../config/database.json";
// boost::property_tree::read_json(json_path, pt);
BOOST_AUTO(child, pt.get_child("Config.MysqlConnection"));
for(BOOST_AUTO(pos, child.begin()); pos!= child.end(); ++pos)
{
if(pos->first == "IP")
host_ = pos->second.data();
if(pos->first == "Port")
port_ = boost::lexical_cast(pos->second.data());
if(pos->first == "User")
user_ = pos->second.data();
if(pos->first == "Passwd")
password_ = pos->second.data();
if(pos->first == "DBName")
dbname_ = pos->second.data();
if(pos->first == "max_connections")
poolSize_ = boost::lexical_cast(pos->second.data());
}
// 构造函数的作用就是根据poolSize的大小来构造多个映射
// 每个映射的连接都是同样的host,user,pass,dbname
for(int i=0; i
{
// boost::shared_ptr conn =
MysqlObj* conn = new MysqlObj(host_, user_, password_, dbname_, port_);
conn->Connect();
if(conn->Connect())
mysql_map.insert(make_pair(conn, 1));
else
{
m_strErrorMessage = conn->ErrorMessage();
delete conn;
}
}
}
MysqlPool::~MysqlPool()
{
// 析构函数就是顺序销毁MysqlObj指针
for(auto it = mysql_map.begin(); it != mysql_map.end(); ++it)
{
delete it->first;
}
mysql_map.clear();
}
// 从map当中得到一个连接
MysqlObj* MysqlPool::getConnection()
{
//get connection operation
MysqlObj* ret = NULL;
while(true)
{
bool flag = false;
for(auto it = mysql_map.begin(); it != mysql_map.end(); ++it)
{
unique_lock lk(resource_mutex);
if(it->second == true)
{
it->second = false;
ret = it->first;
flag = true;
break;
}
}
if(flag == true)
{
break;
}
else
{
usleep(1000);
continue;
}
}
return ret;
}
// 释放一个连接还给线程池
int MysqlPool::releaseConnection(MysqlObj* conn)
{
for(auto it = mysql_map.begin(); it != mysql_map.end(); ++it)
{
unique_lock lk(resource_mutex);
if(it->first == conn)
{
it->second = true;
break;
}
}
return 1;
}
string MysqlPool::ErrorMessage() const
{
return m_strErrorMessage;
}