上一次讲了使用libzdb数据连接池的用法,如果不想用库,想自己实现,也可以。就不需要加库了。
直接上代码
sqlpool.h
#ifndef __SQLPOOL_H_
#define __SQLPOOL_H_
#define IP_LEN 15
#define DBNAME_LEN 64
#define DBUSER_LEN 64
#define PASSWD_LEN 64
#define POOL_MAX_NUMBER 20
typedef struct _SQL_NODE SQL_NODE; /*连接节点*/
typedef struct _SQL_CONN_POOL SQL_CONN_POOL; /*连接池*/
/*连接节点*/
typedef struct _SQL_NODE{
MYSQL fd; /* mysql对象文件描述符 */
MYSQL *mysql_sock; /* 指向已经连接的MYSQL的指针 */
pthread_mutex_t lock; /* 互斥锁*/
int used; /* 使用标志 */
int index; /* 下标 */
enum{
DB_DISCONN, DB_CONN
}sql_state;
}SQL_NODE;
/*连接池*/
typedef struct _SQL_CONN_POOL{
int shutdown; /*是否关闭*/
SQL_NODE sql_pool[POOL_MAX_NUMBER]; /* 一堆连接 */
int pool_number; /* 连接数量 */
int busy_number; /*被获取了的连接数量*/
char ip[IP_LEN+1]; /* 数据库的ip */
int port; /* 数据库的port,一般是3306 */
char db_name[DBNAME_LEN+1]; /* 数据库的名字 */
char user[DBUSER_LEN+1]; /* 用户名 */
char passwd[PASSWD_LEN+1]; /* 密码 */
}SQL_CONN_POOL;
/*创建连接池*/
SQL_CONN_POOL *sql_pool_create(int connect_pool_number, char ip[], int port,
char db_name[], char user[], char passwd[]);
/*节点创建连接*/
int create_db_connect(SQL_CONN_POOL *sp, SQL_NODE *node);
/*销毁连接池*/
void sql_pool_destroy(SQL_CONN_POOL *sp);
/*取出一个未使用的连接*/
SQL_NODE *get_db_connect(SQL_CONN_POOL *sp);
/*归回连接*/
void release_node(SQL_CONN_POOL *sp, SQL_NODE *node);
/*增加或删除连接*/
SQL_CONN_POOL *changeNodeNum(SQL_CONN_POOL *sp, int op);
#endif
sqlpool.c
#include
#include
#include
#include
#include
#include
#include "sqlpool.h"
//sql_pool_create(POOL_MAX_NUMBER, "localhost", 3306, "ceshi", "root", "qc123456");
/*创建连接池*/
SQL_CONN_POOL *sql_pool_create(int connect_pool_number, char ip[], int port,
char db_name[], char user[], char passwd[])
{
SQL_CONN_POOL *sp = NULL;
if (connect_pool_number < 1)
{
printf("connect_pool_number < 1. defalut 1 \n");
connect_pool_number = 1;
}
if ((sp=(SQL_CONN_POOL *)malloc(sizeof(SQL_CONN_POOL))) == NULL)
{
printf("malloc SQL_CONN_POOL error.\n");
return NULL;
}
sp->shutdown = 0; //开启连接池
sp->pool_number = 0;
sp->busy_number = 0;
strcpy(sp->ip, ip);
sp->port = port;
strcpy(sp->db_name, db_name);
strcpy(sp->user, user);
strcpy(sp->passwd, passwd);
/*创建连接*/
if (connect_pool_number > POOL_MAX_NUMBER)
connect_pool_number = POOL_MAX_NUMBER;
int index =0;
for (index=0; index < connect_pool_number; index++)
{
//创建失败
if (0 != create_db_connect(sp, &sp->sql_pool[index]))
{
//销毁连接池
sql_pool_destroy(sp);
return NULL;
}
//创建成功
sp->sql_pool[index].index = index;
sp->pool_number++;
printf("create database pool connect:-%d-.\n",sp->sql_pool[index].index);
}
return sp;
}
/*节点创建连接*/
int create_db_connect(SQL_CONN_POOL *sp, SQL_NODE *node)
{
int opt=1;
int res=0; //0正常 -1初始化失败 1 连接失败
do
{
if (sp->shutdown == 1)
return -1;
/*加锁*/
pthread_mutex_init(&node->lock, NULL);
/*初始化mysql对象*/
if (NULL == mysql_init(&node->fd))
{
printf("mysql init error. \n");
res = -1;
break;
}
if (!(node->mysql_sock = mysql_real_connect(
&node->fd, sp->ip, sp->user, sp->passwd, sp->db_name, sp->port, NULL, 0)))
{
printf("can not connect to mysql.\n");
node->sql_state = DB_DISCONN;
res = 1;
break;
}
node->used = 0;
node->sql_state = DB_CONN;
//设置自动连接开启
mysql_options(&node->fd, MYSQL_OPT_RECONNECT, &opt);
opt = 3;
//设置连接超时时间为3s,3s未连接成功则超时
mysql_options(&node->fd, MYSQL_OPT_CONNECT_TIMEOUT, &opt);
res = 0;
}while(0);
return res;
}
/*销毁连接池*/
void sql_pool_destroy(SQL_CONN_POOL *sp)
{
printf("destroy sql pool ... ... \n");
sp->shutdown = 1; //关闭连接池
int index = 0;
for (index=0; index < sp->pool_number; index++)
{
if (NULL != sp->sql_pool[index].mysql_sock)
{
mysql_close(sp->sql_pool[index].mysql_sock);
sp->sql_pool[index].mysql_sock = NULL;
}
sp->sql_pool[index].sql_state = DB_DISCONN;
sp->pool_number--;
}
}
/*取出一个未使用的连接*/
SQL_NODE *get_db_connect(SQL_CONN_POOL *sp)
{
//获取一个未使用的连接,用随机值访问index,保证每次访问每个节点的概率基本相同
int start_index = 0, index = 0, i;
int ping_res;
if (sp->shutdown == 1)
return NULL;
srand((int)time(0)); //根据当前时间生成随机数
start_index = rand() % sp->pool_number; //访问的开始地址
for (i=0; i < sp->pool_number; i++)
{
index = (start_index + i) % sp->pool_number;
if (!pthread_mutex_trylock(&sp->sql_pool[index].lock))
{
if (DB_DISCONN == sp->sql_pool[index].sql_state)
{
//重新连接
if (0 != create_db_connect(sp, &(sp->sql_pool[index])))
{
//重新连接失败
release_node(sp, &(sp->sql_pool[index]));
continue;
}
}
//检查服务器是否关闭了连接
ping_res = mysql_ping(sp->sql_pool[index].mysql_sock);
if (0 != ping_res)
{
printf("mysql ping error.\n");
sp->sql_pool[index].sql_state = DB_DISCONN;
release_node(sp, &(sp->sql_pool[index]));
}
else
{
sp->sql_pool[index].used = 1;
sp->busy_number++;//被获取的数量增1
break ; //只需要一个节点
}
}
}
if (i == sp->pool_number)
{
return NULL;
}
else
{
return &(sp->sql_pool[index]);
}
}
/*归回连接*/
void release_node(SQL_CONN_POOL *sp, SQL_NODE *node)
{
node->used = 0;
sp->busy_number--;
pthread_mutex_unlock(&node->lock);
}
/*增加或删除连接*/
SQL_CONN_POOL *changeNodeNum(SQL_CONN_POOL *sp, int op) //增加或减少5个连接
{
int Num = 5;
int index;
int endindex;
if (op == 1) //增加 0减少
{
endindex = sp->pool_number + Num;
/*创建连接*/
for (index=sp->pool_number; index < endindex; index++)
{
//创建失败
if (0 != create_db_connect(sp, &sp->sql_pool[index]))
{
//销毁连接池
sql_pool_destroy(sp);
return NULL;
}
//创建成功
sp->sql_pool[index].index = index; sp->pool_number++;
printf("create database pool connect:-%d-.\n",sp->sql_pool[index].index);
}
}
else if (op == 0)
{
endindex = sp->pool_number - Num -1;
//减少连接
for (index=sp->pool_number-1; index>endindex && index>=0; index--)
{
if (NULL != sp->sql_pool[index].mysql_sock)
{
mysql_close(sp->sql_pool[index].mysql_sock);
sp->sql_pool[index].mysql_sock = NULL;
}
sp->sql_pool[index].sql_state = DB_DISCONN;
sp->pool_number--;
printf("delete database pool connect:-%d-.\n",sp->sql_pool[index].index);
}
}
return sp;
}
int main()
{
//MYSQL_FIELD *fd;
SQL_CONN_POOL *sp =
sql_pool_create(10, "localhost", 3306, "edu", "root", "Internet@2014");
SQL_NODE *node = get_db_connect(sp);
SQL_NODE *node2 = get_db_connect(sp);
if (NULL == node)
{
printf("get sql pool node error.\n");
return -1;
}
printf("--%d-- \n", node->index);
printf("busy--%d--\n", sp->busy_number);
if (mysql_query(&(node->fd), "select * from hy_admin"))
{
printf("query error.\n");
return -1;
}
else
{
printf("succeed!\n");
}
changeNodeNum(sp, 0);//减少
changeNodeNum(sp, 1);//增加
sql_pool_destroy(sp);
return 0;
}
[root@VM_0_13_centos db]# ls
db-app makefile sqlpool.c sqlpool.h
[root@VM_0_13_centos db]# ./db-app
create database pool connect:-0-.
create database pool connect:-1-.
create database pool connect:-2-.
create database pool connect:-3-.
create database pool connect:-4-.
create database pool connect:-5-.
create database pool connect:-6-.
create database pool connect:-7-.
create database pool connect:-8-.
create database pool connect:-9-.
--9--
busy--2--
succeed!
delete database pool connect:-9-.
delete database pool connect:-8-.
delete database pool connect:-7-.
delete database pool connect:-6-.
delete database pool connect:-5-.
create database pool connect:-5-.
create database pool connect:-6-.
create database pool connect:-7-.
create database pool connect:-8-.
create database pool connect:-9-.
destroy sql pool ... ...
[root@VM_0_13_centos db]#