From 0cd2edfb52732db6a7a29d57dcc87697fb76dc00 Mon Sep 17 00:00:00 2001 From: hyt15810656168 Date: Sun, 27 Aug 2023 22:31:59 +0800 Subject: [PATCH] Update blockchain.cpp --- .../security/gs_ledger/blockchain.cpp | 263 +++++++++++------- 1 file changed, 155 insertions(+), 108 deletions(-) diff --git a/src/gausskernel/security/gs_ledger/blockchain.cpp b/src/gausskernel/security/gs_ledger/blockchain.cpp index 23c0d946f..bd0c20449 100644 --- a/src/gausskernel/security/gs_ledger/blockchain.cpp +++ b/src/gausskernel/security/gs_ledger/blockchain.cpp @@ -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(¤t_block.globalhash, combine_string, false, NULL); + current_block.blocknum = get_next_g_blocknum();// 获取下一个区块号 + gen_global_hash(¤t_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);//将关系ID(relid)转换为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(¤t_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(¤t_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_modifiedRowHash,CN或单节点使用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; } +