数据库连接池实现

介绍

  • 简单实现数据库连接池,对连接的管理采用双向链表。

代码

  • 管理已连接的连接用到双向链表
  • 目录结构
    01

double_llist.h

#ifndef DOUBLE_LLIST__
#define DOUBLE_LLIST__

typedef void d_llist_node_t;
typedef void d_llist_t;

int llist_init(d_llist_t **llist);

typedef int (*compare)(void *a, void *b);
int llist_insert(d_llist_t *llist, void *key, compare cmp);

d_llist_node_t *llist_pop_first(d_llist_t *llist);
d_llist_node_t *llist_pop_last(d_llist_t *llist);

d_llist_node_t *llist_head_look(d_llist_t *llist);
d_llist_node_t *llist_tail_look(d_llist_t *llist);

int llist_destroy(d_llist_t *llist);

typedef int (*traver)(void *node);
int llist_traver(d_llist_t *llist, traver tvr);

// typedef int (*compare)(void *a, void *b);
int llist_check(d_llist_t *llist, compare cmp);

// new
d_llist_node_t *llist_find_node(d_llist_t *llist, void *key, compare cmp);

int llist_delete_node(d_llist_t *llist, void *key, compare cmp);

#endif

double_llist.c

#include <stdio.h>
#include <stdlib.h>

#include "./double_llist.h"


typedef struct llist_node_s{

    void *key;
    struct llist_node_s *prev;
    struct llist_node_s *next;

}llist_node_t;

typedef struct llist_s{

    llist_node_t *head;
    llist_node_t *tail;

}llist_t;




int llist_init(void **llist){

    llist_t *me = NULL;

    me = (llist_t*)malloc(sizeof(*me));
    if(me == NULL){
        return -1;
    }

    me->head = NULL;
    me->tail = NULL;

    *llist = me;

    return 0;
}

/*
    typedef int (*compare)(void *a, void *b);
    compare return value:
        1 : a > b
        -1 : a < b
        0 : a == b
*/
int llist_insert(d_llist_t *llist, void *key, compare cmp){

    llist_t *me = llist;
    llist_node_t *cur = me->head;
    llist_node_t *node_ = NULL;

    node_ = (llist_node_t*)malloc(sizeof(*node_));
    if(node_ == NULL){
        return -1;
    }
    node_->next = NULL;
    node_->prev = NULL;
    node_->key = key;

    int res = 0;

    while(cur != NULL){

        res = cmp(key, cur->key);
        if(res > 0){
            cur = cur->next;
        }else{  // res < 0 || res == 0
            break;
        }

    }


    if(cur == NULL){
        // insert on tail
        // or head = tail = NULL, llist is null
        node_->prev = me->tail;
        node_->next = NULL;
        if(me->tail != NULL){
            me->tail->next = node_;
            me->tail = node_;
        }else{
            me->tail = node_;
        }
        if(me->head == NULL){
            me->head = node_;
        }

    }else if(cur == me->head){
        // insert on head
        node_->next = me->head;
        node_->prev = NULL;
        me->head->prev = node_;
        me->head = node_;

    }else{

        node_->next = cur;
        node_->prev = cur->prev;
        cur->prev->next = node_;
        cur->prev = node_;

    }

    return 0;
}

void *llist_pop_first(void *llist){

    llist_t *me = llist;
    llist_node_t *cur = me->head;

    if(cur == NULL){

        return NULL;

    }else if(cur->next == NULL){

        me->head = NULL;
        me->tail = NULL;

    }else{

        me->head = cur->next;
        me->head->prev = NULL;

    }

    void *ret = cur->key;

    free(cur);

    return ret;
}

void *llist_pop_last(void *llist){

    llist_t *me = llist;
    llist_node_t *cur = me->tail;

    if(cur == NULL){
        return NULL;
    }else if(cur->prev == NULL){
        me->head = NULL;
        me->tail = NULL;
    }else{
        me->tail = cur->prev;
        me->tail->next = NULL;
    }


    void *ret = cur->key;

    free(cur);

    return ret;
}

int llist_destroy(void *llist){

    llist_t *me = llist;
    llist_node_t *cur = me->head, *temp = NULL;

    while(cur != NULL){

        temp = cur->next;

        free(cur->key);
        free(cur);

        cur = temp;

    }

    free(me);

    llist = NULL;

    return 0;
}

/*
typedef int (*traver)(void *node);
*/
int llist_traver(void *llist, traver tvr){

    llist_t *me = llist;
    llist_node_t *cur = me->head;

    while(cur != NULL){

        tvr(cur->key);

        cur = cur->next;
        if(cur){
            printf(" -> ");
        }
    }
    printf("\n");

    return 0;
}


int llist_check(void *llist, compare cmp){

    llist_t *me = llist;
    llist_node_t *cur = me->head;

    if(cur != NULL && cur->next != NULL){
        cur = cur->next;
    }else{
        return 0;
    }

    while(cur != NULL){

        if(cmp(cur->key, cur->prev->key) < 0){
            return -1;
        }
        cur = cur->next;

    }

    return 0;
}




d_llist_node_t *llist_head_look(d_llist_t *llist){

    llist_t *me = llist;

    if(me->head == NULL){
        return NULL;
    }

    return me->head->key;
}
d_llist_node_t *llist_tail_look(d_llist_t *llist){

    llist_t *me = llist;

    if(me->tail == NULL){
        return NULL;
    }

    return me->tail->key;
}


// new
d_llist_node_t *llist_find_node(d_llist_t *llist, void *key, compare cmp){

    llist_t *me = llist;
    llist_node_t *cur = me->head;
    int res = 0;

    

    while(1){
        if (cur == NULL){
            return NULL;
        }

        res = cmp(key, cur->key);
        if(res == 0){
            return cur;
        }

        cur = cur->next;
    }


    return NULL;
}

int llist_delete_node(d_llist_t *llist, void *key, compare cmp){

    llist_t *me = llist;
    llist_node_t *cur = llist_find_node(llist, key, cmp);

    if(cur == NULL){
        return -1;
    }

    if(cur->prev == NULL && cur->next == NULL){

        me->head = NULL;
        me->tail = NULL;
        
    }else if(cur->prev == NULL){
        me->head = cur->next;
        me->head->prev = NULL;
    }else if(cur->next == NULL){
        me->tail = cur->prev;
        me->tail->next = NULL;
    }else{
        cur->next->prev = cur->prev;
        cur->prev->next = cur->next;
    }

#if 1
    free(cur->key);
    free(cur);
#endif

    return 0;
}

connect_pool.h

#ifndef _CONNECT_POOL_H__
#define _CONNECT_POOL_H__

#include "pthread.h"
#include <mysql/mysql.h>

#include "../double_llist/double_llist.h"

typedef struct connect_pool_st{

    d_llist_t *connect;

    int connect_idel;
    int connect_total;

    pthread_mutex_t mutex;

    char *host;
    char *username;
    char *passwd;
    char *database;
    short port;

}connect_pool_t;

typedef struct sql_msg_st{

    MYSQL *mysql; 
    MYSQL_ROW row;
    MYSQL_RES *res;

}sql_msg_t;

int connect_pool_init(connect_pool_t **pool, int conn_num, const char *host,
                      const char *username, const char *passwd, const char *database,
                      short port);


sql_msg_t *get_a_connection(connect_pool_t *pool);

int return_a_connection(connect_pool_t *pool, sql_msg_t *will);

int connect_pool_destroy(connect_pool_t *pool);

#endif

connect_pool.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <pthread.h>

#include "./connect_pool.h"

static int my_compare(void *a, void *b){
    return 1;
}

static int connect_init_(connect_pool_t *pool){

    connect_pool_t *me = pool;
    int i = 0;

    for(i = 0; i < me->connect_total; i++){
        
        sql_msg_t *cur = (sql_msg_t*)malloc(sizeof(*cur));

        cur->mysql = mysql_init(NULL);

        if(mysql_real_connect(cur->mysql, me->host, me->username, me->passwd, me->database, me->port, NULL, 0) == 0){
            puts(me->host);
            puts(me->username);
            puts(me->passwd);
            puts(me->database);
            printf("port = %d\n", me->port);
            printf("connect error.\n");
            perror("connect()");
            return -1;
        }else{
            printf("[%d] connect success.\n", i + 1);
        }

        cur->res = NULL;
        cur->row = NULL;

        llist_insert(pool->connect, cur, my_compare);

    }
    
    return 0;
}

int connect_pool_init(connect_pool_t **pool, int conn_num, const char *host,
                      const char *username, const char *passwd, const char *database,
                      short port){
    
    connect_pool_t *me = (connect_pool_t*)malloc(sizeof(*me));
    if(me == NULL){
        return -1;
    }

    llist_init(&me->connect);

    me->connect_total = conn_num;
    me->host = (void*)malloc(strlen(host));
    strcpy(me->host, host);
    me->username = (void*)malloc(strlen(username));
    strcpy(me->username, username);
    me->passwd = (void*)malloc(strlen(passwd));
    strcpy(me->passwd, passwd);
    me->database = (void*)malloc(strlen(database));
    strcpy(me->database, database);
    me->port = port;

    pthread_mutex_t mutex_unused = PTHREAD_MUTEX_INITIALIZER;
    memcpy(&me->mutex, &mutex_unused, sizeof(mutex_unused));

    connect_init_(me);

    *pool = me;

    return 0;
}


sql_msg_t *get_a_connection(connect_pool_t *pool){

    connect_pool_t *me = pool;

    pthread_mutex_lock(&me->mutex);
    sql_msg_t *ret = llist_pop_first(me->connect);
    pthread_mutex_unlock(&me->mutex);

    return ret;
}


int return_a_connection(connect_pool_t *pool, sql_msg_t *will){

    connect_pool_t *me = pool;

    pthread_mutex_lock(&me->mutex);
    int ret = llist_insert(me->connect, will, my_compare);
    pthread_mutex_unlock(&me->mutex);

    return ret;
}



int connect_pool_destroy(connect_pool_t *pool){

    connect_pool_t *me = pool;

    free(me->host);
    free(me->username);
    free(me->passwd);
    free(me->database);

    sql_msg_t *cur = NULL;

    while(1){

        pthread_mutex_lock(&me->mutex);
        cur = llist_pop_first(me->connect);
        pthread_mutex_unlock(&me->mutex);
        if(cur == NULL){
            break;
        }

        mysql_close(cur->mysql);
        printf("A connection is closed.\n");
        free(cur);

    }

    free(me);
    
    pool = NULL;

    return 0;
}

test.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "./connect_pool.h"

int my_traver(void *a){
    printf("+");
    return 0;
}

int main(){

    connect_pool_t *pool;

    connect_pool_init(&pool, 10, "192.168.23.1", "saika", "1", "test", 3306);

    sql_msg_t *cur = NULL;
    for (int x = 0; x < 1024; x++)
    {
        cur = get_a_connection(pool);
        if (cur == NULL)
        {
            printf("without get.\n");
        }
        else
        {
            char *query = "select no from user;";
            if (mysql_real_query(cur->mysql, query, strlen(query)) != 0)
            {
                printf("select false\n");
            }
            else
            {
                cur->res = mysql_store_result(cur->mysql);
                while ((cur->row = mysql_fetch_row(cur->res)) != NULL)
                {
                    printf("%s\n", *cur->row);
                }
            }
            // return_a_connection(pool, cur);
        }
    }

    llist_traver(pool->connect, my_traver);

    return_a_connection(pool, cur);

    llist_traver(pool->connect, my_traver);
    

    pause();

    connect_pool_destroy(pool);
    
    exit(0);
}

总结

已实现功能

  1. 获取一个连接
  2. 归还一个连接

待实现功能

  1. 对连接池内的连接数的动态增加和减少
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值