Berkeley DB有几大子系统,包括LOCK, LOG, Memory Pool(MPOOL), Mutex, TXN等。区域(region)文件包括了对这些区域的描述。如果区域文件以磁盘做为备份,则

__db.001为关于数据库本身区域的描述;
__db.002为关于MUTEX区域的描述;
__db.003为关于MPOOL区域的描述;
__db.004为关于LOG区域的描述;
__db.005为关于LOCK区域的描述;
__db.006为关于TXN区域的描述。

区域有类型也有id。各个区域的类型见类型reg_type_t的描述:
typedef enum {
INVALID_REGION_TYPE=0, /* Region type. */
REGION_TYPE_ENV,
REGION_TYPE_LOCK,
REGION_TYPE_LOG,
REGION_TYPE_MPOOL,
REGION_TYPE_MUTEX,
REGION_TYPE_TXN
} reg_type_t;
区域的id体现在文件名上。

在区域创建时,Berkeley DB使用mmap和shmat来进行磁盘和内存的映射以及多进程之间的共享。每个区域都会被映射到内存中。
上图描述了__db.001和__db.005的映射。

__db.001为数据库本身区域的描述,它的内容结构以及映射状况见上图。
头部是一个REGENV的结构体,后面主要是描述各个区域的结构体REGION。
REGENV描述了如下一些信息:
版本幻数,Berkeley DB库的版本,时间戳,一共有多少个区域。
另外,Berkeley 将加密信息、复制投票信息和线程控制块表(用来进行env的failchk)也放置在__db.001中。因此REGENV包含3个字段用来保存这3部分各自被映射后和__db.001映射地址的偏移量。
线程控制块表是用来做环境可用性检查的,参见
Berkeley DB认为至少应该将复制投票信息单独存放于一个区域中,而不是混于环境本身的区域之中。

REGION是一个“静态的”描述,它主要包含一些如下信息:
这是一个什么类型的区域;id是多少,还有一个偏移量,偏移量描述的是此区域映射的文件中主要数据结构被映射后地址相对于此文件的映射地址的偏移量。

对于__db.005,这个偏移量即是0xb71c2044相对于0xb71c2000的偏移。
当一个进程打开环境时,它会调用env_open来打开环境,使用mmap和shmat来attach到环境上。

REGINFO是一种“动态的”数据结构,对于每种不同的区域,它存放的是每次打开环境(或者打开对应区域时)对应文件被映射的地址、主要数据结构被映射的地址以及相对应REGION的地址。见上图所示。

Berkeley DB 的环境DB_ENV中定义了如下一些数据结构来保存对应的REGINFO:
DB_LOCKTAB *lk_handle; /* Lock handle. */
DB_LOG *lg_handle; /* Log handle. */
DB_MPOOL *mp_handle; /* Mpool handle. */
DB_MUTEXMGR *mutex_handle; /* Mutex handle. */
DB_REP *rep_handle; /* Replication handle. */
DB_TXNMGR *tx_handle; /* Txn handle. */
每个中都包含一个REGINFO。

Berkeley DB定义了一批函数来操作这些区域,在进行mmap映射后得到的是一个很大的地址块(chunk),在此地址上分配空间可以避免随意进行malloc分配所产生的内存碎片。

主要的函数包括
__env_attach:环境打开时attach。
__env_region_attach:各个区域打开时attach。
__env_des_get:找到对应的REGION。
__env_alloc_init:为各个区域的数据结构分配资源做初始化。
__env_alloc:在映射的区域上分配空间。



Related posts(相关文章):