c语言自己实现线程池功能

上一次讲了使用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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <mysql/mysql.h>
#include <pthread.h>
#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]# 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值