Update blockchain.cpp
This commit is contained in:
parent
74add04db0
commit
0cd2edfb52
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue