170 lines
4.1 KiB
C++
170 lines
4.1 KiB
C++
#include "CConnectPool.h"
|
|
#include <iostream>
|
|
|
|
#define POOL_SAFE_DELETE(ptr) \
|
|
if (ptr != NULL) \
|
|
{ \
|
|
delete ptr; \
|
|
ptr = NULL; \
|
|
}
|
|
|
|
CConnectPool *CConnectPool::s_pInstance = NULL;
|
|
|
|
CConnectPool::CConnectPool()
|
|
{
|
|
pthread_mutex_init(&m_mutex, NULL);
|
|
pthread_cond_init(&m_cond, NULL);
|
|
// 初始化连接数
|
|
// 此处由主线程调用初始化,无需考虑锁问题
|
|
for (int i = 0; i < My_Info.MaxConnectCount; ++i)
|
|
{
|
|
MYSQL *pConn = _CreateConnect();
|
|
if (NULL == pConn)
|
|
{
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
m_queueFree.push(pConn);
|
|
}
|
|
}
|
|
|
|
CConnectPool::~CConnectPool()
|
|
{
|
|
pthread_mutex_destroy(&m_mutex);
|
|
pthread_cond_destroy(&m_cond);
|
|
MYSQL *pConn = NULL;
|
|
while (m_queueFree.size() > 0)
|
|
{
|
|
pConn = m_queueFree.front();
|
|
POOL_SAFE_DELETE(pConn);
|
|
m_queueFree.pop();
|
|
}
|
|
std::set<MYSQL *>::iterator it = m_setBusy.begin();
|
|
while (it != m_setBusy.end())
|
|
{
|
|
pConn = *it;
|
|
POOL_SAFE_DELETE(pConn);
|
|
// it = m_setBusy.erase(it);
|
|
it++;
|
|
}
|
|
}
|
|
|
|
void CConnectPool::CreatePool(int MinConnectCount, int MaxConnectCount, const char *Host, int Port, const char *Account, const char *Passwd)
|
|
{
|
|
if (NULL == s_pInstance)
|
|
{
|
|
s_pInstance = new CConnectPool;
|
|
s_pInstance->My_Info.MinConnectCount = MinConnectCount;
|
|
s_pInstance->My_Info.MaxConnectCount = MaxConnectCount;
|
|
s_pInstance->My_Info.Host = Host;
|
|
s_pInstance->My_Info.Port = Port;
|
|
s_pInstance->My_Info.Account = Account;
|
|
s_pInstance->My_Info.Passwd = Passwd;
|
|
s_pInstance->My_Info.KName = "taiwan_cain";
|
|
}
|
|
}
|
|
|
|
void CConnectPool::FreePool()
|
|
{
|
|
if (NULL != s_pInstance)
|
|
{
|
|
delete s_pInstance;
|
|
s_pInstance = NULL;
|
|
}
|
|
}
|
|
|
|
MYSQL *CConnectPool::GetConnect()
|
|
{
|
|
return s_pInstance->_GetConnect(false);
|
|
}
|
|
|
|
MYSQL *CConnectPool::TryGetConnect()
|
|
{
|
|
return s_pInstance->_GetConnect(true);
|
|
}
|
|
|
|
void CConnectPool::PutConnect(MYSQL *pConn)
|
|
{
|
|
s_pInstance->_PutConnect(pConn);
|
|
}
|
|
|
|
MYSQL *CConnectPool::_CreateConnect()
|
|
{
|
|
MYSQL *pConn = new MYSQL;
|
|
mysql_init(pConn);
|
|
if (!mysql_real_connect(pConn, My_Info.Host, My_Info.Account, My_Info.Passwd, My_Info.KName, MYSQL_PORT, NULL, CLIENT_FOUND_ROWS))
|
|
{
|
|
printf("connect error:%s\n", mysql_error(pConn));
|
|
delete pConn;
|
|
pConn = NULL;
|
|
}
|
|
return pConn;
|
|
}
|
|
|
|
MYSQL *CConnectPool::_GetConnect(bool bTry)
|
|
{
|
|
static bool bCheck;
|
|
MYSQL *pRet = NULL;
|
|
pthread_mutex_lock(&m_mutex);
|
|
// 取出来还要检查一下是否能正常使用
|
|
bCheck = true;
|
|
if (m_queueFree.size() > 0)
|
|
{
|
|
pRet = m_queueFree.front();
|
|
m_queueFree.pop();
|
|
}
|
|
else
|
|
{
|
|
// 连接数不足,继续创建
|
|
if (m_queueFree.size() + m_setBusy.size() < My_Info.MinConnectCount)
|
|
{
|
|
pRet = _CreateConnect();
|
|
bCheck = false;
|
|
}
|
|
else
|
|
{
|
|
if (!bTry)
|
|
{
|
|
// 阻塞等待空闲连接
|
|
pthread_cond_wait(&m_cond, &m_mutex);
|
|
// 肯定会有空闲连接的
|
|
if (m_queueFree.size() > 0)
|
|
{
|
|
pRet = m_queueFree.front();
|
|
m_queueFree.pop();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// 检查连接是否可用
|
|
if (NULL != pRet && true == bCheck && 0 != mysql_ping(pRet))
|
|
{
|
|
mysql_close(pRet);
|
|
pRet = _CreateConnect();
|
|
}
|
|
// 加入busy队列
|
|
if (NULL != pRet)
|
|
{
|
|
m_setBusy.insert(pRet);
|
|
}
|
|
pthread_mutex_unlock(&m_mutex);
|
|
return pRet;
|
|
}
|
|
|
|
void CConnectPool::_PutConnect(MYSQL *pConn)
|
|
{
|
|
if (NULL == pConn)
|
|
return;
|
|
pthread_mutex_lock(&m_mutex);
|
|
std::set<MYSQL *>::iterator it = m_setBusy.find(pConn);
|
|
if (it != m_setBusy.end())
|
|
{
|
|
m_setBusy.erase(it);
|
|
}
|
|
m_queueFree.push(pConn);
|
|
if (1 == m_queueFree.size())
|
|
{
|
|
// 唤醒等待线程
|
|
pthread_cond_signal(&m_cond);
|
|
}
|
|
pthread_mutex_unlock(&m_mutex);
|
|
} |