SQLite 学习之路 第七节 位图
位图(Bit-map),是一种数据结构,即用一个bit位来标记某个元素对应的Value, Key是该元素。一个位图就是用来记录在一个事务处理过程中数据库的哪些页被日 志记录,或者哪些页有"dont-write"的性质。
Bitvec对象,作为页面缓存的一部分,就是用来追踪那些已记录在日志 的页面(也就是脏页),以提高速度和减少内存的消耗,特别是对于一些大的数据库文件。它实现了用一个对象来表示一个固定长度的位图(Bit-map)。
Bitvec 结构体如下,它实现了一个对象,用这个对象表示一个固定长度的位图,位从1开始编号。当对象被创建时,位图的大小就被固定了。当位图被创建时所有的位都被清空,单独的位可能会被设置或清除一次。
struct Bitvec {
u32 iSize; /*最大位指数,最大值为4,294,967,296。*/
u32 nSet; /*被设置的位的数量,仅适用于aHash元素,最大是BITVEC_NINT。因为BITVEC_SZ 的大小是512,所以这里是125。*/
u32 iDivisor; /*位的数量由每个apSub[]的记录处理。最大的iDivisor是max(u32)/BITVEC_NPTR+1。因为BITVEC_SZ的大小是512,所以这里是34,359,739。*/
union {
BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* 位图的表示 */
u32 aHash[BITVEC_NINT]; /* hash表的表示 */
Bitvec *apSub[BITVEC_NPTR]; /* 递归的表示 */ } u;
};
这个位图记录0或更多位的存在,用在1和iSize之间的值记录,并且包含1和iSize。如果iSize<=BITVEC_NBIT,那么Bitvec.u.aBitmap[]是一个直接的位图,它的最低有效单位是1位。 如果iSize>BITVEC_NBIT并且iDivisor==0,那么Bitvec.u.aHash[]是一个能够容纳BITVEC_MXHASH的不同值的hash表。
下面这个函数用来创建一个能过处理0到iSize个位(包含0和iSize)的新位图对象,返回新对象的指针。如果分配失败返回空。
Bitvec *sqlite3BitvecCreate(u32 iSize){
Bitvec *p;
assert( sizeof(*p)==BITVEC_SZ ); /*定义新位图对象的大小为预定义过的BITVEC_SZ大小,即512字节 */
p = sqlite3MallocZero( sizeof(*p) ); /* 调用API函数分配内存空间 */
if( p ){
p->iSize = iSize;
}
return p;
}
检查第i个位是否被分配,返回真或假。如果p为空(如果位图没有被创建)或i溢出则返回假。
int sqlite3BitvecTest(Bitvec *p, u32 i){}
分配第i个位,成功时返回0,如果出错则返回错误信息。需要注意的是,这个程序可能会分配子位图。假设p和i是有效的,那么对于插入来说需要存放子位图却没有获得内存是唯一可能出错的地方。 调用函数必须确保p是有效的Bitvec对象,并且i的值没有溢出Bitvec对象的范围,否则行为是无效的。
int sqlite3BitvecSet(Bitvec *p, u32 i){}
清除第i位,这里的pBuf必须是一个至少为BITVEC_SZ个字节的指针指向临时存储器,通过临时存储器BitvecClear可以重建hash表。
void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){}