Update blockchain.cpp

This commit is contained in:
hyt15810656168 2023-08-27 22:31:59 +08:00
parent 74add04db0
commit 0cd2edfb52
1 changed files with 155 additions and 108 deletions

View File

@ -32,61 +32,72 @@
#include "utils/snapmgr.h"
/*
* gen_global_hash -- generate globalhash of gchain
* gen_global_hash -- generate globalhash of gchain //生成gchain的全局哈希值
*
* hash_buffer: the buffer that ready to fill generated globalhash.
* info_string: operate info string of current block.
* exist: whether previous block exists.
* prev_hash: the address of previous hash value.
* hash_buffer: the buffer that ready to fill generated globalhash.//准备填充生成的全局哈希值的缓冲区
* info_string: operate info string of current block.//当前块的操作信息字符串。
* exist: whether previous block exists.//前一个块是否存在。
* prev_hash: the address of previous hash value.//前一个哈希值的地址。
*
* Note: globalhash is generated by operate info and previous globalhash using md5.
* 使md5算法
*/
//该函数的作用是根据区块链中块的信息和相关参数,生成全局哈希用于验证和识别区块链的完整性和链式结构。(判断、生成块与MD5哈希值)
bool gen_global_hash(hash32_t *hash_buffer, const char *info_string, bool exist, const hash32_t *prev_hash)
{
errno_t rc = EOK;
int comb_strlen;
char *comb_string = NULL;
/*
* Previous block not exists means current insertion block is genesis,
* then we use global systable as origin combine string for globalhash
* generation. If previous block exists, we will use previous global
* hash as combine string to calculate globalhash.
*/
if (!exist) {
/* 如果前一个块不存在表示当前插入的块是创世块使用全局systable作为全局哈希生成的组合字符串
使 */
if (!exist) {//前一个块不存在
/* generate genesis block globalhash */
comb_strlen = strlen(GCHAIN_NAME) + strlen(info_string) + 1;
comb_string = (char *)palloc0(comb_strlen);
rc = snprintf_s(comb_string, comb_strlen, comb_strlen - 1, "%s%s", GCHAIN_NAME, info_string);
securec_check_ss(rc, "", "");
/* 生成创世块的全局哈希 */
comb_strlen = strlen(GCHAIN_NAME) + strlen(info_string) + 1;//计算组合字符串的长度
comb_string = (char *)palloc0(comb_strlen);//分配足够的内存给组合字符串并初始化为0
rc = snprintf_s(comb_string, comb_strlen, comb_strlen - 1, "%s%s", GCHAIN_NAME, info_string);// 将GCHAIN_NAME和info_string拼接到组合字符串中
//comb_string为存储位置comb_strlen为最大允许字符数
securec_check_ss(rc, "", "");//检查snprintf_s是否成功——如果发生错误并返回值为-1表示目标缓冲区或格式字符串是一个空指针或者无效的参数句柄被调用。此时宏函数会释放分配给缓冲区和其他可变参数的内存并在日志中输出错误信息提供文件名和行号。
//函数来源 src\include\gtm\utils\elog.h
} else {
/* use previous globalhash and current block info to calculate globalhash. */
char *pre_hash_str = DatumGetCString(DirectFunctionCall1(hash32out, HASH32GetDatum(prev_hash)));
comb_strlen = strlen(pre_hash_str) + strlen(info_string) + 1;
comb_string = (char *)palloc0(comb_strlen);
rc = snprintf_s(comb_string, comb_strlen, comb_strlen - 1, "%s%s", info_string, pre_hash_str);
securec_check_ss(rc, "", "");
pfree_ext(pre_hash_str);
/* 使用前一个全局哈希和当前块信息计算全局哈希 */
char *pre_hash_str = DatumGetCString(DirectFunctionCall1(hash32out, HASH32GetDatum(prev_hash)));//将prev_hash转换为字符串形式
comb_strlen = strlen(pre_hash_str) + strlen(info_string) + 1;//计算组合字符串的长度
comb_string = (char *)palloc0(comb_strlen);//分配足够的内存给组合字符串并初始化为0
rc = snprintf_s(comb_string, comb_strlen, comb_strlen - 1, "%s%s", info_string, pre_hash_str); //将info_string和pre_hash_str拼接到组合字符串中
securec_check_ss(rc, "", "");//检查snprintf_s是否成功
pfree_ext(pre_hash_str);//释放pre_hash_str占用的内存
}
if (!pg_md5_binary(comb_string, comb_strlen - 1, hash_buffer->data)) {
pfree(comb_string);
ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Failed to generate globalhash, out of memory")));
/* 使用pg_md5_binary函数计算组合字符串的MD5哈希值并存储在hash_buffer中 */
if (!pg_md5_binary(comb_string, comb_strlen - 1, hash_buffer->data)) {//函数来源src\common\backend\libpq\md5.cpp
pfree(comb_string);//释放组合字符串占用的内存
ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Failed to generate globalhash, out of memory")));// 报错,内存不足
return false;
}
pfree(comb_string);
return true;
pfree(comb_string);//释放组合字符串占用的内存
return true;//返回全局哈希生成是否成功的结果
}
/*
* set_gchain_comb_string -- combine block informations.
* set_gchain_comb_string -- combine block informations.//组合块信息
*
* db_name: the database name where executes cmd.
* user_name: the user name who executes cmd
* nsp_name: namespace name of usertable
* rel_name: rel_name of usertable
* cmd_text: the command query which modified user table.
* rel_hash: rel_hash of current block.
* db_name: the database name where executes cmd.//执行命令的数据库名称
* user_name: the user name who executes cmd//执行命令的用户名
* nsp_name: namespace name of usertable//用户表的命名空间名称
* rel_name: rel_name of usertable//用户表的关系名称
* cmd_text: the command query which modified user table.//修改用户表的命令查询
* rel_hash: rel_hash of current block.//当前块的关系哈希值
*/
//将多个字符串和数值拼接在一起,设置区块链全局哈希生成所需的组合字符串。
char *set_gchain_comb_string(const char *db_name, const char *user_name,
const char *nsp_name, const char *rel_name, const char *cmd_text, uint64 rel_hash)
{
@ -95,97 +106,110 @@ char *set_gchain_comb_string(const char *db_name, const char *user_name,
}
int comb_len = strlen(db_name) + strlen(user_name) + strlen(nsp_name) +
strlen(rel_name) + strlen(cmd_text) + PREVIOUS_HASH_LEN + 1;
char *comb_str = (char *)palloc0(sizeof(char) * comb_len);
errno_t rc = snprintf_s(comb_str, comb_len, comb_len - 1, "%s%s%s%s%s%lu",
char *comb_str = (char *)palloc0(sizeof(char) * comb_len);//分配足够的内存给组合字符串并初始化为0
errno_t rc = snprintf_s(comb_str, comb_len, comb_len - 1, "%s%s%s%s%s%lu",//将各个字符串和数值按指定格式拼接到组合字符串中存入comb_str
db_name, user_name, nsp_name, rel_name, cmd_text, rel_hash);
securec_check_ss(rc, "\0", "\0");
return comb_str;
securec_check_ss(rc, "\0", "\0");//检查snprintf_s是否执行成功
return comb_str;//返回生成的组合字符串
}
/*
* ledger_gchain_append -- record a block to gchain.
* ledger_gchain_append -- record a block to gchain.//将一个块记录到gchain
*
* relid: relation oid of usertable.
* query_string: original query which modified usertable.
* cn_hash: rel_hash in hist table generated by query_string.
* relid: relation oid of usertable.//用户表的关系OID
* query_string: original query which modified usertable.//修改用户表的原始查询语句
* cn_hash: rel_hash in hist table generated by query_string.//通过query_string生成的hist表中的关系哈希值
*
* Note: after block inserted into gchain, its globalhash will flush
* into gchain cache for next block. Thus, previous global hash is
* come from cache directly.
* gchain之后gchain缓存中以供下一个块使用
*/
//用于向全局链表中追加记录,为区块链的增长提供了支持
void ledger_gchain_append(Oid relid, const char *query_string, uint64 cn_hash)
{
Datum current_time;
Datum values[Natts_gs_global_chain] = {0};
bool nulls[Natts_gs_global_chain] = {false};
Datum current_time;//当前时间
Datum values[Natts_gs_global_chain] = {0};//存储要插入的数据值
//Natts_gs_global_chain定义为10来源src\include\catalog\gs_global_chain.h
bool nulls[Natts_gs_global_chain] = {false};//标记是否为 NULL
char *db_name = NULL;
char *user_name = NULL;
char *nsp_name = NULL;
char *rel_name = NULL;
char *combine_string = NULL;
HeapTuple tup = NULL;
Relation rel_gchain = NULL;
GlobalPrevBlock current_block;
char *combine_string = NULL;//存储字符串
HeapTuple tup = NULL; //堆元组
Relation rel_gchain = NULL;//全局链表关系
GlobalPrevBlock current_block;//当前块
/* get basic informations. */
db_name = get_database_name(u_sess->proc_cxt.MyDatabaseId);
user_name = GetUserNameFromId(GetCurrentUserId());
current_time = TimestampTzGetDatum(GetCurrentTimestamp());
nsp_name = get_namespace_name(get_rel_namespace(relid));
rel_name = get_rel_name(relid);
//获取基本信息
db_name = get_database_name(u_sess->proc_cxt.MyDatabaseId);//根据数据库的OID获取当前数据库名来源src\gausskernel\optimizer\commands\dbcommands.cpp
user_name = GetUserNameFromId(GetCurrentUserId());//根据用户OID获取当前用户名来源src\common\backend\utils\init\miscinit.cpp
current_time = TimestampTzGetDatum(GetCurrentTimestamp());//获取当前时间戳
nsp_name = get_namespace_name(get_rel_namespace(relid));//根据给定的命名空间OID获取关系所在命名空间名来源src\common\backend\utils\cache\lsyscache.cpp
rel_name = get_rel_name(relid);//根据给定的关系OID获取关系名来源src\common\backend\utils\cache\lsyscache.cpp
/* Make combine string of current record: rel_name + nsp_name + query_string + rel_hash */
/* 生成当前记录的组合字符串: rel_name + nsp_name + query_string + rel_hash */
//调用本文件中的函数
combine_string = set_gchain_comb_string(db_name, user_name, nsp_name, rel_name, query_string, cn_hash);
/*
* rel_hash: sum of hash in DN which generated by this query_string.
* globalhash: hash for last record of gs_global_chain, it means blockchain prevhash.
* rel_hash: sum of hash in DN which generated by this query_string.//由此查询字符串在DN中生成的哈希值之和
* globalhash: hash for last record of gs_global_chain, it means blockchain prevhash.//gs_global_chain的最后一条记录的哈希值也即区块链的前一个哈希值
*/
current_block.blocknum = get_next_g_blocknum();
gen_global_hash(&current_block.globalhash, combine_string, false, NULL);
current_block.blocknum = get_next_g_blocknum();// 获取下一个区块号
gen_global_hash(&current_block.globalhash, combine_string, false, NULL);// 创建下一个块并生成MD5哈希值
// 准备要插入到全局链表中的数据
values[Anum_gs_global_chain_blocknum - 1] = UInt64GetDatum(current_block.blocknum);//将当前块的块号blocknum转换为UInt64类型并将其存储在values数组的对应位置上。
values[Anum_gs_global_chain_dbname - 1] = DirectFunctionCall1(namein, CStringGetDatum(db_name));//将数据库名db_name转换为namein函数所需的输入参数类型并将其存储在values数组的对应位置上
values[Anum_gs_global_chain_username - 1] = DirectFunctionCall1(namein, CStringGetDatum(user_name));//将用户名user_name转换为namein函数所需的输入参数类型并将其存储在values数组的对应位置上
values[Anum_gs_global_chain_starttime - 1] = current_time;//将当前时间current_time存储在values数组的对应位置上
values[Anum_gs_global_chain_relid - 1] = ObjectIdGetDatum(relid);//将关系IDrelid转换为ObjectId类型并将其存储在values数组的对应位置上
values[Anum_gs_global_chain_relnsp - 1] = DirectFunctionCall1(namein, CStringGetDatum(nsp_name));//将命名空间名nsp_name转换为namein函数所需的输入参数类型并将其存储在values数组的对应位置上
values[Anum_gs_global_chain_relname - 1] = DirectFunctionCall1(namein, CStringGetDatum(rel_name));//将关系名rel_name转换为namein函数所需的输入参数类型并将其存储在values数组的对应位置上
values[Anum_gs_global_chain_relhash - 1] = UInt64GetDatum(cn_hash);//将关系哈希值cn_hash转换为UInt64类型并将其存储在values数组的对应位置上
values[Anum_gs_global_chain_globalhash - 1] = HASH32GetDatum(&current_block.globalhash);//将当前块的全局哈希值current_block.globalhash转换为HASH32类型并将其存储在values数组的对应位置上
values[Anum_gs_global_chain_txcommand - 1] = CStringGetTextDatum(query_string);//将查询字符串query_string转换为text类型并将其存储在values数组的对应位置上
values[Anum_gs_global_chain_blocknum - 1] = UInt64GetDatum(current_block.blocknum);
values[Anum_gs_global_chain_dbname - 1] = DirectFunctionCall1(namein, CStringGetDatum(db_name));
values[Anum_gs_global_chain_username - 1] = DirectFunctionCall1(namein, CStringGetDatum(user_name));
values[Anum_gs_global_chain_starttime - 1] = current_time;
values[Anum_gs_global_chain_relid - 1] = ObjectIdGetDatum(relid);
values[Anum_gs_global_chain_relnsp - 1] = DirectFunctionCall1(namein, CStringGetDatum(nsp_name));
values[Anum_gs_global_chain_relname - 1] = DirectFunctionCall1(namein, CStringGetDatum(rel_name));
values[Anum_gs_global_chain_relhash - 1] = UInt64GetDatum(cn_hash);
values[Anum_gs_global_chain_globalhash - 1] = HASH32GetDatum(&current_block.globalhash);
values[Anum_gs_global_chain_txcommand - 1] = CStringGetTextDatum(query_string);
rel_gchain = heap_open(GsGlobalChainRelationId, RowExclusiveLock);// 打开全局链表关系
tup = heap_form_tuple(rel_gchain->rd_att, values, nulls);//创建新的堆元组
rel_gchain = heap_open(GsGlobalChainRelationId, RowExclusiveLock);
tup = heap_form_tuple(rel_gchain->rd_att, values, nulls);
simple_heap_insert(rel_gchain, tup);
heap_freetuple(tup);
simple_heap_insert(rel_gchain, tup);//插入堆元组到全局链表中
//插入方法来源src\gausskernel\storage\access\heap\heapam.cpp
//通过获取事务标识符,检查冲突,准备缓冲区,将元组插入到关系中,并处理可见性和日志记录等步骤,实现了数据的插入
heap_freetuple(tup);//释放堆元组内存
/* set latest previous global chain block */
heap_close(rel_gchain, RowExclusiveLock);
pfree(combine_string);
/* 设置最新的上一个全局链块 */
heap_close(rel_gchain, RowExclusiveLock);//关闭全局链表关系
pfree(combine_string);//释放组合字符串内存
}
/*
* ledger_output_append_hash -- append relhash to response tag.
* ledger_output_append_hash -- append relhash to response tag.//将relhash附加到响应标签中
*
* resp_tag: response tag address.
* operation: command operation.
* hash: the hash that prepare to append.
* resp_tag: response tag address.//响应标签的地址
* operation: command operation.//命令操作类型
* hash: the hash that prepare to append.//准备附加的哈希值
*/
//该函数的作用是在执行插入、更新和删除操作时,将关系哈希值追加到响应标签中,以便后续处理和记录。
static void ledger_output_append_hash(char *resp_tag, CmdType operation, uint64 hash)
{
Assert(resp_tag != NULL);
size_t len = strlen(resp_tag);
errno_t ret = EOK;
Assert(resp_tag != NULL); //确保resp_tag不为空
size_t len = strlen(resp_tag);//获取resp_tag的长度
errno_t ret = EOK;//初始化错误号
switch (operation) {
case CMD_INSERT:
case CMD_UPDATE:
case CMD_DELETE:
//将哈希值转换为字符串并追加到resp_tag字符串末尾
ret = snprintf_s(resp_tag + len, COMPLETION_TAG_BUFSIZE - len, COMPLETION_TAG_BUFSIZE - len - 1,
" %lu\0", hash);
securec_check_ss(ret, "\0", "\0");
" %lu\0", hash);// 追加的位置是resp_tag的末尾COMPLETION_TAG_BUFSIZE - len为可添加的最大字符数COMPLETION_TAG_BUFSIZE - len - 1为要写入的字符串的最大长度
securec_check_ss(ret, "\0", "\0");//检查函数调用是否成功
break;
default:
break;
@ -193,34 +217,39 @@ static void ledger_output_append_hash(char *resp_tag, CmdType operation, uint64
}
/*
* ledger_ExecutorEnd -- record block to gchain.
* ledger_ExecutorEnd -- record block to gchain.//将块记录到gchain中
*
* query_desc: query descript of executor.
* query_desc: query descript of executor.//执行器的查询描述
*
* Note: append new block to gchain in CN or singlenode.
* Note: append new block to gchain in CN or singlenode.//在CN或单节点中将新的块追加到gchain中
* each DN will link its relhash to es_modifiedRowHash, CN or singlenode
* use es_modifiedRowHash to receive all DN relhash and accumulate them
* as cn_relhash for insertion.
* DN将其关系哈希链接到es_modifiedRowHashCN或单节点使用es_modifiedRowHash接收所有DN的关系哈希并将它们累积为cn_relhash进行插入
*/
//是一个钩子函数,在查询执行完成后被调用。它主要的功能是记录查询的相关信息到全局链表中,
//包括关系ID、查询字符串、哈希值等。同时它还检查并将哈希值追加到响应标签中。
//负责触发记录操作
static void ledger_ExecutorEnd(QueryDesc *query_desc)
{
uint64 hashsum;
bool has_remote_hash = query_desc->estate->es_modifiedRowHash != NIL;
hashsum = hash_combiner(query_desc->estate->es_modifiedRowHash);
uint64 hashsum; //哈希值的总和
bool has_remote_hash = query_desc->estate->es_modifiedRowHash != NIL;//是否存在远程哈希
hashsum = hash_combiner(query_desc->estate->es_modifiedRowHash);//组合远程哈希的哈希值
if ((IS_PGXC_COORDINATOR || g_instance.role == VSINGLENODE) && has_remote_hash) {
//如果当前节点为PGXC_COORDINATOR协调节点或VSINGLENODE单节点并且是否存在远程哈希
Oid relid = InvalidOid;
Relation rel = NULL;
int relnum = query_desc->estate->es_num_result_relations;
int relnum = query_desc->estate->es_num_result_relations;//结果关系数量
if (relnum > 0) {
rel = query_desc->estate->es_result_relations->ri_RelationDesc;
/* gs_global_chain only records following actions */
switch (query_desc->operation) {
switch (query_desc->operation) {//根据查询到的操作类型
case CMD_INSERT:
case CMD_DELETE:
case CMD_UPDATE:
relid = RelationGetRelid(rel);
if (rel->rd_isblockchain) {
ledger_gchain_append(relid, query_desc->sourceText, hashsum);
relid = RelationGetRelid(rel); //获取关系的ID
if (rel->rd_isblockchain) {//如果是块链表
ledger_gchain_append(relid, query_desc->sourceText, hashsum);//将关系哈希信息追加到gchain中
}
break;
default:
@ -230,57 +259,68 @@ static void ledger_ExecutorEnd(QueryDesc *query_desc)
}
if (u_sess->ledger_cxt.resp_tag != NULL && has_remote_hash && !IsConnFromApp()) {
//如果相应标签地址的指针不为空&&存在远程哈希并且&&非应用程序连接,则将哈希值追加到响应标签中
ledger_output_append_hash(u_sess->ledger_cxt.resp_tag, query_desc->operation, hashsum);
u_sess->ledger_cxt.resp_tag = NULL;
u_sess->ledger_cxt.resp_tag = NULL;//清空响应标签
}
if (t_thrd.security_ledger_cxt.prev_ExecutorEnd) {
((ExecutorEnd_hook_type)t_thrd.security_ledger_cxt.prev_ExecutorEnd)(query_desc);
((ExecutorEnd_hook_type)t_thrd.security_ledger_cxt.prev_ExecutorEnd)(query_desc); // 调用前一个ExecutorEnd钩子函数
} else {
standard_ExecutorEnd(query_desc);
standard_ExecutorEnd(query_desc); //执行标准的ExecutorEnd操作
//函数来源src\gausskernel\runtime\executor\execMain.cpp
//该函数功能为释放快照、LLVM 编译清理、切换上下文并释放内存、重置查询描述的字段、输出内存追踪信息到文件、收集指令计数信息、重置永久空间perm space的全局值
}
}
/*
* light_ledger_ExecutorEnd -- record block to gchain in light proxy.
* light_ledger_ExecutorEnd -- record block to gchain in light proxy.//在轻量级代理中将块记录到全局链gchain
*
* query: query of executor.
* relhash: sum of all DN relhash for insertion.
* query: query of executor.//执行器的查询
* relhash: sum of all DN relhash for insertion.//插入操作的所有分布式节点关系哈希值的总和
*
* Note: in light proxy logical, process will extract and
* accumulate relhash from response text of DNs as cn_relhash.
* cn_relhash
*/
//根据传入的查询信息判断关系是否为用户表如果是则将关系的哈希信息追加到gchain中以记录区块链中的数据变动。
void light_ledger_ExecutorEnd(Query *query, uint64 relhash)
{
//如果不是PGXC协调器节点并且当前节点的角色不是单节点VSINGLENODE
if (!IS_PGXC_COORDINATOR && g_instance.role != VSINGLENODE) {
return;
}
Oid relid = InvalidOid;
Oid relid = InvalidOid;//关系ID默认为无效ID
switch (query->commandType) {
switch (query->commandType) {//获取查询对象的命令类型
case CMD_INSERT:
case CMD_DELETE:
case CMD_UPDATE:
relid = get_target_query_relid(query->rtable, query->resultRelation);
if (is_ledger_usertable(relid)) {
ledger_gchain_append(relid, query->sql_statement, relhash);
relid = get_target_query_relid(query->rtable, query->resultRelation);//获取目标查询的关系ID
//函数来源src\gausskernel\security\gs_ledger\ledger_utils.cpp
if (is_ledger_usertable(relid)) {//根据关系ID的有效性、关系类型和所属命名空间判断关系是否为用户表
//函数来源src\gausskernel\security\gs_ledger\ledger_utils.cpp
ledger_gchain_append(relid, query->sql_statement, relhash);//将关系哈希信息追加到gchain中
}
break;
/* Not support others */
//其他指令不做处理
default:
break;
}
}
/*
* light_ledger_ExecutorEnd -- record block to gchain in opfusion.
* light_ledger_ExecutorEnd -- record block to gchain in opfusion.//在操作融合opfusion中将块记录到全局链gchain
*
* fusiontype: operator type.
* relid: relation oid of usertable.
* query: original query which modified usertable.
* relhash: relhash in hist table generated by sourceText.
* fusiontype: operator type.//操作类型
* relid: relation oid of usertable.//用户表的关系OID
* query: original query which modified usertable.//修改了用户表的原始查询
* relhash: relhash in hist table generated by sourceText.//由源文本生成的历史表中的关系哈希值
*/
//和前一个函数相比此函数判断执行条件时要求当前节点的角色是虚拟数据节点或者关系ID对应的表不是用户表。。
void opfusion_ledger_ExecutorEnd(FusionType fusiontype, Oid relid, const char *query, uint64 relhash)
{
//当前节点的角色是VDATANODE虚拟数据节点或者关系ID对应的表不是用户表
if (g_instance.role == VDATANODE || !is_ledger_usertable(relid)) {
return;
}
@ -289,8 +329,8 @@ void opfusion_ledger_ExecutorEnd(FusionType fusiontype, Oid relid, const char *q
case INSERT_FUSION:
case UPDATE_FUSION:
case DELETE_FUSION:
if (is_ledger_usertable(relid)) {
ledger_gchain_append(relid, query, relhash);
if (is_ledger_usertable(relid)) {//根据关系ID的有效性、关系类型和所属命名空间判断关系是否为用户表
ledger_gchain_append(relid, query, relhash);//将关系哈希信息追加到gchain中
}
break;
/* Not support others */
@ -302,16 +342,23 @@ void opfusion_ledger_ExecutorEnd(FusionType fusiontype, Oid relid, const char *q
/*
* ledger_hook_init -- install of gchain block record hook.
*/
//初始化钩子函数,将自定义的执行器结束钩子函数 ledger_ExecutorEnd 替换掉原有的钩子函数 ExecutorEnd_hook
//从而在执行器结束时触发自定义的操作。这样可以实现对关系的哈希信息追加到 gchain 中的功能。
void ledger_hook_init(void)
{
//将原先的 ExecutorEnd_hook 函数保存到 prev_ExecutorEnd 变量中
t_thrd.security_ledger_cxt.prev_ExecutorEnd = (void *)ExecutorEnd_hook;
//将 ledger_ExecutorEnd 函数赋值给 ExecutorEnd_hook以替换原有的钩子函数
ExecutorEnd_hook = ledger_ExecutorEnd;
}
/*
* ledger_hook_fini -- uninstall of gchain block record hook.
*/
//恢复原始的钩子函数,将之前保存的 prev_ExecutorEnd 变量的值重新赋值给 ExecutorEnd_hook以恢复原始的钩子函数的功能。这样可以确保在钩子函数替换后再次恢复原有的钩子函数避免对系统功能产生影响。
void ledger_hook_fini(void)
{
//将prev_ExecutorEnd 变量的值赋值给 ExecutorEnd_hook恢复原始的钩子函数
ExecutorEnd_hook = (ExecutorEnd_hook_type)t_thrd.security_ledger_cxt.prev_ExecutorEnd;
}