首页 技术与阅读 生活 关于我

Zabbix源码分析 -- Zabbix Server的main_dbconfig_loop()分析

文档

相关数据结构

进程main_dbconfig_loop()的作用是将某些数据库中数据导入内存中,以便后面可以更快速、方面的使用这些数据;具体来说就是将数据库中的数据查询出来,并存入结构体ZBX_DC_CONFIG中,ZBX_DC_CONFIG的定义如下所示:

在定义完结构体ZBX_DC_CONFIG后,初始化了一个类型为ZBX_DC_CONFIG的全局变量config

ZBX_DC_CONFIG中,很多变量都定义为zbx_hashset_tzbx_hashset_t是一个结构体,其中包括用于存储数据的HASH链表的入口ZBX_HASHSET_ENTRY_T **slots、存储数据时需要用到的函数、int常量,它的定义如下:

zbx_hashset_t中,除有Hash表相关的一些函数和变量外,还有ZBX_HASHSET_ENTRY_T **slots,即用来保存数据的Hash链表,数据就是存储在ZBX_HASHSET_ENTRY_T中的data字段,ZBX_HASHSET_ENTRY_T的定义如下:

ZBX_HASHSET_ENTRY_T中的data字段为一个柔性数组,关于柔性数组我会在本文的最后做相关介绍。

本文主要通过讲述如何把数据库hosts表格中的数据查询出来,并存入config-->hosts中的过程,来说明进程main_dbconfig_loop()的工作原理。hosts表格中的数据是存于一Hash链表中的,在此Hash链表中存储的数据类型为ZBX_DC_HOSTZBX_DC_HOST的定义如下:

MAIN_ZABBIX_ENTRY()

MAIN_ZABBIX_ENTRY()函数首先做一些初始化工作,然后创建Zabbix Server端各进程,当然包括main_dbconfig_loop()

init_configuration_cache()

init_configuration_cache()函数中,通过调用CREATE_HASHSET(config->hosts),来初始化config->hosts中的相关的Hash函数。init_configuration_cache()函数的定义大致如下:

CREATE_HASHSET(config->hosts)是通过调用函数zbx_hashset_create_ext()来初始化config->hosts,函数zbx_hashset_create_ext()的代码如下所示:

main_dbconfig_loop()

进程main_dbconfig_loop()每隔CONFIG_CONFSYNCER_FREQUENCY秒,就调用函数DCsync_configuration()将数据库中的数据同步到内存中,main_dbconfig_loop()的代码如下所示:

DCsync_configuration()

MAIN_ZABBIX_ENTRY的初始化工作中和进程main_dbconfig_loop()的循环中,都调用了函数DCsync_configuration(),函数DCsync_configuration会从相应的表格中查询出结果,并将结果传入相应的函数做处理,如从hosts表格中查询得到host_result,再将host_result传入函数DCsync_hosts()做进一步处理。函数DCsync_configuration()的部分源码如下所示:

DCsync_hosts()

在函数DCsync_hosts()中,首先定义host为一指向ZBX_DC_HOST的指针,然后调用函数DCfind_id()获取一指向ZBX_HASHSET_ENTRY_T->data的指针并赋值给host,最后调用函数DBfetch(host_result)获得hosts表格中的一行,并将数据赋值给host中的各个字段(如host->proxy_hostid,host->host,host->name,host->maintenance_status,host->maintenance_type,host->maintenance_from等)。 函数DCsync_hosts()的部分源码如下所示:

问题:host = DCfind_id(&config->hosts, hostid, sizeof(ZBX_DB_HOST), &found),host是一个指向ZBX_DC_HOST的指针,而函数DCfind_id()定义时返回的是指向void的指针,DCfind_idptr定义为指向void的指针,而zbx_hashset_search()zbx_hashset_insert()中返回的entry->data的定义为char data[1]。 关于这个问题在后面柔性数组这个章节有所解释。

DCfind_id()

以上面的函数调用形式(host = DCfind_id(&config->host, hostid, sizeof(ZBX_DB_HOST), &found))进行分析,函数DCfind_id()调用函数zbx_hashset_search()&config->host中搜索hostid,若找到就将*found置为1,并返回zbx_hashset_search()的返回值;若未找到就将*found置为0,并调用函数zbx_hashset_insert()&config->host中插入hostid,返回zbx_hashset_insert()的返回值。 函数DCfind_id()的源码如下所示:

函数zbx_hashset_search()zbx_hashset_insert()的源码列于下方:

zbx_hashset_search()

zbx_hashset_insert()

柔性数组

在函数DCsync_hosts()中,重要的一步就是获得host指针,如下所示:

```
ZBX_DC_HOST *host;
host = DCfind_id(&config->hosts, hostid, sizeof(ZBX_DC_HOST), &found);
```

得到host指针后,再对host赋值,对此有两点疑问:

1,host为指向ZBX_DC_HOST的指针,函数DCfind_id返回的是指向void的指针,那么函数DCfind_id的值怎么可以直接赋给host呢?

2,跟踪函数DCfind_id,可以发现真正的返回值是由函数zbx_hashset_searchzbx_hashset_insert返回的,这两个函数的返回值又为entry->data,其中entry为一个指向ZBX_HASHSET_ENTRY_T的指针,而在ZBX_HASHSET_ENTRY_Tdata的定义为char data[1]host中这么多的字段在entry->data中怎么存储得下呢?

关于这两个疑问可以由C语言的两个特性来回答:

  1. ”标准表示一个void *类型的指针可以转换为其他任何类型的指针。但是,有些编译器,尤其是那些老式的编译器,可能要求你在转换时使用强制类型转换。“--《C和指针》p222

  2. 柔性数组

下面用一个示例对柔性数组做进一步的解释,如示例中所示EntryStruct中的c即为柔性数组,尽管它的定义为char c[1],后面我们却可以用它来存储类型为TestStruct的数据; 需要注意的是在为entryStruct分配内存时,需要分配sizeof(EntryStruct) + sizeof(TestStruct) + 1字节的内存,因为entryStruct->c将会用来存储类型为TestStruct的数据。

comments powered by Disqus

技术与阅读

生活

关于我