当前位置: 首页 > 工具软件 > libzdb > 使用案例 >

libzdb --- mysql 的一个数据库连接池代码分析

谭富
2023-12-01
安装了re2c
运行bootstrap后生成了
autom4te.cache目录,m4目录
文件
config\compile
config\config.guess
config\config.sub
config\ltmain.sh

src\xconfig.h.in
test\Makefile.in
aclocal.m4
configure
Makefile.in

configure后生成了
src\stamp-h1 src\xconfig.h(由xconfig.h.in生成)
test\Makefile
tools\bin\filterh,由tools\filterh下的filterh\filterh.l生成
configure的时候执行了cd ./tools/filterh && $CC lex.yy.c -o ../bin/filterh && rm -f lex.yy.o
config.log config.status libtool Makefile zdb.pc(由zdb.pc.in生成)

make 创建了头文件到zdb目录,编译src目录下的代码,生成库到顶层目录。编译test目录下的多个程序
noinst_PROGRAMS,编译的二进制也被放在了.libs目录

filterh的作用是去掉//<<...//>>或者#<<...#>>之间的内容。\000-\377是八进制表示,从0到255

./tools/bin/filterh < src/zdb.h > zdb/zdb.h || exit 1
./tools/bin/filterh < src/db/ConnectionPool.h > zdb/ConnectionPool.h || exit 1
./tools/bin/filterh < src/db/Connection.h > zdb/Connection.h || exit 1
./tools/bin/filterh < src/db/ResultSet.h > zdb/ResultSet.h || exit 1
./tools/bin/filterh < src/net/URL.h > zdb/URL.h || exit 1
./tools/bin/filterh < src/db/PreparedStatement.h > zdb/PreparedStatement.h || exit 1
./tools/bin/filterh < src/exceptions/SQLException.h > zdb/SQLException.h || exit 1
./tools/bin/filterh < src/exceptions/Exception.h > zdb/Exception.h || exit 1
make  all-recursive
make[1]: Entering directory `/home/liuwb/Desktop/code/libzdb-code'
Making all in .
make[2]: Entering directory `/home/liuwb/Desktop/code/libzdb-code'
/bin/bash ./libtool  --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I. -I./src  -I/usr/include/postgresql -I/usr/include/mysql  -I/usr/include/mysql -I/usr/include/postgresql -Isrc -Isrc/util -Isrc/net -Isrc/db -Isrc/exceptions -I/usr/include/postgresql -I/usr/include/mysql   -Wno-address -Wno-pointer-sign -g -O2 -Wall -Wunused -Wno-unused-label -funsigned-char -std=gnu99 -c -o src/util/Str.lo src/util/Str.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I./src -I/usr/include/postgresql -I/usr/include/mysql -I/usr/include/mysql -I/usr/include/postgresql -Isrc -Isrc/util -Isrc/net -Isrc/db -Isrc/exceptions -I/usr/include/postgresql -I/usr/include/mysql -Wno-address -Wno-pointer-sign -g -O2 -Wall -Wunused -Wno-unused-label -funsigned-char -std=gnu99 -c src/util/Str.c  -fPIC -DPIC -o src/util/.libs/Str.o
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I./src -I/usr/include/postgresql -I/usr/include/mysql -I/usr/include/mysql -I/usr/include/postgresql -Isrc -Isrc/util -Isrc/net -Isrc/db -Isrc/exceptions -I/usr/include/postgresql -I/usr/include/mysql -Wno-address -Wno-pointer-sign -g -O2 -Wall -Wunused -Wno-unused-label -funsigned-char -std=gnu99 -c src/util/Str.c -o src/util/Str.o >/dev/null 2>&1

...
/usr/bin/re2c -b src/net/URL.re > src/net/URL.c
...

/bin/bash ./libtool  --tag=CC   --mode=link gcc  -Wno-address -Wno-pointer-sign -g -O2 -Wall -Wunused -Wno-unused-label -funsigned-char -std=gnu99 -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -ldl -L/usr/lib -lpq -version-info 11:0:0 -L/usr/lib -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -ldl  -o libzdb.la -rpath /usr/local/lib src/util/Str.lo src/util/Vector.lo src/util/StringBuffer.lo src/system/Mem.lo src/system/System.lo src/system/Time.lo src/db/ConnectionPool.lo src/db/Connection.lo src/db/ResultSet.lo src/db/PreparedStatement.lo src/exceptions/assert.lo src/exceptions/Exception.lo src/net/URL.lo src/db/mysql/MysqlConnection.lo src/db/mysql/MysqlResultSet.lo src/db/mysql/MysqlPreparedStatement.lo src/db/postgresql/PostgresqlConnection.lo src/db/postgresql/PostgresqlResultSet.lo src/db/postgresql/PostgresqlPreparedStatement.lo src/db/sqlite/SQLiteConnection.lo src/db/sqlite/SQLiteResultSet.lo src/db/sqlite/SQLitePreparedStatement.lo   -lsqlite3 -lpthread
libtool: link: gcc -shared  -fPIC -DPIC  src/util/.libs/Str.o src/util/.libs/Vector.o src/util/.libs/StringBuffer.o src/system/.libs/Mem.o src/system/.libs/System.o src/system/.libs/Time.o src/db/.libs/ConnectionPool.o src/db/.libs/Connection.o src/db/.libs/ResultSet.o src/db/.libs/PreparedStatement.o src/exceptions/.libs/assert.o src/exceptions/.libs/Exception.o src/net/.libs/URL.o src/db/mysql/.libs/MysqlConnection.o src/db/mysql/.libs/MysqlResultSet.o src/db/mysql/.libs/MysqlPreparedStatement.o src/db/postgresql/.libs/PostgresqlConnection.o src/db/postgresql/.libs/PostgresqlResultSet.o src/db/postgresql/.libs/PostgresqlPreparedStatement.o src/db/sqlite/.libs/SQLiteConnection.o src/db/sqlite/.libs/SQLiteResultSet.o src/db/sqlite/.libs/SQLitePreparedStatement.o   -L/usr/lib/x86_64-linux-gnu -L/usr/lib -lpq -lmysqlclient -lz -lm -ldl /usr/lib/x86_64-linux-gnu/libsqlite3.so -lpthread  -g -O2   -Wl,-soname -Wl,libzdb.so.11 -o .libs/libzdb.so.11.0.0
libtool: link: (cd ".libs" && rm -f "libzdb.so.11" && ln -s "libzdb.so.11.0.0" "libzdb.so.11")
libtool: link: (cd ".libs" && rm -f "libzdb.so" && ln -s "libzdb.so.11.0.0" "libzdb.so")
libtool: link: ar cru .libs/libzdb.a  src/util/Str.o src/util/Vector.o src/util/StringBuffer.o src/system/Mem.o src/system/System.o src/system/Time.o src/db/ConnectionPool.o src/db/Connection.o src/db/ResultSet.o src/db/PreparedStatement.o src/exceptions/assert.o src/exceptions/Exception.o src/net/URL.o src/db/mysql/MysqlConnection.o src/db/mysql/MysqlResultSet.o src/db/mysql/MysqlPreparedStatement.o src/db/postgresql/PostgresqlConnection.o src/db/postgresql/PostgresqlResultSet.o src/db/postgresql/PostgresqlPreparedStatement.o src/db/sqlite/SQLiteConnection.o src/db/sqlite/SQLiteResultSet.o src/db/sqlite/SQLitePreparedStatement.o
libtool: link: ranlib .libs/libzdb.a
libtool: link: ( cd ".libs" && rm -f "libzdb.la" && ln -s "../libzdb.la" "libzdb.la" )
make[2]: Leaving directory `/home/liuwb/Desktop/code/libzdb-code'
Making all in test
make[2]: Entering directory `/home/liuwb/Desktop/code/libzdb-code/test'
gcc -DHAVE_CONFIG_H -I. -I../src  -I../src -I../src/util -I../src/net -I../src/db -I../src/exceptions -I/usr/include/postgresql -I/usr/include/mysql   -Wno-address -Wno-pointer-sign -g -O2 -Wall -Wunused -Wno-unused-label -funsigned-char -std=gnu99 -c -o unit.o unit.c
/bin/bash ../libtool  --tag=CC   --mode=link gcc  -Wno-address -Wno-pointer-sign -g -O2 -Wall -Wunused -Wno-unused-label -funsigned-char -std=gnu99  -L/usr/lib -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -ldl  -o unit unit.o ../libzdb.la -lsqlite3 -lpthread
libtool: link: gcc -Wno-address -Wno-pointer-sign -g -O2 -Wall -Wunused -Wno-unused-label -funsigned-char -std=gnu99 -o .libs/unit unit.o  -L/usr/lib -L/usr/lib/x86_64-linux-gnu ../.libs/libzdb.so -lpq -lmysqlclient -lz -lm -ldl /usr/lib/x86_64-linux-gnu/libsqlite3.so -lpthread
...


make doc
doxygen config/Doxyfile
在doc/api-docs目录下生成了png,_8h.html,css,js,index.html文件
HTML_OUTPUT            = doc/api-docs/
INPUT                  = zdb这个目录下的所有文件
RECURSIVE              = YES 递归
FILE_PATTERNS          = *.h 只生成头文件的文档
EXTRACT_ALL            = YES 提取
EXTRACT_PRIVATE        = YES
EXTRACT_STATIC         = YES

GENERATE_HTML          = YES 生成html

MACRO_EXPANSION        = YES 递归展开宏

简短描述:使用单行的 C++ 注释,或使用 <\brief> 标记。
详细描述:使用 JavaDoc 式的注释 /** … test … */(注意开头的两个星号 [*])或 Qt 式的注释 /*! … text … */。
体内描述:类、结构、联合体和名称空间等 C++ 元素都有自己的标记,比如 <\class>、<\struct>、<\union> 和 <\namespace>。
为了为全局函数、变量和枚举类型生成文档,必须先对对应的文件使用 <\file> 标记。
函数标记(<\fn>)、函数参数标记(<\param>)、变量名标记(<\var>)、用于 #define 的标记(<\def>)以及用来表示与一个代码片段相关的问题的标记(<\warning>)。

doxygen在生成网页的同时会自己生成png,css等, 用户也可以连接自己的png,如database.png
...
cp doc/api-docs/files.html doc/api-docs/index.html

mysql://localhost:3306/test?user=root&password=111111
(gdb) p *url
$2 = {port = 3306, ref = 0x0, path = 0x603aa6 "/test", host = 0x603b70 "localhost", user = 0x0, qptr = 0x0,
  query = 0x603b90 "user=root&password=111111", portStr = 0x0, protocol = 0x603a90 "mysql", password = 0x0, toString = 0x0,
  params = 0x603be0, paramNames = 0x0, data = 0x603a90 "mysql", buffer = 0x603ac5 "", marker = 0x603aac "user", ctx = 0x603abe "",
  limit = 0x603ac5 "", token = 0x603abf "111111"}
(gdb) p url->query
$3 = 0x603b90 "user=root&password=111111"
(gdb) p *url->params
$8 = {name = 0x603ab6 "password", value = 0x603abf "111111", next = 0x603bc0}
(gdb) p *(param_t)0x603bc0
$9 = {name = 0x603aac "user", value = 0x603ab1 "root", next = 0x0}

set environment LD_LIBRARY_PATH :/usr/local/lib:/usr/lib64:../.libs

query = ([\040-\377]\[#])*; query只匹配到#以前
mysql://localhost:3306/test?user=root&password=111111\\[#]
r \ s
    match any r which isn’t s. r and s must be regular expressions which can be expressed as character classes.
r / s
    r but only if it is followed by s. Note that s is not part of the matched text. This type of regular expression is called “trailing context”. Trailing context can only be the end of a rule and not part of a named definition.

URL_new,创建一个URL_S,re2c就是为了解析这个uri
ConnectionPool_new,创建ConnectionPool_S
ConnectionPool_start---->fillPool(P)---->Connection_new(P, &P->error)---->setDelegate(C, error)
---->C->op = getOp(URL_getProtocol(C->url));
const struct Cop_T mysqlcops = {
        "mysql",
        MysqlConnection_onstop,
        MysqlConnection_new,
        MysqlConnection_free,
        MysqlConnection_setQueryTimeout,
        MysqlConnection_setMaxRows,
        MysqlConnection_ping,

C语言实现TRY,CATCH,FINALLY
在Exception.c里,T代表Exception_T
typedef struct T {
        const char *name;
} T;只有一个字段name

struct Exception_Frame {
    int line;
    jmp_buf env;
    const char *func;
    const char *file;
    const T *exception; //Exception_T
    Exception_Frame *prev; //上个节点
    char message[EXCEPTION_MESSAGE_LENGTH + 1];
};

enum { Exception_entered=0, Exception_thrown, Exception_handled, Exception_finalized };

#define ThreadData_T pthread_key_t
pthread_setspecific(pthread_key_t key, const void *value)/pthread_getspecific可以在一个线程上绑定key和value
extern ThreadData_T Exception_stack; 定义在Exception.c中

void Exception_init(void);
    pthread_once(&once_control, init_once);
    执行一次init_once,即ThreadData_create(Exception_stack);,即pthread_key_create(&(key), NULL)
void Exception_throw(const T *e, const char *func, const char *file, int line, const char *cause, ...);
    得到当前Exception_Frame,p
    p->exception = e;//e是全局变量SQLException,给Exception_frame的exception字段赋值
    p->func = func;
    p->file = file;
    p->line = line;
    if (cause) {
            va_start(ap, cause);
            vsnprintf(p->message, EXCEPTION_MESSAGE_LENGTH, cause, ap);
            va_end(ap);
    }
    pop_Exception_stack//Exception_stack指向当前Exception_Frame的上一个Exception_Frame
    longjmp(p->env, Exception_thrown);Exception_thrown值是1,Exception_flag != Exception_entered
    所以执行CATCH的else if (Exception_frame.exception == &(e)),要捕获的e和Exception_frame的exception相同
    Exception_flag = Exception_handled;并执行用户的代码

#define pop_Exception_stack ThreadData_set(Exception_stack, ---->key
    ((Exception_Frame*)ThreadData_get(Exception_stack))->prev ---->value)
Exception_stack指向当前Exception_Frame的上一个Exception_Frame
 

#define RETURN switch((pop_Exception_stack,0)) default:return
switch的值是0,RETURN前需要将当前的Exception_Frame从ThreadData移除

TRY {...} CATCH(SQLException) {...} CATCH(XXException) {...} FINALLY {...} END_TRY;
TRY {...} CATCH(SQLException) {...}    END_TRY;
TRY {...} FINALLY {...} END_TRY;
TRY {...} ELSE {...} END_TRY; 和TRY,CATCH类似

TRY {...} CATCH(SQLException) {...}    FINALLY {...} END_TRY;
/*TRY*/
do {
    volatile int Exception_flag;
    Exception_Frame Exception_frame;
    Exception_frame.message[0] = 0;
    Exception_frame.prev = (Exception_Frame*)ThreadData_get(Exception_stack);
    ThreadData_set(Exception_stack, &Exception_frame);
    Exception_flag = setjmp(Exception_frame.env);
    if (Exception_flag == Exception_entered) {
        {...try statement
            THROW(SQLException, "%s", Connection_getLastError(C));
            Exception_throw(&(e), __func__, __FILE__, __LINE__, cause, ##__VA_ARGS__, NULL)
            如果有catch发生异常跳到204行执行,没有异常执行202
            如果没有catch,只有finally,发生异常跳到212,没有异常执行208
            如果没有catch,也没有finally,发生异常跳到219,没有异常216
        }//user code
/*CATCH*/
        if (Exception_flag == Exception_entered)
            pop_Exception_stack;
    } else if (Exception_frame.exception == &(e)) {
        Exception_flag = Exception_handled;
        {...catch statement}//user code
/*FINALLY*/
        if (Exception_flag == Exception_entered)
            pop_Exception_stack;
    }
    {
        if (Exception_flag == Exception_entered)
            Exception_flag = Exception_finalized;
        {...finally statement}//user code
/*END_TRY*/            
        if (Exception_flag == Exception_entered)
                pop_Exception_stack;
    }
    if (Exception_flag == Exception_thrown)
        /*RETHROW*/
        Exception_throw(Exception_frame.exception, \
                Exception_frame.func, Exception_frame.file, Exception_frame.line, NULL)
} while (0)
 类似资料: