对portalmem.cpp的解析

源码链接

https://www.gitlink.org.cn/Eao3piq4e/openGauss-server/tree/master/src%2Fcommon%2Fbackend%2Futils%2Fmmgr%2Fportalmem.cpp

概述

        在前两篇博客对pquery.cpp的解析(一)以及对pquery.cpp的解析(二)中,我们分析了 Portal 模块中的 PortalStart() 和 PortalRun() 函数。不过,当我们分别用它们启动和运行了 portal 时,我们在使用完后还要回收分配给它的内存空间,这时候就用到了 PortalDrop() 函数,这篇文章我来解析一下 portalmem.cpp 中这个十分重要的函数。

解析

PortalDrop()

//代码清单1
//src/common/backend/utils/mmgr/portalmem.cpp
void PortalDrop(Portal portal, bool isTopCommit)
{
······
    if (PointerIsValid(portal->cleanup)) {
        (*portal->cleanup)(portal);
        portal->cleanup = NULL;
    }
    PortalHashTableDelete(portal);
    PortalReleaseCachedPlan(portal);

    if (portal->resowner && (!isTopCommit || portal->status == PORTAL_FAILED)) {
        bool isCommit = (portal->status != PORTAL_FAILED);
        ResourceOwnerRelease(portal->resowner, RESOURCE_RELEASE_BEFORE_LOCKS, isCommit, false);
        ResourceOwnerRelease(portal->resowner, RESOURCE_RELEASE_LOCKS, isCommit, false);
        ResourceOwnerRelease(portal->resowner, RESOURCE_RELEASE_AFTER_LOCKS, isCommit, false);
        ResourceOwnerDelete(portal->resowner);
    }
    portal->resowner = NULL;

#ifndef ENABLE_MULTIPLE_NODES
    if (portal->holdStore && !portal->isAutoOutParam) {
#else
    if (portal->holdStore) {
#endif
        MemoryContext oldcontext;

        oldcontext = MemoryContextSwitchTo(portal->holdContext);
        tuplestore_end(portal->holdStore);
        MemoryContextSwitchTo(oldcontext);
        portal->holdStore = NULL;
    }
······
    pfree(portal);
}

        该函数的作用是释放之前为 portal 分配的内存空间,先是处理与 portal 相关联的各个成员变量,将它们处理后再释放内存。不难看出,该函数调用了多个内存清理函数。代码清单1第6~9行的 if 判断语句块一般来说是在 MarkPortalDone() 或 MarkPortalFailed() 中已经被执行的, MarkPortalDone() 或 MarkPortalFailed() 的代码大体如下:

//代码清单2
//src/common/backend/utils/mmgr/portalmem.cpp
void MarkPortalDone(Portal portal)
{
    Assert(portal->status == PORTAL_ACTIVE);
    portal->status = PORTAL_DONE;
······
    if (PointerIsValid(portal->cleanup)) {
        (*portal->cleanup)(portal);
        portal->cleanup = NULL;
    }
}
//代码清单3
//src/common/backend/utils/mmgr/portalmem.cpp
void MarkPortalFailed(Portal portal)
{
    Assert(portal->status != PORTAL_DONE);
    portal->status = PORTAL_FAILED;
······
    if (PointerIsValid(portal->cleanup)) {
        (*portal->cleanup)(portal);
        portal->cleanup = NULL;
    }
}

换句话说,当 portal 功能行使完毕或发生故障时,我们会将它的状态修改完成或是故障,然后调用 portal 的成员变量 cleanup 指向的钩子函数来处理 portal ,这些都是在调用 PortalDrop() 摧毁 portal 前完成的。

        代码清单1第10行利用宏函数 PortalHashTableDelete() 将 portal 从哈希表中移除,第11行利用函数 PortalReleaseCachedPlan() 用来取消 portal 查询缓存中的计划,当然前提是存在。提一句,这两个函数都在此文件中。

        代码清单1第13~19行的 if 判断语句块用来释放仍然与 portal 连接着的各种资源,第27~32行的语句块在 portal 中有元组存在的情况下必须执行,第35行用来释放为 portal 变量释放的内存。

总结

        一句话,PortalDrop() 在 Portal 模块中就是用来善后的,用来释放与存储该模块执行状态的变量 portal 连接的资源以及 portal 自身。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奔走的月光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值