您的位置:首页 > 其它

自己写的一个基于ocilib的c连接池,未经测试

2011-11-25 09:11 435 查看
#include "ocilib.h"
#include "pthread.h"

#define DBFAIL -1

#define NOWAIT 1
#define WAITING	0

#define USE 0
#define NOUSE 1

typedef struct(
OCI_Connection *cn;
int	status;    //0-未用 1-使用中

TP_DBCONN_NODE *next;
)TP_DBCONN_NODE;

TP_DBCONN_NODE *g_header = NULL;
int g_cur_conn_num = 0;
int g_now_use_conn = 0;
int g_min_conn;
int g_max_conn;
int g_incr_conn;
char g_user[128] = {0};
char g_passwd[128]= {0};
char g_tns[128]= {0};
pthread_mutex_t conn_mutx;
pthread_t pool_thread;

int g_adjust_count = 0; //减少连接数的计数
int g_adjust_pecent = 80; //进行调度的比率
int g_adjust_threshold = 10; //进行调度的阈值

void oci_err_handler(OCI_Error *err)
{
printf(
"code  : ORA-%05i\n"
"msg   : %s\n"
"sql   : %s\n",
OCI_ErrorGetOCICode(err),
OCI_ErrorGetString(err),
OCI_GetSql(OCI_ErrorGetStatement(err))
);
}

int oci_db_pool_init(char *user, char *passwd, char *tns, int min_conn, int max_conn, int incr_conn)
{

TP_DBCONN_NODE *tmp_node = NULL;
TP_DBCONN_NODE *pre_tmp_node = NULL;
pthread_attr_t attr;
int i;

g_min_conn = min_conn;
g_max_conn = max_conn;
g_incr_conn = incr_conn;

strncpy(g_user, user, sizeof(g_user) - 1);
strncpy(g_passwd, passwd, sizeof(g_passwd) - 1);
strncpy(g_tns, tns, sizeof(g_tns) - 1);
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 512000);//500K

//初始化OCI
if (!OCI_Initialize(oci_err_handler, NULL, OCI_ENV_DEFAULT|OCI_ENV_THREADED|OCI_ENV_CONTEXT))
return DBFAIL;

//初始化数据库连接
for (i = 0; i < min_conn; i++)
{
pre_tmp_node = tmp_node;
tmp_node = malloc(sizeof(TP_DBCONN_NODE));
memset((void *)tmp_node, 0, sizeof(TP_DBCONN_NODE));

tmp_node->cn = OCI_ConnectionCreate(tns, user, passwd, OCI_SESSION_DEFAULT);
if (tmp_node->cn == NULL)
{
free(tmp_node);
oci_db_pool_free();
return DBFAIL;
}

if (i == 0)//头节点
g_header = tmp_node;
else//非头节点
pre_tmp_node->next = tmp_node;
//TODO

cur_conn_num++;
}
if (pthread_mutex_init(&conn_mutx, NULL) != 0)
{
oci_db_pool_free();
return DBFAIL;
}
//创建连接池守护线程
if (pthread_create(&pool_thread, &attr, (void *)db_pool_run, NULL) != 0)
printf("pthread_create error\n");
}

int oci_db_pool_free()
{
TP_DBCONN_NODE *tmp_node = g_header;
TP_DBCONN_NODE *pre_tmp_node = NULL;

while (tmp_node != NULL)
{
pre_tmp_node = tmp_node;
tmp_node = tmp_node->next;

//断开数据库连接
OCI_ConnectionFree(pre_tmp_node->cn);

//释放内存
free(pre_tmp_node);
}
cur_conn_num = 0;
g_header = NULL;
OCI_Cleanup();
pthread_mutex_destory(&conn_mutx);
}
//增加一个数据库连接
OCI_Connection *oci_db_add_conn(int type)
{
TP_DBCONN_NODE *tmp_node = NULL;
TP_DBCONN_NODE *pre_tmp_node = NULL;

//加锁
if (pthread_mutex_lock(&conn_mutx) != 0)
{
return NULL;
}
//寻找最后一个节点
tmp_node = g_header;

while (tmp_node->next != NULL)
{
tmp_node = tmp_node->next;
if (tmp_node == NULL)
break;
}
if (tmp_node != NULL)
{
pre_tmp_node = tmp_node;
tmp_node = malloc(sizeof(TP_DBCONN_NODE));
memset((void *)tmp_node, 0, sizeof(TP_DBCONN_NODE));

tmp_node->cn = OCI_ConnectionCreate(g_tns, g_user, g_passwd, OCI_SESSION_DEFAULT);
if (tmp_node->cn == NULL)
{
free(tmp_node);
tmp_node = NULL;
}else
{
if (g_header == NULL)//头节点
g_header = tmp_node;
else//非头节点
pre_tmp_node->next = tmp_node;
tmp_node->status = type;
g_cur_conn_num++;
}
}else
tmp_node = NULL;
//释放锁
if (pthread_mutex_unlock(&conn_mutx) != 0)
{
return NULL;
}
return tmp_node;
}
//减少一个数据库连接
int oci_db_del_conn()
{
TP_DBCONN_NODE *tmp_node = NULL;
TP_DBCONN_NODE *pre_tmp_node = NULL;
int ret;
//加锁
if (pthread_mutex_lock(&conn_mutx) != 0)
{
return NULL;
}
tmp_node = g_header;
//释放连接
while (tmp_node->stauts != 0)
{
pre_tmp_node = tmp_node;
tmp_node = tmp_node->next;
if (tmp_node == NULL)
break;
}
if (tmp_node != NULL)
{
//断开数据库连接
OCI_ConnectionFree(tmp_node->cn);
if (tmp_node == g_header)
{
g_header = g_header->next;
free(tmp_node);
}else
{
pre_tmp_node->next = tmp_node->next;
free(tmp_node);
}
g_cur_conn_num--;
ret = 0;

}else
ret = -1;
//释放锁
if (pthread_mutex_unlock(&conn_mutx) != 0)
{
return NULL;
}
return ret;
}
/*
0-WAITING
1-NOWAIT
*/
OCI_Connection *oci_db_get_conn(int type)
{
TP_DBCONN_NODE *tmp_node = NULL;
OCI_Connection *cn = NULL;
//获取锁
if (type == NOWAIT)
{
if (pthread_mutex_trylock(&conn_mutx) != 0)
return NULL;
}else
{
if (pthread_mutex_lock(&conn_mutx) != 0)
return NULL;
}
tmp_node = g_header;

//查找现有列表获取连接
while (tmp_node->status != 0)
{
tmp_node = tmp_node->next;
if (tmp_node == NULL)
break;
}
//在现有连接中找到
if (tmp_node != NULL)
{
cn = tmp_node->cn;
tmp_node->status = 1;
if ((oci_db_test_conn(tmp_node->cn) != TRUE) //查询失败?
{
OCI_ConnectionFree(tmp_node->cn);
tmp_node->cn = OCI_ConnectionCreate(g_tns, g_user, g_passwd, OCI_SESSION_DEFAULT);
if (tmp_node->cn == NULL)
{
tmp_node->status = 2;
}
}
g_now_use_conn++;
}else //未找到 已满?
{
//新增数据库连接
if (g_cur_conn_num < g_max_conn)
{
cn = oci_db_add_conn(USE);
}
}

//释放锁
if (pthread_mutex_unlock(&conn_mutx) != 0)
{
return NULL;
}
return cn;
}

//释放一个连接
int oci_db_free_conn(OCI_Connection *cn)
{
TP_DBCONN_NODE *tmp_node = NULL;

//加锁
if (pthread_mutex_lock(&conn_mutx) != 0)
{
return NULL;
}
tmp_node = g_header;
//释放连接
while (cn != tmp_node->cn)
{
tmp_node = tmp_node->next;
if (tmp_node == NULL)
break;
}
tmp_node->status = 0;
g_now_use_conn--;
//释放锁
if (pthread_mutex_unlock(&conn_mutx) != 0)
{
return NULL;
}

}
//检测连接
int oci_db_test_conn(OCI_Connection *cn)
{
OCI_Statement *st;
int ret;
st = OCI_StatementCreate(cn);
ret = OCI_ExecuteStmt(st, "select 1 from dual;");
OCI_StatementFree(st);
return ret;
}

//检测活跃状态
int oci_db_active_test()
{
TP_DBCONN_NODE *tmp_node = NULL;

while (tmp_node != NULL)
{
if (tmp_node->status != 1)
{
if ((oci_db_test_conn(tmp_node->cn) != TRUE) //查询失败?
{
OCI_ConnectionFree(tmp_node->cn);
tmp_node->cn = OCI_ConnectionCreate(g_tns, g_user, g_passwd, OCI_SESSION_DEFAULT);
if (tmp_node->cn == NULL)
{
tmp_node->status = 2;
}
}
}
tmp_node = tmp_node->next;
}

}

static void db_pool_run(void * args)
{
while(1)
{
sleep(10);
oci_db_active_test();
if ((g_now_use_conn *100 / g_cur_conn_num) < g_adjust_pecent)
g_adjust_count++;
else
g_adjust_count = 0;

if (g_adjust_count > g_adjust_threshold)
{
oci_db_del_conn();
g_adjust_count = 0;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: