/*=============================================================================
# FileName: Lock.h
# Desc: delare Lock Class
# Author: Pugna
# Email: 860009944@qq.com
# HomePage: http://www.cnblogs.com/pugna/
# Version: 0.0.1
# LastChange: 2014-10-22 18:05:19
# History:
=============================================================================*/
#ifndef _LOCAL_LOCK_H_
#define _LOCAL_LOCK_H_
#include <pthread.h>
class RWLock{
public:
RWLock(){pthread_rwlock_init(&rwlock,NULL);}
~RWLock(){pthread_rwlock_destroy(&rwlock);}
void RLock(){pthread_rwlock_rdlock(&rwlock);}
void WLock(){pthread_rwlock_wrlock(&rwlock);}
void UnLock(){pthread_rwlock_unlock(&rwlock);}
private:
pthread_rwlock_t rwlock;
};
class MutexLock{
public:
MutexLock(){pthread_mutex_init(&lock,NULL);}
~MutexLock(){pthread_mutex_destroy(&lock);}
void Lock(){pthread_mutex_lock(&lock);}
void UnLock(){pthread_mutex_unlock(&lock);}
private:
pthread_mutex_t lock;
};
template<class ClockObj>class LocalLock{
public:
LocalLock(ClockObj& obj):m_lock(obj){m_lock.Lock();}
~LocalLock(){m_lock.UnLock();}
private:
ClockObj & m_lock;
};
typedef LocalLock<MutexLock> LocalMutexLock;
template<class ClockObj>class LocalReadLock{
public:
LocalReadLock(ClockObj& obj):m_lock(obj){m_lock.RLock();}
~LocalReadLock(){m_lock.UnLock();}
private:
ClockObj & m_lock;
};
typedef LocalReadLock<RWLock> LocalRLock;
template<class ClockObj>class LocalWriteLock{
public:
LocalWriteLock(ClockObj& obj):m_lock(obj){m_lock.WLock();}
~LocalWriteLock(){m_lock.UnLock();}
private:
ClockObj & m_lock;
};
typedef LocalWriteLock<RWLock> LocalWLock;
#endif
/*=============================================================================
# FileName: mysqlconnpool.h
# Desc: declare mysqlconnpool class
# Author: Pugna
# Email: 860009944@qq.com
# HomePage: http://www.cnblogs.com/pugna/
# Version: 0.0.1
# LastChange: 2014-10-21 15:14:31
# History:
=============================================================================*/
#ifndef _MYSQLCONN_POOL_H
#define _MYSQLCONN_POOL_H
#include <mysql/mysql.h>
#include <pthread.h>
#include <string>
#include <queue>
#include "../common/Lock.h"
using namespace std;
class mysqlconnpool{
public:
mysqlconnpool(string url,int port,string user,string pwd,string db,string encode,int minSize=10,int maxSize=100);
~mysqlconnpool();
bool Init();
void Uninit();
MYSQL * CreateConn();
bool DeleteConn(MYSQL *conn);
bool PopConn(MYSQL * &conn);
bool PushConn(MYSQL * &conn);
void getCurSize(int & n);
private:
int maxSize;
int curSize;
int minSize;
string username;
string password;
string url;
int port;
string db;
string encode;
MutexLock mutexLock;
queue<MYSQL*>connQueue;
};
template<class ConnPool>class MysqlConn{
public:
MysqlConn(ConnPool & obj):conn(obj){flag=conn.PopConn(pMysql)?true:false;}
~MysqlConn(){if(flag)conn.PushConn(pMysql);}
private:
bool flag;
ConnPool & conn;
public:
MYSQL * pMysql;
};
typedef MysqlConn<mysqlconnpool> LocalMysqlConn;
#endif
/*=============================================================================
# FileName: mysqlconnpool.cpp
# Desc: Functions of MysqlConnPool
# Author: Pugna
# Email: 860009944@qq.com
# HomePage: http://www.cnblogs.com/pugna/
# Version: 0.0.1
# LastChange: 2014-10-21 19:48:53
# History:
=============================================================================*/
#include <stdexcept>
#include <exception>
#include <stdio.h>
#include "mysqlconnpool.h"
#include "../common/Lock.h"
mysqlconnpool::mysqlconnpool(string url,int port,string username,string pwd,string db,string encode,int minSize,int maxSize):
url(url)
,port(port)
,maxSize(maxSize)
,minSize(minSize)
,curSize(0)
,username(username)
,password(pwd)
,db(db)
,encode(encode)
{
}
mysqlconnpool::~mysqlconnpool(){
}
bool mysqlconnpool::Init(){
LocalMutexLock lock(mutexLock);
if(minSize<=0)
return false;
for(int i=0;i<minSize;i++){
MYSQL * pMysql=CreateConn();
if(pMysql==NULL)
return false;
connQueue.push(pMysql);
curSize++;
}
if(curSize==minSize)
return true;
else
return false;
}
void mysqlconnpool::Uninit(){
LocalMutexLock lock(mutexLock);
if(!connQueue.empty()){
do{
MYSQL * pMysql=connQueue.front();
mysql_close(pMysql);
connQueue.pop();
}while(!connQueue.empty());
}
}
MYSQL * mysqlconnpool::CreateConn(){
MYSQL * pMysql=mysql_init(NULL);
if(pMysql==NULL){
return NULL;
}
char value=1;
if(0==mysql_options(pMysql,MYSQL_OPT_RECONNECT,&value)){
if(mysql_real_connect(pMysql , url.c_str(), username.c_str(), password.c_str(), db.c_str(), port, NULL, 0)){
if(0==encode.length()&&!mysql_set_character_set(pMysql,encode.c_str())){
printf("set character false\r\n");
}
else{
return pMysql;
}
}
else{
printf("connect error\r\n");
}
}
else{
printf("optione error\r\n");
}
mysql_close(pMysql);
return NULL;
}
bool mysqlconnpool::PushConn(MYSQL * &conn){
LocalMutexLock lock(mutexLock);
if(curSize>=maxSize)
{
mysql_close(conn);
conn=NULL;
return false;
}
connQueue.push(conn);
curSize++;
return true;
}
bool mysqlconnpool::PopConn(MYSQL * &conn){
{
LocalMutexLock lock(mutexLock);
if(curSize>0){
conn=connQueue.front();
connQueue.pop();
curSize--;
return true;
}
}
conn=CreateConn();
if(NULL!=conn)
return true;
else
return false;
}
void mysqlconnpool::getCurSize(int & n){
LocalMutexLock lock(mutexLock);
n=curSize;
}
/*=============================================================================
# FileName: client.cpp
# Desc: test mysqlconnpool
# Author: Pugna
# Email: 860009944@qq.com
# HomePage: http://www.cnblogs.com/pugna/
# Version: 0.0.1
# LastChange: 2014-10-21 22:13:35
# History:
=============================================================================*/
#include <stdio.h>
#include <pthread.h>
#include "../mysqlconnpool/mysqlconnpool.h"
static const string url="127.0.0.1";
static const string username="root";
static const string password="123456";
static const string dbname="test";
static const int port=3306;
static const string encodetype="";
static const int threadNum=100;
mysqlconnpool conn(url,port,username,password,dbname,encodetype,10,1000);
void * TestThread(void * LpVoid){
LocalMysqlConn connPool(conn);
if(NULL==connPool.pMysql){
printf("thread:%p,conn null\r\n");
connPool.pMysql=conn.CreateConn();
if(NULL==connPool.pMysql){
printf("thread:%p,no mysql\r\n");
pthread_exit(NULL);
}
else{
printf("thread:%p,get new mysql\r\n");
}
}
else{
printf("mysql:%p,thread:%p\r\n",connPool.pMysql,pthread_self());
if(0==mysql_query(connPool.pMysql,"update user set point=point+1 where name=\'lantun\';")){
printf("thread:%p,query ok!\r\n",pthread_self());
}
else{
printf(mysql_error(connPool.pMysql));
}
}
pthread_exit(NULL);
}
int main(){
pthread_t threadID[threadNum];
conn.Init();
int tdCreated=0;
for(int i=0;i<threadNum;i++){
if(0!=pthread_create(&threadID[i],NULL,TestThread,NULL)){
printf("create thread false\r\n");
break;
}
else
tdCreated++;
}
//wate for all threads exit.
for(int i=0;i<tdCreated;i++){
pthread_join(threadID[i],NULL);
}
int mysqlNum=0;
conn.getCurSize(mysqlNum);
printf("mysql Num:%d\r\n",mysqlNum);
conn.Uninit();
return 0;
}
#=============================================================================
# FileName: Makefile
# Desc: :
# Author: Pugna
# Email: 860009944@qq.com
# HomePage: http://www.cnblogs.com/pugna/
# Version: 0.0.1
# LastChange: 2014-10-21 17:00:26
# History:
#=============================================================================
all:
g++ -g ../mysqlconnpool/*.* *.cpp -L /usr/lib64/mysql/ -lmysqlclient_r -lpthread -o client.o
clean:
rm *.o