数据库连接池DBPool分析(四):mysql连接池 mysql_connection_pool

这个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 <string.h>
#include <mutex>
#include <map>
#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<MysqlObj*, bool> 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 <stdlib.h>
#include <iostream>
#include <unistd.h>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>

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<int>(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<int>(pos->second.data());
    }
    // 构造函数的作用就是根据poolSize的大小来构造多个映射
    // 每个映射的连接都是同样的host,user,pass,dbname

    for(int i=0; i<poolSize_; ++i)
    {
//      boost::shared_ptr<Connection> 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<mutex> 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<mutex> lk(resource_mutex);
        if(it->first == conn)
        {
            it->second = true;
            break;
        }
    }
    return 1;
}

string MysqlPool::ErrorMessage() const
{
    return m_strErrorMessage; 
}
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值