postgresql存储引擎源码分析三

postgresql存储引擎源码分析三,第1张

概述    在上一次的分析中,我们分析了验证页面是否有效的函数,向页面中添加元组项PageAddItem函数和一些其他函数的功能。接下来我们来分析其他的页面 *** 作函数。     下一个函数,声明:void PageRestoreTempPage(Page tempPage,Page oldPage)。这个函数的功能是:将经过特殊处理过后的临时页面tempPage拷贝回oldPage中,随后将临时页面的内

在上一次的分析中,我们分析了验证页面是否有效的函数,向页面中添加元组项PageAddItem函数和一些其他函数的功能。接下来我们来分析其他的页面 *** 作函数。

下一个函数,声明:voID PageRestoreTempPage(Page tempPage,Page oldPage)。这个函数的功能是:将经过特殊处理过后的临时页面tempPage拷贝回oldPage中,随后将临时页面的内存空间释放。

接下来,定义了一个结构体,如下:

typedef struct itemIDSortData
{
intoffsetindex;/* linp array index */
intitemoff;/* page offset of item data */
Sizealignedlen;/* MAXAliGN(item data len) */
ItemIDDataolditemID;/* used only in PageIndexMultIDelete */
} itemIDSortData;
typedef itemIDSortData *itemIDSort;

这个结构体是用于页面中元组项排序所需要,将在随后的PageRepairFragmentation和PageIndexMultIDelete函数中用到。结构体中定义了元组项的一些参数:offsetindex:元组项位于页面linp数组中的索引,itemoff:元组项位于页面中的偏移量。alignedlen:元组项大小,最后一个参数olditemID仅用于在PageIndexMultIDelete函数当中。

接下来是一个静态的函数:static int itemoffcompare(const voID *itemIDp1,const voID *itemIDp2),这个函数的功能很简单:它返回两个上面定义的结构体itemIDSortData的itemoff的值之差,也就是两个元组项的偏移量之差,用于后面排序的比较。

下面的一个函数有点长,有120多行。它就是我们上面所提到的PageRepairFragmentation函数,它的声明是:voID PageRepairFragmentation(Page page)。

作用是清除页面page中的碎片。实现原理是:首先判断当前页面page是否有效,如果无效的话,报错,函数退出。接着将变量nline赋值为page中元组项的个数。接下来定义两个变量nstorage,nunused分别用于统计页面中元组项已经使用和未使用的数量值。下面便遍历页面page的所有元组项item,如果item已被使用,将nstorage增值,否则置item标志位为未使用,nunused增值。遍历完成后,如果nstorage为0的话,说明该页面page完全是空的,不需要清除碎片,只需要充值它的值便可以,否则的话建立一个itemIDSortData类型的数组,为他分配空间,用指针itemIDptr来 *** 作。遍历所有的元组项,如果元组项item已被存储,将itemIDptr指向这个元组项,totallen自增元组项的长度。接下来对itemIDSortData数组按偏移量进行降序排序。接下来,遍历这个数组,这段代码为:

upper = pd_special;

for (i = 0,itemIDptr = itemIDbase; i < nstorage; i++,itemIDptr++)
{
lp = PageGetItemID(page,itemIDptr->offsetindex + 1);
upper -= itemIDptr->alignedlen;
memmove((char *) page + upper,
(char *) page + itemIDptr->itemoff,
itemIDptr->alignedlen);
lp->lp_off = upper;
}

upper首先被赋值为page的特殊空间起始偏移量,接下来遍历itemIDSortData类型的数组itemIDbase,lP为page对应itemIDptr位于原linp数组中对应索引的元组项,为什么要对offsetindex加1呢?这是因为在前面的赋值 *** 作对原元组项的偏移量已经减1了。因为之前是对itemIDbase数组按偏移量降序排序的,所以可以看到,我们这里是从页面的“后端”往前 *** 作,每次 *** 作一个元组项,upper减掉此元组项对应的长度。接下来调用memmove函数,将itemIDbase中的元组项,移到页面中的upper位置,相当于“消除”了碎片。这个算法类似于 *** 作系统中的存储管理中的“紧凑” *** 作,将分散的元组项地址连续起来,消除页面中的内部碎片。接下来便是一些收尾工作了,清除itemIDbase数组的空间等 *** 作,函数结束。从中我们可以看到:这个函数宏观上的整体过程是:统计一个页面中的“有内容”的元组项,接着把这些元组项“装入”到一个itemIDbase的数组,借助这个辅助空间,移动这些元组,使得他们的页面偏移量连续起来,消除页面中的碎片,得到更多的剩余空间。

下面的一个函数相对来说就很简单了:原型是,Size PageGetFreeSpace(Page page),这里的返回类型为“Size”, Size是一个宏定义,原型是size_t,这个在标准C语言就是无符号短整形。这个函数的功能是:返回页面page中的剩余空间,实现机制很简单,定义一个变量space为page的pd_lower和pd_upper之差。如果space小于itemIDData的存储空间时,便返回0,说明无剩余空间了,否则返回space-sizeof(itemIDData),这里为什么要扣除一个itemIDData元组项的存储空间,还有待考证。

今天的分析就到这里,希望其他同学发现不足,给予修改。

姓名:鲁笛 主题:页面存储

总结

以上是内存溢出为你收集整理的postgresql存储引擎源码分析三全部内容,希望文章能够帮你解决postgresql存储引擎源码分析三所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1175236.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存