OCI连接池

4 篇文章 0 订阅
#ifndef __OCI__LIB__POLL__
#define __OCI__LIB__POLL__

#include "ocilib.h"
#include <iostream>
#include <string>
#include <pthread.h>

using namespace std;

class OraConnPool
{
protected:

	OraConnPool();
	
public:
	int createConnPool(const char* username, 
	const char* passwd, 
	const char* connectString, 
	int maxCon, 
	int minCon, 
	int incrCon);
	
	void destroyConnPool();
	
	string getErrData(void);
	
	OCI_Connection * getConnection();
	
	void freeConnection(OCI_Connection*);
	
	static OraConnPool* getInstance();
	
	string get_last_error();

	int get_error_code();
	
private:
	static void* check_con_thread(void* );
	bool check_con();
	
	static OraConnPool* _instance_;
	OCI_ConnPool *oci_pool;
	bool m_init_flag;
	bool m_con_pool_restart;

	string sErrInfo;
	int error_code;

	string m_username;
	string m_passwd;
	string m_connectString;
	int m_maxcon;
	int m_mincon;
	int m_incr;
};


#endif
 
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <sstream>
using namespace std;

#include "oraconnpool_poll.h"

#define USING_SINGLE_CONNECTION
#undef  USING_SINGLE_CONNECTION

#define USING_TEMP_LOG

static string get_current_time()
{
	struct tm *t;
	time_t ts;
	time(&ts);
	t = localtime(&ts);
	char buffer[30] = {0};
	sprintf(buffer,"[%.4d-%.2d-%.2d %.2d:%.2d:%.2d]",t->tm_year + 1900,
	t->tm_mon + 1,
	t->tm_mday,
	t->tm_hour,
	t->tm_min,
	t->tm_sec);
	return string(buffer);
}

static void temp_log(string  content )
{
#ifdef USING_TEMP_LOG
	string time_str = get_current_time();
	string file_name = "/usr/local/ptest/ngx_oci_state_log";
	ofstream fobj(file_name.c_str(), ios::app);
	if(fobj.is_open())
	{
		fobj<<time_str <<" "<<content<<endl;
		fobj.close();
	}
#endif
}


/******************************************************************************************************/

OraConnPool* OraConnPool::_instance_ = NULL;
	
OraConnPool::OraConnPool():oci_pool(NULL),m_init_flag(false),m_con_pool_restart(false)
{
	
}

OraConnPool* OraConnPool::getInstance()
{
	if (_instance_ == 0)
	{
		_instance_ = new OraConnPool;
	}
	
	return _instance_;
}


int OraConnPool::createConnPool(const char* username, const char* passwd, const char* connectString, int maxCon, int minCon, int incrCon)
{
#ifndef USING_SINGLE_CONNECTION

	temp_log("start create connection pool.................");
	if(minCon < 0x00 || maxCon < 0x00 || (minCon > maxCon))
	{
		char buffer[500] = {0};
		sprintf(buffer,"param set error , with minCon=%d, maxCon = %d, incrCon = %d",	minCon,maxCon,incrCon);
		sErrInfo = string(buffer);
		return 0x00;
	}
	
	if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT | OCI_ENV_CONTEXT | OCI_ENV_THREADED))
	{
		sErrInfo="Error unexpectd when initlize the OCI environment ! Create DB connection pool FAIL";
		return 0x00;
	}

	if(false == m_init_flag)
		oci_pool = OCI_PoolCreate(connectString, username, passwd, OCI_POOL_CONNECTION, OCI_SESSION_DEFAULT, minCon, maxCon, incrCon);
	else
		oci_pool = OCI_PoolCreate(m_connectString.c_str(), m_username.c_str(), m_passwd.c_str(), OCI_POOL_CONNECTION, OCI_SESSION_DEFAULT, m_mincon, m_maxcon, m_incr);

	if(oci_pool == NULL)
	{
		char buffer[500] = {0};
		sprintf(buffer,"Error in creating DB connect Pool.Pool is NULL with parameters sid=%s,user=%s,pwd=%s.",	connectString,username,passwd);
		sErrInfo = string(buffer);
		return 0x00;
	}

	if(!m_init_flag)
	{
		m_username = string(username);
		m_passwd   = string(passwd);
		m_connectString = string(connectString);
		m_maxcon = maxCon;
		m_mincon = minCon;
		m_incr = incrCon;

		m_init_flag = true;

		pthread_t thread_id;
	  pthread_create( &thread_id, NULL, check_con_thread, (void*)this);
		pthread_detach(thread_id);
	}
	temp_log("start create connection pool ok@@.................");
	
#else
	
	if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT | OCI_ENV_CONTEXT | OCI_ENV_THREADED))
	{
		sErrInfo="Error unexpectd when initlize the OCI environment ! Create DB connection pool FAIL";
		return 0x00;
	}

	if(!m_init_flag)
	{
		m_username = string(username);
		m_passwd   = string(passwd);
		m_connectString = string(connectString);
		m_maxcon = maxCon;
		m_mincon = minCon;
		m_incr = incrCon;

		m_init_flag = true;

		pthread_t thread_id;
	    pthread_create( &thread_id, NULL, check_con_thread, (void*)this);
		pthread_detach(thread_id);
	}
	
#endif
	return 0x01;
}

void OraConnPool::destroyConnPool()
{
#ifndef USING_SINGLE_CONNECTION
	if(oci_pool)
		OCI_PoolFree(oci_pool);
		
	oci_pool = NULL;
    OCI_Cleanup();
#else
	OCI_Cleanup();
#endif
}

	
OCI_Connection* OraConnPool::getConnection()
{
#ifndef USING_SINGLE_CONNECTION

	if(m_con_pool_restart)
	{
		sErrInfo = "connection pool rebuild ...";
		return NULL;
	}

	if( !oci_pool )
	{
		sErrInfo = "oci_pool is NULL ...";
		return NULL;
	}

	OCI_Connection* pConn = NULL;
	pConn = OCI_PoolGetConnection(oci_pool,NULL);
	return pConn;
#else
	if(m_con_pool_restart)
	{
		sErrInfo = "connection pool rebuild ...";
		return NULL;
	}
	OCI_Connection* pConn = NULL;
	pConn = OCI_ConnectionCreate( m_connectString.c_str(), m_username.c_str(), m_passwd.c_str(), OCI_SESSION_DEFAULT);
	return pConn;
#endif

	return NULL;
}

bool OraConnPool::check_con()
{
#ifndef USING_SINGLE_CONNECTION
	if( !oci_pool )
	{
		sErrInfo = "oci_pool is NULL ...";
		return false;
	}
	
	OCI_Connection* pConn = NULL;
		
	pConn = OCI_PoolGetConnection(oci_pool,NULL);

	if(pConn == NULL)
		return false;

	if(OCI_Ping(pConn))
	{
		freeConnection(pConn);
		return true;
	}

	freeConnection(pConn);
	return false;
#else
	OCI_Connection* pConn = NULL;
	pConn = getConnection();
	if(pConn == NULL)
		return false;

	if(OCI_Ping(pConn))
	{
		freeConnection(pConn);
		return true;
	}

	freeConnection(pConn);
	return false;
#endif
}

void OraConnPool::freeConnection(OCI_Connection* pConn)
{
#ifndef USING_SINGLE_CONNECTION
	if(pConn != NULL)
		OCI_ConnectionFree(pConn);
#else
	if(pConn != NULL)
		OCI_ConnectionFree(pConn);
#endif
}

string OraConnPool::getErrData(void)
{
	char buffer[512] = {0x00};
	OCI_Error *err = OCI_GetLastError();
	sprintf(buffer, "oci: errorcode: %d, errmsg: %s",OCI_ErrorGetOCICode(err), OCI_ErrorGetString(err));
	return string(buffer);
	return sErrInfo;
}

string OraConnPool::get_last_error()
{
	char buffer[512] = {0x00};
	OCI_Error *err = OCI_GetLastError();
	sprintf(buffer, "oci: errorcode: %d, errmsg: %s",OCI_ErrorGetOCICode(err), OCI_ErrorGetString(err));
	return string(buffer);
}

int OraConnPool::get_error_code()
{
	OCI_Error *err = OCI_GetLastError();
	return int(OCI_ErrorGetOCICode(err));
}

//检测连接的线程函数
void* OraConnPool::check_con_thread(void* param)
{
	OraConnPool* pObj = (OraConnPool*)param;
	if(!pObj)
		return NULL;
		
	int count = 0x00;
	bool is_start = true;

	while(1)
	{
		if(is_start)
		{
			sleep(10);
			is_start = false;
		}
		
		if((count % 10) == 0x00)
		{
			temp_log("check connection thread is running......");
			if(count >= 1000)
				count = 0x00;
		}
		count++;
		
		bool is_ok = false;
		bool flag  = pObj->check_con();
		string con_str = pObj->get_last_error();

		//检测失败则重新建立连接池
		if(!flag)
		{
			temp_log("check connection failed......");
			if(!con_str.empty())
			{
				temp_log(con_str);
			}

			pObj->m_con_pool_restart = true;
			pObj->destroyConnPool();
			int ret = pObj->createConnPool(NULL,NULL,NULL,0x00,0x00,0x00);
			if(0x00 == ret)
			{
				ostringstream os;
				os<<" create conpool failed....."<<__FILE__<<":"<<__LINE__<<endl;
				temp_log(os.str());
			}
			else
				is_ok = true;
		}
		else if( (count % 20) == 0x00)
			temp_log("check connection ok......");
			
		if(!is_ok && !flag)
		{
			sleep(2);
			continue;
		}
		
		pObj->m_con_pool_restart = false;
		sleep(10);
	}

	return NULL;
}



这连接池后边有个探测和数据库连接的状态功能,如果要是检测到连接失败,会销毁连接池,再次创建。

不过这样也会存在一些未知的问题,不知道哪位仁兄可以帮忙改进,或给出更好的方法。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值