LINUX C++ 数据库连接池

 mysql的c++连接池 xPool 

来自: http://my.oschina.net/u/1179554/blog/149560


最近待业,闲的蛋疼,发现C++下连mysql连接池这么基础的东西都没用过,身为一名计算机毕业生,深感愧疚,遂生一想法,写个或者找个连接池,以增强本人垃圾一样的专业修养。

没想到写出来第一版就存在内存管理问题导致的coredump,查了半天,发现是调用了空指针的成员函数,彻底晕倒,其间为了调试gdb core中bt出来的libmysqlclient.so的mysql_real_connect调用,我下了mysql的5.5.31源代码来编了若干遍,想编个debug版调试最后也是没有成功。发现问题还是看网上帖子讲segfault11这种问题多半都是空指针搞的,反过头加了些指针的打印语句才意识到低级的错误,后来debug过程中还发现了更低级的逻辑错误,略去不表,还是自己太菜,连个空指针这个白痴的内存问题都不预先防范,搞得一个300+行的东西,弄了三天才算稳定了,大大的罪过,浪费自己和社会的生产力。

过程中想到自己既然写不好,干脆找个好用的,结果发现了个libzdb,支持好些个开源db的连接池,随便下了个破代码测了一下,也没仔细搞,debug中参考了一下它的源码,还算是有点启发。

目前这个源码用valgrind自己测,有74KB左右的内存泄露,明白人能改改的话最好,作为一个菜鸟我只能帮自己到这了,当然这个泄露不会随时间线性的增长,这个我还是测过了的,有人能用到生产环境的话,麻烦给我提点改进意见,72小时的作品,太经不起考验了,目前本机上只能支持最多 152条连接,设成153就会报连接失败,牛逼的前辈们狠狠的批这份代码好了,自己也感觉自己水平太残废了,不知道是mysql设置还是系统设置的问题,总之无论是建议还是问题尽管扔过来吧,作为一个傻逼二货我照单全收。

上代码

去Github搞代码看这里 https://github.com/githcx/xPool

pool.h (1 in 3)

01#include <mysql.h>
02#include <stdio.h>
03#include <string.h>
04#include <map>
05#include <vector>
06#include <string>
07#include <iostream>
08#include <pthread.h>
09  
10using std::string;
11using std::vector;
12  
13class Connection;
14  
15class some{
16    public:
17        some(){}
18        Connection * first;
19        boolsecond;
20};
21  
22class Pool{
23    public:
24        staticint initPool(string host,string user,string pass,string dbname,intpoolSize);
25        staticvoid destroyPool();
26  
27        staticConnection* getConnection();
28        staticint releaseConnection(Connection*);
29        staticvoid lock();
30        staticvoid unlock();
31  
32        staticvoid locke();
33        staticvoid unlocke();
34  
35        staticvoid locki();
36        staticvoid unlocki();
37  
38        staticvoid lockl();
39        staticvoid unlockl();
40  
41  
42    private:
43  
44        staticpthread_mutex_t mutex;
45        staticpthread_mutex_t execmutex;
46        staticpthread_mutex_t initmutex;
47        staticpthread_mutex_t logmutex;
48        staticPool* pool_;
49  
50    private:
51        some* vec;    // need an instance to init
52  
53    public:
54        staticstring host_ ;
55        staticstring user_ ;
56        staticstring pass_ ;
57        staticstring dbname_;
58        staticint poolSize_ ;
59  
60    public:
61  
62        Pool(string host,string user,string pass,string dbname,intpoolSize);
63        virtual~Pool();
64};
65  
66class QueryResult;
67  
68class Connection{
69    public:
70        Connection(string host,string user,string pass,string dbname);
71        virtual~Connection();
72  
73        QueryResult executeQuery(string statement);
74    private:
75        // MYSQL代表了一条TCP连接
76        MYSQL* conn;
77};
78  
79class QueryResult{
80    public:
81        intgetRowCount(){returnstring_table.size();}
82        intgetColumnCount(){returnstring_table[0].size();};
83        string getElement(introw,int column){return string_table[row][column];}
84        voidaddRow(constvector<string>& row){string_table.push_back(row);}
85    private:
86        vector<vector<string> > string_table;
87};

pool.h (2 in 3)

001#include "pool.h"
002#include <stdlib.h>
003  
004// for DEBUG
005using std::cout;
006using std::endl;
007  
008  
009// static field init
010string Pool::host_ = "";
011string Pool::user_ = "";
012string Pool::pass_ = "";
013string Pool::dbname_ = "";
014int    Pool::poolSize_ = 0;
015Pool*  Pool::pool_ = NULL;
016pthread_mutex_t Pool::mutex;
017pthread_mutex_t Pool::execmutex;
018pthread_mutex_t Pool::initmutex;
019pthread_mutex_t Pool::logmutex;
020  
021void Pool::lock(){
022    pthread_mutex_lock(&mutex);
023}
024  
025void Pool::unlock(){
026    pthread_mutex_unlock(&mutex);
027}
028  
029void Pool::locke(){
030    pthread_mutex_lock(&execmutex);
031}
032  
033void Pool::unlocke(){
034    pthread_mutex_unlock(&execmutex);
035}
036  
037void Pool::locki(){
038    pthread_mutex_lock(&initmutex);
039}
040  
041void Pool::unlocki(){
042    pthread_mutex_unlock(&initmutex);
043}
044  
045void Pool::lockl(){
046    pthread_mutex_lock(&logmutex);
047}
048  
049void Pool::unlockl(){
050    pthread_mutex_unlock(&logmutex);
051}
052  
053  
054  
055Pool::Pool(string host,string user,string pass,string dbname,intpoolSize){
056  
057    vec =new some[Pool::poolSize_];
058  
059  
060    for(inti=0; i<poolSize_; i++){
061        Connection* conn =new Connection(Pool::host_,Pool::user_,Pool::pass_,Pool::dbname_);
062        //std::cout << conn << std::endl;
063        //std::cout << host << " " << user << " " << pass << " " << dbname << " " << poolSize << std::endl;
064        if(!conn){
065            cout <<"xPool: new Connection Operation failed" << endl;
066            exit(-1);
067        }
068        vec[i].first = conn;
069        vec[i].second =false;
070    }
071  
072  
073}
074  
075Pool::~Pool(){
076    for(inti=0;i<poolSize_;i++){
077        deletevec[i].first;
078    }
079    delete[] vec;
080    //mysql_library_end();
081}
082  
083int Pool::initPool(string host,string user,string pass,string dbname,intpoolSize){
084    host_ = host;
085    user_ = user;
086    pass_ = pass;
087    dbname_ = dbname;
088    poolSize_ = poolSize;
089      
090    return0;
091}
092  
093void Pool::destroyPool(){
094    if(pool_){
095        deletepool_;
096        pool_ = NULL;
097    }
098}
099  
100Connection* Pool::getConnection(){
101  
102    // init pool, open connections
103    Pool::locki();
104    if(pool_ == NULL){
105        pthread_mutex_init(&mutex,0);
106        pthread_mutex_init(&execmutex,0);
107  
108        //mysql_library_init(0,NULL,NULL);
109  
110        pool_ =new Pool(host_,user_,pass_,dbname_,poolSize_);
111    }
112    Pool::unlocki();
113  
114    //get connection operation
115    Connection* ret = NULL;
116    while(true){
117        Pool::lock();
118        boolflag = false;
119        for(inti=0;i<poolSize_;i++){
120            if(pool_->vec[i].second ==false){
121                pool_->vec[i].second =true;
122                ret = pool_->vec[i].first;
123                flag =true;
124                break;
125            }
126        }
127        if(flag ==true){
128            Pool::unlock();
129            break;
130        }
131        else{
132            //cout << "wait" << endl;
133            Pool::unlock();
134            usleep(1000);
135            continue;
136        }
137    }
138    returnret;
139}
140  
141int Pool::releaseConnection(Connection* conn){
142    lock();
143    for(inti=0;i<poolSize_;i++){
144        if(pool_->vec[i].first == conn ){
145            pool_->vec[i].second =false;
146            break;
147        }
148    }
149    unlock();
150    return1;
151}
152  
153  
154Connection::Connection(string host,string user,string pass,string dbname){
155  
156    staticint connectionCount = 0;
157      
158    //cout << "C#:" << connectionCount++ << endl;
159  
160    // 初始化连接
161    conn = mysql_init(NULL);
162  
163    //cout << "conn:" << conn << endl;
164      
165    // 执行物理的tcp连接动作,完成三次握手
166    if(!mysql_real_connect(conn,"localhost","root", "jiqim1ma","hcx",0,NULL,0)){
167        printf("xPool: Error connecting to database: %s\n",mysql_error(conn));
168        exit(-1);
169    }
170    else{
171    }
172}
173  
174Connection::~Connection(){
175  
176    //mysql_thread_end();
177  
178    // 关闭TCP连接,四次挥手
179    mysql_close(conn);
180}
181  
182QueryResult Connection::executeQuery(string statement){
183  
184    //Pool::locke();
185      
186    //cout << "0.start query" << endl;
187  
188    constchar* query = statement.c_str();
189  
190    //cout << "1.before mysql_real_query" << endl;
191  
192    //cout << "strlen=[" << strlen(query) << "]" << endl;
193  
194    unsignedint len = (unsignedint) strlen(query);
195  
196    charq[100];
197    strncpy(q,query,len);
198    q[len]=0;
199  
200    intstatus = mysql_real_query(conn,q,len);
201  
202    //cout << "1.after mysql_real_query" << endl;
203  
204    if(status){
205        printf("Error making query: %s\n",
206                mysql_error(conn));
207    }
208    else{
209        //printf("[%s] made...\n", query); 
210    }
211  
212    MYSQL_RES* resultSet;
213  
214    //cout << "2.before mysql_store_result" << endl;
215  
216    resultSet = mysql_store_result(conn); 
217  
218    //cout << "2.after mysql_store_result" << endl;
219  
220    //cout << "3.before mysql_fetch_row" << endl;
221  
222    QueryResult queryResult;
223    while(true){
224  
225        MYSQL_ROW row;
226        if(!(row = mysql_fetch_row(resultSet))){
227            break;
228        }
229  
230        vector<string> string_row;
231        for(inti=0; i < mysql_num_fields(resultSet); i++){
232            string_row.push_back(row[i]);
233        }
234  
235        queryResult.addRow(string_row);
236    }
237  
238    //cout << "3.after mysql_fetch_row" << endl;
239  
240    //cout << "4.before mysql_free_result" << endl;
241  
242    mysql_free_result(resultSet);    //free result after you get the result
243  
244    //cout << "4.after mysql_free_result" << endl;
245  
246      
247    //cout << "0.finish query" << endl;
248  
249    //Pool::unlocke();
250  
251    returnqueryResult;
252}

mine.cpp ( 3 in 3 )

01#include "pool.h" 
02#include <unistd.h>
03#include <stdlib.h>
04using std::cout;
05using std::endl;
06  
07void* handler(void* arg){
08    longtid = (long)arg;
09  
10    //cout << "tid =[" << tid << "]" << endl;
11    Connection* conn = Pool::getConnection();
12  
13    if(!conn){
14        cout <<"getConnection NULL pointer" << endl;
15        exit(-1);
16    }
17      
18    //cout << "Connection.this:" << conn << endl;
19  
20    constchar* query;
21    query ="select * from student;";
22  
23    QueryResult queryResult = conn->executeQuery(query);
24  
25    Pool::releaseConnection(conn);
26  
27    //for(int i=0;i<queryResult.getRowCount();i++){
28    //  for(int j=0;j<queryResult.getColumnCount();j++){
29    //      cout << queryResult.getElement(i,j) << " ";
30    //  }
31    //  cout << endl;
32    //}
33}
34  
35  
36int main(int argc, char* argv[]){
37    string host ="localhost";
38    string user ="root";
39    string pass ="jiqim1ma";
40    string dbname ="hcx";
41    intpoolSize = 152;
42  
43    Pool::initPool(host,user,pass,dbname,poolSize);
44      
45    ///std::cin.get();
46  
47    unsignedint count = -1;
48    if(argc>1){
49        count =atoi(argv[1]);
50    }
51  
52    for(inti=0;i < count;i++){
53  
54        constint THREAD_COUNT = 250;
55        pthread_t threads[THREAD_COUNT];
56        for(longi=0;i<THREAD_COUNT;i++){
57            pthread_create(&threads[i],NULL,handler,(void*)i);
58            //sleep(1);
59        }
60  
61        for(inti=0;i<THREAD_COUNT;i++){
62            pthread_join(threads[i],0);
63        }
64  
65        cout <<"==============================LOOPBACK================================="<< endl;
66    }
67  
68    Pool::destroyPool();
69  
70  
71  
72    return0;
73}

Makefile

1all: sbpool
2  
3sbpool: mine.cpp pool.cpp
4    g++ -g -o sbpool mine.cpp pool.cpp -lmysqlclient -lpthread
5  
6clean:
7    rm-f *.o accessdb sbpool core*

mypool数据库连接池

来自:
http://www.oschina.net/p/mypool

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值